@across-protocol/contracts 4.0.1 → 4.0.3
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/deploy/consts.d.ts +1 -1
- package/dist/deploy/consts.js +9 -13
- package/dist/deployments/deployments.json +24 -1
- package/dist/hardhat.config.js +17 -1
- package/dist/scripts/svm/fakeFillWithRandomDistribution.js +2 -2
- package/dist/scripts/svm/queryEvents.js +1 -1
- package/dist/scripts/svm/simpleDeposit.js +3 -3
- package/dist/scripts/svm/simpleFakeRelayerRepayment.js +1 -1
- package/dist/scripts/svm/simpleFill.js +19 -6
- package/dist/src/svm/assets/idl/svm_spoke.json +388 -388
- package/dist/src/svm/assets/svm_spoke.d.ts +388 -388
- package/dist/src/svm/clients/SvmSpoke/accounts/executeSlowRelayLeafParams.d.ts +31 -0
- package/dist/src/svm/clients/SvmSpoke/accounts/executeSlowRelayLeafParams.js +70 -0
- package/dist/src/svm/clients/SvmSpoke/accounts/fillRelayParams.d.ts +31 -0
- package/dist/src/svm/clients/SvmSpoke/accounts/fillRelayParams.js +67 -0
- package/dist/src/svm/clients/SvmSpoke/accounts/index.d.ts +3 -3
- package/dist/src/svm/clients/SvmSpoke/accounts/index.js +3 -3
- package/dist/src/svm/clients/SvmSpoke/accounts/requestSlowFillParams.d.ts +27 -0
- package/dist/src/svm/clients/SvmSpoke/accounts/requestSlowFillParams.js +66 -0
- package/dist/src/svm/clients/SvmSpoke/instructions/deposit.d.ts +123 -0
- package/dist/src/svm/clients/SvmSpoke/instructions/{depositV3.js → deposit.js} +23 -23
- package/dist/src/svm/clients/SvmSpoke/instructions/depositNow.d.ts +119 -0
- package/dist/src/svm/clients/SvmSpoke/instructions/{depositV3Now.js → depositNow.js} +23 -23
- package/dist/src/svm/clients/SvmSpoke/instructions/executeSlowRelayLeaf.d.ts +104 -0
- package/dist/src/svm/clients/SvmSpoke/instructions/{executeV3SlowRelayLeaf.js → executeSlowRelayLeaf.js} +26 -26
- package/dist/src/svm/clients/SvmSpoke/instructions/fillRelay.d.ts +104 -0
- package/dist/src/svm/clients/SvmSpoke/instructions/{fillV3Relay.js → fillRelay.js} +26 -26
- package/dist/src/svm/clients/SvmSpoke/instructions/index.d.ts +6 -6
- package/dist/src/svm/clients/SvmSpoke/instructions/index.js +6 -6
- package/dist/src/svm/clients/SvmSpoke/instructions/requestSlowFill.d.ts +76 -0
- package/dist/src/svm/clients/SvmSpoke/instructions/{requestV3SlowFill.js → requestSlowFill.js} +25 -25
- package/dist/src/svm/clients/SvmSpoke/instructions/unsafeDeposit.d.ts +127 -0
- package/dist/src/svm/clients/SvmSpoke/instructions/{unsafeDepositV3.js → unsafeDeposit.js} +23 -23
- package/dist/src/svm/clients/SvmSpoke/programs/svmSpoke.d.ts +23 -23
- package/dist/src/svm/clients/SvmSpoke/programs/svmSpoke.js +29 -29
- package/dist/src/svm/clients/SvmSpoke/types/{filledV3Relay.d.ts → filledRelay.d.ts} +8 -8
- package/dist/src/svm/clients/SvmSpoke/types/{filledV3Relay.js → filledRelay.js} +9 -9
- package/dist/src/svm/clients/SvmSpoke/types/{v3FundsDeposited.d.ts → fundsDeposited.d.ts} +5 -5
- package/dist/src/svm/clients/SvmSpoke/types/{v3FundsDeposited.js → fundsDeposited.js} +7 -7
- package/dist/src/svm/clients/SvmSpoke/types/index.d.ts +6 -6
- package/dist/src/svm/clients/SvmSpoke/types/index.js +6 -6
- package/dist/src/svm/clients/SvmSpoke/types/{v3RelayData.d.ts → relayData.d.ts} +5 -5
- package/dist/src/svm/clients/SvmSpoke/types/{v3RelayData.js → relayData.js} +7 -7
- package/dist/src/svm/clients/SvmSpoke/types/{v3RelayExecutionEventInfo.d.ts → relayExecutionEventInfo.d.ts} +5 -5
- package/dist/src/svm/clients/SvmSpoke/types/{v3RelayExecutionEventInfo.js → relayExecutionEventInfo.js} +7 -7
- package/dist/src/svm/clients/SvmSpoke/types/{requestedV3SlowFill.d.ts → requestedSlowFill.d.ts} +5 -5
- package/dist/src/svm/clients/SvmSpoke/types/{requestedV3SlowFill.js → requestedSlowFill.js} +7 -7
- package/dist/src/svm/clients/SvmSpoke/types/{v3SlowFill.d.ts → slowFill.d.ts} +8 -8
- package/dist/src/svm/clients/SvmSpoke/types/{v3SlowFill.js → slowFill.js} +9 -9
- package/dist/src/svm/web3-v1/instructionParamsUtils.d.ts +8 -8
- package/dist/src/svm/web3-v1/instructionParamsUtils.js +16 -16
- package/dist/src/types/svm.d.ts +6 -6
- package/dist/target/types/svm_spoke.d.ts +388 -388
- package/dist/tasks/enableL1TokenAcrossEcosystem.js +14 -10
- package/dist/test/svm/SvmSpoke.Deposit.js +48 -47
- package/dist/test/svm/SvmSpoke.Fill.AcrossPlus.js +2 -2
- package/dist/test/svm/SvmSpoke.Fill.js +28 -56
- package/dist/test/svm/SvmSpoke.SlowFill.AcrossPlus.js +13 -13
- package/dist/test/svm/SvmSpoke.SlowFill.js +40 -40
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/constants.js +3 -1
- package/package.json +2 -2
- package/dist/src/svm/clients/SvmSpoke/accounts/executeV3SlowRelayLeafParams.d.ts +0 -31
- package/dist/src/svm/clients/SvmSpoke/accounts/executeV3SlowRelayLeafParams.js +0 -70
- package/dist/src/svm/clients/SvmSpoke/accounts/fillV3RelayParams.d.ts +0 -31
- package/dist/src/svm/clients/SvmSpoke/accounts/fillV3RelayParams.js +0 -67
- package/dist/src/svm/clients/SvmSpoke/accounts/requestV3SlowFillParams.d.ts +0 -27
- package/dist/src/svm/clients/SvmSpoke/accounts/requestV3SlowFillParams.js +0 -66
- package/dist/src/svm/clients/SvmSpoke/instructions/depositV3.d.ts +0 -123
- package/dist/src/svm/clients/SvmSpoke/instructions/depositV3Now.d.ts +0 -119
- package/dist/src/svm/clients/SvmSpoke/instructions/executeV3SlowRelayLeaf.d.ts +0 -104
- package/dist/src/svm/clients/SvmSpoke/instructions/fillV3Relay.d.ts +0 -104
- package/dist/src/svm/clients/SvmSpoke/instructions/requestV3SlowFill.d.ts +0 -76
- package/dist/src/svm/clients/SvmSpoke/instructions/unsafeDepositV3.d.ts +0 -127
|
@@ -11,12 +11,13 @@ const { ARBITRUM, OPTIMISM } = constants_1.CHAIN_IDs;
|
|
|
11
11
|
const NO_SYMBOL = "----";
|
|
12
12
|
const NO_ADDRESS = "------------------------------------------";
|
|
13
13
|
// Supported mainnet chain IDs.
|
|
14
|
-
const enabledChainIds =
|
|
15
|
-
.
|
|
16
|
-
.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
const enabledChainIds = (hubChainId) => {
|
|
15
|
+
const chainIds = hubChainId === constants_1.CHAIN_IDs.MAINNET ? constants_1.MAINNET_CHAIN_IDs : constants_1.TESTNET_CHAIN_IDs;
|
|
16
|
+
return Object.values(chainIds)
|
|
17
|
+
.map(Number)
|
|
18
|
+
.filter((chainId) => chainId !== constants_1.CHAIN_IDs.BOBA)
|
|
19
|
+
.sort((x, y) => x - y);
|
|
20
|
+
};
|
|
20
21
|
const getChainsFromList = (taskArgInput) => taskArgInput
|
|
21
22
|
?.replace(/\s/g, "")
|
|
22
23
|
?.split(",")
|
|
@@ -52,20 +53,21 @@ const getChainsFromList = (taskArgInput) => taskArgInput
|
|
|
52
53
|
const { deployments, ethers } = hre;
|
|
53
54
|
const [signer] = await hre.ethers.getSigners();
|
|
54
55
|
// Remove chainIds that are in the ignore list.
|
|
56
|
+
const _enabledChainIds = enabledChainIds(hubChainId);
|
|
55
57
|
let inputChains = [];
|
|
56
58
|
try {
|
|
57
|
-
inputChains = (chains?.split(",") ??
|
|
59
|
+
inputChains = (chains?.split(",") ?? _enabledChainIds).map(Number);
|
|
58
60
|
console.log(`\nParsed 'chains' argument:`, inputChains);
|
|
59
61
|
}
|
|
60
62
|
catch (error) {
|
|
61
63
|
throw new Error(`Failed to parse 'chains' argument ${chains} as a comma-separated list of numbers.`);
|
|
62
64
|
}
|
|
63
65
|
if (inputChains.length === 0)
|
|
64
|
-
inputChains =
|
|
66
|
+
inputChains = _enabledChainIds;
|
|
65
67
|
else if (inputChains.some((chain) => isNaN(chain) || !Number.isInteger(chain) || chain < 0)) {
|
|
66
68
|
throw new Error(`Invalid chains list: ${inputChains}`);
|
|
67
69
|
}
|
|
68
|
-
const chainIds =
|
|
70
|
+
const chainIds = _enabledChainIds.filter((chainId) => inputChains.includes(chainId));
|
|
69
71
|
console.log("\nLoading L2 companion token address for provided L1 token.");
|
|
70
72
|
const tokens = Object.fromEntries(chainIds.map((chainId) => {
|
|
71
73
|
const token = (0, utils_1.resolveTokenOnChain)(matchedSymbol, chainId);
|
|
@@ -97,9 +99,11 @@ const getChainsFromList = (taskArgInput) => taskArgInput
|
|
|
97
99
|
let i = 0; // counter for logging.
|
|
98
100
|
const skipped = {};
|
|
99
101
|
const routeChainIds = Object.keys(tokens).map(Number);
|
|
102
|
+
const chainPadding = _enabledChainIds[enabledChainIds.length - 1].toString().length;
|
|
103
|
+
const formatChainId = (chainId) => chainId.toString().padStart(chainPadding, " ");
|
|
100
104
|
routeChainIds.forEach((fromId) => {
|
|
101
105
|
const formattedFromId = formatChainId(fromId);
|
|
102
|
-
const {
|
|
106
|
+
const { address: inputToken } = tokens[fromId];
|
|
103
107
|
skipped[fromId] = [];
|
|
104
108
|
routeChainIds.forEach((toId) => {
|
|
105
109
|
if (fromId === toId || [fromId, toId].some((chainId) => tokens[chainId].symbol === NO_SYMBOL)) {
|
|
@@ -78,11 +78,11 @@ describe("svm_spoke.deposit", () => {
|
|
|
78
78
|
program: program.programId,
|
|
79
79
|
};
|
|
80
80
|
};
|
|
81
|
-
const
|
|
81
|
+
const approvedDeposit = async (depositDataValues, calledDepositAccounts = depositAccounts) => {
|
|
82
82
|
// Delegate state PDA to pull depositor tokens.
|
|
83
83
|
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(calledDepositAccounts.depositorTokenAccount, calledDepositAccounts.mint, calledDepositAccounts.state, depositor.publicKey, BigInt(depositData.inputAmount.toString()), tokenDecimals, undefined, tokenProgram);
|
|
84
84
|
const depositIx = await program.methods
|
|
85
|
-
.
|
|
85
|
+
.deposit(...depositDataValues)
|
|
86
86
|
.accounts(calledDepositAccounts)
|
|
87
87
|
.instruction();
|
|
88
88
|
const depositTx = new web3_js_1.Transaction().add(approveIx, depositIx);
|
|
@@ -95,13 +95,13 @@ describe("svm_spoke.deposit", () => {
|
|
|
95
95
|
await setupInputToken();
|
|
96
96
|
await enableRoute();
|
|
97
97
|
});
|
|
98
|
-
it("Deposits tokens via
|
|
98
|
+
it("Deposits tokens via deposit function and checks balances", async () => {
|
|
99
99
|
// Verify vault balance is zero before the deposit
|
|
100
100
|
let vaultAccount = await (0, spl_token_1.getAccount)(connection, vault);
|
|
101
101
|
assertSE(vaultAccount.amount, "0", "Vault balance should be zero before the deposit");
|
|
102
|
-
// Execute the
|
|
102
|
+
// Execute the deposit call
|
|
103
103
|
let depositDataValues = Object.values(depositData);
|
|
104
|
-
await
|
|
104
|
+
await approvedDeposit(depositDataValues);
|
|
105
105
|
// Verify tokens leave the depositor's account
|
|
106
106
|
let depositorAccount = await (0, spl_token_1.getAccount)(connection, depositorTA);
|
|
107
107
|
assertSE(depositorAccount.amount, seedBalance - depositData.inputAmount.toNumber(), "Depositor's balance should be reduced by the deposited amount");
|
|
@@ -110,9 +110,9 @@ describe("svm_spoke.deposit", () => {
|
|
|
110
110
|
assertSE(vaultAccount.amount, depositData.inputAmount, "Vault balance should be increased by the deposited amount");
|
|
111
111
|
// Modify depositData for the second deposit
|
|
112
112
|
const secondInputAmount = new anchor_1.BN(300000);
|
|
113
|
-
// Execute the second
|
|
113
|
+
// Execute the second deposit call
|
|
114
114
|
depositDataValues = Object.values({ ...depositData, inputAmount: secondInputAmount });
|
|
115
|
-
await
|
|
115
|
+
await approvedDeposit(depositDataValues);
|
|
116
116
|
// Verify tokens leave the depositor's account again
|
|
117
117
|
depositorAccount = await (0, spl_token_1.getAccount)(connection, depositorTA);
|
|
118
118
|
assertSE(depositorAccount.amount, seedBalance - depositData.inputAmount.toNumber() - secondInputAmount.toNumber(), "Depositor's balance should be reduced by the total deposited amount");
|
|
@@ -120,11 +120,11 @@ describe("svm_spoke.deposit", () => {
|
|
|
120
120
|
vaultAccount = await (0, spl_token_1.getAccount)(connection, vault);
|
|
121
121
|
assertSE(vaultAccount.amount, depositData.inputAmount.add(secondInputAmount), "Vault balance should be increased by the total deposited amount");
|
|
122
122
|
});
|
|
123
|
-
it("Verifies
|
|
123
|
+
it("Verifies FundsDeposited after deposits", async () => {
|
|
124
124
|
depositData.inputAmount = depositData.inputAmount.add(new anchor_1.BN(69));
|
|
125
|
-
// Execute the first
|
|
125
|
+
// Execute the first deposit call
|
|
126
126
|
let depositDataValues = Object.values(depositData);
|
|
127
|
-
const tx = await
|
|
127
|
+
const tx = await approvedDeposit(depositDataValues);
|
|
128
128
|
let events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
129
129
|
let event = events[0].data; // 0th event is the latest event
|
|
130
130
|
const expectedValues1 = { ...depositData, depositId: (0, web3_v1_1.intToU8Array32)(1) }; // Verify the event props emitted match the depositData.
|
|
@@ -137,7 +137,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
137
137
|
assertSE((0, web3_v1_1.u8Array32ToInt)(event.depositId), 1, `depositId should recover to 1`);
|
|
138
138
|
assertSE((0, web3_v1_1.u8Array32ToBigNumber)(event.depositId), ethers_1.BigNumber.from(1), `depositId should recover to 1`);
|
|
139
139
|
// Execute the second deposit_v3 call
|
|
140
|
-
const tx2 = await
|
|
140
|
+
const tx2 = await approvedDeposit(depositDataValues);
|
|
141
141
|
events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx2, [program]);
|
|
142
142
|
event = events[0].data; // 0th event is the latest event.
|
|
143
143
|
const expectedValues2 = { ...expectedValues1, depositId: (0, web3_v1_1.intToU8Array32)(2) }; // Verify the event props emitted match the depositData.
|
|
@@ -150,6 +150,18 @@ describe("svm_spoke.deposit", () => {
|
|
|
150
150
|
assertSE((0, web3_v1_1.u8Array32ToInt)(event.depositId), 2, `depositId should recover to 2`);
|
|
151
151
|
assertSE((0, web3_v1_1.u8Array32ToBigNumber)(event.depositId), ethers_1.BigNumber.from(2), `depositId should recover to 2`);
|
|
152
152
|
});
|
|
153
|
+
it("Deposit with deadline before current time succeeds", async () => {
|
|
154
|
+
const currentTime = await getCurrentTime(program, state);
|
|
155
|
+
// Fill deadline is before current time on the contract
|
|
156
|
+
let fillDeadline = currentTime - 1; // 1 second before current time on the contract.
|
|
157
|
+
depositData.fillDeadline = new anchor_1.BN(fillDeadline);
|
|
158
|
+
depositData.quoteTimestamp = new anchor_1.BN(currentTime - 1); // 1 second before current time on the contract to reset.
|
|
159
|
+
const depositDataValues = Object.values(depositData);
|
|
160
|
+
const tx = await approvedDeposit(depositDataValues);
|
|
161
|
+
const events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
162
|
+
const event = events[0].data; // 0th event is the latest event.
|
|
163
|
+
assertSE(event.fillDeadline, fillDeadline, "Fill deadline should match");
|
|
164
|
+
});
|
|
153
165
|
it("Fails to deposit tokens to a route that is uninitalized", async () => {
|
|
154
166
|
const differentChainId = new anchor_1.BN(2); // Different chain ID
|
|
155
167
|
if (!depositData.inputToken) {
|
|
@@ -162,7 +174,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
162
174
|
...depositData,
|
|
163
175
|
destinationChainId: differentChainId,
|
|
164
176
|
});
|
|
165
|
-
await
|
|
177
|
+
await approvedDeposit(depositDataValues);
|
|
166
178
|
assert.fail("Deposit should have failed for a route that is not initialized");
|
|
167
179
|
}
|
|
168
180
|
catch (err) {
|
|
@@ -177,7 +189,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
177
189
|
.rpc();
|
|
178
190
|
try {
|
|
179
191
|
const depositDataValues = Object.values(depositData);
|
|
180
|
-
await
|
|
192
|
+
await approvedDeposit(depositDataValues);
|
|
181
193
|
assert.fail("Deposit should have failed for a route that is explicitly disabled");
|
|
182
194
|
}
|
|
183
195
|
catch (err) {
|
|
@@ -193,7 +205,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
193
205
|
// Try to deposit. This should fail because deposits are paused.
|
|
194
206
|
try {
|
|
195
207
|
const depositDataValues = Object.values(depositData);
|
|
196
|
-
await
|
|
208
|
+
await approvedDeposit(depositDataValues);
|
|
197
209
|
assert.fail("Should not be able to process deposit when deposits are paused");
|
|
198
210
|
}
|
|
199
211
|
catch (err) {
|
|
@@ -206,7 +218,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
206
218
|
depositData.quoteTimestamp = futureQuoteTimestamp;
|
|
207
219
|
try {
|
|
208
220
|
const depositDataValues = Object.values(depositData);
|
|
209
|
-
await
|
|
221
|
+
await approvedDeposit(depositDataValues);
|
|
210
222
|
assert.fail("Deposit should have failed due to InvalidQuoteTimestamp");
|
|
211
223
|
}
|
|
212
224
|
catch (err) {
|
|
@@ -219,7 +231,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
219
231
|
depositData.quoteTimestamp = futureQuoteTimestamp;
|
|
220
232
|
try {
|
|
221
233
|
const depositDataValues = Object.values(depositData);
|
|
222
|
-
await
|
|
234
|
+
await approvedDeposit(depositDataValues);
|
|
223
235
|
assert.fail("Deposit should have failed due to InvalidQuoteTimestamp");
|
|
224
236
|
}
|
|
225
237
|
catch (err) {
|
|
@@ -228,24 +240,13 @@ describe("svm_spoke.deposit", () => {
|
|
|
228
240
|
});
|
|
229
241
|
it("Fails to deposit tokens with InvalidFillDeadline when fill deadline is invalid", async () => {
|
|
230
242
|
const currentTime = await getCurrentTime(program, state);
|
|
231
|
-
//
|
|
232
|
-
|
|
233
|
-
depositData.fillDeadline = new anchor_1.BN(invalidFillDeadline);
|
|
234
|
-
depositData.quoteTimestamp = new anchor_1.BN(currentTime - 1); // 1 second before current time on the contract to reset.
|
|
235
|
-
try {
|
|
236
|
-
const depositDataValues = Object.values(depositData);
|
|
237
|
-
await approvedDepositV3(depositDataValues);
|
|
238
|
-
assert.fail("Deposit should have failed due to InvalidFillDeadline (past deadline)");
|
|
239
|
-
}
|
|
240
|
-
catch (err) {
|
|
241
|
-
assert.include(err.toString(), "InvalidFillDeadline", "Expected InvalidFillDeadline error for past deadline");
|
|
242
|
-
}
|
|
243
|
-
// Case 2: Fill deadline is too far ahead (longer than fill_deadline_buffer + currentTime)
|
|
244
|
-
invalidFillDeadline = currentTime + fillDeadlineBuffer.toNumber() + 1; // 1 seconds beyond the buffer
|
|
243
|
+
// Fill deadline is too far ahead (longer than fill_deadline_buffer + currentTime)
|
|
244
|
+
const invalidFillDeadline = currentTime + fillDeadlineBuffer.toNumber() + 1; // 1 seconds beyond the buffer
|
|
245
245
|
depositData.fillDeadline = new anchor_1.BN(invalidFillDeadline);
|
|
246
|
+
depositData.quoteTimestamp = new anchor_1.BN(currentTime);
|
|
246
247
|
try {
|
|
247
248
|
const depositDataValues = Object.values(depositData);
|
|
248
|
-
await
|
|
249
|
+
await approvedDeposit(depositDataValues);
|
|
249
250
|
assert.fail("Deposit should have failed due to InvalidFillDeadline (future deadline)");
|
|
250
251
|
}
|
|
251
252
|
catch (err) {
|
|
@@ -259,13 +260,13 @@ describe("svm_spoke.deposit", () => {
|
|
|
259
260
|
// Create a new input token and enable the route (this updates global scope variables).
|
|
260
261
|
await setupInputToken();
|
|
261
262
|
await enableRoute();
|
|
262
|
-
// Try to execute the
|
|
263
|
+
// Try to execute the deposit call with malformed inputs where the first input token and its derived route is
|
|
263
264
|
// passed combined with mint, vault and user token account from the second input token.
|
|
264
265
|
const malformedDepositData = { ...depositData, inputToken: firstInputToken };
|
|
265
266
|
const malformedDepositAccounts = { ...depositAccounts, route: firstDepositAccounts.route };
|
|
266
267
|
try {
|
|
267
268
|
const depositDataValues = Object.values(malformedDepositData);
|
|
268
|
-
await
|
|
269
|
+
await approvedDeposit(depositDataValues, malformedDepositAccounts);
|
|
269
270
|
assert.fail("Should not be able to process deposit for inconsistent mint");
|
|
270
271
|
}
|
|
271
272
|
catch (err) {
|
|
@@ -307,7 +308,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
307
308
|
...depositData,
|
|
308
309
|
destinationChainId: fakeRouteChainId,
|
|
309
310
|
});
|
|
310
|
-
const tx = await
|
|
311
|
+
const tx = await approvedDeposit(depositDataValues, fakeDepositAccounts);
|
|
311
312
|
let events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
312
313
|
let event = events[0].data; // 0th event is the latest event.
|
|
313
314
|
const expectedValues = {
|
|
@@ -327,7 +328,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
327
328
|
const depositDataValues = Object.values({
|
|
328
329
|
...{ ...depositData, destinationChainId: fakeRouteChainId },
|
|
329
330
|
});
|
|
330
|
-
await
|
|
331
|
+
await approvedDeposit(depositDataValues, { ...depositAccounts, route: fakeRoutePda });
|
|
331
332
|
assert.fail("Deposit should have failed for a fake route PDA");
|
|
332
333
|
}
|
|
333
334
|
catch (err) {
|
|
@@ -344,9 +345,9 @@ describe("svm_spoke.deposit", () => {
|
|
|
344
345
|
const fillDeadlineOffset = 60; // 60 seconds offset
|
|
345
346
|
// Delegate state PDA to pull depositor tokens.
|
|
346
347
|
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(depositAccounts.depositorTokenAccount, depositAccounts.mint, depositAccounts.state, depositor.publicKey, BigInt(depositData.inputAmount.toString()), tokenDecimals, undefined, tokenProgram);
|
|
347
|
-
// Execute the
|
|
348
|
+
// Execute the deposit_now call. Remove the quoteTimestamp from the depositData as not needed for this method.
|
|
348
349
|
const depositIx = await program.methods
|
|
349
|
-
.
|
|
350
|
+
.depositNow(depositData.depositor, depositData.recipient, depositData.inputToken, depositData.outputToken, depositData.inputAmount, depositData.outputAmount, depositData.destinationChainId, depositData.exclusiveRelayer, fillDeadlineOffset, 0, depositData.message)
|
|
350
351
|
.accounts(depositAccounts)
|
|
351
352
|
.instruction();
|
|
352
353
|
const depositTx = new web3_js_1.Transaction().add(approveIx, depositIx);
|
|
@@ -375,7 +376,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
375
376
|
depositData.exclusivityParameter = new anchor_1.BN(1);
|
|
376
377
|
try {
|
|
377
378
|
const depositDataValues = Object.values(depositData);
|
|
378
|
-
await
|
|
379
|
+
await approvedDeposit(depositDataValues);
|
|
379
380
|
assert.fail("Should have failed due to InvalidExclusiveRelayer");
|
|
380
381
|
}
|
|
381
382
|
catch (err) {
|
|
@@ -392,7 +393,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
392
393
|
depositData.exclusivityParameter = exclusivityDeadline;
|
|
393
394
|
try {
|
|
394
395
|
const depositDataValues = Object.values(depositData);
|
|
395
|
-
await
|
|
396
|
+
await approvedDeposit(depositDataValues);
|
|
396
397
|
assert.fail("Should have failed due to InvalidExclusiveRelayer");
|
|
397
398
|
}
|
|
398
399
|
catch (err) {
|
|
@@ -402,7 +403,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
402
403
|
// Test with exclusivityDeadline set to 0
|
|
403
404
|
depositData.exclusivityParameter = new anchor_1.BN(0);
|
|
404
405
|
const depositDataValues = Object.values(depositData);
|
|
405
|
-
await
|
|
406
|
+
await approvedDeposit(depositDataValues);
|
|
406
407
|
});
|
|
407
408
|
it("Exclusivity param is used as an offset", async () => {
|
|
408
409
|
const currentTime = new anchor_1.BN(await getCurrentTime(program, state));
|
|
@@ -410,7 +411,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
410
411
|
depositData.exclusiveRelayer = depositor.publicKey;
|
|
411
412
|
depositData.exclusivityParameter = maxExclusivityOffsetSeconds;
|
|
412
413
|
const depositDataValues = Object.values(depositData);
|
|
413
|
-
const tx = await
|
|
414
|
+
const tx = await approvedDeposit(depositDataValues);
|
|
414
415
|
const events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
415
416
|
const event = events[0].data; // 0th event is the latest event
|
|
416
417
|
assertSE(event.exclusivityDeadline, currentTime.add(maxExclusivityOffsetSeconds), "exclusivityDeadline should be current time + offset");
|
|
@@ -422,7 +423,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
422
423
|
depositData.exclusiveRelayer = depositor.publicKey;
|
|
423
424
|
depositData.exclusivityParameter = exclusivityDeadlineTimestamp;
|
|
424
425
|
const depositDataValues = Object.values(depositData);
|
|
425
|
-
const tx = await
|
|
426
|
+
const tx = await approvedDeposit(depositDataValues);
|
|
426
427
|
const events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
427
428
|
const event = events[0].data; // 0th event is the latest event;
|
|
428
429
|
assertSE(event.exclusivityDeadline, exclusivityDeadlineTimestamp, "exclusivityDeadline should be passed in time");
|
|
@@ -434,7 +435,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
434
435
|
depositData.exclusiveRelayer = depositor.publicKey;
|
|
435
436
|
depositData.exclusivityParameter = zeroExclusivity;
|
|
436
437
|
const depositDataValues = Object.values(depositData);
|
|
437
|
-
const tx = await
|
|
438
|
+
const tx = await approvedDeposit(depositDataValues);
|
|
438
439
|
const events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
439
440
|
const event = events[0].data; // 0th event is the latest event;
|
|
440
441
|
assertSE(event.exclusivityDeadline, zeroExclusivity, "Exclusivity deadline should always be 0");
|
|
@@ -457,7 +458,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
457
458
|
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(depositAccounts.depositorTokenAccount, depositAccounts.mint, depositAccounts.state, depositor.publicKey, BigInt(depositData.inputAmount.toString()), tokenDecimals, undefined, tokenProgram);
|
|
458
459
|
// Create the transaction for unsafeDepositV3
|
|
459
460
|
const unsafeDepositIx = await program.methods
|
|
460
|
-
.
|
|
461
|
+
.unsafeDeposit(depositData.depositor, depositData.recipient, depositData.inputToken, depositData.outputToken, depositData.inputAmount, depositData.outputAmount, depositData.destinationChainId, depositData.exclusiveRelayer, forcedDepositId, // deposit nonce
|
|
461
462
|
depositData.quoteTimestamp.toNumber(), depositData.fillDeadline.toNumber(), depositData.exclusivityParameter.toNumber(), depositData.message)
|
|
462
463
|
.accounts(depositAccounts) // Assuming depositAccounts is already set up correctly
|
|
463
464
|
.instruction();
|
|
@@ -485,9 +486,9 @@ describe("svm_spoke.deposit", () => {
|
|
|
485
486
|
// Verify vault balance is zero before the deposit
|
|
486
487
|
let vaultAccount = await (0, spl_token_1.getAccount)(connection, vault, undefined, tokenProgram);
|
|
487
488
|
assertSE(vaultAccount.amount, "0", "Vault balance should be zero before the deposit");
|
|
488
|
-
// Execute the
|
|
489
|
+
// Execute the deposit call
|
|
489
490
|
const depositDataValues = Object.values(depositData);
|
|
490
|
-
await
|
|
491
|
+
await approvedDeposit(depositDataValues);
|
|
491
492
|
// Verify tokens leave the depositor's account
|
|
492
493
|
const depositorAccount = await (0, spl_token_1.getAccount)(connection, depositorTA, undefined, tokenProgram);
|
|
493
494
|
assertSE(depositorAccount.amount, seedBalance - depositData.inputAmount.toNumber(), "Depositor's balance should be reduced by the deposited amount");
|
|
@@ -499,7 +500,7 @@ describe("svm_spoke.deposit", () => {
|
|
|
499
500
|
const depositDataValues = Object.values(depositData);
|
|
500
501
|
try {
|
|
501
502
|
await program.methods
|
|
502
|
-
.
|
|
503
|
+
.deposit(...depositDataValues)
|
|
503
504
|
.accounts(depositAccounts)
|
|
504
505
|
.signers([depositor])
|
|
505
506
|
.rpc();
|
|
@@ -69,14 +69,14 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
69
69
|
// Prepare fill instruction.
|
|
70
70
|
const fillV3RelayValues = [relayHash, relayData, new anchor_1.BN(1), relayer.publicKey];
|
|
71
71
|
if (bufferParams) {
|
|
72
|
-
await (0, web3_v1_1.
|
|
72
|
+
await (0, web3_v1_1.loadFillRelayParams)(program, relayer, fillV3RelayValues[1], fillV3RelayValues[2], fillV3RelayValues[3]);
|
|
73
73
|
[accounts.instructionParams] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("instruction_params"), relayer.publicKey.toBuffer()], program.programId);
|
|
74
74
|
}
|
|
75
75
|
const fillV3RelayParams = bufferParams
|
|
76
76
|
? [fillV3RelayValues[0], null, null, null]
|
|
77
77
|
: fillV3RelayValues;
|
|
78
78
|
const fillIx = await program.methods
|
|
79
|
-
.
|
|
79
|
+
.fillRelay(...fillV3RelayParams)
|
|
80
80
|
.accounts(accounts)
|
|
81
81
|
.remainingAccounts(remainingAccounts)
|
|
82
82
|
.instruction();
|
|
@@ -61,11 +61,11 @@ describe("svm_spoke.fill", () => {
|
|
|
61
61
|
program: program.programId,
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
|
-
const
|
|
64
|
+
const approvedFillRelay = async (fillDataValues, calledFillAccounts = accounts, callingRelayer = relayer) => {
|
|
65
65
|
// Delegate state PDA to pull relayer tokens.
|
|
66
66
|
const approveIx = await (0, spl_token_1.createApproveCheckedInstruction)(calledFillAccounts.relayerTokenAccount, calledFillAccounts.mint, calledFillAccounts.state, calledFillAccounts.signer, BigInt(fillDataValues[1].outputAmount.toString()), tokenDecimals, undefined, tokenProgram);
|
|
67
67
|
const fillIx = await program.methods
|
|
68
|
-
.
|
|
68
|
+
.fillRelay(...fillDataValues)
|
|
69
69
|
.accounts(calledFillAccounts)
|
|
70
70
|
.remainingAccounts(fillRemainingAccounts)
|
|
71
71
|
.instruction();
|
|
@@ -114,7 +114,7 @@ describe("svm_spoke.fill", () => {
|
|
|
114
114
|
let relayerAccount = await (0, spl_token_1.getAccount)(connection, relayerTA);
|
|
115
115
|
assertSE(relayerAccount.amount, seedBalance, "Relayer's balance should be equal to seed balance before the fill");
|
|
116
116
|
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
117
|
-
await
|
|
117
|
+
await approvedFillRelay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
118
118
|
// Verify relayer's balance after the fill
|
|
119
119
|
relayerAccount = await (0, spl_token_1.getAccount)(connection, relayerTA);
|
|
120
120
|
assertSE(relayerAccount.amount, seedBalance - relayAmount, "Relayer's balance should be reduced by the relay amount");
|
|
@@ -122,13 +122,13 @@ describe("svm_spoke.fill", () => {
|
|
|
122
122
|
recipientAccount = await (0, spl_token_1.getAccount)(connection, recipientTA);
|
|
123
123
|
assertSE(recipientAccount.amount, relayAmount, "Recipient's balance should be increased by the relay amount");
|
|
124
124
|
});
|
|
125
|
-
it("Verifies
|
|
125
|
+
it("Verifies FilledRelay event after filling a relay", async () => {
|
|
126
126
|
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
127
|
-
const tx = await
|
|
128
|
-
// Fetch and verify the
|
|
127
|
+
const tx = await approvedFillRelay([relayHash, relayData, new anchor_1.BN(420), otherRelayer.publicKey]);
|
|
128
|
+
// Fetch and verify the FilledRelay event
|
|
129
129
|
const events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
130
|
-
const event = events.find((event) => event.name === "
|
|
131
|
-
assert.isNotNull(event, "
|
|
130
|
+
const event = events.find((event) => event.name === "filledRelay")?.data;
|
|
131
|
+
assert.isNotNull(event, "FilledRelay event should be emitted");
|
|
132
132
|
// Verify that the event data matches the relay data.
|
|
133
133
|
Object.entries(relayData).forEach(([key, value]) => {
|
|
134
134
|
if (key === "message") {
|
|
@@ -150,7 +150,7 @@ describe("svm_spoke.fill", () => {
|
|
|
150
150
|
updateRelayData({ ...relayData, fillDeadline: Math.floor(Date.now() / 1000) - 69 }); // 69 seconds ago
|
|
151
151
|
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
152
152
|
try {
|
|
153
|
-
await
|
|
153
|
+
await approvedFillRelay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
154
154
|
assert.fail("Fill should have failed due to fill deadline passed");
|
|
155
155
|
}
|
|
156
156
|
catch (err) {
|
|
@@ -162,7 +162,7 @@ describe("svm_spoke.fill", () => {
|
|
|
162
162
|
accounts.relayerTokenAccount = otherRelayerTA;
|
|
163
163
|
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
164
164
|
try {
|
|
165
|
-
await
|
|
165
|
+
await approvedFillRelay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey], undefined, otherRelayer);
|
|
166
166
|
assert.fail("Fill should have failed due to non-exclusive relayer before exclusivity deadline");
|
|
167
167
|
}
|
|
168
168
|
catch (err) {
|
|
@@ -176,7 +176,7 @@ describe("svm_spoke.fill", () => {
|
|
|
176
176
|
const recipientAccountBefore = await (0, spl_token_1.getAccount)(connection, recipientTA);
|
|
177
177
|
const relayerAccountBefore = await (0, spl_token_1.getAccount)(connection, otherRelayerTA);
|
|
178
178
|
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
179
|
-
await
|
|
179
|
+
await approvedFillRelay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey], undefined, otherRelayer);
|
|
180
180
|
// Verify relayer's balance after the fill
|
|
181
181
|
const relayerAccountAfter = await (0, spl_token_1.getAccount)(connection, otherRelayerTA);
|
|
182
182
|
assertSE(relayerAccountAfter.amount, BigInt(relayerAccountBefore.amount) - BigInt(relayAmount), "Relayer's balance should be reduced by the relay amount");
|
|
@@ -187,10 +187,10 @@ describe("svm_spoke.fill", () => {
|
|
|
187
187
|
it("Fails to fill a V3 relay with the same deposit data multiple times", async () => {
|
|
188
188
|
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
189
189
|
// First fill attempt
|
|
190
|
-
await
|
|
190
|
+
await approvedFillRelay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
191
191
|
// Second fill attempt with the same data
|
|
192
192
|
try {
|
|
193
|
-
await
|
|
193
|
+
await approvedFillRelay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
194
194
|
assert.fail("Fill should have failed due to RelayFilled error");
|
|
195
195
|
}
|
|
196
196
|
catch (err) {
|
|
@@ -206,7 +206,7 @@ describe("svm_spoke.fill", () => {
|
|
|
206
206
|
systemProgram: anchor.web3.SystemProgram.programId,
|
|
207
207
|
};
|
|
208
208
|
// Execute the fill_v3_relay call
|
|
209
|
-
await
|
|
209
|
+
await approvedFillRelay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
210
210
|
// Verify the fill PDA exists before closing
|
|
211
211
|
const fillStatusAccountBefore = await connection.getAccountInfo(accounts.fillStatus);
|
|
212
212
|
assert.isNotNull(fillStatusAccountBefore, "Fill PDA should exist before closing");
|
|
@@ -233,7 +233,7 @@ describe("svm_spoke.fill", () => {
|
|
|
233
233
|
let fillStatusAccount = await program.account.fillStatusAccount.fetchNullable(fillStatusPDA);
|
|
234
234
|
assert.isNull(fillStatusAccount, "FillStatusAccount should be uninitialized before fillV3Relay");
|
|
235
235
|
// Fill the relay
|
|
236
|
-
await
|
|
236
|
+
await approvedFillRelay([Array.from(relayHash), relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
237
237
|
// Fetch FillStatusAccount after fillV3Relay
|
|
238
238
|
fillStatusAccount = await program.account.fillStatusAccount.fetch(fillStatusPDA);
|
|
239
239
|
assert.isNotNull(fillStatusAccount, "FillStatusAccount should be initialized after fillV3Relay");
|
|
@@ -249,7 +249,7 @@ describe("svm_spoke.fill", () => {
|
|
|
249
249
|
// Try to fill the relay. This should fail because fills are paused.
|
|
250
250
|
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
251
251
|
try {
|
|
252
|
-
await
|
|
252
|
+
await approvedFillRelay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
253
253
|
assert.fail("Should not be able to fill relay when fills are paused");
|
|
254
254
|
}
|
|
255
255
|
catch (err) {
|
|
@@ -263,7 +263,7 @@ describe("svm_spoke.fill", () => {
|
|
|
263
263
|
const wrongRecipientTA = (await (0, spl_token_1.getOrCreateAssociatedTokenAccount)(connection, payer, mint, wrongRecipient)).address;
|
|
264
264
|
const [wrongFillStatus] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("fills"), relayHash], program.programId);
|
|
265
265
|
try {
|
|
266
|
-
await
|
|
266
|
+
await approvedFillRelay([Array.from(relayHash), relayData, new anchor_1.BN(1), relayer.publicKey], {
|
|
267
267
|
...accounts,
|
|
268
268
|
recipientTokenAccount: wrongRecipientTA,
|
|
269
269
|
fillStatus: wrongFillStatus,
|
|
@@ -283,7 +283,7 @@ describe("svm_spoke.fill", () => {
|
|
|
283
283
|
.address;
|
|
284
284
|
await (0, spl_token_1.mintTo)(connection, payer, wrongMint, wrongRelayerTA, owner, seedBalance);
|
|
285
285
|
try {
|
|
286
|
-
await
|
|
286
|
+
await approvedFillRelay([Array.from(relayHash), relayData, new anchor_1.BN(1), relayer.publicKey], {
|
|
287
287
|
...accounts,
|
|
288
288
|
mint: wrongMint,
|
|
289
289
|
relayerTokenAccount: wrongRelayerTA,
|
|
@@ -295,34 +295,6 @@ describe("svm_spoke.fill", () => {
|
|
|
295
295
|
assert.include(err.toString(), "InvalidMint", "Expected InvalidMint error");
|
|
296
296
|
}
|
|
297
297
|
});
|
|
298
|
-
it("Self-relay does not invoke token transfer", async () => {
|
|
299
|
-
// Set recipient to be the same as relayer.
|
|
300
|
-
updateRelayData({ ...relayData, depositor: relayer.publicKey, recipient: relayer.publicKey });
|
|
301
|
-
accounts.recipientTokenAccount = relayerTA;
|
|
302
|
-
// Store relayer's balance before the fill
|
|
303
|
-
const iRelayerBalance = (await (0, spl_token_1.getAccount)(connection, relayerTA)).amount;
|
|
304
|
-
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
305
|
-
// No need for approval in self-relay.
|
|
306
|
-
const txSignature = await program.methods
|
|
307
|
-
.fillV3Relay(relayHash, relayData, new anchor_1.BN(1), relayer.publicKey)
|
|
308
|
-
.accounts(accounts)
|
|
309
|
-
.remainingAccounts(fillRemainingAccounts)
|
|
310
|
-
.signers([relayer])
|
|
311
|
-
.rpc();
|
|
312
|
-
// Verify relayer's balance after the fill is unchanged
|
|
313
|
-
const fRelayerBalance = (await (0, spl_token_1.getAccount)(connection, relayerTA)).amount;
|
|
314
|
-
assertSE(fRelayerBalance, iRelayerBalance, "Relayer's balance should not have changed");
|
|
315
|
-
await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait for tx processing
|
|
316
|
-
const txResult = await connection.getTransaction(txSignature, {
|
|
317
|
-
commitment: "confirmed",
|
|
318
|
-
maxSupportedTransactionVersion: 0,
|
|
319
|
-
});
|
|
320
|
-
if (txResult === null || txResult.meta === null)
|
|
321
|
-
throw new Error("Transaction meta not confirmed");
|
|
322
|
-
if (txResult.meta.logMessages === null || txResult.meta.logMessages === undefined)
|
|
323
|
-
throw new Error("Transaction logs not found");
|
|
324
|
-
assert.isTrue(txResult.meta.logMessages.every((log) => !log.includes(`Program ${spl_token_1.TOKEN_PROGRAM_ID} invoke`)), "Token Program should not be invoked");
|
|
325
|
-
});
|
|
326
298
|
it("Fills a V3 relay from custom relayer token account", async () => {
|
|
327
299
|
// Create and mint to custom relayer token account
|
|
328
300
|
const customKeypair = web3_js_1.Keypair.generate();
|
|
@@ -334,7 +306,7 @@ describe("svm_spoke.fill", () => {
|
|
|
334
306
|
// Fill relay from custom relayer token account
|
|
335
307
|
accounts.relayerTokenAccount = customRelayerTA;
|
|
336
308
|
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
337
|
-
await
|
|
309
|
+
await approvedFillRelay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
338
310
|
// Verify balances after the fill
|
|
339
311
|
const fRelayerBal = (await (0, spl_token_1.getAccount)(connection, customRelayerTA)).amount;
|
|
340
312
|
const fRecipientBal = (await (0, spl_token_1.getAccount)(connection, recipientTA)).amount;
|
|
@@ -355,7 +327,7 @@ describe("svm_spoke.fill", () => {
|
|
|
355
327
|
accounts.recipientTokenAccount = newRecipientATA;
|
|
356
328
|
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(newRelayData, chainId));
|
|
357
329
|
try {
|
|
358
|
-
await
|
|
330
|
+
await approvedFillRelay([relayHash, newRelayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
359
331
|
assert.fail("Fill should have failed due to missing ATA");
|
|
360
332
|
}
|
|
361
333
|
catch (err) {
|
|
@@ -373,7 +345,7 @@ describe("svm_spoke.fill", () => {
|
|
|
373
345
|
// Fill the deposit in the same transaction
|
|
374
346
|
const approveInstruction = await (0, spl_token_1.createApproveCheckedInstruction)(accounts.relayerTokenAccount, accounts.mint, accounts.state, accounts.signer, BigInt(newRelayData.outputAmount.toString()), tokenDecimals, undefined, tokenProgram);
|
|
375
347
|
const fillInstruction = await program.methods
|
|
376
|
-
.
|
|
348
|
+
.fillRelay(relayHash, newRelayData, new anchor_1.BN(1), relayer.publicKey)
|
|
377
349
|
.accounts(accounts)
|
|
378
350
|
.remainingAccounts(fillRemainingAccounts)
|
|
379
351
|
.instruction();
|
|
@@ -415,7 +387,7 @@ describe("svm_spoke.fill", () => {
|
|
|
415
387
|
accounts.recipientTokenAccount = recipientAssociatedTokens[i];
|
|
416
388
|
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(newRelayData, chainId));
|
|
417
389
|
const fillInstruction = await program.methods
|
|
418
|
-
.
|
|
390
|
+
.fillRelay(relayHash, newRelayData, new anchor_1.BN(1), relayer.publicKey)
|
|
419
391
|
.accounts(accounts)
|
|
420
392
|
.remainingAccounts(fillRemainingAccounts)
|
|
421
393
|
.instruction();
|
|
@@ -433,7 +405,7 @@ describe("svm_spoke.fill", () => {
|
|
|
433
405
|
assertSE(recipientBal, BigInt(relayAmount), "Recipient's balance should be increased by the relay amount");
|
|
434
406
|
});
|
|
435
407
|
});
|
|
436
|
-
it("Fills a
|
|
408
|
+
it("Fills a relay with enabled CPI-guard", async () => {
|
|
437
409
|
// CPI-guard is available only for the 2022 token program.
|
|
438
410
|
tokenProgram = spl_token_1.TOKEN_2022_PROGRAM_ID;
|
|
439
411
|
// Remint the tokens on the token 2022 program.
|
|
@@ -454,7 +426,7 @@ describe("svm_spoke.fill", () => {
|
|
|
454
426
|
let relayerAccount = await (0, spl_token_1.getAccount)(connection, relayerTA, undefined, tokenProgram);
|
|
455
427
|
assertSE(relayerAccount.amount, seedBalance, "Relayer's balance should be equal to seed balance before the fill");
|
|
456
428
|
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
457
|
-
await
|
|
429
|
+
await approvedFillRelay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
458
430
|
// Verify relayer's balance after the fill
|
|
459
431
|
relayerAccount = await (0, spl_token_1.getAccount)(connection, relayerTA, undefined, tokenProgram);
|
|
460
432
|
assertSE(relayerAccount.amount, seedBalance - relayAmount, "Relayer's balance should be reduced by the relay amount");
|
|
@@ -465,11 +437,11 @@ describe("svm_spoke.fill", () => {
|
|
|
465
437
|
it("Emits zeroed hash for empty message", async () => {
|
|
466
438
|
updateRelayData({ ...relayData, message: Buffer.alloc(0) });
|
|
467
439
|
const relayHash = Array.from((0, web3_v1_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
468
|
-
const tx = await
|
|
469
|
-
// Fetch and verify the
|
|
440
|
+
const tx = await approvedFillRelay([relayHash, relayData, new anchor_1.BN(420), otherRelayer.publicKey]);
|
|
441
|
+
// Fetch and verify the FilledRelay event
|
|
470
442
|
const events = await (0, web3_v1_1.readEventsUntilFound)(connection, tx, [program]);
|
|
471
|
-
const event = events.find((event) => event.name === "
|
|
472
|
-
assert.isNotNull(event, "
|
|
443
|
+
const event = events.find((event) => event.name === "filledRelay")?.data;
|
|
444
|
+
assert.isNotNull(event, "FilledRelay event should be emitted");
|
|
473
445
|
// Verify that the event data has zeroed message hash.
|
|
474
446
|
assertSE(event.messageHash, new Uint8Array(32), `MessageHash should be zeroed`);
|
|
475
447
|
assertSE(event.relayExecutionInfo.updatedMessageHash, new Uint8Array(32), `UpdatedMessageHash should be zeroed`);
|