@across-protocol/contracts 4.0.11 → 4.0.12
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/dist/scripts/svm/{enableRoute.js → createVault.js} +13 -35
- package/dist/scripts/svm/fakeFillWithRandomDistribution.js +9 -8
- package/dist/scripts/svm/nativeDeposit.js +138 -0
- package/dist/scripts/svm/queryEventsV2.js +3 -3
- package/dist/scripts/svm/{queryRoute.js → queryVault.js} +10 -25
- package/dist/scripts/svm/remoteHubPoolPauseDeposits.js +2 -2
- package/dist/scripts/svm/simpleDeposit.js +3 -12
- package/dist/scripts/svm/simpleFakeRelayerRepayment.js +2 -9
- package/dist/scripts/svm/simpleFill.js +3 -2
- package/dist/src/svm/assets/idl/svm_spoke.json +43 -369
- package/dist/src/svm/assets/svm_spoke.d.ts +40 -366
- package/dist/src/svm/clients/SvmSpoke/accounts/index.d.ts +0 -1
- package/dist/src/svm/clients/SvmSpoke/accounts/index.js +0 -1
- package/dist/src/svm/clients/SvmSpoke/errors/svmSpoke.d.ts +3 -1
- package/dist/src/svm/clients/SvmSpoke/errors/svmSpoke.js +4 -1
- package/dist/src/svm/clients/SvmSpoke/instructions/deposit.d.ts +21 -13
- package/dist/src/svm/clients/SvmSpoke/instructions/deposit.js +38 -6
- package/dist/src/svm/clients/SvmSpoke/instructions/depositNow.d.ts +21 -13
- package/dist/src/svm/clients/SvmSpoke/instructions/depositNow.js +38 -6
- package/dist/src/svm/clients/SvmSpoke/instructions/fillRelay.d.ts +20 -16
- package/dist/src/svm/clients/SvmSpoke/instructions/fillRelay.js +6 -1
- package/dist/src/svm/clients/SvmSpoke/instructions/index.d.ts +0 -1
- package/dist/src/svm/clients/SvmSpoke/instructions/index.js +0 -1
- package/dist/src/svm/clients/SvmSpoke/instructions/unsafeDeposit.d.ts +21 -13
- package/dist/src/svm/clients/SvmSpoke/instructions/unsafeDeposit.js +38 -6
- package/dist/src/svm/clients/SvmSpoke/programs/svmSpoke.d.ts +6 -10
- package/dist/src/svm/clients/SvmSpoke/programs/svmSpoke.js +5 -13
- package/dist/src/svm/clients/SvmSpoke/types/index.d.ts +0 -1
- package/dist/src/svm/clients/SvmSpoke/types/index.js +0 -1
- package/dist/src/svm/web3-v1/helpers.d.ts +114 -1
- package/dist/src/svm/web3-v1/helpers.js +179 -1
- package/dist/target/types/svm_spoke.d.ts +40 -366
- package/dist/test/svm/SvmSpoke.Deposit.js +143 -176
- package/dist/test/svm/SvmSpoke.Fill.AcrossPlus.js +20 -17
- package/dist/test/svm/SvmSpoke.Fill.js +52 -38
- package/dist/test/svm/SvmSpoke.HandleReceiveMessage.js +2 -114
- package/dist/test/svm/SvmSpoke.SlowFill.AcrossPlus.js +2 -2
- package/dist/test/svm/SvmSpoke.SlowFill.js +37 -34
- package/dist/test/svm/SvmSpoke.common.d.ts +2 -3
- package/dist/test/svm/SvmSpoke.common.js +3 -12
- package/package.json +1 -1
- package/dist/scripts/svm/remoteHubPoolSetDepositRoute.d.ts +0 -1
- package/dist/scripts/svm/remoteHubPoolSetDepositRoute.js +0 -252
- package/dist/src/svm/clients/SvmSpoke/accounts/route.d.ts +0 -27
- package/dist/src/svm/clients/SvmSpoke/accounts/route.js +0 -66
- package/dist/src/svm/clients/SvmSpoke/instructions/setEnableRoute.d.ts +0 -95
- package/dist/src/svm/clients/SvmSpoke/instructions/setEnableRoute.js +0 -213
- package/dist/src/svm/clients/SvmSpoke/types/enabledDepositRoute.d.ts +0 -21
- package/dist/src/svm/clients/SvmSpoke/types/enabledDepositRoute.js +0 -30
- package/dist/test/svm/SvmSpoke.Routes.js +0 -167
- /package/dist/scripts/svm/{enableRoute.d.ts → createVault.d.ts} +0 -0
- /package/dist/scripts/svm/{queryRoute.d.ts → nativeDeposit.d.ts} +0 -0
- /package/dist/{test/svm/SvmSpoke.Routes.d.ts → scripts/svm/queryVault.d.ts} +0 -0
|
@@ -35,44 +35,29 @@ const web3_v1_1 = require("../../src/svm/web3-v1");
|
|
|
35
35
|
const test_utils_1 = require("../../test-utils");
|
|
36
36
|
const SvmSpoke_common_1 = require("./SvmSpoke.common");
|
|
37
37
|
const utils_1 = require("./utils");
|
|
38
|
-
const { provider, connection, program, owner, seedBalance, initializeState, depositData,
|
|
38
|
+
const { provider, connection, program, owner, seedBalance, initializeState, depositData, assertSE, assert, getCurrentTime, depositQuoteTimeBuffer, fillDeadlineBuffer, getOrCreateVaultAta, } = SvmSpoke_common_1.common;
|
|
39
39
|
const maxExclusivityOffsetSeconds = new anchor_1.BN(test_utils_1.MAX_EXCLUSIVITY_OFFSET_SECONDS); // 1 year in seconds
|
|
40
40
|
describe("svm_spoke.deposit", () => {
|
|
41
41
|
anchor.setProvider(provider);
|
|
42
42
|
const depositor = web3_js_1.Keypair.generate();
|
|
43
|
-
const payer = anchor.AnchorProvider.env().wallet
|
|
43
|
+
const { payer } = anchor.AnchorProvider.env().wallet;
|
|
44
44
|
const tokenDecimals = 6;
|
|
45
45
|
let state, inputToken, depositorTA, vault, tokenProgram;
|
|
46
46
|
let seed;
|
|
47
47
|
let depositAccounts;
|
|
48
|
-
let setEnableRouteAccounts; // Common variable for setEnableRoute accounts
|
|
49
48
|
const setupInputToken = async () => {
|
|
50
49
|
inputToken = await (0, spl_token_1.createMint)(connection, payer, owner, owner, tokenDecimals, undefined, undefined, tokenProgram);
|
|
51
50
|
depositorTA = (await (0, spl_token_1.getOrCreateAssociatedTokenAccount)(connection, payer, inputToken, depositor.publicKey, undefined, undefined, undefined, tokenProgram)).address;
|
|
52
51
|
await (0, spl_token_1.mintTo)(connection, payer, inputToken, depositorTA, owner, seedBalance, undefined, undefined, tokenProgram);
|
|
53
52
|
};
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
const route = createRoutePda(inputToken, seed, routeChainId);
|
|
57
|
-
vault = await getVaultAta(inputToken, state);
|
|
58
|
-
setEnableRouteAccounts = {
|
|
59
|
-
signer: owner,
|
|
60
|
-
payer: owner,
|
|
61
|
-
state,
|
|
62
|
-
route,
|
|
63
|
-
vault,
|
|
64
|
-
originTokenMint: inputToken, // Note the Sol expects this to be named originTokenMint.
|
|
65
|
-
tokenProgram: tokenProgram ?? spl_token_1.TOKEN_PROGRAM_ID,
|
|
66
|
-
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
67
|
-
systemProgram: anchor.web3.SystemProgram.programId,
|
|
68
|
-
};
|
|
69
|
-
await program.methods.setEnableRoute(inputToken, routeChainId, true).accounts(setEnableRouteAccounts).rpc();
|
|
53
|
+
const createVault = async () => {
|
|
54
|
+
vault = await getOrCreateVaultAta(payer, inputToken, state);
|
|
70
55
|
// Set known fields in the depositData.
|
|
71
56
|
depositData.depositor = depositor.publicKey;
|
|
72
57
|
depositData.inputToken = inputToken;
|
|
73
58
|
depositAccounts = {
|
|
74
59
|
state,
|
|
75
|
-
|
|
60
|
+
delegate: (0, web3_v1_1.getDepositPda)(depositData, program.programId),
|
|
76
61
|
signer: depositor.publicKey,
|
|
77
62
|
depositorTokenAccount: depositorTA,
|
|
78
63
|
vault,
|
|
@@ -81,30 +66,33 @@ describe("svm_spoke.deposit", () => {
|
|
|
81
66
|
program: program.programId,
|
|
82
67
|
};
|
|
83
68
|
};
|
|
84
|
-
const approvedDeposit = async (
|
|
85
|
-
|
|
86
|
-
|
|
69
|
+
const approvedDeposit = async (depositData, calledDepositAccounts = depositAccounts) => {
|
|
70
|
+
const delegatePda = (0, web3_v1_1.getDepositPda)(depositData, program.programId);
|
|
71
|
+
calledDepositAccounts.delegate = delegatePda;
|
|
72
|
+
// Delegate delegate PDA to pull depositor tokens.
|
|
73
|
+
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(calledDepositAccounts.depositorTokenAccount, calledDepositAccounts.mint, delegatePda, depositor.publicKey, BigInt(depositData.inputAmount.toString()), tokenDecimals, undefined, tokenProgram);
|
|
87
74
|
const depositIx = await program.methods
|
|
88
|
-
.deposit(
|
|
75
|
+
.deposit(depositData.depositor, depositData.recipient, depositData.inputToken, depositData.outputToken, depositData.inputAmount, depositData.outputAmount, depositData.destinationChainId, depositData.exclusiveRelayer, depositData.quoteTimestamp.toNumber(), depositData.fillDeadline.toNumber(), depositData.exclusivityParameter.toNumber(), depositData.message)
|
|
89
76
|
.accounts(calledDepositAccounts)
|
|
90
77
|
.instruction();
|
|
91
78
|
const depositTx = new web3_js_1.Transaction().add(approveIx, depositIx);
|
|
92
|
-
|
|
93
|
-
return tx;
|
|
79
|
+
return (0, web3_js_1.sendAndConfirmTransaction)(connection, depositTx, [depositor]);
|
|
94
80
|
};
|
|
81
|
+
before(async () => {
|
|
82
|
+
await connection.requestAirdrop(depositor.publicKey, 10_000_000_000); // 10 SOL
|
|
83
|
+
});
|
|
95
84
|
beforeEach(async () => {
|
|
96
85
|
({ state, seed } = await initializeState());
|
|
97
86
|
tokenProgram = spl_token_1.TOKEN_PROGRAM_ID; // Some tests might override this.
|
|
98
87
|
await setupInputToken();
|
|
99
|
-
await
|
|
88
|
+
await createVault();
|
|
100
89
|
});
|
|
101
90
|
it("Deposits tokens via deposit function and checks balances", async () => {
|
|
102
91
|
// Verify vault balance is zero before the deposit
|
|
103
92
|
let vaultAccount = await (0, spl_token_1.getAccount)(connection, vault);
|
|
104
93
|
assertSE(vaultAccount.amount, "0", "Vault balance should be zero before the deposit");
|
|
105
94
|
// Execute the deposit call
|
|
106
|
-
|
|
107
|
-
await approvedDeposit(depositDataValues);
|
|
95
|
+
await approvedDeposit(depositData);
|
|
108
96
|
// Verify tokens leave the depositor's account
|
|
109
97
|
let depositorAccount = await (0, spl_token_1.getAccount)(connection, depositorTA);
|
|
110
98
|
assertSE(depositorAccount.amount, seedBalance - depositData.inputAmount.toNumber(), "Depositor's balance should be reduced by the deposited amount");
|
|
@@ -114,8 +102,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
114
102
|
// Modify depositData for the second deposit
|
|
115
103
|
const secondInputAmount = new anchor_1.BN(300000);
|
|
116
104
|
// Execute the second deposit call
|
|
117
|
-
|
|
118
|
-
await approvedDeposit(depositDataValues);
|
|
105
|
+
await approvedDeposit({ ...depositData, inputAmount: secondInputAmount });
|
|
119
106
|
// Verify tokens leave the depositor's account again
|
|
120
107
|
depositorAccount = await (0, spl_token_1.getAccount)(connection, depositorTA);
|
|
121
108
|
assertSE(depositorAccount.amount, seedBalance - depositData.inputAmount.toNumber() - secondInputAmount.toNumber(), "Depositor's balance should be reduced by the total deposited amount");
|
|
@@ -126,8 +113,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
126
113
|
it("Verifies FundsDeposited after deposits", async () => {
|
|
127
114
|
depositData.inputAmount = depositData.inputAmount.add(new anchor_1.BN(69));
|
|
128
115
|
// Execute the first deposit call
|
|
129
|
-
|
|
130
|
-
const tx = await approvedDeposit(depositDataValues);
|
|
116
|
+
const tx = await approvedDeposit(depositData);
|
|
131
117
|
let events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
132
118
|
let event = events[0].data; // 0th event is the latest event
|
|
133
119
|
const expectedValues1 = { ...depositData, depositId: (0, web3_v1_1.intToU8Array32)(1) }; // Verify the event props emitted match the depositData.
|
|
@@ -139,8 +125,8 @@ describe("svm_spoke.deposit", () => {
|
|
|
139
125
|
// Test the id recovery with the conversion utils
|
|
140
126
|
assertSE((0, web3_v1_1.u8Array32ToInt)(event.depositId), 1, `depositId should recover to 1`);
|
|
141
127
|
assertSE((0, web3_v1_1.u8Array32ToBigNumber)(event.depositId), ethers_1.BigNumber.from(1), `depositId should recover to 1`);
|
|
142
|
-
// Execute the second
|
|
143
|
-
const tx2 = await approvedDeposit(
|
|
128
|
+
// Execute the second deposit call
|
|
129
|
+
const tx2 = await approvedDeposit(depositData);
|
|
144
130
|
events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx2, [program]);
|
|
145
131
|
event = events[0].data; // 0th event is the latest event.
|
|
146
132
|
const expectedValues2 = { ...expectedValues1, depositId: (0, web3_v1_1.intToU8Array32)(2) }; // Verify the event props emitted match the depositData.
|
|
@@ -159,46 +145,11 @@ describe("svm_spoke.deposit", () => {
|
|
|
159
145
|
let fillDeadline = currentTime - 1; // 1 second before current time on the contract.
|
|
160
146
|
depositData.fillDeadline = new anchor_1.BN(fillDeadline);
|
|
161
147
|
depositData.quoteTimestamp = new anchor_1.BN(currentTime - 1); // 1 second before current time on the contract to reset.
|
|
162
|
-
const
|
|
163
|
-
const tx = await approvedDeposit(depositDataValues);
|
|
148
|
+
const tx = await approvedDeposit(depositData);
|
|
164
149
|
const events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
165
150
|
const event = events[0].data; // 0th event is the latest event.
|
|
166
151
|
assertSE(event.fillDeadline, fillDeadline, "Fill deadline should match");
|
|
167
152
|
});
|
|
168
|
-
it("Fails to deposit tokens to a route that is uninitalized", async () => {
|
|
169
|
-
const differentChainId = new anchor_1.BN(2); // Different chain ID
|
|
170
|
-
if (!depositData.inputToken) {
|
|
171
|
-
throw new Error("Input token is null");
|
|
172
|
-
}
|
|
173
|
-
const differentRoutePda = createRoutePda(depositData.inputToken, seed, differentChainId);
|
|
174
|
-
depositAccounts.route = differentRoutePda;
|
|
175
|
-
try {
|
|
176
|
-
const depositDataValues = Object.values({
|
|
177
|
-
...depositData,
|
|
178
|
-
destinationChainId: differentChainId,
|
|
179
|
-
});
|
|
180
|
-
await approvedDeposit(depositDataValues);
|
|
181
|
-
assert.fail("Deposit should have failed for a route that is not initialized");
|
|
182
|
-
}
|
|
183
|
-
catch (err) {
|
|
184
|
-
assert.include(err.toString(), "AccountNotInitialized", "Expected AccountNotInitialized error");
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
it("Fails to deposit tokens to a route that is explicitly disabled", async () => {
|
|
188
|
-
// Disable the route
|
|
189
|
-
await program.methods
|
|
190
|
-
.setEnableRoute(depositData.inputToken, depositData.destinationChainId, false)
|
|
191
|
-
.accounts(setEnableRouteAccounts)
|
|
192
|
-
.rpc();
|
|
193
|
-
try {
|
|
194
|
-
const depositDataValues = Object.values(depositData);
|
|
195
|
-
await approvedDeposit(depositDataValues);
|
|
196
|
-
assert.fail("Deposit should have failed for a route that is explicitly disabled");
|
|
197
|
-
}
|
|
198
|
-
catch (err) {
|
|
199
|
-
assert.include(err.toString(), "DisabledRoute", "Expected DisabledRoute error");
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
153
|
it("Fails to process deposit when deposits are paused", async () => {
|
|
203
154
|
// Pause deposits
|
|
204
155
|
const pauseDepositsAccounts = { state, signer: owner, program: program.programId };
|
|
@@ -207,8 +158,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
207
158
|
assert.isTrue(stateAccountData.pausedDeposits, "Deposits should be paused");
|
|
208
159
|
// Try to deposit. This should fail because deposits are paused.
|
|
209
160
|
try {
|
|
210
|
-
|
|
211
|
-
await approvedDeposit(depositDataValues);
|
|
161
|
+
await approvedDeposit(depositData);
|
|
212
162
|
assert.fail("Should not be able to process deposit when deposits are paused");
|
|
213
163
|
}
|
|
214
164
|
catch (err) {
|
|
@@ -220,8 +170,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
220
170
|
const futureQuoteTimestamp = new anchor_1.BN(currentTime + 10); // 10 seconds in the future
|
|
221
171
|
depositData.quoteTimestamp = futureQuoteTimestamp;
|
|
222
172
|
try {
|
|
223
|
-
|
|
224
|
-
await approvedDeposit(depositDataValues);
|
|
173
|
+
await approvedDeposit(depositData);
|
|
225
174
|
assert.fail("Deposit should have failed due to InvalidQuoteTimestamp");
|
|
226
175
|
}
|
|
227
176
|
catch (err) {
|
|
@@ -233,8 +182,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
233
182
|
const futureQuoteTimestamp = new anchor_1.BN(currentTime - depositQuoteTimeBuffer.toNumber() - 1); // older than buffer.
|
|
234
183
|
depositData.quoteTimestamp = futureQuoteTimestamp;
|
|
235
184
|
try {
|
|
236
|
-
|
|
237
|
-
await approvedDeposit(depositDataValues);
|
|
185
|
+
await approvedDeposit(depositData);
|
|
238
186
|
assert.fail("Deposit should have failed due to InvalidQuoteTimestamp");
|
|
239
187
|
}
|
|
240
188
|
catch (err) {
|
|
@@ -248,8 +196,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
248
196
|
depositData.fillDeadline = new anchor_1.BN(invalidFillDeadline);
|
|
249
197
|
depositData.quoteTimestamp = new anchor_1.BN(currentTime);
|
|
250
198
|
try {
|
|
251
|
-
|
|
252
|
-
await approvedDeposit(depositDataValues);
|
|
199
|
+
await approvedDeposit(depositData);
|
|
253
200
|
assert.fail("Deposit should have failed due to InvalidFillDeadline (future deadline)");
|
|
254
201
|
}
|
|
255
202
|
catch (err) {
|
|
@@ -257,101 +204,41 @@ describe("svm_spoke.deposit", () => {
|
|
|
257
204
|
}
|
|
258
205
|
});
|
|
259
206
|
it("Fails to process deposit for mint inconsistent input_token", async () => {
|
|
260
|
-
// Save the correct data
|
|
207
|
+
// Save the correct data from global scope before changing it when creating a new input token.
|
|
261
208
|
const firstInputToken = inputToken;
|
|
262
|
-
|
|
263
|
-
// Create a new input token and enable the route (this updates global scope variables).
|
|
209
|
+
// Create a new input token and the vault.
|
|
264
210
|
await setupInputToken();
|
|
265
|
-
await
|
|
266
|
-
// Try to execute the deposit call with malformed inputs where the first input token
|
|
267
|
-
//
|
|
211
|
+
await createVault();
|
|
212
|
+
// Try to execute the deposit call with malformed inputs where the first input token is passed combined with mint,
|
|
213
|
+
// vault and user token account from the second input token.
|
|
268
214
|
const malformedDepositData = { ...depositData, inputToken: firstInputToken };
|
|
269
|
-
const malformedDepositAccounts = { ...depositAccounts
|
|
215
|
+
const malformedDepositAccounts = { ...depositAccounts };
|
|
270
216
|
try {
|
|
271
|
-
|
|
272
|
-
await approvedDeposit(depositDataValues, malformedDepositAccounts);
|
|
217
|
+
await approvedDeposit(malformedDepositData, malformedDepositAccounts);
|
|
273
218
|
assert.fail("Should not be able to process deposit for inconsistent mint");
|
|
274
219
|
}
|
|
275
220
|
catch (err) {
|
|
276
221
|
assert.include(err.toString(), "Error Code: InvalidMint", "Expected InvalidMint error");
|
|
277
222
|
}
|
|
278
223
|
});
|
|
279
|
-
it("
|
|
280
|
-
// Create fake program state
|
|
281
|
-
const fakeState = await initializeState();
|
|
282
|
-
const fakeVault = await getVaultAta(inputToken, fakeState.state);
|
|
283
|
-
const fakeRouteChainId = new anchor_1.BN(3);
|
|
284
|
-
const fakeRoutePda = createRoutePda(inputToken, fakeState.seed, fakeRouteChainId);
|
|
285
|
-
// A seeds constraint was violated.
|
|
286
|
-
const fakeSetEnableRouteAccounts = {
|
|
287
|
-
signer: owner,
|
|
288
|
-
payer: owner,
|
|
289
|
-
state: fakeState.state,
|
|
290
|
-
route: fakeRoutePda,
|
|
291
|
-
vault: fakeVault,
|
|
292
|
-
originTokenMint: inputToken,
|
|
293
|
-
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
294
|
-
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
295
|
-
systemProgram: anchor.web3.SystemProgram.programId,
|
|
296
|
-
program: program.programId,
|
|
297
|
-
};
|
|
298
|
-
await program.methods.setEnableRoute(inputToken, fakeRouteChainId, true).accounts(fakeSetEnableRouteAccounts).rpc();
|
|
299
|
-
const fakeDepositAccounts = {
|
|
300
|
-
state: fakeState.state,
|
|
301
|
-
route: fakeRoutePda,
|
|
302
|
-
signer: depositor.publicKey,
|
|
303
|
-
depositorTokenAccount: depositorTA,
|
|
304
|
-
vault: fakeVault,
|
|
305
|
-
mint: inputToken,
|
|
306
|
-
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
307
|
-
program: program.programId,
|
|
308
|
-
};
|
|
309
|
-
// Deposit with the fake state and route PDA should succeed.
|
|
310
|
-
const depositDataValues = Object.values({
|
|
311
|
-
...depositData,
|
|
312
|
-
destinationChainId: fakeRouteChainId,
|
|
313
|
-
});
|
|
314
|
-
const tx = await approvedDeposit(depositDataValues, fakeDepositAccounts);
|
|
315
|
-
let events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
316
|
-
let event = events[0].data; // 0th event is the latest event.
|
|
317
|
-
const expectedValues = {
|
|
318
|
-
...{ ...depositData, destinationChainId: fakeRouteChainId },
|
|
319
|
-
depositId: (0, web3_v1_1.intToU8Array32)(1),
|
|
320
|
-
}; // Verify the event props emitted match the depositData.
|
|
321
|
-
for (let [key, value] of Object.entries(expectedValues)) {
|
|
322
|
-
if (key === "exclusivityParameter")
|
|
323
|
-
key = "exclusivityDeadline"; // the prop and the event names differ on this key.
|
|
324
|
-
assertSE(event[key], value, `${key} should match`);
|
|
325
|
-
}
|
|
326
|
-
// Check fake vault acount balance
|
|
327
|
-
const fakeVaultAccount = await (0, spl_token_1.getAccount)(connection, fakeVault);
|
|
328
|
-
assertSE(fakeVaultAccount.amount, depositData.inputAmount.toNumber(), "Fake vault balance should be increased by the deposited amount");
|
|
329
|
-
// Deposit with the fake route in the original program state should fail.
|
|
330
|
-
try {
|
|
331
|
-
const depositDataValues = Object.values({
|
|
332
|
-
...{ ...depositData, destinationChainId: fakeRouteChainId },
|
|
333
|
-
});
|
|
334
|
-
await approvedDeposit(depositDataValues, { ...depositAccounts, route: fakeRoutePda });
|
|
335
|
-
assert.fail("Deposit should have failed for a fake route PDA");
|
|
336
|
-
}
|
|
337
|
-
catch (err) {
|
|
338
|
-
assert.include(err.toString(), "A seeds constraint was violated");
|
|
339
|
-
}
|
|
340
|
-
const vaultAccount = await (0, spl_token_1.getAccount)(connection, vault);
|
|
341
|
-
assertSE(vaultAccount.amount, 0, "Vault balance should not be changed by the fake route deposit");
|
|
342
|
-
});
|
|
343
|
-
it("depositV3Now behaves as deposit but forces the quote timestamp as expected", async () => {
|
|
224
|
+
it("depositNow behaves as deposit but forces the quote timestamp as expected", async () => {
|
|
344
225
|
// Set up initial deposit data. Note that this method has a slightly different interface to deposit, using
|
|
345
226
|
// fillDeadlineOffset rather than fillDeadline. current chain time is added to fillDeadlineOffset to set the
|
|
346
227
|
// fillDeadline for the deposit. exclusivityPeriod operates the same as in standard deposit.
|
|
347
|
-
// Equally,
|
|
228
|
+
// Equally, depositNow does not have `quoteTimestamp`. this is set to the current time from the program.
|
|
348
229
|
const fillDeadlineOffset = 60; // 60 seconds offset
|
|
230
|
+
const depositNowData = {
|
|
231
|
+
...depositData,
|
|
232
|
+
fillDeadlineOffset: new anchor_1.BN(fillDeadlineOffset),
|
|
233
|
+
exclusivityPeriod: new anchor_1.BN(0),
|
|
234
|
+
};
|
|
235
|
+
const delegatePda = (0, web3_v1_1.getDepositNowPda)(depositNowData, program.programId);
|
|
349
236
|
// Delegate state PDA to pull depositor tokens.
|
|
350
|
-
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(depositAccounts.depositorTokenAccount, depositAccounts.mint,
|
|
237
|
+
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(depositAccounts.depositorTokenAccount, depositAccounts.mint, delegatePda, depositor.publicKey, BigInt(depositData.inputAmount.toString()), tokenDecimals, undefined, tokenProgram);
|
|
351
238
|
// Execute the deposit_now call. Remove the quoteTimestamp from the depositData as not needed for this method.
|
|
352
239
|
const depositIx = await program.methods
|
|
353
|
-
.depositNow(
|
|
354
|
-
.accounts(depositAccounts)
|
|
240
|
+
.depositNow(depositNowData.depositor, depositNowData.recipient, depositNowData.inputToken, depositNowData.outputToken, depositNowData.inputAmount, depositNowData.outputAmount, depositNowData.destinationChainId, depositNowData.exclusiveRelayer, fillDeadlineOffset, 0, depositNowData.message)
|
|
241
|
+
.accounts({ ...depositAccounts, delegate: delegatePda })
|
|
355
242
|
.instruction();
|
|
356
243
|
const depositTx = new web3_js_1.Transaction().add(approveIx, depositIx);
|
|
357
244
|
const tx = await (0, web3_js_1.sendAndConfirmTransaction)(connection, depositTx, [payer, depositor]);
|
|
@@ -378,8 +265,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
378
265
|
depositData.exclusiveRelayer = new web3_js_1.PublicKey("11111111111111111111111111111111");
|
|
379
266
|
depositData.exclusivityParameter = new anchor_1.BN(1);
|
|
380
267
|
try {
|
|
381
|
-
|
|
382
|
-
await approvedDeposit(depositDataValues);
|
|
268
|
+
await approvedDeposit(depositData);
|
|
383
269
|
assert.fail("Should have failed due to InvalidExclusiveRelayer");
|
|
384
270
|
}
|
|
385
271
|
catch (err) {
|
|
@@ -395,8 +281,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
395
281
|
for (const exclusivityDeadline of invalidExclusivityDeadlines) {
|
|
396
282
|
depositData.exclusivityParameter = exclusivityDeadline;
|
|
397
283
|
try {
|
|
398
|
-
|
|
399
|
-
await approvedDeposit(depositDataValues);
|
|
284
|
+
await approvedDeposit(depositData);
|
|
400
285
|
assert.fail("Should have failed due to InvalidExclusiveRelayer");
|
|
401
286
|
}
|
|
402
287
|
catch (err) {
|
|
@@ -405,16 +290,14 @@ describe("svm_spoke.deposit", () => {
|
|
|
405
290
|
}
|
|
406
291
|
// Test with exclusivityDeadline set to 0
|
|
407
292
|
depositData.exclusivityParameter = new anchor_1.BN(0);
|
|
408
|
-
|
|
409
|
-
await approvedDeposit(depositDataValues);
|
|
293
|
+
await approvedDeposit(depositData);
|
|
410
294
|
});
|
|
411
295
|
it("Exclusivity param is used as an offset", async () => {
|
|
412
296
|
const currentTime = new anchor_1.BN(await getCurrentTime(program, state));
|
|
413
297
|
depositData.quoteTimestamp = currentTime;
|
|
414
298
|
depositData.exclusiveRelayer = depositor.publicKey;
|
|
415
299
|
depositData.exclusivityParameter = maxExclusivityOffsetSeconds;
|
|
416
|
-
const
|
|
417
|
-
const tx = await approvedDeposit(depositDataValues);
|
|
300
|
+
const tx = await approvedDeposit(depositData);
|
|
418
301
|
const events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
419
302
|
const event = events[0].data; // 0th event is the latest event
|
|
420
303
|
assertSE(event.exclusivityDeadline, currentTime.add(maxExclusivityOffsetSeconds), "exclusivityDeadline should be current time + offset");
|
|
@@ -425,8 +308,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
425
308
|
const exclusivityDeadlineTimestamp = maxExclusivityOffsetSeconds.add(new anchor_1.BN(1)); // 1 year + 1 second
|
|
426
309
|
depositData.exclusiveRelayer = depositor.publicKey;
|
|
427
310
|
depositData.exclusivityParameter = exclusivityDeadlineTimestamp;
|
|
428
|
-
const
|
|
429
|
-
const tx = await approvedDeposit(depositDataValues);
|
|
311
|
+
const tx = await approvedDeposit(depositData);
|
|
430
312
|
const events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
431
313
|
const event = events[0].data; // 0th event is the latest event;
|
|
432
314
|
assertSE(event.exclusivityDeadline, exclusivityDeadlineTimestamp, "exclusivityDeadline should be passed in time");
|
|
@@ -437,8 +319,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
437
319
|
const zeroExclusivity = new anchor_1.BN(0);
|
|
438
320
|
depositData.exclusiveRelayer = depositor.publicKey;
|
|
439
321
|
depositData.exclusivityParameter = zeroExclusivity;
|
|
440
|
-
const
|
|
441
|
-
const tx = await approvedDeposit(depositDataValues);
|
|
322
|
+
const tx = await approvedDeposit(depositData);
|
|
442
323
|
const events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
443
324
|
const event = events[0].data; // 0th event is the latest event;
|
|
444
325
|
assertSE(event.exclusivityDeadline, zeroExclusivity, "Exclusivity deadline should always be 0");
|
|
@@ -458,8 +339,8 @@ describe("svm_spoke.deposit", () => {
|
|
|
458
339
|
.view();
|
|
459
340
|
assert.strictEqual(expectedDepositIdArray.toString(), unsafeDepositIdTx.toString(), "Deposit ID should match the expected hash");
|
|
460
341
|
// Delegate state PDA to pull depositor tokens.
|
|
461
|
-
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(depositAccounts.depositorTokenAccount, depositAccounts.mint,
|
|
462
|
-
// Create the transaction for
|
|
342
|
+
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(depositAccounts.depositorTokenAccount, depositAccounts.mint, (0, web3_v1_1.getDepositPda)(depositData, program.programId), depositor.publicKey, BigInt(depositData.inputAmount.toString()), tokenDecimals, undefined, tokenProgram);
|
|
343
|
+
// Create the transaction for unsafeDeposit
|
|
463
344
|
const unsafeDepositIx = await program.methods
|
|
464
345
|
.unsafeDeposit(depositData.depositor, depositData.recipient, depositData.inputToken, depositData.outputToken, depositData.inputAmount, depositData.outputAmount, depositData.destinationChainId, depositData.exclusiveRelayer, forcedDepositId, // deposit nonce
|
|
465
346
|
depositData.quoteTimestamp.toNumber(), depositData.fillDeadline.toNumber(), depositData.exclusivityParameter.toNumber(), depositData.message)
|
|
@@ -482,7 +363,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
482
363
|
// CPI-guard is available only for the 2022 token program.
|
|
483
364
|
tokenProgram = spl_token_1.TOKEN_2022_PROGRAM_ID;
|
|
484
365
|
await setupInputToken();
|
|
485
|
-
await
|
|
366
|
+
await createVault();
|
|
486
367
|
// Enable CPI-guard for the depositor (requires TA reallocation).
|
|
487
368
|
const enableCpiGuardTx = new web3_js_1.Transaction().add((0, spl_token_1.createReallocateInstruction)(depositorTA, payer.publicKey, [spl_token_1.ExtensionType.CpiGuard], depositor.publicKey), (0, spl_token_1.createEnableCpiGuardInstruction)(depositorTA, depositor.publicKey));
|
|
488
369
|
await (0, web3_js_1.sendAndConfirmTransaction)(connection, enableCpiGuardTx, [payer, depositor]);
|
|
@@ -490,8 +371,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
490
371
|
let vaultAccount = await (0, spl_token_1.getAccount)(connection, vault, undefined, tokenProgram);
|
|
491
372
|
assertSE(vaultAccount.amount, "0", "Vault balance should be zero before the deposit");
|
|
492
373
|
// Execute the deposit call
|
|
493
|
-
|
|
494
|
-
await approvedDeposit(depositDataValues);
|
|
374
|
+
await approvedDeposit(depositData);
|
|
495
375
|
// Verify tokens leave the depositor's account
|
|
496
376
|
const depositorAccount = await (0, spl_token_1.getAccount)(connection, depositorTA, undefined, tokenProgram);
|
|
497
377
|
assertSE(depositorAccount.amount, seedBalance - depositData.inputAmount.toNumber(), "Depositor's balance should be reduced by the deposited amount");
|
|
@@ -513,6 +393,93 @@ describe("svm_spoke.deposit", () => {
|
|
|
513
393
|
assert.include(err.toString(), "owner does not match");
|
|
514
394
|
}
|
|
515
395
|
});
|
|
396
|
+
it("Deposit native token, new token account", async () => {
|
|
397
|
+
// Fund depositor account with SOL.
|
|
398
|
+
const nativeAmount = 1_000_000_000; // 1 SOL
|
|
399
|
+
await connection.requestAirdrop(depositor.publicKey, nativeAmount * 2); // Add buffer for transaction fees.
|
|
400
|
+
// Setup wSOL as the input token.
|
|
401
|
+
inputToken = spl_token_1.NATIVE_MINT;
|
|
402
|
+
const nativeDecimals = 9;
|
|
403
|
+
depositorTA = (0, spl_token_1.getAssociatedTokenAddressSync)(inputToken, depositor.publicKey);
|
|
404
|
+
await createVault();
|
|
405
|
+
// Will need to add rent exemption to the deposit amount, will recover it at the end of the transaction.
|
|
406
|
+
const rentExempt = await (0, spl_token_1.getMinimumBalanceForRentExemptAccount)(connection);
|
|
407
|
+
const transferIx = web3_js_1.SystemProgram.transfer({
|
|
408
|
+
fromPubkey: depositor.publicKey,
|
|
409
|
+
toPubkey: depositorTA,
|
|
410
|
+
lamports: BigInt(nativeAmount) + BigInt(rentExempt),
|
|
411
|
+
});
|
|
412
|
+
// Create wSOL user account.
|
|
413
|
+
const createIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(depositor.publicKey, depositorTA, depositor.publicKey, inputToken);
|
|
414
|
+
const nativeDepositData = { ...depositData, inputAmount: new anchor_1.BN(nativeAmount), outputAmount: new anchor_1.BN(nativeAmount) };
|
|
415
|
+
const depositDataValues = Object.values(nativeDepositData);
|
|
416
|
+
const delegate = (0, web3_v1_1.getDepositPda)(nativeDepositData, program.programId);
|
|
417
|
+
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(depositAccounts.depositorTokenAccount, depositAccounts.mint, delegate, depositor.publicKey, BigInt(nativeAmount), nativeDecimals, undefined, tokenProgram);
|
|
418
|
+
const depositIx = await program.methods
|
|
419
|
+
.deposit(...depositDataValues)
|
|
420
|
+
.accounts({ ...depositAccounts, delegate })
|
|
421
|
+
.instruction();
|
|
422
|
+
const closeIx = (0, spl_token_1.createCloseAccountInstruction)(depositorTA, depositor.publicKey, depositor.publicKey);
|
|
423
|
+
const iVaultAmount = (await (0, spl_token_1.getAccount)(connection, vault, undefined, tokenProgram)).amount;
|
|
424
|
+
const depositTx = new web3_js_1.Transaction().add(transferIx, createIx, approveIx, depositIx, closeIx);
|
|
425
|
+
const tx = await (0, web3_js_1.sendAndConfirmTransaction)(connection, depositTx, [depositor]);
|
|
426
|
+
const fVaultAmount = (await (0, spl_token_1.getAccount)(connection, vault, undefined, tokenProgram)).amount;
|
|
427
|
+
assertSE(fVaultAmount, iVaultAmount + BigInt(nativeAmount), "Vault balance should be increased by the deposited amount");
|
|
428
|
+
});
|
|
429
|
+
it("Deposit native token, existing token account", async () => {
|
|
430
|
+
// Fund depositor account with SOL.
|
|
431
|
+
const nativeAmount = 1_000_000_000; // 1 SOL
|
|
432
|
+
await connection.requestAirdrop(depositor.publicKey, nativeAmount * 2); // Add buffer for transaction fees.
|
|
433
|
+
// Setup wSOL as the input token, creating the associated token account for the user.
|
|
434
|
+
inputToken = spl_token_1.NATIVE_MINT;
|
|
435
|
+
const nativeDecimals = 9;
|
|
436
|
+
depositorTA = (await (0, spl_token_1.getOrCreateAssociatedTokenAccount)(connection, payer, inputToken, depositor.publicKey)).address;
|
|
437
|
+
await createVault();
|
|
438
|
+
// Transfer SOL to the user token account.
|
|
439
|
+
const transferIx = web3_js_1.SystemProgram.transfer({
|
|
440
|
+
fromPubkey: depositor.publicKey,
|
|
441
|
+
toPubkey: depositorTA,
|
|
442
|
+
lamports: nativeAmount,
|
|
443
|
+
});
|
|
444
|
+
// Sync the user token account with the native balance.
|
|
445
|
+
const syncIx = (0, spl_token_1.createSyncNativeInstruction)(depositorTA);
|
|
446
|
+
const nativeDepositData = { ...depositData, inputAmount: new anchor_1.BN(nativeAmount), outputAmount: new anchor_1.BN(nativeAmount) };
|
|
447
|
+
const depositDataValues = Object.values(nativeDepositData);
|
|
448
|
+
const delegate = (0, web3_v1_1.getDepositPda)(nativeDepositData, program.programId);
|
|
449
|
+
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(depositAccounts.depositorTokenAccount, depositAccounts.mint, delegate, depositor.publicKey, BigInt(nativeAmount), nativeDecimals, undefined, tokenProgram);
|
|
450
|
+
const depositIx = await program.methods
|
|
451
|
+
.deposit(...depositDataValues)
|
|
452
|
+
.accounts({ ...depositAccounts, delegate })
|
|
453
|
+
.instruction();
|
|
454
|
+
const iVaultAmount = (await (0, spl_token_1.getAccount)(connection, vault, undefined, tokenProgram)).amount;
|
|
455
|
+
const depositTx = new web3_js_1.Transaction().add(transferIx, syncIx, approveIx, depositIx);
|
|
456
|
+
const tx = await (0, web3_js_1.sendAndConfirmTransaction)(connection, depositTx, [depositor]);
|
|
457
|
+
const fVaultAmount = (await (0, spl_token_1.getAccount)(connection, vault, undefined, tokenProgram)).amount;
|
|
458
|
+
assertSE(fVaultAmount, iVaultAmount + BigInt(nativeAmount), "Vault balance should be increased by the deposited amount");
|
|
459
|
+
});
|
|
460
|
+
it("Deposits tokens to a new vault", async () => {
|
|
461
|
+
// Create new input token without creating a new vault for it.
|
|
462
|
+
await setupInputToken();
|
|
463
|
+
const inputTokenAccount = await provider.connection.getAccountInfo(inputToken);
|
|
464
|
+
if (inputTokenAccount === null)
|
|
465
|
+
throw new Error("Input mint account not found");
|
|
466
|
+
vault = (0, spl_token_1.getAssociatedTokenAddressSync)(inputToken, state, true, inputTokenAccount.owner, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
467
|
+
// Update global variables using the new input token.
|
|
468
|
+
depositData.inputToken = inputToken;
|
|
469
|
+
depositAccounts.depositorTokenAccount = depositorTA;
|
|
470
|
+
depositAccounts.vault = vault;
|
|
471
|
+
depositAccounts.mint = inputToken;
|
|
472
|
+
// Verify there is no vault account before the deposit.
|
|
473
|
+
assert.isNull(await provider.connection.getAccountInfo(vault), "Vault should not exist before the deposit");
|
|
474
|
+
// Execute the deposit call
|
|
475
|
+
await approvedDeposit(depositData);
|
|
476
|
+
// Verify tokens leave the depositor's account
|
|
477
|
+
const depositorAccount = await (0, spl_token_1.getAccount)(connection, depositorTA);
|
|
478
|
+
assertSE(depositorAccount.amount, seedBalance - depositData.inputAmount.toNumber(), "Depositor's balance should be reduced by the deposited amount");
|
|
479
|
+
// Verify tokens are credited into the new vault
|
|
480
|
+
const vaultAccount = await (0, spl_token_1.getAccount)(connection, vault);
|
|
481
|
+
assertSE(vaultAccount.amount, depositData.inputAmount, "Vault balance should equal the deposited amount");
|
|
482
|
+
});
|
|
516
483
|
describe("codama client and solana kit", () => {
|
|
517
484
|
it("Deposit with with solana kit and codama client", async () => {
|
|
518
485
|
// typescript is not happy with the depositData object
|
|
@@ -534,7 +501,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
534
501
|
const approveIx = (0, token_1.getApproveCheckedInstruction)({
|
|
535
502
|
source: (0, kit_1.address)(depositAccounts.depositorTokenAccount.toString()),
|
|
536
503
|
mint: (0, kit_1.address)(depositAccounts.mint.toString()),
|
|
537
|
-
delegate: (0, kit_1.address)(
|
|
504
|
+
delegate: (0, kit_1.address)((0, web3_v1_1.getDepositPda)(depositData, program.programId).toString()),
|
|
538
505
|
owner: (0, kit_1.address)(depositor.publicKey.toString()),
|
|
539
506
|
amount: BigInt(depositData.inputAmount.toString()),
|
|
540
507
|
decimals: tokenDecimals,
|
|
@@ -555,7 +522,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
555
522
|
};
|
|
556
523
|
const formattedAccounts = {
|
|
557
524
|
state: (0, kit_1.address)(depositAccounts.state.toString()),
|
|
558
|
-
|
|
525
|
+
delegate: (0, kit_1.address)((0, web3_v1_1.getDepositPda)(depositData, program.programId).toString()),
|
|
559
526
|
depositorTokenAccount: (0, kit_1.address)(depositAccounts.depositorTokenAccount.toString()),
|
|
560
527
|
mint: (0, kit_1.address)(depositAccounts.mint.toString()),
|
|
561
528
|
tokenProgram: (0, kit_1.address)(tokenProgram.toString()),
|
|
@@ -36,20 +36,21 @@ const utils_1 = require("./utils");
|
|
|
36
36
|
const { provider, connection, program, owner, chainId, seedBalance, initializeState, assertSE } = SvmSpoke_common_1.common;
|
|
37
37
|
describe("svm_spoke.fill.across_plus", () => {
|
|
38
38
|
anchor.setProvider(provider);
|
|
39
|
-
const payer = anchor.AnchorProvider.env().wallet
|
|
39
|
+
const { payer } = anchor.AnchorProvider.env().wallet;
|
|
40
40
|
const relayer = web3_js_1.Keypair.generate();
|
|
41
41
|
const handlerProgram = anchor.workspace.MulticallHandler;
|
|
42
|
-
let handlerSigner, handlerATA, finalRecipient, finalRecipientATA, state, mint, relayerATA;
|
|
42
|
+
let handlerSigner, handlerATA, finalRecipient, finalRecipientATA, state, mint, relayerATA, seed;
|
|
43
43
|
const relayAmount = 500000;
|
|
44
44
|
const mintDecimals = 6;
|
|
45
45
|
let relayData; // reused relay data for all tests.
|
|
46
46
|
let accounts; // Store accounts to simplify contract interactions.
|
|
47
|
-
|
|
47
|
+
const updateRelayData = (newRelayData) => {
|
|
48
48
|
relayData = newRelayData;
|
|
49
49
|
const relayHashUint8Array = (0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId);
|
|
50
50
|
const [fillStatusPDA] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("fills"), relayHashUint8Array], program.programId);
|
|
51
51
|
accounts = {
|
|
52
52
|
state,
|
|
53
|
+
delegate: (0, web3_v1_1.getFillRelayDelegatePda)(relayHashUint8Array, new anchor_1.BN(1), relayer.publicKey, program.programId).pda,
|
|
53
54
|
signer: relayer.publicKey,
|
|
54
55
|
instructionParams: program.programId,
|
|
55
56
|
mint: mint,
|
|
@@ -60,31 +61,30 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
60
61
|
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
61
62
|
systemProgram: anchor.web3.SystemProgram.programId,
|
|
62
63
|
};
|
|
63
|
-
}
|
|
64
|
-
async
|
|
64
|
+
};
|
|
65
|
+
const createApproveAndFillIx = async (multicallHandlerCoder, bufferParams = false) => {
|
|
66
|
+
const relayHashUint8Array = (0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId);
|
|
67
|
+
const relayHash = Array.from(relayHashUint8Array);
|
|
65
68
|
// Delegate state PDA to pull relayer tokens.
|
|
66
|
-
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(accounts.relayerTokenAccount, accounts.mint,
|
|
69
|
+
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(accounts.relayerTokenAccount, accounts.mint, (0, web3_v1_1.getFillRelayDelegatePda)(relayHashUint8Array, new anchor_1.BN(1), relayer.publicKey, program.programId).pda, accounts.signer, BigInt(relayAmount), mintDecimals);
|
|
67
70
|
const remainingAccounts = [
|
|
68
71
|
{ pubkey: handlerProgram.programId, isSigner: false, isWritable: false },
|
|
69
72
|
...multicallHandlerCoder.compiledKeyMetas,
|
|
70
73
|
];
|
|
71
|
-
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
72
74
|
// Prepare fill instruction.
|
|
73
|
-
const
|
|
75
|
+
const fillRelayValues = [relayHash, relayData, new anchor_1.BN(1), relayer.publicKey];
|
|
74
76
|
if (bufferParams) {
|
|
75
|
-
await (0, web3_v1_1.loadFillRelayParams)(program, relayer,
|
|
77
|
+
await (0, web3_v1_1.loadFillRelayParams)(program, relayer, fillRelayValues[1], fillRelayValues[2], fillRelayValues[3]);
|
|
76
78
|
[accounts.instructionParams] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("instruction_params"), relayer.publicKey.toBuffer()], program.programId);
|
|
77
79
|
}
|
|
78
|
-
const
|
|
79
|
-
? [fillV3RelayValues[0], null, null, null]
|
|
80
|
-
: fillV3RelayValues;
|
|
80
|
+
const fillRelayParams = bufferParams ? [fillRelayValues[0], null, null, null] : fillRelayValues;
|
|
81
81
|
const fillIx = await program.methods
|
|
82
|
-
.fillRelay(...
|
|
82
|
+
.fillRelay(...fillRelayParams)
|
|
83
83
|
.accounts(accounts)
|
|
84
84
|
.remainingAccounts(remainingAccounts)
|
|
85
85
|
.instruction();
|
|
86
86
|
return { approveIx, fillIx };
|
|
87
|
-
}
|
|
87
|
+
};
|
|
88
88
|
before("Creates token mint and associated token accounts", async () => {
|
|
89
89
|
mint = await (0, spl_token_1.createMint)(connection, payer, owner, owner, mintDecimals);
|
|
90
90
|
relayerATA = (await (0, spl_token_1.getOrCreateAssociatedTokenAccount)(connection, payer, mint, relayer.publicKey)).address;
|
|
@@ -96,7 +96,7 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
96
96
|
beforeEach(async () => {
|
|
97
97
|
finalRecipient = web3_js_1.Keypair.generate().publicKey;
|
|
98
98
|
finalRecipientATA = (await (0, spl_token_1.getOrCreateAssociatedTokenAccount)(connection, payer, mint, finalRecipient)).address;
|
|
99
|
-
({ state } = await initializeState());
|
|
99
|
+
({ state, seed } = await initializeState());
|
|
100
100
|
const initialRelayData = {
|
|
101
101
|
depositor: finalRecipient,
|
|
102
102
|
recipient: handlerSigner, // Handler PDA that can forward tokens as needed within the message call.
|
|
@@ -279,9 +279,12 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
279
279
|
programAddress: (0, kit_1.address)(program.programId.toString()),
|
|
280
280
|
seeds: ["__event_authority"],
|
|
281
281
|
});
|
|
282
|
-
const
|
|
282
|
+
const relayHashUint8Array = (0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId);
|
|
283
|
+
const relayHash = Array.from(relayHashUint8Array);
|
|
284
|
+
const delegate = (0, kit_1.address)((0, web3_v1_1.getFillRelayDelegatePda)(relayHashUint8Array, new anchor_1.BN(1), relayer.publicKey, program.programId).pda.toString());
|
|
283
285
|
const formattedAccounts = {
|
|
284
286
|
state: (0, kit_1.address)(accounts.state.toString()),
|
|
287
|
+
delegate,
|
|
285
288
|
instructionParams: (0, kit_1.address)(program.programId.toString()),
|
|
286
289
|
mint: (0, kit_1.address)(mint.toString()),
|
|
287
290
|
relayerTokenAccount: (0, kit_1.address)(relayerATA.toString()),
|
|
@@ -316,7 +319,7 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
316
319
|
const approveIx = (0, token_1.getApproveCheckedInstruction)({
|
|
317
320
|
source: (0, kit_1.address)(accounts.relayerTokenAccount.toString()),
|
|
318
321
|
mint: (0, kit_1.address)(accounts.mint.toString()),
|
|
319
|
-
delegate
|
|
322
|
+
delegate,
|
|
320
323
|
owner: (0, kit_1.address)(accounts.signer.toString()),
|
|
321
324
|
amount: BigInt(relayData.outputAmount.toString()),
|
|
322
325
|
decimals: mintDecimals,
|