@vultisig/core-chain 2.37.0 → 2.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/chains/solana/kamino/KaminoServiceError.d.ts +63 -0
- package/dist/chains/solana/kamino/KaminoServiceError.d.ts.map +1 -0
- package/dist/chains/solana/kamino/KaminoServiceError.js +29 -0
- package/dist/chains/solana/kamino/KaminoServiceError.js.map +1 -0
- package/dist/chains/solana/kamino/amount.d.ts +141 -0
- package/dist/chains/solana/kamino/amount.d.ts.map +1 -0
- package/dist/chains/solana/kamino/amount.js +156 -0
- package/dist/chains/solana/kamino/amount.js.map +1 -0
- package/dist/chains/solana/kamino/api.d.ts +20 -0
- package/dist/chains/solana/kamino/api.d.ts.map +1 -0
- package/dist/chains/solana/kamino/api.js +59 -0
- package/dist/chains/solana/kamino/api.js.map +1 -0
- package/dist/chains/solana/kamino/baseUnits.d.ts +23 -0
- package/dist/chains/solana/kamino/baseUnits.d.ts.map +1 -0
- package/dist/chains/solana/kamino/baseUnits.js +30 -0
- package/dist/chains/solana/kamino/baseUnits.js.map +1 -0
- package/dist/chains/solana/kamino/config.d.ts +27 -0
- package/dist/chains/solana/kamino/config.d.ts.map +1 -0
- package/dist/chains/solana/kamino/config.js +27 -0
- package/dist/chains/solana/kamino/config.js.map +1 -0
- package/dist/chains/solana/kamino/decimal.d.ts +24 -0
- package/dist/chains/solana/kamino/decimal.d.ts.map +1 -0
- package/dist/chains/solana/kamino/decimal.js +52 -0
- package/dist/chains/solana/kamino/decimal.js.map +1 -0
- package/dist/chains/solana/kamino/models.d.ts +148 -0
- package/dist/chains/solana/kamino/models.d.ts.map +1 -0
- package/dist/chains/solana/kamino/models.js +2 -0
- package/dist/chains/solana/kamino/models.js.map +1 -0
- package/dist/chains/solana/kamino/position.d.ts +79 -0
- package/dist/chains/solana/kamino/position.d.ts.map +1 -0
- package/dist/chains/solana/kamino/position.js +52 -0
- package/dist/chains/solana/kamino/position.js.map +1 -0
- package/dist/chains/solana/kamino/rate.d.ts +57 -0
- package/dist/chains/solana/kamino/rate.d.ts.map +1 -0
- package/dist/chains/solana/kamino/rate.js +88 -0
- package/dist/chains/solana/kamino/rate.js.map +1 -0
- package/dist/chains/solana/kamino/registry.d.ts +70 -0
- package/dist/chains/solana/kamino/registry.d.ts.map +1 -0
- package/dist/chains/solana/kamino/registry.js +67 -0
- package/dist/chains/solana/kamino/registry.js.map +1 -0
- package/dist/chains/solana/kamino/tx/actions.d.ts +22 -0
- package/dist/chains/solana/kamino/tx/actions.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/actions.js +85 -0
- package/dist/chains/solana/kamino/tx/actions.js.map +1 -0
- package/dist/chains/solana/kamino/tx/computeBudget.d.ts +66 -0
- package/dist/chains/solana/kamino/tx/computeBudget.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/computeBudget.js +73 -0
- package/dist/chains/solana/kamino/tx/computeBudget.js.map +1 -0
- package/dist/chains/solana/kamino/tx/decode.d.ts +121 -0
- package/dist/chains/solana/kamino/tx/decode.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/decode.js +458 -0
- package/dist/chains/solana/kamino/tx/decode.js.map +1 -0
- package/dist/chains/solana/kamino/tx/instructions.d.ts +260 -0
- package/dist/chains/solana/kamino/tx/instructions.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/instructions.js +256 -0
- package/dist/chains/solana/kamino/tx/instructions.js.map +1 -0
- package/dist/chains/solana/kamino/tx/sequence.d.ts +123 -0
- package/dist/chains/solana/kamino/tx/sequence.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/sequence.js +235 -0
- package/dist/chains/solana/kamino/tx/sequence.js.map +1 -0
- package/dist/chains/solana/kamino/tx/validate.d.ts +138 -0
- package/dist/chains/solana/kamino/tx/validate.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/validate.js +542 -0
- package/dist/chains/solana/kamino/tx/validate.js.map +1 -0
- package/dist/chains/solana/kamino/tx/wire.d.ts +107 -0
- package/dist/chains/solana/kamino/tx/wire.d.ts.map +1 -0
- package/dist/chains/solana/kamino/tx/wire.js +274 -0
- package/dist/chains/solana/kamino/tx/wire.js.map +1 -0
- package/dist/chains/solana/kamino/vaultInfo.d.ts +17 -0
- package/dist/chains/solana/kamino/vaultInfo.d.ts.map +1 -0
- package/dist/chains/solana/kamino/vaultInfo.js +150 -0
- package/dist/chains/solana/kamino/vaultInfo.js.map +1 -0
- package/package.json +91 -1
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
import { getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
2
|
+
import { PublicKey } from '@solana/web3.js';
|
|
3
|
+
import { kaminoShareAmount } from '../amount.js';
|
|
4
|
+
import { kaminoMaxBaseUnits } from '../baseUnits.js';
|
|
5
|
+
import { kaminoConfig } from '../config.js';
|
|
6
|
+
import { getKaminoVaultDescriptor } from '../registry.js';
|
|
7
|
+
import { anchorU64Argument, anchorU128Argument, computeUnitLimitArgument, computeUnitPriceArgument, deriveKaminoFarmsUserState, hasNoAnchorArgument, isAttributionMemoData, isBuilderComposedProgram, kaminoAllowedProgram, kaminoAllowedPrograms, kaminoFarmsStakeScale, kaminoInstructionAccounts, systemTransferLamports, } from './instructions.js';
|
|
8
|
+
import { expectedKaminoSequence, kaminoInstructionKind, kaminoInstructionKindName, matchKaminoSequence, } from './sequence.js';
|
|
9
|
+
import { isKaminoAccountWritable, isUnsignedSingleSigner, resolveKaminoAccountAddresses, resolveKaminoLookupTables, totalKaminoAccountCount, } from './wire.js';
|
|
10
|
+
/**
|
|
11
|
+
* Shares the farm has to release before the withdraw can burn its amount:
|
|
12
|
+
* the shortfall, and nothing more. Measured against captured builds: a
|
|
13
|
+
* request covered by the unstaked balance is built with no farms
|
|
14
|
+
* instructions at all, and anything above it unstakes exactly the
|
|
15
|
+
* difference.
|
|
16
|
+
*/
|
|
17
|
+
export const kaminoUnstakeShares = ({ shares, unstakedShares }) => {
|
|
18
|
+
const shortfall = shares.baseUnits - unstakedShares.baseUnits;
|
|
19
|
+
return kaminoShareAmount(shortfall > 0n ? shortfall : 0n, shares.decimals);
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* A refusal from the fail-closed validator. Everything it finds is a refusal
|
|
23
|
+
* — nothing downgrades to a warning — and `finding` names the category so
|
|
24
|
+
* callers and tests branch on data rather than message text.
|
|
25
|
+
*/
|
|
26
|
+
export class KaminoValidationError extends Error {
|
|
27
|
+
finding;
|
|
28
|
+
constructor(finding, detail) {
|
|
29
|
+
super(`Kamino transaction refused (${finding}): ${detail}`);
|
|
30
|
+
this.name = 'KaminoValidationError';
|
|
31
|
+
this.finding = finding;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const refuse = (finding, detail) => {
|
|
35
|
+
throw new KaminoValidationError(finding, detail);
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* The user's associated token accounts for one mint, one per token program.
|
|
39
|
+
* Both token programs are tried because a mint belongs to exactly one and
|
|
40
|
+
* which one is not knowable from the address alone.
|
|
41
|
+
*/
|
|
42
|
+
export const kaminoUserTokenAccounts = ({ owner, mint }) => {
|
|
43
|
+
try {
|
|
44
|
+
const ownerKey = new PublicKey(owner);
|
|
45
|
+
const mintKey = new PublicKey(mint);
|
|
46
|
+
return new Set([TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID].map(program => getAssociatedTokenAddressSync(mintKey, ownerKey, false, program).toBase58()));
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return new Set();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const instructionAccounts = (context, position) => Array.from(context.transaction.message.compiledInstructions[position].accountKeyIndexes, index => {
|
|
53
|
+
const address = context.accounts[index];
|
|
54
|
+
return address ?? refuse('accountResolution', `instruction ${position} indexes account ${index}`);
|
|
55
|
+
});
|
|
56
|
+
const requireOwner = (context, account, role) => {
|
|
57
|
+
if (account !== context.intent.owner) {
|
|
58
|
+
refuse('accountMismatch', `${role} is ${account}, expected ${context.intent.owner}`);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const requireAccount = (account, expected, role) => {
|
|
62
|
+
if (account !== expected)
|
|
63
|
+
refuse('accountMismatch', `${role} is ${account}, expected ${expected}`);
|
|
64
|
+
};
|
|
65
|
+
const requireUserTokenAccount = (context, account, role) => {
|
|
66
|
+
if (!context.userTokenAccounts.has(account))
|
|
67
|
+
refuse('accountNotOwnedByUser', `${role} ${account}`);
|
|
68
|
+
};
|
|
69
|
+
const requireUserShareAccount = (context, account, role) => {
|
|
70
|
+
if (!context.userShareAccounts.has(account))
|
|
71
|
+
refuse('accountNotOwnedByUser', `${role} ${account}`);
|
|
72
|
+
};
|
|
73
|
+
const requireFarm = (context, account) => {
|
|
74
|
+
const farm = context.intent.vault.descriptor.farm;
|
|
75
|
+
if (!farm)
|
|
76
|
+
refuse('instructionNotForOperation', 'farm instruction against a farmless vault');
|
|
77
|
+
else
|
|
78
|
+
requireAccount(account, farm, 'farm');
|
|
79
|
+
};
|
|
80
|
+
const requireFarmUserState = (context, account) => {
|
|
81
|
+
const farm = context.intent.vault.descriptor.farm;
|
|
82
|
+
if (!farm)
|
|
83
|
+
return refuse('instructionNotForOperation', 'farm instruction against a farmless vault');
|
|
84
|
+
const expected = deriveKaminoFarmsUserState({ farm, owner: context.intent.owner });
|
|
85
|
+
if (!expected)
|
|
86
|
+
return refuse('derivationFailed', `the farm user state for ${farm}`);
|
|
87
|
+
requireAccount(account, expected, 'farm user state');
|
|
88
|
+
};
|
|
89
|
+
const requireNoAccounts = (accounts, position, detail) => {
|
|
90
|
+
if (accounts.length > 0)
|
|
91
|
+
refuse('malformedInstruction', `instruction ${position}: ${detail} takes no accounts`);
|
|
92
|
+
};
|
|
93
|
+
const requireU64 = (value, role) => {
|
|
94
|
+
if (value < 0n || value > kaminoMaxBaseUnits)
|
|
95
|
+
refuse('amountOutOfRange', `${role} ${value}`);
|
|
96
|
+
return value;
|
|
97
|
+
};
|
|
98
|
+
const requireAnchorAmount = (data, position, expected, role) => {
|
|
99
|
+
const argument = anchorU64Argument(data);
|
|
100
|
+
if (argument === undefined) {
|
|
101
|
+
return refuse('malformedInstruction', `instruction ${position}: ${role} argument`);
|
|
102
|
+
}
|
|
103
|
+
if (argument !== requireU64(expected, role)) {
|
|
104
|
+
refuse('amountMismatch', `${role} is ${argument}, expected ${expected}`);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const operationKind = (intent) => 'deposit' in intent.operation ? 'deposit' : 'withdraw';
|
|
108
|
+
const layout = kaminoInstructionAccounts;
|
|
109
|
+
/**
|
|
110
|
+
* The compute unit limit, pinned to the value the app injected. A limit is
|
|
111
|
+
* half of the fee — the network charges `limit × price` — so one raised
|
|
112
|
+
* beyond what the transaction needs is SOL spent for nothing.
|
|
113
|
+
*/
|
|
114
|
+
const checkComputeUnitLimit = ({ context, position, data, accounts }) => {
|
|
115
|
+
requireNoAccounts(accounts, position, 'compute budget');
|
|
116
|
+
const limit = computeUnitLimitArgument(data);
|
|
117
|
+
const fee = context.intent.priorityFee;
|
|
118
|
+
if (!fee || limit === undefined) {
|
|
119
|
+
return refuse('malformedInstruction', `instruction ${position}: compute unit limit`);
|
|
120
|
+
}
|
|
121
|
+
if (limit !== fee.unitLimit) {
|
|
122
|
+
refuse('amountMismatch', `compute unit limit is ${limit}, expected ${fee.unitLimit}`);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* The price per compute unit, pinned to the value the app injected. This is
|
|
127
|
+
* the half an attacker would inflate: a u64 of micro-lamports, and nothing on
|
|
128
|
+
* chain caps the resulting fee below the payer's balance.
|
|
129
|
+
*/
|
|
130
|
+
const checkComputeUnitPrice = ({ context, position, data, accounts }) => {
|
|
131
|
+
requireNoAccounts(accounts, position, 'compute budget');
|
|
132
|
+
const price = computeUnitPriceArgument(data);
|
|
133
|
+
const fee = context.intent.priorityFee;
|
|
134
|
+
if (!fee || price === undefined) {
|
|
135
|
+
return refuse('malformedInstruction', `instruction ${position}: compute unit price`);
|
|
136
|
+
}
|
|
137
|
+
if (price !== fee.unitPriceMicroLamports) {
|
|
138
|
+
refuse('amountMismatch', `compute unit price is ${price}, expected ${fee.unitPriceMicroLamports}`);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* A CreateIdempotent may only create one of the vault's two mints' accounts,
|
|
143
|
+
* for the user, at the address derivation says it must have. Creating an
|
|
144
|
+
* account is harmless in itself, but it is also where a third-party
|
|
145
|
+
* destination would first appear.
|
|
146
|
+
*/
|
|
147
|
+
const checkCreateTokenAccount = ({ context, accounts, requireMinimumAccounts }) => {
|
|
148
|
+
const { intent } = context;
|
|
149
|
+
requireMinimumAccounts(layout.associatedToken.count);
|
|
150
|
+
requireOwner(context, accounts[layout.associatedToken.payer], 'token account funder');
|
|
151
|
+
requireOwner(context, accounts[layout.associatedToken.wallet], 'token account owner');
|
|
152
|
+
const mint = accounts[layout.associatedToken.mint];
|
|
153
|
+
const { tokenMint, sharesMint } = intent.vault.descriptor;
|
|
154
|
+
if (mint !== tokenMint && mint !== sharesMint) {
|
|
155
|
+
return refuse('accountMismatch', `created token account mint is ${mint}`);
|
|
156
|
+
}
|
|
157
|
+
const tokenProgramId = accounts[layout.associatedToken.tokenProgram];
|
|
158
|
+
const tokenProgram = splTokenProgram(tokenProgramId);
|
|
159
|
+
if (!tokenProgram)
|
|
160
|
+
return refuse('programNotAllowed', `token program ${tokenProgramId}`);
|
|
161
|
+
const derived = getAssociatedTokenAddressSync(new PublicKey(mint), new PublicKey(intent.owner), false, tokenProgram).toBase58();
|
|
162
|
+
requireAccount(accounts[layout.associatedToken.account], derived, 'created token account');
|
|
163
|
+
};
|
|
164
|
+
const splTokenProgram = (programId) => {
|
|
165
|
+
if (programId === kaminoAllowedPrograms.token)
|
|
166
|
+
return TOKEN_PROGRAM_ID;
|
|
167
|
+
if (programId === kaminoAllowedPrograms.token2022)
|
|
168
|
+
return TOKEN_2022_PROGRAM_ID;
|
|
169
|
+
return undefined;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* The lamports that fund the wSOL account: the only native SOL movement the
|
|
173
|
+
* operation performs, so both endpoints and the amount are pinned.
|
|
174
|
+
*/
|
|
175
|
+
const checkWrapSolTransfer = ({ context, position, data, accounts, requireMinimumAccounts }) => {
|
|
176
|
+
const { intent } = context;
|
|
177
|
+
requireMinimumAccounts(layout.systemTransfer.count);
|
|
178
|
+
const lamports = systemTransferLamports(data);
|
|
179
|
+
if (lamports === undefined) {
|
|
180
|
+
return refuse('malformedInstruction', `instruction ${position}: system transfer`);
|
|
181
|
+
}
|
|
182
|
+
requireOwner(context, accounts[layout.systemTransfer.source], 'SOL transfer source');
|
|
183
|
+
requireUserTokenAccount(context, accounts[layout.systemTransfer.destination], 'SOL transfer destination');
|
|
184
|
+
if (!('deposit' in intent.operation)) {
|
|
185
|
+
return refuse('instructionNotForOperation', 'SOL wrap on a withdraw');
|
|
186
|
+
}
|
|
187
|
+
const expected = requireU64(intent.operation.deposit.baseUnits, 'deposit amount');
|
|
188
|
+
if (lamports !== expected) {
|
|
189
|
+
refuse('amountMismatch', `wrapped SOL amount is ${lamports}, expected ${expected}`);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
const checkSyncNative = ({ context, accounts, requireMinimumAccounts }) => {
|
|
193
|
+
requireMinimumAccounts(1);
|
|
194
|
+
requireUserTokenAccount(context, accounts[0], 'wrapped SOL account');
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* Closing a token account sends its remaining lamports somewhere. Both the
|
|
198
|
+
* account being closed and where its rent lands have to be the user's.
|
|
199
|
+
*/
|
|
200
|
+
const checkCloseTokenAccount = ({ context, accounts, requireMinimumAccounts }) => {
|
|
201
|
+
requireMinimumAccounts(layout.closeAccount.count);
|
|
202
|
+
const closed = accounts[layout.closeAccount.account];
|
|
203
|
+
if (!context.userTokenAccounts.has(closed) && !context.userShareAccounts.has(closed)) {
|
|
204
|
+
return refuse('accountNotOwnedByUser', `closed token account ${closed}`);
|
|
205
|
+
}
|
|
206
|
+
requireOwner(context, accounts[layout.closeAccount.destination], 'closed account rent destination');
|
|
207
|
+
requireOwner(context, accounts[layout.closeAccount.authority], 'closed account authority');
|
|
208
|
+
};
|
|
209
|
+
const checkKvaultDeposit = ({ context, position, data, accounts, requireMinimumAccounts }) => {
|
|
210
|
+
const { intent } = context;
|
|
211
|
+
requireMinimumAccounts(layout.kvaultDeposit.minimumCount);
|
|
212
|
+
if (!('deposit' in intent.operation)) {
|
|
213
|
+
return refuse('instructionNotForOperation', 'vault deposit on a withdraw');
|
|
214
|
+
}
|
|
215
|
+
const { address, tokenMint, sharesMint } = intent.vault.descriptor;
|
|
216
|
+
requireOwner(context, accounts[layout.kvaultDeposit.user], 'deposit authority');
|
|
217
|
+
requireAccount(accounts[layout.kvaultDeposit.vault], address, 'vault');
|
|
218
|
+
requireAccount(accounts[layout.kvaultDeposit.tokenMint], tokenMint, 'deposit token mint');
|
|
219
|
+
requireAccount(accounts[layout.kvaultDeposit.sharesMint], sharesMint, 'deposit shares mint');
|
|
220
|
+
requireUserTokenAccount(context, accounts[layout.kvaultDeposit.userTokenAccount], 'deposit source');
|
|
221
|
+
requireUserShareAccount(context, accounts[layout.kvaultDeposit.userShareAccount], 'deposit share destination');
|
|
222
|
+
requireAnchorAmount(data, position, intent.operation.deposit.baseUnits, 'deposit amount');
|
|
223
|
+
};
|
|
224
|
+
const checkKvaultWithdraw = ({ context, position, data, accounts, requireMinimumAccounts }) => {
|
|
225
|
+
const { intent } = context;
|
|
226
|
+
requireMinimumAccounts(layout.kvaultWithdraw.minimumCount);
|
|
227
|
+
if (!('withdraw' in intent.operation)) {
|
|
228
|
+
return refuse('instructionNotForOperation', 'vault withdraw on a deposit');
|
|
229
|
+
}
|
|
230
|
+
const { address, tokenMint, sharesMint } = intent.vault.descriptor;
|
|
231
|
+
requireOwner(context, accounts[layout.kvaultWithdraw.user], 'withdraw authority');
|
|
232
|
+
requireAccount(accounts[layout.kvaultWithdraw.vault], address, 'vault');
|
|
233
|
+
requireAccount(accounts[layout.kvaultWithdraw.tokenMint], tokenMint, 'withdraw token mint');
|
|
234
|
+
requireAccount(accounts[layout.kvaultWithdraw.sharesMint], sharesMint, 'withdraw shares mint');
|
|
235
|
+
requireUserTokenAccount(context, accounts[layout.kvaultWithdraw.userTokenAccount], 'withdraw destination');
|
|
236
|
+
requireUserShareAccount(context, accounts[layout.kvaultWithdraw.userShareAccount], 'withdraw share source');
|
|
237
|
+
// Shares, not tokens. The API takes the same `amount` field for both actions
|
|
238
|
+
// with inverted units, and an amount above the user's balance is silently
|
|
239
|
+
// rewritten to u64::MAX — withdraw everything — so this is the check that
|
|
240
|
+
// stands between a partial exit and a full one.
|
|
241
|
+
requireAnchorAmount(data, position, intent.operation.withdraw.shares.baseUnits, 'withdraw share amount');
|
|
242
|
+
};
|
|
243
|
+
const checkFarmsInitializeUser = ({ context, accounts, requireMinimumAccounts }) => {
|
|
244
|
+
requireMinimumAccounts(layout.farmsInitializeUser.minimumCount);
|
|
245
|
+
requireOwner(context, accounts[layout.farmsInitializeUser.authority], 'farm user authority');
|
|
246
|
+
requireFarm(context, accounts[layout.farmsInitializeUser.farm]);
|
|
247
|
+
};
|
|
248
|
+
/**
|
|
249
|
+
* The stake that makes the deposit's shares invisible in the wallet. It must
|
|
250
|
+
* move the user's own shares into this vault's own farm — a farm belonging to
|
|
251
|
+
* another vault would park the position somewhere the app never reads.
|
|
252
|
+
*/
|
|
253
|
+
const checkFarmsStake = ({ context, position, data, accounts, requireMinimumAccounts }) => {
|
|
254
|
+
requireMinimumAccounts(layout.farmsStake.minimumCount);
|
|
255
|
+
requireOwner(context, accounts[layout.farmsStake.owner], 'stake authority');
|
|
256
|
+
requireFarm(context, accounts[layout.farmsStake.farm]);
|
|
257
|
+
requireUserShareAccount(context, accounts[layout.farmsStake.userShareAccount], 'stake source');
|
|
258
|
+
requireAccount(accounts[layout.farmsStake.sharesMint], context.intent.vault.descriptor.sharesMint, 'stake shares mint');
|
|
259
|
+
// Kamino stakes the whole share balance rather than the freshly minted
|
|
260
|
+
// amount, so the argument is the u64 sentinel. A different value is a
|
|
261
|
+
// behaviour change, not a variation, and is worth stopping on.
|
|
262
|
+
const argument = anchorU64Argument(data);
|
|
263
|
+
if (argument === undefined) {
|
|
264
|
+
return refuse('malformedInstruction', `instruction ${position}: farms stake argument`);
|
|
265
|
+
}
|
|
266
|
+
if (argument !== kaminoMaxBaseUnits) {
|
|
267
|
+
refuse('amountMismatch', `staked share amount is ${argument}, expected ${kaminoMaxBaseUnits}`);
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
/**
|
|
271
|
+
* The release of staked shares from the farm, and the one amount in this
|
|
272
|
+
* feature that is not a u64: a u128 scaled by 10^18, checked in exact bigint
|
|
273
|
+
* arithmetic with no division and no narrowing.
|
|
274
|
+
*
|
|
275
|
+
* Pinned to the exact shortfall rather than bounded above by it: a LARGER
|
|
276
|
+
* unstake would release shares the transaction then leaves sitting out of the
|
|
277
|
+
* farm and no longer earning — a real loss, silent, and invisible on the
|
|
278
|
+
* verify screen; a smaller one simply cannot settle.
|
|
279
|
+
*/
|
|
280
|
+
const checkFarmsUnstake = ({ context, position, data, accounts, requireMinimumAccounts }) => {
|
|
281
|
+
const { intent } = context;
|
|
282
|
+
requireMinimumAccounts(layout.farmsUnstake.minimumCount);
|
|
283
|
+
if (!('withdraw' in intent.operation)) {
|
|
284
|
+
return refuse('instructionNotForOperation', 'farm unstake on a deposit');
|
|
285
|
+
}
|
|
286
|
+
requireOwner(context, accounts[layout.farmsUnstake.owner], 'unstake authority');
|
|
287
|
+
requireFarm(context, accounts[layout.farmsUnstake.farm]);
|
|
288
|
+
requireFarmUserState(context, accounts[layout.farmsUnstake.userState]);
|
|
289
|
+
const scaled = anchorU128Argument(data);
|
|
290
|
+
if (scaled === undefined) {
|
|
291
|
+
return refuse('malformedInstruction', `instruction ${position}: farms unstake argument`);
|
|
292
|
+
}
|
|
293
|
+
const expected = kaminoUnstakeShares(intent.operation.withdraw).baseUnits * kaminoFarmsStakeScale;
|
|
294
|
+
if (scaled !== expected) {
|
|
295
|
+
refuse('amountMismatch', `unstaked share amount is ${scaled}, expected ${expected}`);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
/**
|
|
299
|
+
* Moving what the unstake released into the user's own share account. It
|
|
300
|
+
* takes no argument — it always moves the whole released balance — so
|
|
301
|
+
* everything checkable here is an account, and the one that matters is the
|
|
302
|
+
* destination: the vault withdraw burns from that same account, and a
|
|
303
|
+
* destination belonging to anyone else would hand the position over.
|
|
304
|
+
*/
|
|
305
|
+
const checkFarmsWithdrawUnstakedDeposits = ({ context, position, data, accounts, requireMinimumAccounts, }) => {
|
|
306
|
+
requireMinimumAccounts(layout.farmsWithdrawUnstakedDeposits.minimumCount);
|
|
307
|
+
if (!('withdraw' in context.intent.operation)) {
|
|
308
|
+
return refuse('instructionNotForOperation', 'farm unstaked share withdrawal on a deposit');
|
|
309
|
+
}
|
|
310
|
+
if (!hasNoAnchorArgument(data)) {
|
|
311
|
+
return refuse('malformedInstruction', `instruction ${position}: farms withdrawUnstakedDeposits takes no argument`);
|
|
312
|
+
}
|
|
313
|
+
requireOwner(context, accounts[layout.farmsWithdrawUnstakedDeposits.owner], 'unstaked share withdrawal authority');
|
|
314
|
+
requireFarm(context, accounts[layout.farmsWithdrawUnstakedDeposits.farm]);
|
|
315
|
+
requireFarmUserState(context, accounts[layout.farmsWithdrawUnstakedDeposits.userState]);
|
|
316
|
+
requireUserShareAccount(context, accounts[layout.farmsWithdrawUnstakedDeposits.userShareAccount], 'unstaked share destination');
|
|
317
|
+
};
|
|
318
|
+
/**
|
|
319
|
+
* The sequence already refuses any other payload under the Memo program, so
|
|
320
|
+
* reaching here with different bytes is impossible — which is exactly why it
|
|
321
|
+
* is asserted rather than assumed: the tag is the only reason this program is
|
|
322
|
+
* allow-listed at all. No accounts, either: a memo listing accounts is the
|
|
323
|
+
* Memo program attesting that they signed, and attribution is not an
|
|
324
|
+
* attestation.
|
|
325
|
+
*/
|
|
326
|
+
const checkAttributionMemo = ({ position, data, accounts }) => {
|
|
327
|
+
requireNoAccounts(accounts, position, 'attribution memo');
|
|
328
|
+
if (!isAttributionMemoData(data)) {
|
|
329
|
+
refuse('malformedInstruction', `instruction ${position}: attribution memo`);
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
/**
|
|
333
|
+
* The account and amount checks each matched instruction must pass, one entry
|
|
334
|
+
* per template step. A record rather than a switch so every check stands on
|
|
335
|
+
* its own, and so a template step added without a check is a type error
|
|
336
|
+
* rather than an instruction that silently goes unchecked.
|
|
337
|
+
*/
|
|
338
|
+
const instructionChecks = {
|
|
339
|
+
computeUnitLimit: checkComputeUnitLimit,
|
|
340
|
+
computeUnitPrice: checkComputeUnitPrice,
|
|
341
|
+
createTokenAccount: checkCreateTokenAccount,
|
|
342
|
+
wrapSolTransfer: checkWrapSolTransfer,
|
|
343
|
+
syncNative: checkSyncNative,
|
|
344
|
+
closeTokenAccount: checkCloseTokenAccount,
|
|
345
|
+
kvaultDeposit: checkKvaultDeposit,
|
|
346
|
+
kvaultWithdraw: checkKvaultWithdraw,
|
|
347
|
+
farmsInitializeUser: checkFarmsInitializeUser,
|
|
348
|
+
farmsStake: checkFarmsStake,
|
|
349
|
+
farmsUnstake: checkFarmsUnstake,
|
|
350
|
+
farmsWithdrawUnstakedDeposits: checkFarmsWithdrawUnstakedDeposits,
|
|
351
|
+
attributionMemo: checkAttributionMemo,
|
|
352
|
+
};
|
|
353
|
+
const validateInstruction = (context, kind, position) => {
|
|
354
|
+
const accounts = instructionAccounts(context, position);
|
|
355
|
+
instructionChecks[kind]({
|
|
356
|
+
context,
|
|
357
|
+
position,
|
|
358
|
+
data: context.transaction.message.compiledInstructions[position].data,
|
|
359
|
+
accounts,
|
|
360
|
+
requireMinimumAccounts: minimum => {
|
|
361
|
+
if (accounts.length < minimum) {
|
|
362
|
+
refuse('malformedInstruction', `instruction ${position}: ${kaminoInstructionKindName[kind]} needs ${minimum} accounts`);
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
};
|
|
367
|
+
/**
|
|
368
|
+
* Two rules, together covering "no unexplained writes". A writable account
|
|
369
|
+
* nothing references is a loaded write privilege with no purpose, which is
|
|
370
|
+
* not a shape any legitimate builder emits. And an account that a
|
|
371
|
+
* builder-composed instruction can write to has to be one this operation can
|
|
372
|
+
* name — the user, the vault, its two mints, or the user's own token accounts
|
|
373
|
+
* for them. A drain has to write somewhere, and outside the `kvault`/`farms`
|
|
374
|
+
* programs there is nowhere left for it to write.
|
|
375
|
+
*/
|
|
376
|
+
const validateWritableAccounts = (context) => {
|
|
377
|
+
const { transaction, accounts, programs } = context;
|
|
378
|
+
const instructions = transaction.message.compiledInstructions;
|
|
379
|
+
const referenced = new Set();
|
|
380
|
+
for (const instruction of instructions) {
|
|
381
|
+
for (const index of instruction.accountKeyIndexes)
|
|
382
|
+
referenced.add(index);
|
|
383
|
+
}
|
|
384
|
+
for (let index = 0; index < accounts.length; index++) {
|
|
385
|
+
if (isKaminoAccountWritable({ transaction, index }) && !referenced.has(index)) {
|
|
386
|
+
refuse('unreferencedWritableAccount', accounts[index]);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
for (let position = 0; position < instructions.length; position++) {
|
|
390
|
+
const program = programs[position];
|
|
391
|
+
if (!program || !isBuilderComposedProgram(program))
|
|
392
|
+
continue;
|
|
393
|
+
for (const index of instructions[position].accountKeyIndexes) {
|
|
394
|
+
if (!isKaminoAccountWritable({ transaction, index }))
|
|
395
|
+
continue;
|
|
396
|
+
const account = accounts[index];
|
|
397
|
+
if (!context.explainedAccounts.has(account)) {
|
|
398
|
+
refuse('unattributableWritableAccount', `${program} writes ${account}`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
/**
|
|
404
|
+
* Fail-closed validation of a Kamino-built Solana transaction.
|
|
405
|
+
*
|
|
406
|
+
* Kamino builds the transaction and the app signs the bytes verbatim, so
|
|
407
|
+
* between an API response and a signature over it there is only this. It runs
|
|
408
|
+
* before simulation and before keysign, and every finding is a refusal.
|
|
409
|
+
*
|
|
410
|
+
* What it establishes, in layers: the shape (one unsigned signature, paid by
|
|
411
|
+
* the user, every lookup table the vault's own); the programs (every
|
|
412
|
+
* `programIdIndex` resolves to an allow-listed program — the outer bound on
|
|
413
|
+
* what the signature can authorise); the sequence (the instruction list
|
|
414
|
+
* matches the shape this operation produces, so a new instruction fails
|
|
415
|
+
* closed); the identity of every account that decides where money goes,
|
|
416
|
+
* compared against values the app already had — registry and local
|
|
417
|
+
* derivations, never the response, because checking a transaction the API
|
|
418
|
+
* built against metadata the same API supplied would be circular; the amounts
|
|
419
|
+
* (the kvault `u64` equals what the user was shown, the priority fee equals
|
|
420
|
+
* what the app injected); and the writable accounts (no unexplained writes).
|
|
421
|
+
*
|
|
422
|
+
* What it does not establish is what the `kvault` and `farms` programs do
|
|
423
|
+
* with the accounts they are handed. That is the protocol, and choosing to
|
|
424
|
+
* trust it is what the registry allow-list expresses.
|
|
425
|
+
*
|
|
426
|
+
* Pure — lookup tables arrive resolved, so tests can drive it against pinned
|
|
427
|
+
* contents. `validateKaminoTransactionOnline` is the fetching entry point.
|
|
428
|
+
*/
|
|
429
|
+
export const validateKaminoTransaction = ({ transaction, intent, lookupTables, }) => {
|
|
430
|
+
const vaultAddress = intent.vault.descriptor.address;
|
|
431
|
+
const registered = getKaminoVaultDescriptor(vaultAddress);
|
|
432
|
+
if (!registered)
|
|
433
|
+
return refuse('vaultNotAllowed', vaultAddress);
|
|
434
|
+
// The registry's own object, not a value-equal copy. Every value the checks
|
|
435
|
+
// below rest on — the mints, their decimals, the farm — lives on this
|
|
436
|
+
// descriptor, so accepting one that merely *claims* an allow-listed address
|
|
437
|
+
// would hand an attacker the pinning itself. Identity makes the registry
|
|
438
|
+
// the only possible source of a vault's identity, structurally rather than
|
|
439
|
+
// by convention.
|
|
440
|
+
if (registered !== intent.vault.descriptor) {
|
|
441
|
+
return refuse('vaultDescriptorMismatch', vaultAddress);
|
|
442
|
+
}
|
|
443
|
+
if (!isUnsignedSingleSigner(transaction, intent.owner)) {
|
|
444
|
+
return refuse('transactionShape', 'not an unsigned single-signer transaction paid by the owner');
|
|
445
|
+
}
|
|
446
|
+
// Every table the transaction reads from must be the vault's own. A table
|
|
447
|
+
// decides which pubkey an account index names, so a foreign one is how an
|
|
448
|
+
// account substitution would be hidden. Zero tables is allowed — then every
|
|
449
|
+
// account is a static key and there is nothing to hide behind.
|
|
450
|
+
const lookups = transaction.message.addressTableLookups;
|
|
451
|
+
if (lookups.length > 1)
|
|
452
|
+
return refuse('unexpectedLookupTable', `${lookups.length} lookup tables`);
|
|
453
|
+
for (const lookup of lookups) {
|
|
454
|
+
const address = lookup.accountKey.toBase58();
|
|
455
|
+
if (address !== intent.vault.lookupTable) {
|
|
456
|
+
return refuse('unexpectedLookupTable', `${address}, expected ${intent.vault.lookupTable}`);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
const accounts = resolveKaminoAccountAddresses({ transaction, lookupTables });
|
|
460
|
+
if (!accounts || accounts.length !== totalKaminoAccountCount(transaction)) {
|
|
461
|
+
return refuse('accountResolution', 'lookup tables do not resolve every account index');
|
|
462
|
+
}
|
|
463
|
+
const instructions = transaction.message.compiledInstructions;
|
|
464
|
+
const programs = instructions.map(instruction => kaminoAllowedProgram(accounts[instruction.programIdIndex]));
|
|
465
|
+
for (let position = 0; position < programs.length; position++) {
|
|
466
|
+
if (!programs[position]) {
|
|
467
|
+
return refuse('programNotAllowed', `instruction ${position} invokes ${accounts[instructions[position].programIdIndex]}`);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
// Before injection the app has chosen no fee and written no memo, so either
|
|
471
|
+
// arriving in the response came from the builder — and each is named
|
|
472
|
+
// separately so the refusal says what is actually wrong, rather than
|
|
473
|
+
// reading as a sequencing error.
|
|
474
|
+
if (!intent.priorityFee && programs.includes('computeBudget')) {
|
|
475
|
+
return refuse('unexpectedPriorityFee', 'compute budget instruction before injection');
|
|
476
|
+
}
|
|
477
|
+
if (!intent.carriesAttributionMemo && programs.includes('memo')) {
|
|
478
|
+
return refuse('unexpectedMemo', 'memo instruction before injection');
|
|
479
|
+
}
|
|
480
|
+
const userTokenAccounts = kaminoUserTokenAccounts({ owner: intent.owner, mint: intent.vault.descriptor.tokenMint });
|
|
481
|
+
const userShareAccounts = kaminoUserTokenAccounts({ owner: intent.owner, mint: intent.vault.descriptor.sharesMint });
|
|
482
|
+
if (userTokenAccounts.size === 0 || userShareAccounts.size === 0) {
|
|
483
|
+
return refuse('derivationFailed', "the user's associated token accounts");
|
|
484
|
+
}
|
|
485
|
+
const context = {
|
|
486
|
+
intent,
|
|
487
|
+
transaction,
|
|
488
|
+
accounts,
|
|
489
|
+
programs,
|
|
490
|
+
userTokenAccounts,
|
|
491
|
+
userShareAccounts,
|
|
492
|
+
explainedAccounts: new Set([
|
|
493
|
+
...userTokenAccounts,
|
|
494
|
+
...userShareAccounts,
|
|
495
|
+
intent.owner,
|
|
496
|
+
intent.vault.descriptor.address,
|
|
497
|
+
intent.vault.descriptor.tokenMint,
|
|
498
|
+
intent.vault.descriptor.sharesMint,
|
|
499
|
+
]),
|
|
500
|
+
};
|
|
501
|
+
const kinds = instructions.map((instruction, position) => kaminoInstructionKind(programs[position], instruction.data));
|
|
502
|
+
const steps = expectedKaminoSequence({
|
|
503
|
+
operation: operationKind(intent),
|
|
504
|
+
isWrappedSolVault: intent.vault.descriptor.tokenMint === kaminoConfig.wrappedSolMint,
|
|
505
|
+
hasFarm: intent.vault.descriptor.farm !== undefined,
|
|
506
|
+
hasPriorityFee: intent.priorityFee !== undefined,
|
|
507
|
+
hasAttributionMemo: intent.carriesAttributionMemo,
|
|
508
|
+
// This device read the position, so it knows which of the two withdraw
|
|
509
|
+
// shapes it asked for and says so. Never 'unknown' here: accepting either
|
|
510
|
+
// shape would let a transaction that unstakes shares pass as one that was
|
|
511
|
+
// not supposed to touch the farm.
|
|
512
|
+
farmUnstake: 'withdraw' in intent.operation
|
|
513
|
+
? kaminoUnstakeShares(intent.operation.withdraw).baseUnits > 0n
|
|
514
|
+
? 'required'
|
|
515
|
+
: 'forbidden'
|
|
516
|
+
: 'forbidden',
|
|
517
|
+
});
|
|
518
|
+
const outcome = matchKaminoSequence(kinds, steps);
|
|
519
|
+
if ('mismatch' in outcome) {
|
|
520
|
+
const { mismatch } = outcome;
|
|
521
|
+
if ('unexpectedInstruction' in mismatch) {
|
|
522
|
+
return refuse('unexpectedInstruction', `instruction ${mismatch.unexpectedInstruction.index}`);
|
|
523
|
+
}
|
|
524
|
+
return refuse('missingInstruction', 'missingInstruction' in mismatch ? mismatch.missingInstruction : mismatch.incompleteInstructionPair);
|
|
525
|
+
}
|
|
526
|
+
outcome.matched.forEach((kind, position) => validateInstruction(context, kind, position));
|
|
527
|
+
validateWritableAccounts(context);
|
|
528
|
+
};
|
|
529
|
+
/**
|
|
530
|
+
* Resolves the transaction's address lookup tables from the RPC, then runs
|
|
531
|
+
* the pure validator against them.
|
|
532
|
+
*
|
|
533
|
+
* Rejects with `KaminoValidationError` for a refusal of the transaction, and
|
|
534
|
+
* with `KaminoWireError` when the lookup tables could not be resolved at all
|
|
535
|
+
* (missing table, stalled node past the read deadline, transport failure) —
|
|
536
|
+
* callers must not assume every rejection carries a `finding`.
|
|
537
|
+
*/
|
|
538
|
+
export const validateKaminoTransactionOnline = async ({ transaction, intent, }) => {
|
|
539
|
+
const lookupTables = await resolveKaminoLookupTables(transaction);
|
|
540
|
+
validateKaminoTransaction({ transaction, intent, lookupTables });
|
|
541
|
+
};
|
|
542
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../../../../../../packages/core/chain/chains/solana/kamino/tx/validate.ts"],"names":[],"mappings":"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"}
|