@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.
Files changed (95) hide show
  1. package/README.md +2 -0
  2. package/artifacts/build-info/9cb910e5bb5dd730cd01af84a0fb0466.json +1 -0
  3. package/artifacts/contracts/Ink_SpokePool.sol/Ink_SpokePool.dbg.json +4 -0
  4. package/artifacts/contracts/Ink_SpokePool.sol/Ink_SpokePool.json +2316 -0
  5. package/contracts/Ink_SpokePool.sol +72 -0
  6. package/dist/deploy/consts.js +8 -2
  7. package/dist/deployments/deployments.json +7 -1
  8. package/dist/hardhat.config.js +17 -0
  9. package/dist/scripts/svm/addressToPublicKey.d.ts +1 -0
  10. package/dist/scripts/svm/addressToPublicKey.js +20 -0
  11. package/dist/scripts/svm/bridgeLiabilityToHubPool.d.ts +25 -0
  12. package/dist/scripts/svm/bridgeLiabilityToHubPool.js +221 -0
  13. package/dist/scripts/svm/closeRelayerPdas.js +8 -9
  14. package/dist/scripts/svm/enableRoute.js +7 -1
  15. package/dist/scripts/svm/executeRebalanceToHubPool.d.ts +29 -0
  16. package/dist/scripts/svm/executeRebalanceToHubPool.js +345 -0
  17. package/dist/scripts/svm/executeRebalanceToSpokePool.d.ts +1 -0
  18. package/dist/scripts/svm/executeRebalanceToSpokePool.js +240 -0
  19. package/dist/scripts/svm/fakeFillWithRandomDistribution.js +6 -7
  20. package/dist/scripts/svm/initialize.js +2 -2
  21. package/dist/scripts/svm/proposeRebalanceToHubPool.d.ts +27 -0
  22. package/dist/scripts/svm/proposeRebalanceToHubPool.js +117 -0
  23. package/dist/scripts/svm/proposeRebalanceToSpokePool.d.ts +1 -0
  24. package/dist/scripts/svm/proposeRebalanceToSpokePool.js +97 -0
  25. package/dist/scripts/svm/publicKeyToAddress.d.ts +1 -0
  26. package/dist/scripts/svm/publicKeyToAddress.js +20 -0
  27. package/dist/scripts/svm/queryDeposits.js +3 -2
  28. package/dist/scripts/svm/queryFills.js +12 -14
  29. package/dist/scripts/svm/queryRoute.js +7 -1
  30. package/dist/scripts/svm/queryState.js +1 -0
  31. package/dist/scripts/svm/remoteHubPoolPauseDeposits.d.ts +1 -0
  32. package/dist/scripts/svm/remoteHubPoolPauseDeposits.js +191 -0
  33. package/dist/scripts/svm/remoteHubPoolSetDepositRoute.js +16 -29
  34. package/dist/scripts/svm/remotePauseDeposits.js +21 -27
  35. package/dist/scripts/svm/simpleDeposit.js +7 -1
  36. package/dist/scripts/svm/simpleFakeRelayerRepayment.js +3 -3
  37. package/dist/scripts/svm/simpleFill.js +6 -6
  38. package/dist/scripts/svm/utils/constants.d.ts +4 -0
  39. package/dist/scripts/svm/utils/constants.js +8 -1
  40. package/dist/scripts/svm/utils/helpers.d.ts +33 -0
  41. package/dist/scripts/svm/utils/helpers.js +60 -1
  42. package/dist/scripts/svm/utils/poolRebalanceTree.d.ts +22 -0
  43. package/dist/scripts/svm/utils/poolRebalanceTree.js +20 -0
  44. package/dist/src/svm/coders.d.ts +37 -0
  45. package/dist/src/svm/coders.js +250 -0
  46. package/dist/src/svm/conversionUtils.d.ts +22 -0
  47. package/dist/src/svm/conversionUtils.js +73 -0
  48. package/dist/src/svm/index.d.ts +6 -0
  49. package/dist/src/svm/index.js +22 -0
  50. package/dist/src/svm/instructionParamsUtils.d.ts +31 -0
  51. package/dist/src/svm/instructionParamsUtils.js +128 -0
  52. package/dist/src/svm/relayHashUtils.d.ts +30 -0
  53. package/dist/src/svm/relayHashUtils.js +209 -0
  54. package/dist/src/svm/solanaProgramUtils.d.ts +38 -0
  55. package/dist/src/svm/solanaProgramUtils.js +147 -0
  56. package/dist/src/svm/transactionUtils.d.ts +8 -0
  57. package/dist/src/svm/transactionUtils.js +55 -0
  58. package/dist/src/types/svm.d.ts +118 -0
  59. package/dist/src/types/svm.js +2 -0
  60. package/dist/target/types/svm_spoke.d.ts +47 -42
  61. package/dist/tasks/enableL1TokenAcrossEcosystem.js +3 -33
  62. package/dist/tasks/types.d.ts +2 -0
  63. package/dist/tasks/types.js +2 -0
  64. package/dist/tasks/utils.d.ts +12 -0
  65. package/dist/tasks/utils.js +34 -0
  66. package/dist/test/svm/MulticallHandler.js +2 -2
  67. package/dist/test/svm/SvmSpoke.Bundle.js +59 -60
  68. package/dist/test/svm/SvmSpoke.Deposit.js +23 -31
  69. package/dist/test/svm/SvmSpoke.Fill.AcrossPlus.js +16 -18
  70. package/dist/test/svm/SvmSpoke.Fill.js +38 -40
  71. package/dist/test/svm/SvmSpoke.HandleReceiveMessage.js +2 -2
  72. package/dist/test/svm/SvmSpoke.Ownership.js +11 -17
  73. package/dist/test/svm/SvmSpoke.RefundClaims.js +12 -11
  74. package/dist/test/svm/SvmSpoke.Routes.js +11 -7
  75. package/dist/test/svm/SvmSpoke.SlowFill.AcrossPlus.js +72 -16
  76. package/dist/test/svm/SvmSpoke.SlowFill.js +33 -28
  77. package/dist/test/svm/SvmSpoke.TokenBridge.js +15 -17
  78. package/dist/test/svm/SvmSpoke.common.d.ts +1 -49
  79. package/dist/test/svm/SvmSpoke.common.js +6 -5
  80. package/dist/test/svm/cctpHelpers.js +2 -2
  81. package/dist/test/svm/utils.d.ts +5 -67
  82. package/dist/test/svm/utils.js +10 -220
  83. package/dist/typechain/contracts/Ink_SpokePool.d.ts +1251 -0
  84. package/dist/typechain/contracts/Ink_SpokePool.js +2 -0
  85. package/dist/typechain/contracts/index.d.ts +1 -0
  86. package/dist/typechain/factories/contracts/Ink_SpokePool__factory.d.ts +1833 -0
  87. package/dist/typechain/factories/contracts/Ink_SpokePool__factory.js +2347 -0
  88. package/dist/typechain/factories/contracts/index.d.ts +1 -0
  89. package/dist/typechain/factories/contracts/index.js +3 -1
  90. package/dist/typechain/hardhat.d.ts +9 -0
  91. package/dist/typechain/index.d.ts +2 -0
  92. package/dist/typechain/index.js +5 -3
  93. package/package.json +2 -2
  94. package/dist/src/SvmUtils.d.ts +0 -50
  95. package/dist/src/SvmUtils.js +0 -415
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  // This script bridges remote call to pause deposits on Solana Spoke Pool. Required environment:
3
- // - ETHERS_PROVIDER_URL: Ethereum RPC provider URL.
4
- // - ETHERS_MNEMONIC: Mnemonic of the wallet that will sign the sending transaction on Ethereum
3
+ // - NODE_URL_${CHAIN_ID}: Ethereum RPC URL (must point to the Mainnet or Sepolia depending on Solana cluster).
4
+ // - MNEMONIC: Mnemonic of the wallet that will sign the sending transaction on Ethereum
5
5
  // - HUB_POOL_ADDRESS: Hub Pool address
