@across-protocol/contracts 3.0.17 → 3.0.18

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.
Files changed (52) hide show
  1. package/dist/scripts/svm/addressToPublicKey.d.ts +1 -0
  2. package/dist/scripts/svm/addressToPublicKey.js +20 -0
  3. package/dist/scripts/svm/bridgeLiabilityToHubPool.d.ts +28 -0
  4. package/dist/scripts/svm/bridgeLiabilityToHubPool.js +231 -0
  5. package/dist/scripts/svm/closeRelayerPdas.js +6 -7
  6. package/dist/scripts/svm/enableRoute.js +7 -1
  7. package/dist/scripts/svm/executeRebalanceToHubPool.d.ts +32 -0
  8. package/dist/scripts/svm/executeRebalanceToHubPool.js +355 -0
  9. package/dist/scripts/svm/executeRebalanceToSpokePool.d.ts +1 -0
  10. package/dist/scripts/svm/executeRebalanceToSpokePool.js +253 -0
  11. package/dist/scripts/svm/proposeRebalanceToHubPool.d.ts +27 -0
  12. package/dist/scripts/svm/proposeRebalanceToHubPool.js +117 -0
  13. package/dist/scripts/svm/proposeRebalanceToSpokePool.d.ts +1 -0
  14. package/dist/scripts/svm/proposeRebalanceToSpokePool.js +101 -0
  15. package/dist/scripts/svm/publicKeyToAddress.d.ts +1 -0
  16. package/dist/scripts/svm/publicKeyToAddress.js +20 -0
  17. package/dist/scripts/svm/queryDeposits.js +1 -0
  18. package/dist/scripts/svm/queryFills.js +11 -12
  19. package/dist/scripts/svm/queryRoute.js +7 -1
  20. package/dist/scripts/svm/queryState.js +1 -0
  21. package/dist/scripts/svm/remoteHubPoolPauseDeposits.d.ts +1 -0
  22. package/dist/scripts/svm/remoteHubPoolPauseDeposits.js +205 -0
  23. package/dist/scripts/svm/simpleDeposit.js +7 -1
  24. package/dist/scripts/svm/simpleFill.js +5 -4
  25. package/dist/scripts/svm/utils/constants.d.ts +4 -0
  26. package/dist/scripts/svm/utils/constants.js +8 -1
  27. package/dist/scripts/svm/utils/helpers.d.ts +31 -0
  28. package/dist/scripts/svm/utils/helpers.js +50 -1
  29. package/dist/scripts/svm/utils/poolRebalanceTree.d.ts +22 -0
  30. package/dist/scripts/svm/utils/poolRebalanceTree.js +20 -0
  31. package/dist/src/SvmUtils.d.ts +24 -2
  32. package/dist/src/SvmUtils.js +107 -26
  33. package/dist/target/types/svm_spoke.d.ts +47 -42
  34. package/dist/tasks/enableL1TokenAcrossEcosystem.js +3 -33
  35. package/dist/tasks/types.d.ts +2 -0
  36. package/dist/tasks/types.js +2 -0
  37. package/dist/tasks/utils.d.ts +12 -0
  38. package/dist/tasks/utils.js +34 -0
  39. package/dist/test/svm/SvmSpoke.Bundle.js +15 -16
  40. package/dist/test/svm/SvmSpoke.Deposit.js +18 -26
  41. package/dist/test/svm/SvmSpoke.Fill.AcrossPlus.js +1 -1
  42. package/dist/test/svm/SvmSpoke.Fill.js +13 -14
  43. package/dist/test/svm/SvmSpoke.Ownership.js +10 -16
  44. package/dist/test/svm/SvmSpoke.RefundClaims.js +9 -8
  45. package/dist/test/svm/SvmSpoke.Routes.js +10 -6
  46. package/dist/test/svm/SvmSpoke.SlowFill.AcrossPlus.js +59 -2
  47. package/dist/test/svm/SvmSpoke.SlowFill.js +23 -18
  48. package/dist/test/svm/SvmSpoke.TokenBridge.js +3 -5
  49. package/dist/test/svm/SvmSpoke.common.js +2 -1
  50. package/dist/test/svm/utils.d.ts +4 -5
  51. package/dist/test/svm/utils.js +24 -18
  52. package/package.json +2 -2
