@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.
- package/dist/scripts/svm/addressToPublicKey.d.ts +1 -0
- package/dist/scripts/svm/addressToPublicKey.js +20 -0
- package/dist/scripts/svm/bridgeLiabilityToHubPool.d.ts +28 -0
- package/dist/scripts/svm/bridgeLiabilityToHubPool.js +231 -0
- package/dist/scripts/svm/closeRelayerPdas.js +6 -7
- package/dist/scripts/svm/enableRoute.js +7 -1
- package/dist/scripts/svm/executeRebalanceToHubPool.d.ts +32 -0
- package/dist/scripts/svm/executeRebalanceToHubPool.js +355 -0
- package/dist/scripts/svm/executeRebalanceToSpokePool.d.ts +1 -0
- package/dist/scripts/svm/executeRebalanceToSpokePool.js +253 -0
- 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 +101 -0
- package/dist/scripts/svm/publicKeyToAddress.d.ts +1 -0
- package/dist/scripts/svm/publicKeyToAddress.js +20 -0
- package/dist/scripts/svm/queryDeposits.js +1 -0
- package/dist/scripts/svm/queryFills.js +11 -12
- 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 +205 -0
- package/dist/scripts/svm/simpleDeposit.js +7 -1
- package/dist/scripts/svm/simpleFill.js +5 -4
- 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 +31 -0
- package/dist/scripts/svm/utils/helpers.js +50 -1
- package/dist/scripts/svm/utils/poolRebalanceTree.d.ts +22 -0
- package/dist/scripts/svm/utils/poolRebalanceTree.js +20 -0
- package/dist/src/SvmUtils.d.ts +24 -2
- package/dist/src/SvmUtils.js +107 -26
- 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/SvmSpoke.Bundle.js +15 -16
- package/dist/test/svm/SvmSpoke.Deposit.js +18 -26
- package/dist/test/svm/SvmSpoke.Fill.AcrossPlus.js +1 -1
- package/dist/test/svm/SvmSpoke.Fill.js +13 -14
- package/dist/test/svm/SvmSpoke.Ownership.js +10 -16
- package/dist/test/svm/SvmSpoke.RefundClaims.js +9 -8
- package/dist/test/svm/SvmSpoke.Routes.js +10 -6
- package/dist/test/svm/SvmSpoke.SlowFill.AcrossPlus.js +59 -2
- package/dist/test/svm/SvmSpoke.SlowFill.js +23 -18
- package/dist/test/svm/SvmSpoke.TokenBridge.js +3 -5
- package/dist/test/svm/SvmSpoke.common.js +2 -1
- package/dist/test/svm/utils.d.ts +4 -5
- package/dist/test/svm/utils.js +24 -18
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const SvmUtils_1 = require("../../src/SvmUtils");
|
|
7
|
+
const yargs_1 = __importDefault(require("yargs"));
|
|
8
|
+
const helpers_1 = require("yargs/helpers");
|
|
9
|
+
const argv = (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv)).option("address", {
|
|
10
|
+
type: "string",
|
|
11
|
+
demandOption: true,
|
|
12
|
+
describe: "Ethereum address to convert",
|
|
13
|
+
}).argv;
|
|
14
|
+
async function logPublicKey() {
|
|
15
|
+
const address = (await argv).address;
|
|
16
|
+
const publicKey = (0, SvmUtils_1.evmAddressToPublicKey)(address);
|
|
17
|
+
console.log("Ethereum Address:", address);
|
|
18
|
+
console.log("Associated Public Key:", publicKey.toString());
|
|
19
|
+
}
|
|
20
|
+
logPublicKey();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Script: Bridge USDC Liability to Hub Pool
|
|
3
|
+
*
|
|
4
|
+
* This script bridges pending USDC liabilities from the Solana Spoke Pool to the Ethereum Hub Pool using the CCTP
|
|
5
|
+
* (Circle Cross-Chain Transfer Protocol). It manages CCTP message attestations, verifies transfer completion, and
|
|
6
|
+
* updates the Hub Pool’s USDC balance.
|
|
7
|
+
*
|
|
8
|
+
* Required Environment Variables:
|
|
9
|
+
* - TESTNET: (Optional) Set to "true" to use Sepolia; defaults to mainnet.
|
|
10
|
+
* - MNEMONIC: Wallet mnemonic to sign the Ethereum transaction.
|
|
11
|
+
* - HUB_POOL_ADDRESS: Ethereum address of the Hub Pool.
|
|
12
|
+
* - NODE_URL_1: Ethereum RPC URL for mainnet (ignored if TESTNET=true).
|
|
13
|
+
* - NODE_URL_11155111: Ethereum RPC URL for Sepolia (ignored if TESTNET=false).
|
|
14
|
+
*
|
|
15
|
+
* Example Usage:
|
|
16
|
+
* TESTNET=true \
|
|
17
|
+
* NODE_URL_11155111=$NODE_URL_11155111 \
|
|
18
|
+
* MNEMONIC=$MNEMONIC \
|
|
19
|
+
* HUB_POOL_ADDRESS=$HUB_POOL_ADDRESS \
|
|
20
|
+
* anchor run bridgeLiabilityToHubPool \
|
|
21
|
+
* --provider.cluster "devnet" \
|
|
22
|
+
* --provider.wallet $SOLANA_PKEY_PATH
|
|
23
|
+
*
|
|
24
|
+
* Note:
|
|
25
|
+
* - Ensure all required environment variables are properly configured.
|
|
26
|
+
* - Pending USDC liabilities must exist in the Solana Spoke Pool for the script to execute.
|
|
27
|
+
*/
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Script: Bridge USDC Liability to Hub Pool
|
|
4
|
+
*
|
|
5
|
+
* This script bridges pending USDC liabilities from the Solana Spoke Pool to the Ethereum Hub Pool using the CCTP
|
|
6
|
+
* (Circle Cross-Chain Transfer Protocol). It manages CCTP message attestations, verifies transfer completion, and
|
|
7
|
+
* updates the Hub Pool’s USDC balance.
|
|
8
|
+
*
|
|
9
|
+
* Required Environment Variables:
|
|
10
|
+
* - TESTNET: (Optional) Set to "true" to use Sepolia; defaults to mainnet.
|
|
11
|
+
* - MNEMONIC: Wallet mnemonic to sign the Ethereum transaction.
|
|
12
|
+
* - HUB_POOL_ADDRESS: Ethereum address of the Hub Pool.
|
|
13
|
+
* - NODE_URL_1: Ethereum RPC URL for mainnet (ignored if TESTNET=true).
|
|
14
|
+
* - NODE_URL_11155111: Ethereum RPC URL for Sepolia (ignored if TESTNET=false).
|
|
15
|
+
*
|
|
16
|
+
* Example Usage:
|
|
17
|
+
* TESTNET=true \
|
|
18
|
+
* NODE_URL_11155111=$NODE_URL_11155111 \
|
|
19
|
+
* MNEMONIC=$MNEMONIC \
|
|
20
|
+
* HUB_POOL_ADDRESS=$HUB_POOL_ADDRESS \
|
|
21
|
+
* anchor run bridgeLiabilityToHubPool \
|
|
22
|
+
* --provider.cluster "devnet" \
|
|
23
|
+
* --provider.wallet $SOLANA_PKEY_PATH
|
|
24
|
+
*
|
|
25
|
+
* Note:
|
|
26
|
+
* - Ensure all required environment variables are properly configured.
|
|
27
|
+
* - Pending USDC liabilities must exist in the Solana Spoke Pool for the script to execute.
|
|
28
|
+
*/
|
|
29
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
30
|
+
if (k2 === undefined) k2 = k;
|
|
31
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
32
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
33
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
34
|
+
}
|
|
35
|
+
Object.defineProperty(o, k2, desc);
|
|
36
|
+
}) : (function(o, m, k, k2) {
|
|
37
|
+
if (k2 === undefined) k2 = k;
|
|
38
|
+
o[k2] = m[k];
|
|
39
|
+
}));
|
|
40
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
41
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
42
|
+
}) : function(o, v) {
|
|
43
|
+
o["default"] = v;
|
|
44
|
+
});
|
|
45
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
46
|
+
if (mod && mod.__esModule) return mod;
|
|
47
|
+
var result = {};
|
|
48
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
49
|
+
__setModuleDefault(result, mod);
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
const anchor = __importStar(require("@coral-xyz/anchor"));
|
|
54
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
55
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
56
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
57
|
+
// eslint-disable-next-line camelcase
|
|
58
|
+
const constants_1 = require("./utils/constants");
|
|
59
|
+
const constants_2 = require("@across-protocol/constants");
|
|
60
|
+
const common_1 = require("@uma/common");
|
|
61
|
+
const ethers_1 = require("ethers");
|
|
62
|
+
const cctpHelpers_1 = require("../../test/svm/cctpHelpers");
|
|
63
|
+
const typechain_1 = require("../../typechain");
|
|
64
|
+
const helpers_1 = require("./utils/helpers");
|
|
65
|
+
// Set up Solana provider.
|
|
66
|
+
const provider = anchor_1.AnchorProvider.env();
|
|
67
|
+
anchor.setProvider(provider);
|
|
68
|
+
// Get Solana programs and IDLs.
|
|
69
|
+
const svmSpokeIdl = require("../../target/idl/svm_spoke.json");
|
|
70
|
+
const svmSpokeProgram = new anchor_1.Program(svmSpokeIdl, provider);
|
|
71
|
+
const messageTransmitterIdl = require("../../target/idl/message_transmitter.json");
|
|
72
|
+
const tokenMessengerMinterIdl = require("../../target/idl/token_messenger_minter.json");
|
|
73
|
+
// CCTP domains.
|
|
74
|
+
const ethereumDomain = 0; // Ethereum
|
|
75
|
+
const solanaDomain = 5; // Solana
|
|
76
|
+
// Set up Ethereum provider and signer.
|
|
77
|
+
const nodeURL = process.env.TESTNET === "true" ? (0, common_1.getNodeUrl)("sepolia", true) : (0, common_1.getNodeUrl)("mainnet", true);
|
|
78
|
+
const ethersProvider = new ethers_1.ethers.providers.JsonRpcProvider(nodeURL);
|
|
79
|
+
const ethersSigner = ethers_1.ethers.Wallet.fromMnemonic((0, helpers_1.requireEnv)("MNEMONIC")).connect(ethersProvider);
|
|
80
|
+
// Get the HubPool contract instance.
|
|
81
|
+
const hubPoolAddress = ethers_1.ethers.utils.getAddress((0, helpers_1.requireEnv)("HUB_POOL_ADDRESS")); // Used to check USDC balance before and after.
|
|
82
|
+
const messageTransmitterAbi = [
|
|
83
|
+
{
|
|
84
|
+
inputs: [
|
|
85
|
+
{
|
|
86
|
+
internalType: "bytes",
|
|
87
|
+
name: "message",
|
|
88
|
+
type: "bytes",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
internalType: "bytes",
|
|
92
|
+
name: "attestation",
|
|
93
|
+
type: "bytes",
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
name: "receiveMessage",
|
|
97
|
+
outputs: [
|
|
98
|
+
{
|
|
99
|
+
internalType: "bool",
|
|
100
|
+
name: "success",
|
|
101
|
+
type: "bool",
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
stateMutability: "nonpayable",
|
|
105
|
+
type: "function",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
inputs: [
|
|
109
|
+
{
|
|
110
|
+
internalType: "bytes32",
|
|
111
|
+
name: "",
|
|
112
|
+
type: "bytes32",
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
name: "usedNonces",
|
|
116
|
+
outputs: [
|
|
117
|
+
{
|
|
118
|
+
internalType: "uint256",
|
|
119
|
+
name: "",
|
|
120
|
+
type: "uint256",
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
stateMutability: "view",
|
|
124
|
+
type: "function",
|
|
125
|
+
},
|
|
126
|
+
];
|
|
127
|
+
async function bridgeLiabilityToHubPool() {
|
|
128
|
+
const seed = constants_1.SOLANA_SPOKE_STATE_SEED; // Seed is always 0 for the state account PDA in public networks.
|
|
129
|
+
// Resolve Solana cluster, EVM chain ID, Iris API URL and USDC addresses.
|
|
130
|
+
let isDevnet;
|
|
131
|
+
const solanaRpcEndpoint = provider.connection.rpcEndpoint;
|
|
132
|
+
if (solanaRpcEndpoint.includes("devnet"))
|
|
133
|
+
isDevnet = true;
|
|
134
|
+
else if (solanaRpcEndpoint.includes("mainnet"))
|
|
135
|
+
isDevnet = false;
|
|
136
|
+
else
|
|
137
|
+
throw new Error(`Unsupported solanaCluster endpoint: ${solanaRpcEndpoint}`);
|
|
138
|
+
const svmUsdc = isDevnet ? constants_1.SOLANA_USDC_DEVNET : constants_1.SOLANA_USDC_MAINNET;
|
|
139
|
+
const [statePda, _] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("state"), seed.toArrayLike(Buffer, "le", 8)], svmSpokeProgram.programId);
|
|
140
|
+
const irisApiUrl = isDevnet ? constants_1.CIRCLE_IRIS_API_URL_DEVNET : constants_1.CIRCLE_IRIS_API_URL_MAINNET;
|
|
141
|
+
const cctpMessageTransmitter = isDevnet
|
|
142
|
+
? constants_1.SEPOLIA_CCTP_MESSAGE_TRANSMITTER_ADDRESS
|
|
143
|
+
: constants_1.MAINNET_CCTP_MESSAGE_TRANSMITTER_ADDRESS;
|
|
144
|
+
const messageTransmitter = new ethers_1.ethers.Contract(cctpMessageTransmitter, messageTransmitterAbi, ethersSigner);
|
|
145
|
+
const evmChainId = (await ethersProvider.getNetwork()).chainId;
|
|
146
|
+
const usdcAddress = constants_2.TOKEN_SYMBOLS_MAP.USDC.addresses[evmChainId];
|
|
147
|
+
const usdc = typechain_1.BondToken__factory.connect(usdcAddress, ethersProvider);
|
|
148
|
+
const usdcBalanceBefore = await usdc.balanceOf(hubPoolAddress);
|
|
149
|
+
console.log("Receiving liability from Solana Spoke Pool to Ethereum Hub Pool...");
|
|
150
|
+
console.table([
|
|
151
|
+
{ Property: "isTestnet", Value: process.env.TESTNET === "true" },
|
|
152
|
+
{ Property: "hubPoolAddress", Value: hubPoolAddress },
|
|
153
|
+
{ Property: "svmSpokeProgramProgramId", Value: svmSpokeProgram.programId.toString() },
|
|
154
|
+
{ Property: "providerPublicKey", Value: provider.wallet.publicKey.toString() },
|
|
155
|
+
{ Property: "usdcBalanceBefore", Value: usdcBalanceBefore.toString() },
|
|
156
|
+
]);
|
|
157
|
+
const [transferLiability] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("transfer_liability"), new web3_js_1.PublicKey(svmUsdc).toBuffer()], svmSpokeProgram.programId);
|
|
158
|
+
const liability = await svmSpokeProgram.account.transferLiability.fetch(transferLiability);
|
|
159
|
+
console.log(`Pending transfer liability: ${(0, helpers_1.formatUsdc)(ethers_1.BigNumber.from(liability.pendingToHubPool.toString()))} USDC.`);
|
|
160
|
+
if (liability.pendingToHubPool.eq(new anchor_1.BN(0))) {
|
|
161
|
+
console.log("No pending transfer liability to bridge. Exiting...");
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
console.log("Bridging liability to hub pool...");
|
|
165
|
+
const txHash = await bridgeTokensToHubPool(liability.pendingToHubPool, provider.wallet, statePda, new web3_js_1.PublicKey(svmUsdc));
|
|
166
|
+
const attestationResponse = await (0, cctpHelpers_1.getMessages)(txHash, solanaDomain, irisApiUrl);
|
|
167
|
+
const { attestation, message, eventNonce } = attestationResponse.messages[0];
|
|
168
|
+
console.log("CCTP attestation response:", attestationResponse.messages[0]);
|
|
169
|
+
const nonceHash = ethers_1.ethers.utils.solidityKeccak256(["uint32", "uint64"], [solanaDomain, eventNonce]);
|
|
170
|
+
const usedNonces = await messageTransmitter.usedNonces(nonceHash);
|
|
171
|
+
if (usedNonces.eq(1)) {
|
|
172
|
+
console.log(`Skipping already received message. Exiting...`);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
console.log("Receiving message from CCTP...");
|
|
176
|
+
const receiveTx = await messageTransmitter.receiveMessage(message, attestation);
|
|
177
|
+
console.log(`Tx hash: ${receiveTx.hash}`);
|
|
178
|
+
await receiveTx.wait();
|
|
179
|
+
console.log(`Received message`);
|
|
180
|
+
const usdcBalanceAfter = await usdc.balanceOf(hubPoolAddress);
|
|
181
|
+
console.log(`Hub Pool USDC balance after: ${(0, helpers_1.formatUsdc)(usdcBalanceAfter)}. Received ${(0, helpers_1.formatUsdc)(usdcBalanceAfter.sub(usdcBalanceBefore))} USDC.`);
|
|
182
|
+
console.log("✅ Bridge liability to hub pool completed successfully.");
|
|
183
|
+
}
|
|
184
|
+
async function bridgeTokensToHubPool(amount, signer, statePda, inputToken) {
|
|
185
|
+
const messageTransmitterProgram = new anchor_1.Program(messageTransmitterIdl, provider);
|
|
186
|
+
const vault = (0, spl_token_1.getAssociatedTokenAddressSync)(inputToken, statePda, true, spl_token_1.TOKEN_PROGRAM_ID, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
187
|
+
// Derive the transferLiability PDA
|
|
188
|
+
const [transferLiability] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("transfer_liability"), inputToken.toBuffer()], svmSpokeProgram.programId);
|
|
189
|
+
const tokenMessengerMinterProgram = new anchor_1.Program(tokenMessengerMinterIdl, provider);
|
|
190
|
+
const [tokenMessengerMinterSenderAuthority] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("sender_authority")], tokenMessengerMinterProgram.programId);
|
|
191
|
+
const [messageTransmitter] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("message_transmitter")], messageTransmitterProgram.programId);
|
|
192
|
+
const [tokenMessenger] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("token_messenger")], tokenMessengerMinterProgram.programId);
|
|
193
|
+
const [remoteTokenMessenger] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("remote_token_messenger"), Buffer.from(anchor.utils.bytes.utf8.encode(ethereumDomain.toString()))], tokenMessengerMinterProgram.programId);
|
|
194
|
+
const [tokenMinter] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("token_minter")], tokenMessengerMinterProgram.programId);
|
|
195
|
+
const [localToken] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("local_token"), inputToken.toBuffer()], tokenMessengerMinterProgram.programId);
|
|
196
|
+
const [cctpEventAuthority] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("__event_authority")], tokenMessengerMinterProgram.programId);
|
|
197
|
+
const messageSentEventData = anchor.web3.Keypair.generate(); // This will hold the message sent event data.
|
|
198
|
+
const bridgeTokensToHubPoolAccounts = {
|
|
199
|
+
payer: signer.publicKey,
|
|
200
|
+
mint: inputToken,
|
|
201
|
+
state: statePda,
|
|
202
|
+
transferLiability,
|
|
203
|
+
vault,
|
|
204
|
+
tokenMessengerMinterSenderAuthority,
|
|
205
|
+
messageTransmitter,
|
|
206
|
+
tokenMessenger,
|
|
207
|
+
remoteTokenMessenger,
|
|
208
|
+
tokenMinter,
|
|
209
|
+
localToken,
|
|
210
|
+
messageSentEventData: messageSentEventData.publicKey,
|
|
211
|
+
messageTransmitterProgram: messageTransmitterProgram.programId,
|
|
212
|
+
tokenMessengerMinterProgram: tokenMessengerMinterProgram.programId,
|
|
213
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
214
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
215
|
+
cctpEventAuthority: cctpEventAuthority,
|
|
216
|
+
program: svmSpokeProgram.programId,
|
|
217
|
+
};
|
|
218
|
+
const initialVaultBalance = (await provider.connection.getTokenAccountBalance(vault)).value.amount;
|
|
219
|
+
const tx = await svmSpokeProgram.methods
|
|
220
|
+
.bridgeTokensToHubPool(new anchor_1.BN(amount))
|
|
221
|
+
.accounts(bridgeTokensToHubPoolAccounts)
|
|
222
|
+
.signers([messageSentEventData])
|
|
223
|
+
.rpc();
|
|
224
|
+
const finalVaultBalance = (await provider.connection.getTokenAccountBalance(vault)).value.amount;
|
|
225
|
+
console.log(`SVM Spoke Pool Initial Vault balance: ${(0, helpers_1.formatUsdc)(ethers_1.BigNumber.from(initialVaultBalance))} USDC.`);
|
|
226
|
+
console.log(`SVM Spoke Pool Final Vault balance: ${(0, helpers_1.formatUsdc)(ethers_1.BigNumber.from(finalVaultBalance))} USDC.`);
|
|
227
|
+
console.log(`Sent ${(0, helpers_1.formatUsdc)(ethers_1.BigNumber.from(initialVaultBalance).sub(ethers_1.BigNumber.from(finalVaultBalance)))} USDC through CCTP.`);
|
|
228
|
+
return tx;
|
|
229
|
+
}
|
|
230
|
+
// Run the bridgeLiabilityToHubPool function
|
|
231
|
+
bridgeLiabilityToHubPool();
|
|
@@ -34,7 +34,6 @@ const web3_js_1 = require("@solana/web3.js");
|
|
|
34
34
|
const yargs_1 = __importDefault(require("yargs"));
|
|
35
35
|
const helpers_1 = require("yargs/helpers");
|
|
36
36
|
const SvmUtils_1 = require("../../src/SvmUtils");
|
|
37
|
-
const SvmUtils_2 = require("../../src/SvmUtils");
|
|
38
37
|
// Set up the provider
|
|
39
38
|
const provider = anchor_1.AnchorProvider.env();
|
|
40
39
|
anchor.setProvider(provider);
|
|
@@ -78,7 +77,7 @@ async function closeExpiredRelays() {
|
|
|
78
77
|
}
|
|
79
78
|
async function closeFillPda(eventData, seed) {
|
|
80
79
|
// Accept seed as a parameter
|
|
81
|
-
const
|
|
80
|
+
const relayEventData = {
|
|
82
81
|
depositor: new web3_js_1.PublicKey(eventData.depositor),
|
|
83
82
|
recipient: new web3_js_1.PublicKey(eventData.recipient),
|
|
84
83
|
exclusiveRelayer: new web3_js_1.PublicKey(eventData.exclusiveRelayer),
|
|
@@ -90,13 +89,13 @@ async function closeFillPda(eventData, seed) {
|
|
|
90
89
|
depositId: eventData.depositId,
|
|
91
90
|
fillDeadline: eventData.fillDeadline,
|
|
92
91
|
exclusivityDeadline: eventData.exclusivityDeadline,
|
|
93
|
-
|
|
92
|
+
messageHash: eventData.messageHash,
|
|
94
93
|
};
|
|
95
94
|
const [statePda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("state"), seed.toArrayLike(Buffer, "le", 8)], programId);
|
|
96
95
|
// Fetch the state to get the chainId
|
|
97
96
|
const state = await program.account.state.fetch(statePda);
|
|
98
97
|
const chainId = new anchor_1.BN(state.chainId);
|
|
99
|
-
const relayHashUint8Array = (0,
|
|
98
|
+
const relayHashUint8Array = (0, SvmUtils_1.calculateRelayEventHashUint8Array)(relayEventData, chainId);
|
|
100
99
|
const [fillStatusPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("fills"), relayHashUint8Array], programId);
|
|
101
100
|
try {
|
|
102
101
|
// Check if the fillStatusPda account exists
|
|
@@ -106,8 +105,8 @@ async function closeFillPda(eventData, seed) {
|
|
|
106
105
|
return;
|
|
107
106
|
}
|
|
108
107
|
// Display additional information in a table
|
|
109
|
-
console.log("Found a relay to close. Relay
|
|
110
|
-
console.table(Object.entries(
|
|
108
|
+
console.log("Found a relay to close. Relay event data:");
|
|
109
|
+
console.table(Object.entries(relayEventData).map(([key, value]) => ({
|
|
111
110
|
key,
|
|
112
111
|
value: value.toString(),
|
|
113
112
|
})));
|
|
@@ -116,7 +115,7 @@ async function closeFillPda(eventData, seed) {
|
|
|
116
115
|
{ Property: "Fill Status PDA", Value: fillStatusPda.toString() },
|
|
117
116
|
{ Property: "Relay Hash", Value: Buffer.from(relayHashUint8Array).toString("hex") },
|
|
118
117
|
]);
|
|
119
|
-
const tx = await program.methods.closeFillPda(
|
|
118
|
+
const tx = await program.methods.closeFillPda()
|
|
120
119
|
.accounts({
|
|
121
120
|
state: statePda,
|
|
122
121
|
signer: provider.wallet.publicKey,
|
|
@@ -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" })
|
|
@@ -54,7 +55,12 @@ async function enableRoute() {
|
|
|
54
55
|
// Define the state account PDA
|
|
55
56
|
const [statePda, _] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("state"), seed.toArrayLike(Buffer, "le", 8)], programId);
|
|
56
57
|
// Define the route account PDA
|
|
57
|
-
const [routePda] = web3_js_1.PublicKey.findProgramAddressSync([
|
|
58
|
+
const [routePda] = web3_js_1.PublicKey.findProgramAddressSync([
|
|
59
|
+
Buffer.from("route"),
|
|
60
|
+
originToken.toBytes(),
|
|
61
|
+
seed.toArrayLike(Buffer, "le", 8),
|
|
62
|
+
chainId.toArrayLike(Buffer, "le", 8),
|
|
63
|
+
], programId);
|
|
58
64
|
// Define the signer (replace with your actual signer)
|
|
59
65
|
const signer = provider.wallet.publicKey;
|
|
60
66
|
console.log("Enabling route...");
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Script: Execute USDC Rebalance to Hub Pool
|
|
3
|
+
*
|
|
4
|
+
* This script executes a previously proposed root bundle on the Hub Pool to rebalance USDC from the Solana Spoke Pool
|
|
5
|
+
* to the Ethereum Hub Pool. It handles CCTP attestations, relayer refund leaf execution, and prepares pending
|
|
6
|
+
* liabilities for bridging back to the Hub Pool.
|
|
7
|
+
*
|
|
8
|
+
* Required Environment Variables:
|
|
9
|
+
* - TESTNET: (Optional) Set to "true" to use Sepolia; defaults to mainnet.
|
|
10
|
+
* - MNEMONIC: Wallet mnemonic to sign the Ethereum transaction.
|
|
11
|
+
* - HUB_POOL_ADDRESS: Ethereum address of the Hub Pool.
|
|
12
|
+
* - NODE_URL_1: Ethereum RPC URL for mainnet (ignored if TESTNET=true).
|
|
13
|
+
* - NODE_URL_11155111: Ethereum RPC URL for Sepolia (ignored if TESTNET=false).
|
|
14
|
+
*
|
|
15
|
+
* Required Arguments:
|
|
16
|
+
* - `--netSendAmount`: The unscaled amount of USDC to rebalance (e.g., for USDC with 6 decimals, 1 = 0.000001 USDC).
|
|
17
|
+
* - `--resumeRemoteTx`: (Optional) Hash of a previously submitted remote transaction to resume.
|
|
18
|
+
*
|
|
19
|
+
* Example Usage:
|
|
20
|
+
* TESTNET=true \
|
|
21
|
+
* NODE_URL_11155111=$NODE_URL_11155111 \
|
|
22
|
+
* MNEMONIC=$MNEMONIC \
|
|
23
|
+
* HUB_POOL_ADDRESS=$HUB_POOL_ADDRESS \
|
|
24
|
+
* anchor run executeRebalanceToHubPool \
|
|
25
|
+
* --provider.cluster "devnet" \
|
|
26
|
+
* --provider.wallet $SOLANA_PKEY_PATH \
|
|
27
|
+
* -- --netSendAmount 7
|
|
28
|
+
*
|
|
29
|
+
* Note:
|
|
30
|
+
* - Ensure all required environment variables are properly configured.
|
|
31
|
+
*/
|
|
32
|
+
export {};
|