@across-protocol/contracts 3.0.17 → 3.0.19
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/README.md +2 -0
- package/artifacts/build-info/9cb910e5bb5dd730cd01af84a0fb0466.json +1 -0
- package/artifacts/contracts/Ink_SpokePool.sol/Ink_SpokePool.dbg.json +4 -0
- package/artifacts/contracts/Ink_SpokePool.sol/Ink_SpokePool.json +2316 -0
- package/contracts/Ink_SpokePool.sol +72 -0
- package/dist/deploy/consts.js +8 -2
- package/dist/deployments/deployments.json +7 -1
- package/dist/hardhat.config.js +17 -0
- package/dist/scripts/svm/addressToPublicKey.d.ts +1 -0
- package/dist/scripts/svm/addressToPublicKey.js +20 -0
- package/dist/scripts/svm/bridgeLiabilityToHubPool.d.ts +25 -0
- package/dist/scripts/svm/bridgeLiabilityToHubPool.js +221 -0
- package/dist/scripts/svm/closeRelayerPdas.js +8 -9
- package/dist/scripts/svm/enableRoute.js +7 -1
- package/dist/scripts/svm/executeRebalanceToHubPool.d.ts +29 -0
- package/dist/scripts/svm/executeRebalanceToHubPool.js +345 -0
- package/dist/scripts/svm/executeRebalanceToSpokePool.d.ts +1 -0
- package/dist/scripts/svm/executeRebalanceToSpokePool.js +240 -0
- package/dist/scripts/svm/fakeFillWithRandomDistribution.js +6 -7
- package/dist/scripts/svm/initialize.js +2 -2
- package/dist/scripts/svm/proposeRebalanceToHubPool.d.ts +27 -0
- package/dist/scripts/svm/proposeRebalanceToHubPool.js +117 -0
- package/dist/scripts/svm/proposeRebalanceToSpokePool.d.ts +1 -0
- package/dist/scripts/svm/proposeRebalanceToSpokePool.js +97 -0
- package/dist/scripts/svm/publicKeyToAddress.d.ts +1 -0
- package/dist/scripts/svm/publicKeyToAddress.js +20 -0
- package/dist/scripts/svm/queryDeposits.js +3 -2
- package/dist/scripts/svm/queryFills.js +12 -14
- package/dist/scripts/svm/queryRoute.js +7 -1
- package/dist/scripts/svm/queryState.js +1 -0
- package/dist/scripts/svm/remoteHubPoolPauseDeposits.d.ts +1 -0
- package/dist/scripts/svm/remoteHubPoolPauseDeposits.js +191 -0
- package/dist/scripts/svm/remoteHubPoolSetDepositRoute.js +16 -29
- package/dist/scripts/svm/remotePauseDeposits.js +21 -27
- package/dist/scripts/svm/simpleDeposit.js +7 -1
- package/dist/scripts/svm/simpleFakeRelayerRepayment.js +3 -3
- package/dist/scripts/svm/simpleFill.js +6 -6
- package/dist/scripts/svm/utils/constants.d.ts +4 -0
- package/dist/scripts/svm/utils/constants.js +8 -1
- package/dist/scripts/svm/utils/helpers.d.ts +33 -0
- package/dist/scripts/svm/utils/helpers.js +60 -1
- package/dist/scripts/svm/utils/poolRebalanceTree.d.ts +22 -0
- package/dist/scripts/svm/utils/poolRebalanceTree.js +20 -0
- package/dist/src/svm/coders.d.ts +37 -0
- package/dist/src/svm/coders.js +250 -0
- package/dist/src/svm/conversionUtils.d.ts +22 -0
- package/dist/src/svm/conversionUtils.js +73 -0
- package/dist/src/svm/index.d.ts +6 -0
- package/dist/src/svm/index.js +22 -0
- package/dist/src/svm/instructionParamsUtils.d.ts +31 -0
- package/dist/src/svm/instructionParamsUtils.js +128 -0
- package/dist/src/svm/relayHashUtils.d.ts +30 -0
- package/dist/src/svm/relayHashUtils.js +209 -0
- package/dist/src/svm/solanaProgramUtils.d.ts +38 -0
- package/dist/src/svm/solanaProgramUtils.js +147 -0
- package/dist/src/svm/transactionUtils.d.ts +8 -0
- package/dist/src/svm/transactionUtils.js +55 -0
- package/dist/src/types/svm.d.ts +118 -0
- package/dist/src/types/svm.js +2 -0
- package/dist/target/types/svm_spoke.d.ts +47 -42
- package/dist/tasks/enableL1TokenAcrossEcosystem.js +3 -33
- package/dist/tasks/types.d.ts +2 -0
- package/dist/tasks/types.js +2 -0
- package/dist/tasks/utils.d.ts +12 -0
- package/dist/tasks/utils.js +34 -0
- package/dist/test/svm/MulticallHandler.js +2 -2
- package/dist/test/svm/SvmSpoke.Bundle.js +59 -60
- package/dist/test/svm/SvmSpoke.Deposit.js +23 -31
- package/dist/test/svm/SvmSpoke.Fill.AcrossPlus.js +16 -18
- package/dist/test/svm/SvmSpoke.Fill.js +38 -40
- package/dist/test/svm/SvmSpoke.HandleReceiveMessage.js +2 -2
- package/dist/test/svm/SvmSpoke.Ownership.js +11 -17
- package/dist/test/svm/SvmSpoke.RefundClaims.js +12 -11
- package/dist/test/svm/SvmSpoke.Routes.js +11 -7
- package/dist/test/svm/SvmSpoke.SlowFill.AcrossPlus.js +72 -16
- package/dist/test/svm/SvmSpoke.SlowFill.js +33 -28
- package/dist/test/svm/SvmSpoke.TokenBridge.js +15 -17
- package/dist/test/svm/SvmSpoke.common.d.ts +1 -49
- package/dist/test/svm/SvmSpoke.common.js +6 -5
- package/dist/test/svm/cctpHelpers.js +2 -2
- package/dist/test/svm/utils.d.ts +5 -67
- package/dist/test/svm/utils.js +10 -220
- package/dist/typechain/contracts/Ink_SpokePool.d.ts +1251 -0
- package/dist/typechain/contracts/Ink_SpokePool.js +2 -0
- package/dist/typechain/contracts/index.d.ts +1 -0
- package/dist/typechain/factories/contracts/Ink_SpokePool__factory.d.ts +1833 -0
- package/dist/typechain/factories/contracts/Ink_SpokePool__factory.js +2347 -0
- package/dist/typechain/factories/contracts/index.d.ts +1 -0
- package/dist/typechain/factories/contracts/index.js +3 -1
- package/dist/typechain/hardhat.d.ts +9 -0
- package/dist/typechain/index.d.ts +2 -0
- package/dist/typechain/index.js +5 -3
- package/package.json +2 -2
- package/dist/src/SvmUtils.d.ts +0 -50
- package/dist/src/SvmUtils.js +0 -415
|
@@ -27,10 +27,8 @@ const anchor = __importStar(require("@coral-xyz/anchor"));
|
|
|
27
27
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
28
28
|
const spl_token_1 = require("@solana/spl-token");
|
|
29
29
|
const web3_js_1 = require("@solana/web3.js");
|
|
30
|
-
const
|
|
31
|
-
const SvmUtils_1 = require("../../src/SvmUtils");
|
|
30
|
+
const svm_1 = require("../../src/svm");
|
|
32
31
|
const SvmSpoke_common_1 = require("./SvmSpoke.common");
|
|
33
|
-
const utils_2 = require("./utils");
|
|
34
32
|
const { provider, connection, program, owner, chainId, seedBalance } = SvmSpoke_common_1.common;
|
|
35
33
|
const { initializeState, assertSE } = SvmSpoke_common_1.common;
|
|
36
34
|
describe("svm_spoke.fill.across_plus", () => {
|
|
@@ -45,7 +43,7 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
45
43
|
let accounts; // Store accounts to simplify contract interactions.
|
|
46
44
|
function updateRelayData(newRelayData) {
|
|
47
45
|
relayData = newRelayData;
|
|
48
|
-
const relayHashUint8Array = (0,
|
|
46
|
+
const relayHashUint8Array = (0, svm_1.calculateRelayHashUint8Array)(relayData, chainId);
|
|
49
47
|
const [fillStatusPDA] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("fills"), relayHashUint8Array], program.programId);
|
|
50
48
|
accounts = {
|
|
51
49
|
state,
|
|
@@ -67,11 +65,11 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
67
65
|
{ pubkey: handlerProgram.programId, isSigner: false, isWritable: false },
|
|
68
66
|
...multicallHandlerCoder.compiledKeyMetas,
|
|
69
67
|
];
|
|
70
|
-
const relayHash = Array.from((0,
|
|
68
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
71
69
|
// Prepare fill instruction.
|
|
72
70
|
const fillV3RelayValues = [relayHash, relayData, new anchor_1.BN(1), relayer.publicKey];
|
|
73
71
|
if (bufferParams) {
|
|
74
|
-
await (0,
|
|
72
|
+
await (0, svm_1.loadFillV3RelayParams)(program, relayer, fillV3RelayValues[1], fillV3RelayValues[2], fillV3RelayValues[3]);
|
|
75
73
|
[accounts.instructionParams] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("instruction_params"), relayer.publicKey.toBuffer()], program.programId);
|
|
76
74
|
}
|
|
77
75
|
const fillV3RelayParams = bufferParams
|
|
@@ -105,7 +103,7 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
105
103
|
inputAmount: new anchor_1.BN(relayAmount),
|
|
106
104
|
outputAmount: new anchor_1.BN(relayAmount),
|
|
107
105
|
originChainId: new anchor_1.BN(1),
|
|
108
|
-
depositId: (0,
|
|
106
|
+
depositId: (0, svm_1.intToU8Array32)(Math.floor(Math.random() * 1000000)), // force that we always have a new deposit id.
|
|
109
107
|
fillDeadline: new anchor_1.BN(Math.floor(Date.now() / 1000) + 60), // 1 minute from now
|
|
110
108
|
exclusivityDeadline: new anchor_1.BN(Math.floor(Date.now() / 1000) + 30), // 30 seconds from now
|
|
111
109
|
message: Buffer.from(""), // Will be populated in the tests below.
|
|
@@ -116,9 +114,9 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
116
114
|
const iRelayerBal = (await (0, spl_token_1.getAccount)(connection, relayerATA)).amount;
|
|
117
115
|
// Construct ix to transfer all tokens from handler to the final recipient.
|
|
118
116
|
const transferIx = (0, spl_token_1.createTransferCheckedInstruction)(handlerATA, mint, finalRecipientATA, handlerSigner, relayData.outputAmount, mintDecimals);
|
|
119
|
-
const multicallHandlerCoder = new
|
|
117
|
+
const multicallHandlerCoder = new svm_1.MulticallHandlerCoder([transferIx]);
|
|
120
118
|
const handlerMessage = multicallHandlerCoder.encode();
|
|
121
|
-
const message = new
|
|
119
|
+
const message = new svm_1.AcrossPlusMessageCoder({
|
|
122
120
|
handler: handlerProgram.programId,
|
|
123
121
|
readOnlyLen: multicallHandlerCoder.readOnlyLen,
|
|
124
122
|
valueAmount: new anchor_1.BN(0),
|
|
@@ -153,9 +151,9 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
153
151
|
const transferInstruction = (0, spl_token_1.createTransferCheckedInstruction)(handlerATA, mint, recipientATA, handlerSigner, distributionAmount, mintDecimals);
|
|
154
152
|
transferInstructions.push(transferInstruction);
|
|
155
153
|
}
|
|
156
|
-
const multicallHandlerCoder = new
|
|
154
|
+
const multicallHandlerCoder = new svm_1.MulticallHandlerCoder(transferInstructions);
|
|
157
155
|
const handlerMessage = multicallHandlerCoder.encode();
|
|
158
|
-
const message = new
|
|
156
|
+
const message = new svm_1.AcrossPlusMessageCoder({
|
|
159
157
|
handler: handlerProgram.programId,
|
|
160
158
|
readOnlyLen: multicallHandlerCoder.readOnlyLen,
|
|
161
159
|
valueAmount: new anchor_1.BN(0),
|
|
@@ -174,9 +172,9 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
174
172
|
const { approveIx, fillIx } = await createApproveAndFillIx(multicallHandlerCoder, bufferParams);
|
|
175
173
|
// Fill using the ALT.
|
|
176
174
|
const computeBudgetIx = web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: 1_400_000 });
|
|
177
|
-
await (0,
|
|
175
|
+
await (0, svm_1.sendTransactionWithLookupTable)(connection, [computeBudgetIx, approveIx, fillIx], relayer);
|
|
178
176
|
// Verify relayer's balance after the fill
|
|
179
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
177
|
+
await new Promise((resolve) => setTimeout(resolve, 500)); // Make sure token transfers get processed.
|
|
180
178
|
const fRelayerBal = (await (0, spl_token_1.getAccount)(connection, relayerATA)).amount;
|
|
181
179
|
assertSE(fRelayerBal, iRelayerBal - BigInt(distributionAmount * numberOfDistributions), "Relayer's balance should be reduced by the relay amount");
|
|
182
180
|
// Verify all recipient account balances after the fill.
|
|
@@ -200,9 +198,9 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
200
198
|
it("Sends lamports from the relayer to value recipient", async () => {
|
|
201
199
|
const valueAmount = new anchor_1.BN(1_000_000_000);
|
|
202
200
|
const valueRecipient = web3_js_1.Keypair.generate().publicKey;
|
|
203
|
-
const multicallHandlerCoder = new
|
|
201
|
+
const multicallHandlerCoder = new svm_1.MulticallHandlerCoder([], valueRecipient);
|
|
204
202
|
const handlerMessage = multicallHandlerCoder.encode();
|
|
205
|
-
const message = new
|
|
203
|
+
const message = new svm_1.AcrossPlusMessageCoder({
|
|
206
204
|
handler: handlerProgram.programId,
|
|
207
205
|
readOnlyLen: multicallHandlerCoder.readOnlyLen,
|
|
208
206
|
valueAmount,
|
|
@@ -232,9 +230,9 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
232
230
|
// Construct ix to transfer all tokens from handler to the recipient ATA.
|
|
233
231
|
const transferInstruction = (0, spl_token_1.createTransferCheckedInstruction)(handlerATA, mint, anotherRecipientATA, handlerSigner, relayData.outputAmount, mintDecimals);
|
|
234
232
|
// Encode both instructions with handler PDA as the payer for ATA initialization.
|
|
235
|
-
const multicallHandlerCoder = new
|
|
233
|
+
const multicallHandlerCoder = new svm_1.MulticallHandlerCoder([createTokenAccountInstruction, transferInstruction], handlerSigner);
|
|
236
234
|
const handlerMessage = multicallHandlerCoder.encode();
|
|
237
|
-
const message = new
|
|
235
|
+
const message = new svm_1.AcrossPlusMessageCoder({
|
|
238
236
|
handler: handlerProgram.programId,
|
|
239
237
|
readOnlyLen: multicallHandlerCoder.readOnlyLen,
|
|
240
238
|
valueAmount: new anchor_1.BN(valueAmount), // Must exactly cover ATA creation.
|
|
@@ -248,7 +246,7 @@ describe("svm_spoke.fill.across_plus", () => {
|
|
|
248
246
|
// Prepare approval and fill instructions as we will need to use Address Lookup Table (ALT).
|
|
249
247
|
const { approveIx, fillIx } = await createApproveAndFillIx(multicallHandlerCoder);
|
|
250
248
|
// Fill using the ALT.
|
|
251
|
-
await (0,
|
|
249
|
+
await (0, svm_1.sendTransactionWithLookupTable)(connection, [approveIx, fillIx], relayer);
|
|
252
250
|
// Verify recipient's balance after the fill
|
|
253
251
|
await new Promise((resolve) => setTimeout(resolve, 500)); // Make sure token transfer gets processed.
|
|
254
252
|
const anotherRecipientAccount = await (0, spl_token_1.getAccount)(connection, anotherRecipientATA);
|
|
@@ -27,10 +27,9 @@ const anchor = __importStar(require("@coral-xyz/anchor"));
|
|
|
27
27
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
28
28
|
const spl_token_1 = require("@solana/spl-token");
|
|
29
29
|
const web3_js_1 = require("@solana/web3.js");
|
|
30
|
-
const
|
|
31
|
-
const utils_1 = require("./utils");
|
|
30
|
+
const svm_1 = require("../../src/svm");
|
|
32
31
|
const SvmSpoke_common_1 = require("./SvmSpoke.common");
|
|
33
|
-
const
|
|
32
|
+
const utils_1 = require("./utils");
|
|
34
33
|
const { provider, connection, program, owner, chainId, seedBalance } = SvmSpoke_common_1.common;
|
|
35
34
|
const { recipient, initializeState, setCurrentTime, assertSE, assert } = SvmSpoke_common_1.common;
|
|
36
35
|
describe("svm_spoke.fill", () => {
|
|
@@ -38,7 +37,7 @@ describe("svm_spoke.fill", () => {
|
|
|
38
37
|
const payer = anchor.AnchorProvider.env().wallet.payer;
|
|
39
38
|
const relayer = web3_js_1.Keypair.generate();
|
|
40
39
|
const otherRelayer = web3_js_1.Keypair.generate();
|
|
41
|
-
const { encodedMessage, fillRemainingAccounts } = (0,
|
|
40
|
+
const { encodedMessage, fillRemainingAccounts } = (0, utils_1.testAcrossPlusMessage)();
|
|
42
41
|
const tokenDecimals = 6;
|
|
43
42
|
let state, mint, relayerTA, recipientTA, otherRelayerTA, tokenProgram;
|
|
44
43
|
const relayAmount = 500000;
|
|
@@ -46,7 +45,7 @@ describe("svm_spoke.fill", () => {
|
|
|
46
45
|
let accounts; // Store accounts to simplify contract interactions.
|
|
47
46
|
function updateRelayData(newRelayData) {
|
|
48
47
|
relayData = newRelayData;
|
|
49
|
-
const relayHashUint8Array = (0,
|
|
48
|
+
const relayHashUint8Array = (0, svm_1.calculateRelayHashUint8Array)(relayData, chainId);
|
|
50
49
|
const [fillStatusPDA] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("fills"), relayHashUint8Array], program.programId);
|
|
51
50
|
accounts = {
|
|
52
51
|
state,
|
|
@@ -71,7 +70,8 @@ describe("svm_spoke.fill", () => {
|
|
|
71
70
|
.remainingAccounts(fillRemainingAccounts)
|
|
72
71
|
.instruction();
|
|
73
72
|
const fillTx = new web3_js_1.Transaction().add(approveIx, fillIx);
|
|
74
|
-
await (0, web3_js_1.sendAndConfirmTransaction)(connection, fillTx, [payer, callingRelayer]);
|
|
73
|
+
const tx = await (0, web3_js_1.sendAndConfirmTransaction)(connection, fillTx, [payer, callingRelayer]);
|
|
74
|
+
return tx;
|
|
75
75
|
};
|
|
76
76
|
before("Funds relayer wallets", async () => {
|
|
77
77
|
await connection.requestAirdrop(relayer.publicKey, 10_000_000_000); // 10 SOL
|
|
@@ -99,7 +99,7 @@ describe("svm_spoke.fill", () => {
|
|
|
99
99
|
inputAmount: new anchor_1.BN(relayAmount),
|
|
100
100
|
outputAmount: new anchor_1.BN(relayAmount),
|
|
101
101
|
originChainId: new anchor_1.BN(1),
|
|
102
|
-
depositId: (0,
|
|
102
|
+
depositId: (0, svm_1.intToU8Array32)(Math.floor(Math.random() * 1000000)), // force that we always have a new deposit id.
|
|
103
103
|
fillDeadline: Math.floor(Date.now() / 1000) + 60, // 1 minute from now
|
|
104
104
|
exclusivityDeadline: Math.floor(Date.now() / 1000) + 30, // 30 seconds from now
|
|
105
105
|
message: encodedMessage,
|
|
@@ -113,7 +113,7 @@ describe("svm_spoke.fill", () => {
|
|
|
113
113
|
// Verify relayer's balance before the 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
|
-
const relayHash = Array.from((0,
|
|
116
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
117
117
|
await approvedFillV3Relay([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);
|
|
@@ -123,24 +123,23 @@ describe("svm_spoke.fill", () => {
|
|
|
123
123
|
assertSE(recipientAccount.amount, relayAmount, "Recipient's balance should be increased by the relay amount");
|
|
124
124
|
});
|
|
125
125
|
it("Verifies FilledV3Relay event after filling a relay", async () => {
|
|
126
|
-
const relayHash = Array.from((0,
|
|
127
|
-
await approvedFillV3Relay([relayHash, relayData, new anchor_1.BN(420), otherRelayer.publicKey]);
|
|
126
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
127
|
+
const tx = await approvedFillV3Relay([relayHash, relayData, new anchor_1.BN(420), otherRelayer.publicKey]);
|
|
128
128
|
// Fetch and verify the FilledV3Relay event
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
const event = events.find((event) => event.name === "filledV3Relay").data;
|
|
129
|
+
const events = await (0, svm_1.readEventsUntilFound)(connection, tx, [program]);
|
|
130
|
+
const event = events.find((event) => event.name === "filledV3Relay")?.data;
|
|
132
131
|
assert.isNotNull(event, "FilledV3Relay event should be emitted");
|
|
133
132
|
// Verify that the event data matches the relay data.
|
|
134
133
|
Object.entries(relayData).forEach(([key, value]) => {
|
|
135
134
|
if (key === "message") {
|
|
136
|
-
assertSE(event.messageHash, (0,
|
|
135
|
+
assertSE(event.messageHash, (0, svm_1.hashNonEmptyMessage)(value), `MessageHash should match`);
|
|
137
136
|
}
|
|
138
137
|
else
|
|
139
138
|
assertSE(event[key], value, `${key.charAt(0).toUpperCase() + key.slice(1)} should match`);
|
|
140
139
|
});
|
|
141
140
|
// RelayExecutionInfo should match.
|
|
142
141
|
assertSE(event.relayExecutionInfo.updatedRecipient, relayData.recipient, "UpdatedRecipient should match");
|
|
143
|
-
assertSE(event.relayExecutionInfo.updatedMessageHash, (0,
|
|
142
|
+
assertSE(event.relayExecutionInfo.updatedMessageHash, (0, svm_1.hashNonEmptyMessage)(relayData.message), "UpdatedMessageHash should match");
|
|
144
143
|
assertSE(event.relayExecutionInfo.updatedOutputAmount, relayData.outputAmount, "UpdatedOutputAmount should match");
|
|
145
144
|
assert.equal(JSON.stringify(event.relayExecutionInfo.fillType), `{"fastFill":{}}`, "FillType should be FastFill");
|
|
146
145
|
// These props below are not part of relayData.
|
|
@@ -149,7 +148,7 @@ describe("svm_spoke.fill", () => {
|
|
|
149
148
|
});
|
|
150
149
|
it("Fails to fill a V3 relay after the fill deadline", async () => {
|
|
151
150
|
updateRelayData({ ...relayData, fillDeadline: Math.floor(Date.now() / 1000) - 69 }); // 69 seconds ago
|
|
152
|
-
const relayHash = Array.from((0,
|
|
151
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
153
152
|
try {
|
|
154
153
|
await approvedFillV3Relay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
155
154
|
assert.fail("Fill should have failed due to fill deadline passed");
|
|
@@ -161,7 +160,7 @@ describe("svm_spoke.fill", () => {
|
|
|
161
160
|
it("Fails to fill a V3 relay by non-exclusive relayer before exclusivity deadline", async () => {
|
|
162
161
|
accounts.signer = otherRelayer.publicKey;
|
|
163
162
|
accounts.relayerTokenAccount = otherRelayerTA;
|
|
164
|
-
const relayHash = Array.from((0,
|
|
163
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
165
164
|
try {
|
|
166
165
|
await approvedFillV3Relay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey], undefined, otherRelayer);
|
|
167
166
|
assert.fail("Fill should have failed due to non-exclusive relayer before exclusivity deadline");
|
|
@@ -176,7 +175,7 @@ describe("svm_spoke.fill", () => {
|
|
|
176
175
|
accounts.relayerTokenAccount = otherRelayerTA;
|
|
177
176
|
const recipientAccountBefore = await (0, spl_token_1.getAccount)(connection, recipientTA);
|
|
178
177
|
const relayerAccountBefore = await (0, spl_token_1.getAccount)(connection, otherRelayerTA);
|
|
179
|
-
const relayHash = Array.from((0,
|
|
178
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
180
179
|
await approvedFillV3Relay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey], undefined, otherRelayer);
|
|
181
180
|
// Verify relayer's balance after the fill
|
|
182
181
|
const relayerAccountAfter = await (0, spl_token_1.getAccount)(connection, otherRelayerTA);
|
|
@@ -186,7 +185,7 @@ describe("svm_spoke.fill", () => {
|
|
|
186
185
|
assertSE(recipientAccountAfter.amount, BigInt(recipientAccountBefore.amount) + BigInt(relayAmount), "Recipient's balance should be increased by the relay amount");
|
|
187
186
|
});
|
|
188
187
|
it("Fails to fill a V3 relay with the same deposit data multiple times", async () => {
|
|
189
|
-
const relayHash = Array.from((0,
|
|
188
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
190
189
|
// First fill attempt
|
|
191
190
|
await approvedFillV3Relay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
192
191
|
// Second fill attempt with the same data
|
|
@@ -199,7 +198,7 @@ describe("svm_spoke.fill", () => {
|
|
|
199
198
|
}
|
|
200
199
|
});
|
|
201
200
|
it("Closes the fill PDA after the fill", async () => {
|
|
202
|
-
const relayHash = Array.from((0,
|
|
201
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
203
202
|
const closeFillPdaAccounts = {
|
|
204
203
|
state,
|
|
205
204
|
signer: relayer.publicKey,
|
|
@@ -213,7 +212,7 @@ describe("svm_spoke.fill", () => {
|
|
|
213
212
|
assert.isNotNull(fillStatusAccountBefore, "Fill PDA should exist before closing");
|
|
214
213
|
// Attempt to close the fill PDA before the fill deadline should fail.
|
|
215
214
|
try {
|
|
216
|
-
await program.methods.closeFillPda(
|
|
215
|
+
await program.methods.closeFillPda().accounts(closeFillPdaAccounts).signers([relayer]).rpc();
|
|
217
216
|
assert.fail("Closing fill PDA should have failed before fill deadline");
|
|
218
217
|
}
|
|
219
218
|
catch (err) {
|
|
@@ -222,13 +221,13 @@ describe("svm_spoke.fill", () => {
|
|
|
222
221
|
// Set the current time to past the fill deadline
|
|
223
222
|
await setCurrentTime(program, state, relayer, new anchor_1.BN(relayData.fillDeadline + 1));
|
|
224
223
|
// Close the fill PDA
|
|
225
|
-
await program.methods.closeFillPda(
|
|
224
|
+
await program.methods.closeFillPda().accounts(closeFillPdaAccounts).signers([relayer]).rpc();
|
|
226
225
|
// Verify the fill PDA is closed
|
|
227
226
|
const fillStatusAccountAfter = await connection.getAccountInfo(accounts.fillStatus);
|
|
228
227
|
assert.isNull(fillStatusAccountAfter, "Fill PDA should be closed after closing");
|
|
229
228
|
});
|
|
230
229
|
it("Fetches FillStatusAccount before and after fillV3Relay", async () => {
|
|
231
|
-
const relayHash = (0,
|
|
230
|
+
const relayHash = (0, svm_1.calculateRelayHashUint8Array)(relayData, chainId);
|
|
232
231
|
const [fillStatusPDA] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("fills"), relayHash], program.programId);
|
|
233
232
|
// Fetch FillStatusAccount before fillV3Relay
|
|
234
233
|
let fillStatusAccount = await program.account.fillStatusAccount.fetchNullable(fillStatusPDA);
|
|
@@ -248,7 +247,7 @@ describe("svm_spoke.fill", () => {
|
|
|
248
247
|
const stateAccountData = await program.account.state.fetch(state);
|
|
249
248
|
assert.isTrue(stateAccountData.pausedFills, "Fills should be paused");
|
|
250
249
|
// Try to fill the relay. This should fail because fills are paused.
|
|
251
|
-
const relayHash = Array.from((0,
|
|
250
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
252
251
|
try {
|
|
253
252
|
await approvedFillV3Relay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
254
253
|
assert.fail("Should not be able to fill relay when fills are paused");
|
|
@@ -258,7 +257,7 @@ describe("svm_spoke.fill", () => {
|
|
|
258
257
|
}
|
|
259
258
|
});
|
|
260
259
|
it("Fails to fill a relay to wrong recipient token account", async () => {
|
|
261
|
-
const relayHash = (0,
|
|
260
|
+
const relayHash = (0, svm_1.calculateRelayHashUint8Array)(relayData, chainId);
|
|
262
261
|
// Create new accounts as derived from wrong recipient.
|
|
263
262
|
const wrongRecipient = web3_js_1.Keypair.generate().publicKey;
|
|
264
263
|
const wrongRecipientTA = (await (0, spl_token_1.getOrCreateAssociatedTokenAccount)(connection, payer, mint, wrongRecipient)).address;
|
|
@@ -276,7 +275,7 @@ describe("svm_spoke.fill", () => {
|
|
|
276
275
|
}
|
|
277
276
|
});
|
|
278
277
|
it("Fails to fill a relay for mint inconsistent output_token", async () => {
|
|
279
|
-
const relayHash = (0,
|
|
278
|
+
const relayHash = (0, svm_1.calculateRelayHashUint8Array)(relayData, chainId);
|
|
280
279
|
// Create and fund new accounts as derived from wrong mint account.
|
|
281
280
|
const wrongMint = await (0, spl_token_1.createMint)(connection, payer, owner, owner, tokenDecimals);
|
|
282
281
|
const wrongRecipientTA = (await (0, spl_token_1.getOrCreateAssociatedTokenAccount)(connection, payer, wrongMint, recipient)).address;
|
|
@@ -302,7 +301,7 @@ describe("svm_spoke.fill", () => {
|
|
|
302
301
|
accounts.recipientTokenAccount = relayerTA;
|
|
303
302
|
// Store relayer's balance before the fill
|
|
304
303
|
const iRelayerBalance = (await (0, spl_token_1.getAccount)(connection, relayerTA)).amount;
|
|
305
|
-
const relayHash = Array.from((0,
|
|
304
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
306
305
|
// No need for approval in self-relay.
|
|
307
306
|
const txSignature = await program.methods
|
|
308
307
|
.fillV3Relay(relayHash, relayData, new anchor_1.BN(1), relayer.publicKey)
|
|
@@ -334,7 +333,7 @@ describe("svm_spoke.fill", () => {
|
|
|
334
333
|
const iRecipientBal = (await (0, spl_token_1.getAccount)(connection, recipientTA)).amount;
|
|
335
334
|
// Fill relay from custom relayer token account
|
|
336
335
|
accounts.relayerTokenAccount = customRelayerTA;
|
|
337
|
-
const relayHash = Array.from((0,
|
|
336
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
338
337
|
await approvedFillV3Relay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
339
338
|
// Verify balances after the fill
|
|
340
339
|
const fRelayerBal = (await (0, spl_token_1.getAccount)(connection, customRelayerTA)).amount;
|
|
@@ -350,11 +349,11 @@ describe("svm_spoke.fill", () => {
|
|
|
350
349
|
const newRelayData = {
|
|
351
350
|
...relayData,
|
|
352
351
|
recipient: newRecipient,
|
|
353
|
-
depositId: (0,
|
|
352
|
+
depositId: (0, svm_1.intToU8Array32)(Math.floor(Math.random() * 1000000)),
|
|
354
353
|
};
|
|
355
354
|
updateRelayData(newRelayData);
|
|
356
355
|
accounts.recipientTokenAccount = newRecipientATA;
|
|
357
|
-
const relayHash = Array.from((0,
|
|
356
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(newRelayData, chainId));
|
|
358
357
|
try {
|
|
359
358
|
await approvedFillV3Relay([relayHash, newRelayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
360
359
|
assert.fail("Fill should have failed due to missing ATA");
|
|
@@ -409,12 +408,12 @@ describe("svm_spoke.fill", () => {
|
|
|
409
408
|
const newRelayData = {
|
|
410
409
|
...relayData,
|
|
411
410
|
recipient: recipientAuthorities[i],
|
|
412
|
-
depositId: (0,
|
|
411
|
+
depositId: (0, svm_1.intToU8Array32)(Math.floor(Math.random() * 1000000)),
|
|
413
412
|
};
|
|
414
413
|
totalFillAmount = totalFillAmount.add(newRelayData.outputAmount);
|
|
415
414
|
updateRelayData(newRelayData);
|
|
416
415
|
accounts.recipientTokenAccount = recipientAssociatedTokens[i];
|
|
417
|
-
const relayHash = Array.from((0,
|
|
416
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(newRelayData, chainId));
|
|
418
417
|
const fillInstruction = await program.methods
|
|
419
418
|
.fillV3Relay(relayHash, newRelayData, new anchor_1.BN(1), relayer.publicKey)
|
|
420
419
|
.accounts(accounts)
|
|
@@ -424,9 +423,9 @@ describe("svm_spoke.fill", () => {
|
|
|
424
423
|
}
|
|
425
424
|
const approveInstruction = await (0, spl_token_1.createApproveCheckedInstruction)(accounts.relayerTokenAccount, accounts.mint, accounts.state, accounts.signer, BigInt(totalFillAmount.toString()), tokenDecimals, undefined, tokenProgram);
|
|
426
425
|
// Fill using the ALT.
|
|
427
|
-
await (0,
|
|
426
|
+
await (0, svm_1.sendTransactionWithLookupTable)(connection, [createTokenAccountsInstruction, approveInstruction, ...fillInstructions], relayer);
|
|
428
427
|
// Verify balances after the fill
|
|
429
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
428
|
+
await new Promise((resolve) => setTimeout(resolve, 500)); // Wait for tx processing
|
|
430
429
|
const fRelayerBal = (await (0, spl_token_1.getAccount)(connection, relayerTA)).amount;
|
|
431
430
|
assertSE(fRelayerBal, iRelayerBal - BigInt(relayAmount * numberOfFills), "Relayer's balance should be reduced by total relay amount");
|
|
432
431
|
recipientAssociatedTokens.forEach(async (recipientAssociatedToken) => {
|
|
@@ -454,7 +453,7 @@ describe("svm_spoke.fill", () => {
|
|
|
454
453
|
// Verify relayer's balance before the fill
|
|
455
454
|
let relayerAccount = await (0, spl_token_1.getAccount)(connection, relayerTA, undefined, tokenProgram);
|
|
456
455
|
assertSE(relayerAccount.amount, seedBalance, "Relayer's balance should be equal to seed balance before the fill");
|
|
457
|
-
const relayHash = Array.from((0,
|
|
456
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
458
457
|
await approvedFillV3Relay([relayHash, relayData, new anchor_1.BN(1), relayer.publicKey]);
|
|
459
458
|
// Verify relayer's balance after the fill
|
|
460
459
|
relayerAccount = await (0, spl_token_1.getAccount)(connection, relayerTA, undefined, tokenProgram);
|
|
@@ -465,12 +464,11 @@ describe("svm_spoke.fill", () => {
|
|
|
465
464
|
});
|
|
466
465
|
it("Emits zeroed hash for empty message", async () => {
|
|
467
466
|
updateRelayData({ ...relayData, message: Buffer.alloc(0) });
|
|
468
|
-
const relayHash = Array.from((0,
|
|
469
|
-
await approvedFillV3Relay([relayHash, relayData, new anchor_1.BN(420), otherRelayer.publicKey]);
|
|
467
|
+
const relayHash = Array.from((0, svm_1.calculateRelayHashUint8Array)(relayData, chainId));
|
|
468
|
+
const tx = await approvedFillV3Relay([relayHash, relayData, new anchor_1.BN(420), otherRelayer.publicKey]);
|
|
470
469
|
// Fetch and verify the FilledV3Relay event
|
|
471
|
-
|
|
472
|
-
const
|
|
473
|
-
const event = events.find((event) => event.name === "filledV3Relay").data;
|
|
470
|
+
const events = await (0, svm_1.readEventsUntilFound)(connection, tx, [program]);
|
|
471
|
+
const event = events.find((event) => event.name === "filledV3Relay")?.data;
|
|
474
472
|
assert.isNotNull(event, "FilledV3Relay event should be emitted");
|
|
475
473
|
// Verify that the event data has zeroed message hash.
|
|
476
474
|
assertSE(event.messageHash, new Uint8Array(32), `MessageHash should be zeroed`);
|
|
@@ -30,7 +30,7 @@ const spl_token_1 = require("@solana/spl-token");
|
|
|
30
30
|
const web3_js_1 = require("@solana/web3.js");
|
|
31
31
|
const chai_1 = require("chai");
|
|
32
32
|
const ethers_1 = require("ethers");
|
|
33
|
-
const
|
|
33
|
+
const svm_1 = require("../../src/svm");
|
|
34
34
|
const cctpHelpers_1 = require("./cctpHelpers");
|
|
35
35
|
const SvmSpoke_common_1 = require("./SvmSpoke.common");
|
|
36
36
|
const { createRoutePda, getVaultAta, initializeState, crossDomainAdmin, remoteDomain, localDomain } = SvmSpoke_common_1.common;
|
|
@@ -262,7 +262,7 @@ describe("svm_spoke.handle_receive_message", () => {
|
|
|
262
262
|
});
|
|
263
263
|
it("Sets cross-domain admin remotely", async () => {
|
|
264
264
|
const newCrossDomainAdminAddress = ethers_1.ethers.Wallet.createRandom().address;
|
|
265
|
-
const newCrossDomainAdminPubkey = (0,
|
|
265
|
+
const newCrossDomainAdminPubkey = (0, svm_1.evmAddressToPublicKey)(newCrossDomainAdminAddress);
|
|
266
266
|
let calldata = ethereumIface.encodeFunctionData("setCrossDomainAdmin", [newCrossDomainAdminAddress]);
|
|
267
267
|
let messageBody = Buffer.from(calldata.slice(2), "hex");
|
|
268
268
|
let message = (0, cctpHelpers_1.encodeMessageHeader)({
|
|
@@ -28,7 +28,7 @@ const anchor_1 = require("@coral-xyz/anchor");
|
|
|
28
28
|
const web3_js_1 = require("@solana/web3.js");
|
|
29
29
|
const chai_1 = require("chai");
|
|
30
30
|
const SvmSpoke_common_1 = require("./SvmSpoke.common");
|
|
31
|
-
const
|
|
31
|
+
const svm_1 = require("../../src/svm");
|
|
32
32
|
const { provider, program, owner, initializeState, crossDomainAdmin, assertSE } = SvmSpoke_common_1.common;
|
|
33
33
|
describe("svm_spoke.ownership", () => {
|
|
34
34
|
anchor.setProvider(provider);
|
|
@@ -62,23 +62,21 @@ describe("svm_spoke.ownership", () => {
|
|
|
62
62
|
chai_1.assert.isFalse((await program.account.state.fetch(state)).pausedDeposits, "Deposits should not be paused");
|
|
63
63
|
// Pause deposits as owner
|
|
64
64
|
const pauseDepositsAccounts = { state, signer: owner, program: program.programId };
|
|
65
|
-
await program.methods.pauseDeposits(true).accounts(pauseDepositsAccounts).rpc();
|
|
66
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
65
|
+
const tx = await program.methods.pauseDeposits(true).accounts(pauseDepositsAccounts).rpc();
|
|
67
66
|
// Fetch the updated state
|
|
68
67
|
let stateAccountData = await program.account.state.fetch(state);
|
|
69
68
|
chai_1.assert.isTrue(stateAccountData.pausedDeposits, "Deposits should be paused");
|
|
70
69
|
// Verify the PausedDeposits event
|
|
71
|
-
let events = await (0,
|
|
70
|
+
let events = await (0, svm_1.readEventsUntilFound)(provider.connection, tx, [program]);
|
|
72
71
|
let pausedDepositEvents = events.filter((event) => event.name === "pausedDeposits");
|
|
73
72
|
chai_1.assert.isTrue(pausedDepositEvents[0].data.isPaused, "PausedDeposits event should indicate deposits are paused");
|
|
74
73
|
// Unpause deposits as owner
|
|
75
|
-
await program.methods.pauseDeposits(false).accounts(pauseDepositsAccounts).rpc();
|
|
76
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
74
|
+
const tx2 = await program.methods.pauseDeposits(false).accounts(pauseDepositsAccounts).rpc();
|
|
77
75
|
// Fetch the updated state
|
|
78
76
|
stateAccountData = await program.account.state.fetch(state);
|
|
79
77
|
chai_1.assert.isFalse(stateAccountData.pausedDeposits, "Deposits should not be paused");
|
|
80
78
|
// Verify the PausedDeposits event
|
|
81
|
-
events = await (0,
|
|
79
|
+
events = await (0, svm_1.readEventsUntilFound)(provider.connection, tx2, [program]);
|
|
82
80
|
pausedDepositEvents = events.filter((event) => event.name === "pausedDeposits");
|
|
83
81
|
chai_1.assert.isFalse(pausedDepositEvents[0].data.isPaused, "PausedDeposits event should indicate deposits are unpaused");
|
|
84
82
|
// Try to pause deposits as non-owner
|
|
@@ -95,23 +93,21 @@ describe("svm_spoke.ownership", () => {
|
|
|
95
93
|
chai_1.assert.isFalse((await program.account.state.fetch(state)).pausedFills, "Fills should not be paused");
|
|
96
94
|
// Pause fills as owner
|
|
97
95
|
const pauseFillsAccounts = { state, signer: owner, program: program.programId };
|
|
98
|
-
await program.methods.pauseFills(true).accounts(pauseFillsAccounts).rpc();
|
|
99
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
96
|
+
const tx = await program.methods.pauseFills(true).accounts(pauseFillsAccounts).rpc();
|
|
100
97
|
// Fetch the updated state
|
|
101
98
|
let stateAccountData = await program.account.state.fetch(state);
|
|
102
99
|
chai_1.assert.isTrue(stateAccountData.pausedFills, "Fills should be paused");
|
|
103
100
|
// Verify the PausedFills event
|
|
104
|
-
let events = await (0,
|
|
101
|
+
let events = await (0, svm_1.readEventsUntilFound)(provider.connection, tx, [program]);
|
|
105
102
|
let pausedFillEvents = events.filter((event) => event.name === "pausedFills");
|
|
106
103
|
chai_1.assert.isTrue(pausedFillEvents[0].data.isPaused, "PausedFills event should indicate fills are paused");
|
|
107
104
|
// Unpause fills as owner
|
|
108
|
-
await program.methods.pauseFills(false).accounts(pauseFillsAccounts).rpc();
|
|
109
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
105
|
+
const tx2 = await program.methods.pauseFills(false).accounts(pauseFillsAccounts).rpc();
|
|
110
106
|
// Fetch the updated state
|
|
111
107
|
stateAccountData = await program.account.state.fetch(state);
|
|
112
108
|
chai_1.assert.isFalse(stateAccountData.pausedFills, "Fills should not be paused");
|
|
113
109
|
// Verify the PausedFills event
|
|
114
|
-
events = await (0,
|
|
110
|
+
events = await (0, svm_1.readEventsUntilFound)(provider.connection, tx2, [program]);
|
|
115
111
|
pausedFillEvents = events.filter((event) => event.name === "pausedFills");
|
|
116
112
|
chai_1.assert.isFalse(pausedFillEvents[0].data.isPaused, "PausedFills event should indicate fills are unpaused");
|
|
117
113
|
// Try to pause fills as non-owner
|
|
@@ -128,7 +124,6 @@ describe("svm_spoke.ownership", () => {
|
|
|
128
124
|
// Transfer ownership to newOwner
|
|
129
125
|
const transferOwnershipAccounts = { state, signer: owner };
|
|
130
126
|
await program.methods.transferOwnership(newOwner.publicKey).accounts(transferOwnershipAccounts).rpc();
|
|
131
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
132
127
|
// Verify the new owner
|
|
133
128
|
let stateAccountData = await program.account.state.fetch(state);
|
|
134
129
|
chai_1.assert.equal(stateAccountData.owner.toString(), newOwner.publicKey.toString(), "Ownership should be transferred");
|
|
@@ -149,16 +144,15 @@ describe("svm_spoke.ownership", () => {
|
|
|
149
144
|
it("Sets cross-domain admin", async () => {
|
|
150
145
|
// Set cross-domain admin as owner
|
|
151
146
|
const setCrossDomainAdminAccounts = { state, signer: owner, program: program.programId };
|
|
152
|
-
await program.methods
|
|
147
|
+
const tx = await program.methods
|
|
153
148
|
.setCrossDomainAdmin(newCrossDomainAdmin.publicKey)
|
|
154
149
|
.accounts(setCrossDomainAdminAccounts)
|
|
155
150
|
.rpc();
|
|
156
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
157
151
|
// Verify the new cross-domain admin
|
|
158
152
|
let stateAccountData = await program.account.state.fetch(state);
|
|
159
153
|
chai_1.assert.equal(stateAccountData.crossDomainAdmin.toString(), newCrossDomainAdmin.publicKey.toString(), "Cross-domain admin should be set");
|
|
160
154
|
// Verify the SetXDomainAdmin event
|
|
161
|
-
let events = await (0,
|
|
155
|
+
let events = await (0, svm_1.readEventsUntilFound)(provider.connection, tx, [program]);
|
|
162
156
|
let setXDomainAdminEvents = events.filter((event) => event.name === "setXDomainAdmin");
|
|
163
157
|
chai_1.assert.equal(setXDomainAdminEvents[0].data.newAdmin.toString(), newCrossDomainAdmin.publicKey.toString(), "SetXDomainAdmin event should indicate the new admin");
|
|
164
158
|
// Try to set cross-domain admin as non-owner
|
|
@@ -30,7 +30,7 @@ const chai_1 = require("chai");
|
|
|
30
30
|
const SvmSpoke_common_1 = require("./SvmSpoke.common");
|
|
31
31
|
const MerkleTree_1 = require("@uma/common/dist/MerkleTree");
|
|
32
32
|
const spl_token_1 = require("@solana/spl-token");
|
|
33
|
-
const
|
|
33
|
+
const svm_1 = require("../../src/svm");
|
|
34
34
|
const { provider, program, owner, initializeState, connection, chainId, assertSE } = SvmSpoke_common_1.common;
|
|
35
35
|
describe("svm_spoke.refund_claims", () => {
|
|
36
36
|
anchor.setProvider(provider);
|
|
@@ -69,7 +69,7 @@ describe("svm_spoke.refund_claims", () => {
|
|
|
69
69
|
refundAddresses: [relayer.publicKey],
|
|
70
70
|
refundAmounts: [relayerRefund],
|
|
71
71
|
});
|
|
72
|
-
const merkleTree = new MerkleTree_1.MerkleTree(relayerRefundLeaves,
|
|
72
|
+
const merkleTree = new MerkleTree_1.MerkleTree(relayerRefundLeaves, svm_1.relayerRefundHashFn);
|
|
73
73
|
const root = merkleTree.getRoot();
|
|
74
74
|
const proof = merkleTree.getProof(relayerRefundLeaves[0]);
|
|
75
75
|
const leaf = relayerRefundLeaves[0];
|
|
@@ -99,7 +99,7 @@ describe("svm_spoke.refund_claims", () => {
|
|
|
99
99
|
program: program.programId,
|
|
100
100
|
};
|
|
101
101
|
const proofAsNumbers = proof.map((p) => Array.from(p));
|
|
102
|
-
await (0,
|
|
102
|
+
await (0, svm_1.loadExecuteRelayerRefundLeafParams)(program, owner, stateAccountData.rootBundleId, leaf, proofAsNumbers);
|
|
103
103
|
await program.methods
|
|
104
104
|
.executeRelayerRefundLeafDeferred()
|
|
105
105
|
.accounts(executeRelayerRefundLeafAccounts)
|
|
@@ -142,16 +142,18 @@ describe("svm_spoke.refund_claims", () => {
|
|
|
142
142
|
const iVaultBal = (await connection.getTokenAccountBalance(vault)).value.amount;
|
|
143
143
|
const iRelayerBal = (await connection.getTokenAccountBalance(tokenAccount)).value.amount;
|
|
144
144
|
// Claim refund for the relayer.
|
|
145
|
-
await program.methods
|
|
145
|
+
const tx = await program.methods
|
|
146
|
+
.claimRelayerRefundFor(relayer.publicKey)
|
|
147
|
+
.accounts(claimRelayerRefundAccounts)
|
|
148
|
+
.rpc();
|
|
146
149
|
// The relayer should have received funds from the vault.
|
|
147
150
|
const fVaultBal = (await connection.getTokenAccountBalance(vault)).value.amount;
|
|
148
151
|
const fRelayerBal = (await connection.getTokenAccountBalance(tokenAccount)).value.amount;
|
|
149
152
|
assertSE(BigInt(iVaultBal) - BigInt(fVaultBal), relayerRefund, "Vault balance");
|
|
150
153
|
assertSE(BigInt(fRelayerBal) - BigInt(iRelayerBal), relayerRefund, "Relayer balance");
|
|
151
154
|
// Verify the ClaimedRelayerRefund event
|
|
152
|
-
|
|
153
|
-
const
|
|
154
|
-
const event = events.find((event) => event.name === "claimedRelayerRefund").data;
|
|
155
|
+
const events = await (0, svm_1.readEventsUntilFound)(connection, tx, [program]);
|
|
156
|
+
const event = events.find((event) => event.name === "claimedRelayerRefund")?.data;
|
|
155
157
|
assertSE(event.l2TokenAddress, mint, "l2TokenAddress should match");
|
|
156
158
|
assertSE(event.claimAmount, relayerRefund, "Relayer refund amount should match");
|
|
157
159
|
assertSE(event.refundAddress, relayer.publicKey, "Relayer refund address should match");
|
|
@@ -300,16 +302,15 @@ describe("svm_spoke.refund_claims", () => {
|
|
|
300
302
|
claimRelayerRefundAccounts.tokenAccount = customTokenAccount;
|
|
301
303
|
claimRelayerRefundAccounts.signer = relayer.publicKey; // Only relayer itself should be able to do this.
|
|
302
304
|
// Relayer can claim refund to custom token account.
|
|
303
|
-
await program.methods.claimRelayerRefund().accounts(claimRelayerRefundAccounts).signers([relayer]).rpc();
|
|
305
|
+
const tx = await program.methods.claimRelayerRefund().accounts(claimRelayerRefundAccounts).signers([relayer]).rpc();
|
|
304
306
|
// The relayer should have received funds from the vault.
|
|
305
307
|
const fVaultBal = (await connection.getTokenAccountBalance(vault)).value.amount;
|
|
306
308
|
const fRelayerBal = (await connection.getTokenAccountBalance(customTokenAccount)).value.amount;
|
|
307
309
|
assertSE(BigInt(iVaultBal) - BigInt(fVaultBal), relayerRefund, "Vault balance");
|
|
308
310
|
assertSE(BigInt(fRelayerBal) - BigInt(iRelayerBal), relayerRefund, "Relayer balance");
|
|
309
311
|
// Verify the ClaimedRelayerRefund event
|
|
310
|
-
|
|
311
|
-
const
|
|
312
|
-
const event = events.find((event) => event.name === "claimedRelayerRefund").data;
|
|
312
|
+
const events = await (0, svm_1.readEventsUntilFound)(connection, tx, [program]);
|
|
313
|
+
const event = events.find((event) => event.name === "claimedRelayerRefund")?.data;
|
|
313
314
|
assertSE(event.l2TokenAddress, mint, "l2TokenAddress should match");
|
|
314
315
|
assertSE(event.claimAmount, relayerRefund, "Relayer refund amount should match");
|
|
315
316
|
assertSE(event.refundAddress, relayer.publicKey, "Relayer refund address should match");
|
|
@@ -29,7 +29,7 @@ const spl_token_1 = require("@solana/spl-token");
|
|
|
29
29
|
const web3_js_1 = require("@solana/web3.js");
|
|
30
30
|
const chai_1 = require("chai");
|
|
31
31
|
const SvmSpoke_common_1 = require("./SvmSpoke.common");
|
|
32
|
-
const
|
|
32
|
+
const svm_1 = require("../../src/svm");
|
|
33
33
|
const { provider, program, owner, initializeState, createRoutePda, getVaultAta } = SvmSpoke_common_1.common;
|
|
34
34
|
describe("svm_spoke.routes", () => {
|
|
35
35
|
anchor.setProvider(provider);
|
|
@@ -60,25 +60,29 @@ describe("svm_spoke.routes", () => {
|
|
|
60
60
|
});
|
|
61
61
|
it("Sets, retrieves, and controls access to route enablement", async () => {
|
|
62
62
|
// Enable the route as owner
|
|
63
|
-
await program.methods
|
|
64
|
-
|
|
63
|
+
const tx = await program.methods
|
|
64
|
+
.setEnableRoute(tokenMint, routeChainId, true)
|
|
65
|
+
.accounts(setEnableRouteAccounts)
|
|
66
|
+
.rpc();
|
|
65
67
|
// Retrieve and verify the route is enabled
|
|
66
68
|
let routeAccount = await program.account.route.fetch(routePda);
|
|
67
69
|
chai_1.assert.isTrue(routeAccount.enabled, "Route should be enabled");
|
|
68
70
|
// Verify the enabledDepositRoute event
|
|
69
|
-
let events =
|
|
71
|
+
let events = await (0, svm_1.readEventsUntilFound)(provider.connection, tx, [program]);
|
|
70
72
|
let event = events[0].data;
|
|
71
73
|
chai_1.assert.strictEqual(event.originToken.toString(), tokenMint.toString(), "originToken event match");
|
|
72
74
|
chai_1.assert.strictEqual(event.destinationChainId.toString(), routeChainId.toString(), "destinationChainId should match");
|
|
73
75
|
chai_1.assert.isTrue(event.enabled, "enabledDepositRoute enabled");
|
|
74
76
|
// Disable the route as owner
|
|
75
|
-
await program.methods
|
|
76
|
-
|
|
77
|
+
const tx2 = await program.methods
|
|
78
|
+
.setEnableRoute(tokenMint, routeChainId, false)
|
|
79
|
+
.accounts(setEnableRouteAccounts)
|
|
80
|
+
.rpc();
|
|
77
81
|
// Retrieve and verify the route is disabled
|
|
78
82
|
routeAccount = await program.account.route.fetch(routePda);
|
|
79
83
|
chai_1.assert.isFalse(routeAccount.enabled, "Route should be disabled");
|
|
80
84
|
// Verify the enabledDepositRoute event
|
|
81
|
-
events =
|
|
85
|
+
events = await (0, svm_1.readEventsUntilFound)(provider.connection, tx2, [program]);
|
|
82
86
|
event = events[0].data; // take most recent event, index 0.
|
|
83
87
|
chai_1.assert.strictEqual(event.originToken.toString(), tokenMint.toString(), "originToken event match");
|
|
84
88
|
chai_1.assert.strictEqual(event.destinationChainId.toString(), routeChainId.toString(), "destinationChainId should match");
|