@@ -31,6 +31,7 @@ const web3_js_1 = require("@solana/web3.js");
31
31
  const SvmSpoke_common_1 = require("./SvmSpoke.common");
32
32
  const MerkleTree_1 = require("@uma/common/dist/MerkleTree");
33
33
  const utils_1 = require("./utils");
34
+ const SvmUtils_1 = require("../../src/SvmUtils");
34
35
  const { provider, connection, program, owner, chainId, seedBalance, initializeState } = SvmSpoke_common_1.common;
35
36
  const { recipient, setCurrentTime, assertSE, assert } = SvmSpoke_common_1.common;
36
37
  describe("svm_spoke.slow_fill", () => {
@@ -163,16 +164,19 @@ describe("svm_spoke.slow_fill", () => {
163
164
  }
164
165
  // Set the contract time to be after the exclusivityDeadline
165
166
  await setCurrentTime(program, state, relayer, new anchor_1.BN(relayData.exclusivityDeadline + 1));
166
- await program.methods.requestV3SlowFill(relayHash, relayData).accounts(requestAccounts).signers([relayer]).rpc();
167
+ const tx = await program.methods
168
+ .requestV3SlowFill(relayHash, relayData)
169
+ .accounts(requestAccounts)
170
+ .signers([relayer])
171
+ .rpc();
167
172
  // Fetch and verify the RequestedV3SlowFill event
168
- await new Promise((resolve) => setTimeout(resolve, 500));
169
- const events = await (0, utils_1.readProgramEvents)(connection, program);
170
- const event = events.find((event) => event.name === "requestedV3SlowFill").data;
173
+ const events = await (0, utils_1.readEventsUntilFound)(connection, tx, [program]);
174
+ const event = events.find((event) => event.name === "requestedV3SlowFill")?.data;
171
175
  assert.isNotNull(event, "RequestedV3SlowFill event should be emitted");
172
176
  // Verify that the event data matches the relay data.
173
177
  Object.entries(relayData).forEach(([key, value]) => {
174
178
  if (key === "message") {
175
- assertSE(event.messageHash, (0, utils_1.hashNonEmptyMessage)(value), `MessageHash should match`);
179
+ assertSE(event.messageHash, (0, SvmUtils_1.hashNonEmptyMessage)(value), `MessageHash should match`);
176
180
  }
177
181
  else
178
182
  assertSE(event[key], value, `${key.charAt(0).toUpperCase() + key.slice(1)} should match`);
@@ -293,28 +297,29 @@ describe("svm_spoke.slow_fill", () => {
293
297
  .remainingAccounts(fillRemainingAccounts)
294
298
  .instruction();
295
299
  const computeBudgetInstruction = web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({ units: 1_400_000 });
296
- await (0, web3_js_1.sendAndConfirmTransaction)(connection, new web3_js_1.Transaction().add(computeBudgetInstruction, ix), [payer]);
300
+ const tx = await (0, web3_js_1.sendAndConfirmTransaction)(connection, new web3_js_1.Transaction().add(computeBudgetInstruction, ix), [
301
+ payer,
302
+ ]);
297
303
  // Verify the results
298
304
  const fVaultBal = (await connection.getTokenAccountBalance(vault)).value.amount;
299
305
  const fRecipientBal = (await connection.getTokenAccountBalance(recipientTA)).value.amount;
300
306
  assert.strictEqual(BigInt(iVaultBal) - BigInt(fVaultBal), BigInt(leaf.updatedOutputAmount.toNumber()), "Vault balance should be reduced by relay amount");
301
307
  assert.strictEqual(BigInt(fRecipientBal) - BigInt(iRecipientBal), BigInt(leaf.updatedOutputAmount.toNumber()), "Recipient balance should be increased by relay amount");
302
308
  // Fetch and verify the FilledV3Relay event
303
- await new Promise((resolve) => setTimeout(resolve, 500));
304
- const events = await (0, utils_1.readProgramEvents)(connection, program);
305
- const event = events.find((event) => event.name === "filledV3Relay").data;
309
+ const events = await (0, utils_1.readEventsUntilFound)(connection, tx, [program]);
310
+ const event = events.find((event) => event.name === "filledV3Relay")?.data;
306
311
  assert.isNotNull(event, "FilledV3Relay event should be emitted");
307
312
  // Verify that the event data matches the relay data.
308
313
  Object.entries(relayData).forEach(([key, value]) => {
309
314
  if (key === "message") {
310
- assertSE(event.messageHash, (0, utils_1.hashNonEmptyMessage)(value), `MessageHash should match`);
315
+ assertSE(event.messageHash, (0, SvmUtils_1.hashNonEmptyMessage)(value), `MessageHash should match`);
311
316
  }
312
317
  else
313
318
  assertSE(event[key], value, `${key.charAt(0).toUpperCase() + key.slice(1)} should match`);
314
319
  });
315
320
  // RelayExecutionInfo should match.
316
321
  assertSE(event.relayExecutionInfo.updatedRecipient, relayData.recipient, "UpdatedRecipient should match");
317
- assertSE(event.relayExecutionInfo.updatedMessageHash, (0, utils_1.hashNonEmptyMessage)(relayData.message), "UpdatedMessageHash should match");
322
+ assertSE(event.relayExecutionInfo.updatedMessageHash, (0, SvmUtils_1.hashNonEmptyMessage)(relayData.message), "UpdatedMessageHash should match");
318
323
  assertSE(event.relayExecutionInfo.updatedOutputAmount, relayData.outputAmount, "UpdatedOutputAmount should match");
319
324
  assert.equal(JSON.stringify(event.relayExecutionInfo.fillType), `{"slowFill":{}}`, "FillType should be SlowFill");
320
325
  // These props below are not part of relayData.
@@ -531,7 +536,7 @@ describe("svm_spoke.slow_fill", () => {
531
536
  // Relay root bundle of slow fill leaf with empty message.
532
537
  const { relayHash, leaf, rootBundleId, proofAsNumbers, rootBundle } = await relaySlowFillRootBundle(undefined, undefined, Buffer.alloc(0));
533
538
  // Request V3 slow fill
534
- await program.methods
539
+ const tx1 = await program.methods
535
540
  .requestV3SlowFill(Array.from(relayHash), leaf.relayData)
536
541
  .accounts(requestAccounts)
537
542
  .signers([relayer])
@@ -549,19 +554,19 @@ describe("svm_spoke.slow_fill", () => {
549
554
  recipientTokenAccount: recipientTA,
550
555
  program: program.programId,
551
556
  };
552
- await program.methods
557
+ const tx2 = await program.methods
553
558
  .executeV3SlowRelayLeaf(Array.from(relayHash), leaf, rootBundleId, proofAsNumbers)
554
559
  .accounts(executeSlowRelayLeafAccounts)
555
560
  .remainingAccounts(fillRemainingAccounts)
556
561
  .rpc();
557
562
  // Fetch and verify message hash in the RequestedV3SlowFill and FilledV3Relay events
558
- await new Promise((resolve) => setTimeout(resolve, 500));
559
- const events = await (0, utils_1.readProgramEvents)(connection, program);
560
- const requestEvent = events.find((event) => event.name === "requestedV3SlowFill").data;
561
- const fillEvent = events.find((event) => event.name === "filledV3Relay").data;
563
+ const requestEvents = await (0, utils_1.readEventsUntilFound)(connection, tx1, [program]);
564
+ const requestEvent = requestEvents.find((event) => event.name === "requestedV3SlowFill")?.data;
562
565
  assert.isNotNull(requestEvent, "RequestedV3SlowFill event should be emitted");
563
- assert.isNotNull(fillEvent, "FilledV3Relay event should be emitted");
564
566
  assertSE(requestEvent.messageHash, new Uint8Array(32), `MessageHash should be zeroed`);
567
+ const fillEvents = await (0, utils_1.readEventsUntilFound)(connection, tx2, [program]);
568
+ const fillEvent = fillEvents.find((event) => event.name === "filledV3Relay")?.data;
569
+ assert.isNotNull(fillEvent, "FilledV3Relay event should be emitted");
565
570
  assertSE(fillEvent.messageHash, new Uint8Array(32), `MessageHash should be zeroed`);
566
571
  assertSE(fillEvent.relayExecutionInfo.updatedMessageHash, new Uint8Array(32), `UpdatedMessageHash should be zeroed`);
567
572
  });
@@ -260,15 +260,13 @@ describe("svm_spoke.token_bridge", () => {
260
260
  // Create a new Keypair for the message event data.
261
261
  const simpleBridgeMessageSentEventData = anchor_1.web3.Keypair.generate();
262
262
  // Perform the bridge operation.
263
- await program.methods
263
+ const tx = await program.methods
264
264
  .bridgeTokensToHubPool(new anchor_1.BN(simpleBridgeAmount))
265
265
  .accounts({ ...bridgeTokensToHubPoolAccounts, messageSentEventData: simpleBridgeMessageSentEventData.publicKey })
266
266
  .signers([simpleBridgeMessageSentEventData])
267
267
  .rpc();
268
- // Wait for the event to be emitted.
269
- await new Promise((resolve) => setTimeout(resolve, 500));
270
- const events = await (0, utils_1.readProgramEvents)(connection, program);
271
- const event = events.find((event) => event.name === "bridgedToHubPool").data;
268
+ const events = await (0, utils_1.readEventsUntilFound)(connection, tx, [program]);
269
+ const event = events.find((event) => event.name === "bridgedToHubPool")?.data;
272
270
  chai_1.assert.isNotNull(event, "BridgedToHubPool event should be emitted");
273
271
  chai_1.assert.strictEqual(event.amount.toString(), simpleBridgeAmount.toString(), "Invalid amount");
274
272
  chai_1.assert.strictEqual(event.mint.toString(), mint.toString(), "Invalid mint");
@@ -31,6 +31,7 @@ const ethers_1 = require("ethers");
31
31
  const spl_token_1 = require("@solana/spl-token");
32
32
  const SvmUtils_1 = require("../../src/SvmUtils");
33
33
  const chai_1 = require("chai");
34
+ const crypto_1 = require("crypto");
34
35
  const provider = anchor.AnchorProvider.env();
35
36
  const program = anchor.workspace.SvmSpoke;
36
37
  const owner = provider.wallet.publicKey;
@@ -52,7 +53,7 @@ const message = Buffer.from("Test message");
52
53
  const depositQuoteTimeBuffer = new anchor_1.BN(3600); // 1 hour.
53
54
  const fillDeadlineBuffer = new anchor_1.BN(3600 * 4); // 4 hours.
54
55
  const initializeState = async (seed, initialState) => {
55
- const actualSeed = seed || new anchor_1.BN(Math.floor(Math.random() * 1000000));
56
+ const actualSeed = seed || new anchor_1.BN((0, crypto_1.randomBytes)(8).toString("hex"), 16); // Generate a random u64
56
57
  const seeds = [Buffer.from("state"), actualSeed.toArrayLike(Buffer, "le", 8)];
57
58
  const [state] = web3_js_1.PublicKey.findProgramAddressSync(seeds, program.programId);
58
59
  if (!initialState) {
@@ -2,10 +2,10 @@ import { BN, Program } from "@coral-xyz/anchor";
2
2
  import { AccountMeta, Keypair, PublicKey, TransactionInstruction } from "@solana/web3.js";
3
3
  import { BigNumber } from "ethers";
4
4
  import { SvmSpoke } from "../../target/types/svm_spoke";
5
- import { readEvents, readProgramEvents, calculateRelayHashUint8Array, findProgramAddress } from "../../src/SvmUtils";
5
+ import { readEvents, readProgramEvents, calculateRelayHashUint8Array, findProgramAddress, readEventsUntilFound } from "../../src/SvmUtils";
6
6
  import { MerkleTree } from "@uma/common";
7
7
  import { RelayData } from "./SvmSpoke.common";
8
- export { readEvents, readProgramEvents, calculateRelayHashUint8Array, findProgramAddress };
8
+ export { readEvents, readProgramEvents, calculateRelayHashUint8Array, findProgramAddress, readEventsUntilFound };
9
9
  export declare function printLogs(connection: any, program: any, tx: any): Promise<void>;
10
10
  export declare function randomAddress(): string;
11
11
  export declare function randomBigInt(bytes?: number, signed?: boolean): bigint;
@@ -82,10 +82,9 @@ export declare function createFillV3RelayParamsInstructions(program: Program<Svm
82
82
  export declare function loadFillV3RelayParams(program: Program<SvmSpoke>, signer: Keypair, relayData: RelayData, repaymentChainId: BN, repaymentAddress: PublicKey): Promise<void>;
83
83
  export declare function loadRequestV3SlowFillParams(program: Program<SvmSpoke>, signer: Keypair, relayData: RelayData): Promise<TransactionInstruction[]>;
84
84
  export declare function loadExecuteV3SlowRelayLeafParams(program: Program<SvmSpoke>, signer: Keypair, slowFillLeaf: SlowFillLeaf, rootBundleId: number, proof: number[][]): Promise<TransactionInstruction[]>;
85
- export declare function intToU8Array32(num: number): number[];
86
- export declare function u8Array32ToInt(u8Array: Uint8Array): bigint;
85
+ export declare function intToU8Array32(num: number | BN): number[];
86
+ export declare function u8Array32ToInt(u8Array: Uint8Array | number[]): bigint;
87
87
  export declare function testAcrossPlusMessage(): {
88
88
  encodedMessage: Buffer;
89
89
  fillRemainingAccounts: AccountMeta[];
90
90
  };
91
- export declare function hashNonEmptyMessage(message: Buffer): Uint8Array;
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.relayerRefundHashFn = exports.findProgramAddress = exports.calculateRelayHashUint8Array = exports.readProgramEvents = exports.readEvents = void 0;
26
+ exports.relayerRefundHashFn = exports.readEventsUntilFound = exports.findProgramAddress = exports.calculateRelayHashUint8Array = exports.readProgramEvents = exports.readEvents = void 0;
27
27
  exports.printLogs = printLogs;
28
28
  exports.randomAddress = randomAddress;
29
29
  exports.randomBigInt = randomBigInt;
@@ -40,7 +40,6 @@ exports.loadExecuteV3SlowRelayLeafParams = loadExecuteV3SlowRelayLeafParams;
40
40
  exports.intToU8Array32 = intToU8Array32;
41
41
  exports.u8Array32ToInt = u8Array32ToInt;
42
42
  exports.testAcrossPlusMessage = testAcrossPlusMessage;
43
- exports.hashNonEmptyMessage = hashNonEmptyMessage;
44
43
  const anchor_1 = require("@coral-xyz/anchor");
45
44
  const web3_js_1 = require("@solana/web3.js");
46
45
  const ethers_1 = require("ethers");
@@ -50,6 +49,7 @@ Object.defineProperty(exports, "readEvents", { enumerable: true, get: function (
50
49
  Object.defineProperty(exports, "readProgramEvents", { enumerable: true, get: function () { return SvmUtils_1.readProgramEvents; } });
51
50
  Object.defineProperty(exports, "calculateRelayHashUint8Array", { enumerable: true, get: function () { return SvmUtils_1.calculateRelayHashUint8Array; } });
52
51
  Object.defineProperty(exports, "findProgramAddress", { enumerable: true, get: function () { return SvmUtils_1.findProgramAddress; } });
52
+ Object.defineProperty(exports, "readEventsUntilFound", { enumerable: true, get: function () { return SvmUtils_1.readEventsUntilFound; } });
53
53
  const common_1 = require("@uma/common");
54
54
  async function printLogs(connection, program, tx) {
55
55
  const latestBlockHash = await connection.getLatestBlockhash();
@@ -295,22 +295,36 @@ async function loadExecuteV3SlowRelayLeafParams(program, signer, slowFillLeaf, r
295
295
  return loadInstructions;
296
296
  }
297
297
  function intToU8Array32(num) {
298
- if (!Number.isInteger(num) || num < 0) {
299
- throw new Error("Input must be a non-negative integer");
298
+ let bigIntValue;
299
+ if (typeof num === "number") {
300
+ if (!Number.isInteger(num) || num < 0) {
301
+ throw new Error("Input must be a non-negative integer");
302
+ }
303
+ bigIntValue = BigInt(num);
304
+ }
305
+ else if (anchor_1.BN.isBN(num)) {
306
+ if (num.isNeg()) {
307
+ throw new Error("Input must be a non-negative BN");
308
+ }
309
+ bigIntValue = BigInt(num.toString());
310
+ }
311
+ else {
312
+ throw new Error("Input must be a non-negative integer or BN");
300
313
  }
301
314
  const u8Array = new Array(32).fill(0);
302
315
  let i = 0;
303
- while (num > 0 && i < 32) {
304
- u8Array[i++] = num & 0xff; // Get least significant byte
305
- num >>= 8; // Shift right by 8 bits
316
+ while (bigIntValue > 0 && i < 32) {
317
+ u8Array[i++] = Number(bigIntValue & 0xffn); // Get least significant byte
318
+ bigIntValue >>= 8n; // Shift right by 8 bits
306
319
  }
307
320
  return u8Array;
308
321
  }
309
322
  function u8Array32ToInt(u8Array) {
310
- if (!(u8Array instanceof Uint8Array) || u8Array.length !== 32) {
311
- throw new Error("Input must be a Uint8Array of length 32");
323
+ const isValidArray = (arr) => Array.isArray(arr) && arr.every(Number.isInteger);
324
+ if ((u8Array instanceof Uint8Array || isValidArray(u8Array)) && u8Array.length === 32) {
325
+ return Array.from(u8Array).reduce((num, byte, i) => num | (BigInt(byte) << BigInt(i * 8)), 0n);
312
326
  }
313
- return u8Array.reduce((num, byte, i) => num | (BigInt(byte) << BigInt(i * 8)), 0n);
327
+ throw new Error("Input must be a Uint8Array or an array of 32 numbers.");
314
328
  }
315
329
  // Encodes empty list of multicall handler instructions to be used as a test message field for fills.
316
330
  function testAcrossPlusMessage() {
@@ -331,11 +345,3 @@ function testAcrossPlusMessage() {
331
345
  ];
332
346
  return { encodedMessage, fillRemainingAccounts };
333
347
  }
334
- function hashNonEmptyMessage(message) {
335
- if (message.length > 0) {
336
- const hash = ethers_1.ethers.utils.keccak256(message);
337
- return Uint8Array.from(Buffer.from(hash.slice(2), "hex"));
338
- }
339
- // else return zeroed bytes32
340
- return new Uint8Array(32);
341
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@across-protocol/contracts",
3
- "version": "3.0.17",
3
+ "version": "3.0.18",
4
4
  "author": "UMA Team",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -39,7 +39,7 @@
39
39
  "pre-commit-hook": "sh scripts/preCommitHook.sh"
40
40
  },
41
41
  "dependencies": {
42
- "@across-protocol/constants": "^3.1.19",
42
+ "@across-protocol/constants": "^3.1.22",
43
43
  "@coral-xyz/anchor": "^0.30.1",
44
44
  "@defi-wonderland/smock": "^2.3.4",
45
45
  "@eth-optimism/contracts": "^0.5.40",