6
6
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
7
  if (k2 === undefined) k2 = k;
@@ -37,11 +37,13 @@ const web3_js_1 = require("@solana/web3.js");
37
37
  const yargs_1 = __importDefault(require("yargs"));
38
38
  const helpers_1 = require("yargs/helpers");
39
39
  const ethers_1 = require("ethers");
40
+ const common_1 = require("@uma/common");
40
41
  const cctpHelpers_1 = require("../../test/svm/cctpHelpers");
41
42
  const typechain_1 = require("../../typechain");
42
43
  const spl_token_1 = require("@solana/spl-token");
43
44
  const constants_1 = require("./utils/constants");
44
45
  const helpers_2 = require("./utils/helpers");
46
+ const constants_2 = require("../../utils/constants");
45
47
  // Set up Solana provider.
46
48
  const provider = anchor_1.AnchorProvider.env();
47
49
  anchor.setProvider(provider);
@@ -58,28 +60,12 @@ async function remoteHubPoolSetDepositRoute() {
58
60
  const depositsEnabled = resolvedArgv.depositsEnabled;
59
61
  const seed = new anchor_1.BN(0);
60
62
  const resumeRemoteTx = resolvedArgv.resumeRemoteTx;
61
- // Set up Ethereum provider.
62
- if (!process.env.ETHERS_PROVIDER_URL) {
63
- throw new Error("Environment variable ETHERS_PROVIDER_URL is not set");
64
- }
65
- const ethersProvider = new ethers_1.ethers.providers.JsonRpcProvider(process.env.ETHERS_PROVIDER_URL);
66
- if (!process.env.ETHERS_MNEMONIC) {
67
- throw new Error("Environment variable ETHERS_MNEMONIC is not set");
68
- }
69
- const ethersSigner = ethers_1.ethers.Wallet.fromMnemonic(process.env.ETHERS_MNEMONIC).connect(ethersProvider);
70
- if (!process.env.HUB_POOL_ADDRESS) {
71
- throw new Error("Environment variable HUB_POOL_ADDRESS is not set");
72
- }
73
- const hubPoolAddress = process.env.HUB_POOL_ADDRESS;
74
- let cluster;
75
- const rpcEndpoint = provider.connection.rpcEndpoint;
76
- if (rpcEndpoint.includes("devnet"))
77
- cluster = "devnet";
78
- else if (rpcEndpoint.includes("mainnet"))
79
- cluster = "mainnet";
80
- else
81
- throw new Error(`Unsupported cluster endpoint: ${rpcEndpoint}`);
82
- const isDevnet = cluster == "devnet";
63
+ // Set up Ethereum provider and signer.
64
+ const isDevnet = (0, helpers_2.isSolanaDevnet)(provider);
65
+ const nodeURL = isDevnet ? (0, common_1.getNodeUrl)("sepolia", true) : (0, common_1.getNodeUrl)("mainnet", true);
66
+ const ethersProvider = new ethers_1.ethers.providers.JsonRpcProvider(nodeURL);
67
+ const ethersSigner = ethers_1.ethers.Wallet.fromMnemonic((0, helpers_2.requireEnv)("MNEMONIC")).connect(ethersProvider);
68
+ const hubPoolAddress = (0, helpers_2.requireEnv)("HUB_POOL_ADDRESS");
83
69
  const usdcProgramId = isDevnet ? constants_1.SOLANA_USDC_DEVNET : constants_1.SOLANA_USDC_MAINNET;
84
70
  const originToken = new web3_js_1.PublicKey(usdcProgramId);
85
71
  const originTokenAddress = (0, helpers_2.fromBytes32ToAddress)((0, helpers_2.fromBase58ToBytes32)(originToken.toBase58()));
@@ -103,16 +89,17 @@ async function remoteHubPoolSetDepositRoute() {
103
89
  const [selfAuthority] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("self_authority")], svmSpokeProgram.programId);
104
90
  const [eventAuthority] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("__event_authority")], svmSpokeProgram.programId);
105
91
  const irisApiUrl = isDevnet ? constants_1.CIRCLE_IRIS_API_URL_DEVNET : constants_1.CIRCLE_IRIS_API_URL_MAINNET;
106
- const supportedChainId = isDevnet ? 11155111 : 1; // Sepolia is bridged to devnet, Ethereum to mainnet in CCTP.
107
- const chainId = (await ethersProvider.getNetwork()).chainId;
108
- if (chainId !== supportedChainId) {
109
- throw new Error(`Chain ID ${chainId} does not match expected Solana cluster ${cluster}`);
92
+ const solanaCluster = isDevnet ? "devnet" : "mainnet";
93
+ const supportedEvmChainId = isDevnet ? constants_2.CHAIN_IDs.SEPOLIA : constants_2.CHAIN_IDs.MAINNET; // Sepolia is bridged to devnet, Ethereum to mainnet in CCTP.
94
+ const evmChainId = (await ethersProvider.getNetwork()).chainId;
95
+ if (evmChainId !== supportedEvmChainId) {
96
+ throw new Error(`Chain ID ${evmChainId} does not match expected Solana cluster ${solanaCluster}`);
110
97
  }
111
98
  const hubPool = typechain_1.HubPool__factory.connect(hubPoolAddress, ethersProvider);
112
99
  console.log("Remotely configuring deposit route...");
113
100
  console.table([
114
101
  { Property: "seed", Value: seed.toString() },
115
- { Property: "chainId", Value: chainId.toString() },
102
+ { Property: "evmChainId", Value: evmChainId.toString() },
116
103
  { Property: "originChainId", Value: originChainId },
117
104
  { Property: "destinationChainId", Value: destinationChainId },
118
105
  { Property: "depositsEnabled", Value: depositsEnabled },
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  // This script bridges remote call to pause deposits on Solana Spoke Pool. Required environment:
3
- // - ETHERS_PROVIDER_URL: Ethereum RPC provider URL.
4
- // - ETHERS_MNEMONIC: Mnemonic of the wallet that will sign the sending transaction on Ethereum
3
+ // - NODE_URL_${CHAIN_ID}: Ethereum RPC URL (must point to the Mainnet or Sepolia depending on Solana cluster).
4
+ // - MNEMONIC: Mnemonic of the wallet that will sign the sending transaction on Ethereum
5
5
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
6
  if (k2 === undefined) k2 = k;
7
7
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -36,7 +36,11 @@ const web3_js_1 = require("@solana/web3.js");
36
36
  const yargs_1 = __importDefault(require("yargs"));
37
37
  const helpers_1 = require("yargs/helpers");
38
38
  const ethers_1 = require("ethers");
39
+ const common_1 = require("@uma/common");
39
40
  const cctpHelpers_1 = require("../../test/svm/cctpHelpers");
41
+ const helpers_2 = require("./utils/helpers");
42
+ const constants_1 = require("./utils/constants");
43
+ const constants_2 = require("../../utils/constants");
40
44
  // Set up Solana provider.
41
45
  const provider = anchor_1.AnchorProvider.env();
42
46
  anchor.setProvider(provider);
@@ -59,15 +63,11 @@ async function remotePauseDeposits() {
59
63
  const seed = new anchor_1.BN(resolvedArgv.seed);
60
64
  const pause = resolvedArgv.pause;
61
65
  const resumeRemoteTx = resolvedArgv.resumeRemoteTx;
62
- // Set up Ethereum provider.
63
- if (!process.env.ETHERS_PROVIDER_URL) {
64
- throw new Error("Environment variable ETHERS_PROVIDER_URL is not set");
65
- }
66
- const ethersProvider = new ethers_1.ethers.providers.JsonRpcProvider(process.env.ETHERS_PROVIDER_URL);
67
- if (!process.env.ETHERS_MNEMONIC) {
68
- throw new Error("Environment variable ETHERS_MNEMONIC is not set");
69
- }
70
- const ethersSigner = ethers_1.ethers.Wallet.fromMnemonic(process.env.ETHERS_MNEMONIC).connect(ethersProvider);
66
+ // Set up Ethereum provider and signer.
67
+ const isDevnet = (0, helpers_2.isSolanaDevnet)(provider);
68
+ const nodeURL = isDevnet ? (0, common_1.getNodeUrl)("sepolia", true) : (0, common_1.getNodeUrl)("mainnet", true);
69
+ const ethersProvider = new ethers_1.ethers.providers.JsonRpcProvider(nodeURL);
70
+ const ethersSigner = ethers_1.ethers.Wallet.fromMnemonic((0, helpers_2.requireEnv)("MNEMONIC")).connect(ethersProvider);
71
71
  // CCTP domains.
72
72
  const remoteDomain = 0; // Ethereum
73
73
  const localDomain = 5; // Solana
@@ -81,33 +81,27 @@ async function remotePauseDeposits() {
81
81
  const [authorityPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("message_transmitter_authority"), svmSpokeProgram.programId.toBuffer()], messageTransmitterProgram.programId);
82
82
  const [selfAuthority] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("self_authority")], svmSpokeProgram.programId);
83
83
  const [eventAuthority] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("__event_authority")], svmSpokeProgram.programId);
84
- let cluster;
85
- const rpcEndpoint = provider.connection.rpcEndpoint;
86
- if (rpcEndpoint.includes("devnet"))
87
- cluster = "devnet";
88
- else if (rpcEndpoint.includes("mainnet"))
89
- cluster = "mainnet";
90
- else
91
- throw new Error(`Unsupported cluster endpoint: ${rpcEndpoint}`);
92
- const irisApiUrl = cluster == "devnet" ? "https://iris-api-sandbox.circle.com" : "https://iris-api.circle.com";
93
- const supportedChainId = cluster == "devnet" ? 11155111 : 1; // Sepolia is bridged to devnet, Ethereum to mainnet in CCTP.
94
- const chainId = (await ethersProvider.getNetwork()).chainId;
95
- // TODO: improve type casting.
96
- if (chainId !== BigInt(supportedChainId)) {
97
- throw new Error(`Chain ID ${chainId} does not match expected Solana cluster ${cluster}`);
84
+ const solanaCluster = isDevnet ? "devnet" : "mainnet";
85
+ const irisApiUrl = isDevnet ? constants_1.CIRCLE_IRIS_API_URL_DEVNET : constants_1.CIRCLE_IRIS_API_URL_MAINNET;
86
+ const supportedEvmChainId = isDevnet ? constants_2.CHAIN_IDs.SEPOLIA : constants_2.CHAIN_IDs.MAINNET; // Sepolia is bridged to devnet, Ethereum to mainnet in CCTP.
87
+ const evmChainId = (await ethersProvider.getNetwork()).chainId;
88
+ if (evmChainId !== supportedEvmChainId) {
89
+ throw new Error(`Chain ID ${evmChainId} does not match expected Solana cluster ${solanaCluster}`);
98
90
  }
99
91
  const messageTransmitterRemoteIface = new ethers_1.ethers.utils.Interface([
100
92
  "function sendMessage(uint32 destinationDomain, bytes32 recipient, bytes messageBody)",
101
93
  "event MessageSent(bytes message)",
102
94
  ]);
103
95
  // CCTP MessageTransmitter from https://developers.circle.com/stablecoins/docs/evm-smart-contracts
104
- const messageTransmitterRemoteAddress = cluster == "devnet" ? "0x7865fAfC2db2093669d92c0F33AeEF291086BEFD" : "0x0a992d191deec32afe36203ad87d7d289a738f81";
96
+ const messageTransmitterRemoteAddress = isDevnet
97
+ ? constants_1.SEPOLIA_CCTP_MESSAGE_TRANSMITTER_ADDRESS
98
+ : constants_1.MAINNET_CCTP_MESSAGE_TRANSMITTER_ADDRESS;
105
99
  const messageTransmitterRemote = new ethers_1.ethers.Contract(messageTransmitterRemoteAddress, messageTransmitterRemoteIface, ethersSigner);
106
100
  const spokePoolIface = new ethers_1.ethers.utils.Interface(["function pauseDeposits(bool pause)"]);
107
101
  console.log("Remotely controlling pausedDeposits...");
108
102
  console.table([
109
103
  { Property: "seed", Value: seed.toString() },
110
- { Property: "chainId", Value: chainId.toString() },
104
+ { Property: "evmChainId", Value: evmChainId.toString() },
111
105
  { Property: "pause", Value: pause },
112
106
  { Property: "svmSpokeProgramProgramId", Value: svmSpokeProgram.programId.toString() },
113
107
  { Property: "providerPublicKey", Value: provider.wallet.publicKey.toString() },
@@ -39,6 +39,7 @@ anchor.setProvider(provider);
39
39
  const idl = require("../../target/idl/svm_spoke.json");
40
40
  const program = new anchor_1.Program(idl, provider);
41
41
  const programId = program.programId;
42
+ console.log("SVM-Spoke Program ID:", programId.toString());
42
43
  // Parse arguments
43
44
  const argv = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
44
45
  .option("seed", { type: "string", demandOption: true, describe: "Seed for the state account PDA" })
@@ -65,7 +66,12 @@ async function depositV3() {
65
66
  // Define the state account PDA
66
67
  const [statePda, _] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("state"), seed.toArrayLike(Buffer, "le", 8)], programId);
67
68
  // Define the route account PDA
68
- const [routePda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("route"), inputToken.toBytes(), statePda.toBytes(), destinationChainId.toArrayLike(Buffer, "le", 8)], programId);
69
+ const [routePda] = web3_js_1.PublicKey.findProgramAddressSync([
70
+ Buffer.from("route"),
71
+ inputToken.toBytes(),
72
+ seed.toArrayLike(Buffer, "le", 8),
73
+ destinationChainId.toArrayLike(Buffer, "le", 8),
74
+ ], programId);
69
75
  // Define the signer (replace with your actual signer)
70
76
  const signer = provider.wallet.payer;
71
77
  // Find ATA for the input token to be stored by state (vault). This was created when the route was enabled.
@@ -34,7 +34,7 @@ const spl_token_1 = require("@solana/spl-token");
34
34
  const yargs_1 = __importDefault(require("yargs"));
35
35
  const helpers_1 = require("yargs/helpers");
36
36
  const MerkleTree_1 = require("@uma/common/dist/MerkleTree");
37
- const utils_1 = require("../../test/svm/utils");
37
+ const svm_1 = require("../../src/svm");
38
38
  // Set up the provider
39
39
  const provider = anchor_1.AnchorProvider.env();
40
40
  anchor.setProvider(provider);
@@ -121,7 +121,7 @@ async function testBundleLogic() {
121
121
  refundAddresses, // Array of refund authority addresses
122
122
  refundAmounts: amounts, // Array of amounts
123
123
  };
124
- const merkleTree = new MerkleTree_1.MerkleTree([relayerRefundLeaf], utils_1.relayerRefundHashFn);
124
+ const merkleTree = new MerkleTree_1.MerkleTree([relayerRefundLeaf], svm_1.relayerRefundHashFn);
125
125
  const root = merkleTree.getRoot();
126
126
  console.log("Merkle Tree Generated. Root: ", Buffer.from(root).toString("hex"));
127
127
  // Set the tree using the methods from the .Bundle test
@@ -197,7 +197,7 @@ async function testBundleLogic() {
197
197
  if (!lookupTableAccount) {
198
198
  throw new Error("AddressLookupTableAccount not fetched");
199
199
  }
200
- await (0, utils_1.loadExecuteRelayerRefundLeafParams)(program, signer.publicKey, rootBundleId, leaf, proofAsNumbers);
200
+ await (0, svm_1.loadExecuteRelayerRefundLeafParams)(program, signer.publicKey, rootBundleId, leaf, proofAsNumbers);
201
201
  console.log(`loaded execute relayer refund leaf params ${instructionParams}. \nExecuting relayer refund leaf...`);
202
202
  const executeInstruction = await program.methods
203
203
  .executeRelayerRefundLeaf()
@@ -34,7 +34,7 @@ const web3_js_1 = require("@solana/web3.js");
34
34
  const spl_token_1 = require("@solana/spl-token");
35
35
  const yargs_1 = __importDefault(require("yargs"));
36
36
  const helpers_1 = require("yargs/helpers");
37
- const SvmUtils_1 = require("../../src/SvmUtils");
37
+ const svm_1 = require("../../src/svm");
38
38
  // Set up the provider
39
39
  const provider = anchor_1.AnchorProvider.env();
40
40
  anchor.setProvider(provider);
@@ -52,7 +52,7 @@ const argv = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
52
52
  .option("inputAmount", { type: "number", demandOption: true, describe: "Input amount" })
53
53
  .option("outputAmount", { type: "number", demandOption: true, describe: "Output amount" })
54
54
  .option("originChainId", { type: "string", demandOption: true, describe: "Origin chain ID" })
55
- .option("depositId", { type: "array", demandOption: true, describe: "Deposit ID" })
55
+ .option("depositId", { type: "string", demandOption: true, describe: "Deposit ID" })
56
56
  .option("fillDeadline", { type: "number", demandOption: false, describe: "Fill deadline" })
57
57
  .option("exclusivityDeadline", { type: "number", demandOption: false, describe: "Exclusivity deadline" }).argv;
58
58
  async function fillV3Relay() {
@@ -65,7 +65,7 @@ async function fillV3Relay() {
65
65
  const inputAmount = new anchor_1.BN(resolvedArgv.inputAmount);
66
66
  const outputAmount = new anchor_1.BN(resolvedArgv.outputAmount);
67
67
  const originChainId = new anchor_1.BN(resolvedArgv.originChainId);
68
- const depositId = resolvedArgv.depositId;
68
+ const depositId = (0, svm_1.intToU8Array32)(new anchor_1.BN(resolvedArgv.depositId));
69
69
  const fillDeadline = resolvedArgv.fillDeadline || Math.floor(Date.now() / 1000) + 60; // Current time + 1 minute
70
70
  const exclusivityDeadline = resolvedArgv.exclusivityDeadline || Math.floor(Date.now() / 1000) + 30; // Current time + 30 seconds
71
71
  const message = Buffer.from("");
@@ -79,7 +79,7 @@ async function fillV3Relay() {
79
79
  inputAmount,
80
80
  outputAmount,
81
81
  originChainId,
82
- depositId: depositId.map((id) => Number(id)),
82
+ depositId,
83
83
  fillDeadline,
84
84
  exclusivityDeadline,
85
85
  message,
@@ -92,7 +92,7 @@ async function fillV3Relay() {
92
92
  // Fetch the state from the on-chain program to get chainId
93
93
  const state = await program.account.state.fetch(statePda);
94
94
  const chainId = new anchor_1.BN(state.chainId);
95
- const relayHashUint8Array = (0, SvmUtils_1.calculateRelayHashUint8Array)(relayData, chainId);
95
+ const relayHashUint8Array = (0, svm_1.calculateRelayHashUint8Array)(relayData, chainId);
96
96
  // Define the fill status account PDA
97
97
  const [fillStatusPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("fills"), relayHashUint8Array], programId);
98
98
  // Create ATA for the relayer and recipient token accounts
@@ -122,7 +122,7 @@ async function fillV3Relay() {
122
122
  state: statePda,
123
123
  signer: signer.publicKey,
124
124
  instructionParams: program.programId,
125
- mintAccount: outputToken,
125
+ mint: outputToken,
126
126
  relayerTokenAccount: relayerTokenAccount,
127
127
  recipientTokenAccount: recipientTokenAccount,
128
128
  fillStatus: fillStatusPda,
@@ -1,4 +1,8 @@
1
+ import BN from "bn.js";
1
2
  export declare const CIRCLE_IRIS_API_URL_DEVNET = "https://iris-api-sandbox.circle.com";
2
3
  export declare const CIRCLE_IRIS_API_URL_MAINNET = "https://iris-api.circle.com";
3
4
  export declare const SOLANA_USDC_MAINNET = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
4
5
  export declare const SOLANA_USDC_DEVNET = "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU";
6
+ export declare const SEPOLIA_CCTP_MESSAGE_TRANSMITTER_ADDRESS = "0x7865fAfC2db2093669d92c0F33AeEF291086BEFD";
7
+ export declare const MAINNET_CCTP_MESSAGE_TRANSMITTER_ADDRESS = "0x0a992d191deec32afe36203ad87d7d289a738f81";
8
+ export declare const SOLANA_SPOKE_STATE_SEED: BN;
@@ -1,7 +1,14 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SOLANA_USDC_DEVNET = exports.SOLANA_USDC_MAINNET = exports.CIRCLE_IRIS_API_URL_MAINNET = exports.CIRCLE_IRIS_API_URL_DEVNET = void 0;
6
+ exports.SOLANA_SPOKE_STATE_SEED = exports.MAINNET_CCTP_MESSAGE_TRANSMITTER_ADDRESS = exports.SEPOLIA_CCTP_MESSAGE_TRANSMITTER_ADDRESS = exports.SOLANA_USDC_DEVNET = exports.SOLANA_USDC_MAINNET = exports.CIRCLE_IRIS_API_URL_MAINNET = exports.CIRCLE_IRIS_API_URL_DEVNET = void 0;
7
+ const bn_js_1 = __importDefault(require("bn.js"));
4
8
  exports.CIRCLE_IRIS_API_URL_DEVNET = "https://iris-api-sandbox.circle.com";
5
9
  exports.CIRCLE_IRIS_API_URL_MAINNET = "https://iris-api.circle.com";
6
10
  exports.SOLANA_USDC_MAINNET = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
7
11
  exports.SOLANA_USDC_DEVNET = "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU";
12
+ exports.SEPOLIA_CCTP_MESSAGE_TRANSMITTER_ADDRESS = "0x7865fAfC2db2093669d92c0F33AeEF291086BEFD";
13
+ exports.MAINNET_CCTP_MESSAGE_TRANSMITTER_ADDRESS = "0x0a992d191deec32afe36203ad87d7d289a738f81";
14
+ exports.SOLANA_SPOKE_STATE_SEED = new bn_js_1.default(0);
@@ -1,2 +1,35 @@
1
+ import { AnchorProvider } from "@coral-xyz/anchor";
2
+ import { BigNumber } from "ethers";
3
+ import { PublicKey } from "@solana/web3.js";
4
+ import { MerkleTree } from "@uma/common";
5
+ import { RelayerRefundLeafSolana, RelayerRefundLeafType } from "../../../src/types/svm";
6
+ export declare const requireEnv: (name: string) => string;
7
+ export declare const getSolanaChainId: (cluster: "devnet" | "mainnet") => BigNumber;
8
+ export declare const isSolanaDevnet: (provider: AnchorProvider) => boolean;
9
+ export declare const formatUsdc: (amount: BigNumber) => string;
1
10
  export declare const fromBase58ToBytes32: (input: string) => string;
2
11
  export declare const fromBytes32ToAddress: (input: string) => string;
12
+ export declare function constructEmptyPoolRebalanceTree(chainId: BigNumber, groupIndex: number): {
13
+ poolRebalanceLeaf: {
14
+ chainId: BigNumber;
15
+ groupIndex: BigNumber;
16
+ bundleLpFees: never[];
17
+ netSendAmounts: never[];
18
+ runningBalances: never[];
19
+ leafId: BigNumber;
20
+ l1Tokens: never[];
21
+ };
22
+ poolRebalanceTree: MerkleTree<{
23
+ chainId: BigNumber;
24
+ groupIndex: BigNumber;
25
+ bundleLpFees: never[];
26
+ netSendAmounts: never[];
27
+ runningBalances: never[];
28
+ leafId: BigNumber;
29
+ l1Tokens: never[];
30
+ }>;
31
+ };
32
+ export declare const constructSimpleRebalanceTreeToHubPool: (netSendAmount: BigNumber, solanaChainId: BigNumber, svmUsdc: PublicKey) => {
33
+ merkleTree: MerkleTree<RelayerRefundLeafType>;
34
+ leaves: RelayerRefundLeafSolana[];
35
+ };
@@ -1,7 +1,36 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fromBytes32ToAddress = exports.fromBase58ToBytes32 = void 0;
3
+ exports.constructSimpleRebalanceTreeToHubPool = exports.fromBytes32ToAddress = exports.fromBase58ToBytes32 = exports.formatUsdc = exports.isSolanaDevnet = exports.getSolanaChainId = exports.requireEnv = void 0;
4
+ exports.constructEmptyPoolRebalanceTree = constructEmptyPoolRebalanceTree;
4
5
  const anchor_1 = require("@coral-xyz/anchor");
6
+ const ethers_1 = require("ethers");
7
+ const web3_js_1 = require("@solana/web3.js");
8
+ const common_1 = require("@uma/common");
9
+ const svm_1 = require("../../../src/svm");
10
+ const requireEnv = (name) => {
11
+ if (!process.env[name])
12
+ throw new Error(`Environment variable ${name} is not set`);
13
+ return process.env[name];
14
+ };
15
+ exports.requireEnv = requireEnv;
16
+ const getSolanaChainId = (cluster) => {
17
+ return ethers_1.BigNumber.from(BigInt(ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.toUtf8Bytes(`solana-${cluster}`))) & BigInt("0xFFFFFFFFFFFFFFFF"));
18
+ };
19
+ exports.getSolanaChainId = getSolanaChainId;
20
+ const isSolanaDevnet = (provider) => {
21
+ const solanaRpcEndpoint = provider.connection.rpcEndpoint;
22
+ if (solanaRpcEndpoint.includes("devnet"))
23
+ return true;
24
+ else if (solanaRpcEndpoint.includes("mainnet"))
25
+ return false;
26
+ else
27
+ throw new Error(`Unsupported solanaCluster endpoint: ${solanaRpcEndpoint}`);
28
+ };
29
+ exports.isSolanaDevnet = isSolanaDevnet;
30
+ const formatUsdc = (amount) => {
31
+ return ethers_1.ethers.utils.formatUnits(amount, 6);
32
+ };
33
+ exports.formatUsdc = formatUsdc;
5
34
  const fromBase58ToBytes32 = (input) => {
6
35
  const decodedBytes = anchor_1.utils.bytes.bs58.decode(input);
7
36
  return "0x" + Buffer.from(decodedBytes).toString("hex");
@@ -19,3 +48,33 @@ const fromBytes32ToAddress = (input) => {
19
48
  return "0x" + address;
20
49
  };
21
50
  exports.fromBytes32ToAddress = fromBytes32ToAddress;
51
+ function constructEmptyPoolRebalanceTree(chainId, groupIndex) {
52
+ const poolRebalanceLeaf = {
53
+ chainId,
54
+ groupIndex: ethers_1.BigNumber.from(groupIndex),
55
+ bundleLpFees: [],
56
+ netSendAmounts: [],
57
+ runningBalances: [],
58
+ leafId: ethers_1.BigNumber.from(0),
59
+ l1Tokens: [],
60
+ };
61
+ const rebalanceParamType = "tuple( uint256 chainId, uint256[] bundleLpFees, int256[] netSendAmounts, int256[] runningBalances, uint256 groupIndex, uint8 leafId, address[] l1Tokens )";
62
+ const rebalanceHashFn = (input) => ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.defaultAbiCoder.encode([rebalanceParamType], [input]));
63
+ const poolRebalanceTree = new common_1.MerkleTree([poolRebalanceLeaf], rebalanceHashFn);
64
+ return { poolRebalanceLeaf, poolRebalanceTree };
65
+ }
66
+ const constructSimpleRebalanceTreeToHubPool = (netSendAmount, solanaChainId, svmUsdc) => {
67
+ const relayerRefundLeaves = [];
68
+ relayerRefundLeaves.push({
69
+ isSolana: true,
70
+ leafId: new anchor_1.BN(0),
71
+ chainId: new anchor_1.BN(solanaChainId.toString()),
72
+ amountToReturn: new anchor_1.BN(netSendAmount.toString()),
73
+ mintPublicKey: new web3_js_1.PublicKey(svmUsdc),
74
+ refundAddresses: [],
75
+ refundAmounts: [],
76
+ });
77
+ const merkleTree = new common_1.MerkleTree(relayerRefundLeaves, svm_1.relayerRefundHashFn);
78
+ return { merkleTree, leaves: relayerRefundLeaves };
79
+ };
80
+ exports.constructSimpleRebalanceTreeToHubPool = constructSimpleRebalanceTreeToHubPool;
@@ -0,0 +1,22 @@
1
+ import { MerkleTree } from "@uma/common";
2
+ import { BigNumber } from "ethers";
3
+ export declare function constructSimpleRebalanceTree(l1TokenAddress: string, netSendAmount: BigNumber, chainId: BigNumber): {
4
+ poolRebalanceLeaf: {
5
+ chainId: BigNumber;
6
+ groupIndex: BigNumber;
7
+ bundleLpFees: BigNumber[];
8
+ netSendAmounts: BigNumber[];
9
+ runningBalances: BigNumber[];
10
+ leafId: BigNumber;
11
+ l1Tokens: string[];
12
+ };
13
+ poolRebalanceTree: MerkleTree<{
14
+ chainId: BigNumber;
15
+ groupIndex: BigNumber;
16
+ bundleLpFees: BigNumber[];
17
+ netSendAmounts: BigNumber[];
18
+ runningBalances: BigNumber[];
19
+ leafId: BigNumber;
20
+ l1Tokens: string[];
21
+ }>;
22
+ };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.constructSimpleRebalanceTree = constructSimpleRebalanceTree;
4
+ const common_1 = require("@uma/common");
5
+ const ethers_1 = require("ethers");
6
+ function constructSimpleRebalanceTree(l1TokenAddress, netSendAmount, chainId) {
7
+ const poolRebalanceLeaf = {
8
+ chainId,
9
+ groupIndex: ethers_1.BigNumber.from(1), // Not 0 as this script is not relaying root bundles, only sending tokens to spoke.
10
+ bundleLpFees: [ethers_1.BigNumber.from(0)],
11
+ netSendAmounts: [netSendAmount],
12
+ runningBalances: [netSendAmount],
13
+ leafId: ethers_1.BigNumber.from(0),
14
+ l1Tokens: [l1TokenAddress],
15
+ };
16
+ const rebalanceParamType = "tuple( uint256 chainId, uint256[] bundleLpFees, int256[] netSendAmounts, int256[] runningBalances, uint256 groupIndex, uint8 leafId, address[] l1Tokens )";
17
+ const rebalanceHashFn = (input) => ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.defaultAbiCoder.encode([rebalanceParamType], [input]));
18
+ const poolRebalanceTree = new common_1.MerkleTree([poolRebalanceLeaf], rebalanceHashFn);
19
+ return { poolRebalanceLeaf, poolRebalanceTree };
20
+ }
@@ -0,0 +1,37 @@
1
+ import { BorshAccountsCoder } from "@coral-xyz/anchor";
2
+ import { Message, PublicKey, TransactionInstruction } from "@solana/web3.js";
3
+ import { AcrossPlusMessage } from "../types/svm";
4
+ /**
5
+ * Extended Anchor accounts coder to handle large account data.
6
+ */
7
+ export declare class LargeAccountsCoder<A extends string = string> extends BorshAccountsCoder<A> {
8
+ private getAccountLayouts;
9
+ encode<T = any>(accountName: A, account: T): Promise<Buffer>;
10
+ }
11
+ /**
12
+ * Helper to encode MulticallHandler transactions.
13
+ */
14
+ export declare class MulticallHandlerCoder {
15
+ readonly compiledMessage: Message;
16
+ private readonly layout;
17
+ constructor(instructions: TransactionInstruction[], payerKey?: PublicKey);
18
+ private static coderArg;
19
+ private static coderTypes;
20
+ get readOnlyLen(): number;
21
+ get compiledKeyMetas(): {
22
+ pubkey: PublicKey;
23
+ isSigner: boolean;
24
+ isWritable: boolean;
25
+ }[];
26
+ encode(): Buffer;
27
+ }
28
+ /**
29
+ * Helper to encode Across+ messages.
30
+ */
31
+ export declare class AcrossPlusMessageCoder {
32
+ private acrossPlusMessage;
33
+ constructor(acrossPlusMessage: AcrossPlusMessage);
34
+ private static coderArg;
35
+ private static coderTypes;
36
+ encode(): Buffer;
37
+ }