From f3b7fd961094bfae9ec2100bd3dd87c7896e6665 Mon Sep 17 00:00:00 2001 From: Oleksii Matiiasevych Date: Thu, 19 Jun 2025 15:36:33 +0700 Subject: [PATCH 1/4] Add cctp helper script and docs --- README.md | 55 +++++++++++++++++++++++++++++++++++++++++++++ hardhat.config.ts | 57 +++++++++++++++++++++++++++++++++++++++++++++-- scripts/common.ts | 10 +++++++++ 3 files changed, 120 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2642c5c..cbaa28a 100644 --- a/README.md +++ b/README.md @@ -43,3 +43,58 @@ You could optionally set VERIFY to `true` in order to publish the source code af [Base Sepolia](deployments/deploy-basesepolia.log), [Optimism Sepolia](deployments/deploy-opsepolia.log), [Arbitrum Sepolia](deployments/deploy-arbitrumsepolia.log) [Base](deployments/deploy-base.log), [Optimism Mainnet](deployments/deploy-opmainnet.log), [Arbitrum One](deployments/deploy-arbitrumone.log) + +### Rebalancing + +Manual Rebalance transaction creation through Safe UI: + +1. Connect to the operations multisig on the source chain. +2. Click New Transaction -> Transaction Builder (URL is like: https://app.safe.global/apps/open?safe=base:0x83B8D2eAda788943c3e80892f37f9c102271C1D6&appUrl=https%3A%2F%2Fapps-portal.safe.global%2Ftx-builder) +3. Enter Rebalancer address from deployments config: 0xA85Cf46c150db2600b1D03E437bedD5513869888 +4. Enter initiateRebalance ABI: + [{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"sourcePool","type":"address"},{"internalType":"address","name":"destinationPool","type":"address"},{"internalType":"enum IRoute.Domain","name":"destinationDomain","type":"uint8"},{"internalType":"enum IRoute.Provider","name":"provider","type":"uint8"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"initiateRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"}] +5. Fill in transaction details (Base -> Base): +5.1 Amount: 100000000000 (100,000,000000 USDC with 6 decimals). +5.2 Source Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). +5.3 Destination Pool: 0xB58Bb9643884abbbad64FA7eBc874c5481E5c032 (USDC pool). +5.4 Destination Domain: 4 (Base, Reference https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L38). +5.5 Provider: 0 (Local, Reference: https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L30). +5.6 Extra Data: 0x (Depends on the selected provider). + +6. Click + Add new transaction. +7. Optionally add more transactions to the batch. + +7. Fill in transaction details (Base -> Arbitrum): +7.1 Amount: 500000000000 (500,000,000000 USDC with 6 decimals). +7.2 Source Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). +7.3 Destination Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). +7.4 Destination Domain: 3 (Arbitrum One, Reference https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L38). +7.5 Provider: 1 (CCTP, Reference: https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L30). +7.6 Extra Data: 0x (Depends on the selected provider). + +8. Click Create Batch. +9. Click Simulate. +10. Click Send Batch. + +=== + +If rebalancing destination was another chain, then you will need to execute one more transaction on the destination multisig. +By CCTP V1 docs it says that attestation could be produced 9-19 minutes after initial transaction, you will need a tx hash for that. + +1. Execute the following in the sprinter stash repo for the source network `hardhat --network BASE cctp-get-process-data --txhash {initiate tx hash}` to get extra data. If there were multiple rebalances, there would be multiple extra datas, one for each processRebalance call. +2. Connect to the operations multisig on the destination chain. +3. Click New Transaction -> Transaction Builder. +4. Enter Rebalancer address from deployments config: 0xA85Cf46c150db2600b1D03E437bedD5513869888 +5. Enter processRebalance ABI: + [{"inputs":[{"internalType":"address","name":"destinationPool","type":"address"},{"internalType":"enum IRoute.Provider","name":"provider","type":"uint8"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"processRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"}] +6. Fill in transaction details: +6.1 Destination Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). +6.2 Provider: 1 (CCTP, Reference: https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L30). +6.3 Extra Data: take form step (1). + +7. Click + Add new transaction. +8. Optionally add more transactions to the batch. + +9. Click Create Batch. +10. Click Simulate. +11. Click Send Batch. diff --git a/hardhat.config.ts b/hardhat.config.ts index 1c0b2af..902597a 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,12 +1,12 @@ import {HardhatUserConfig, task, types} from "hardhat/config"; import "@nomicfoundation/hardhat-toolbox"; import {networkConfig, Network, Provider} from "./network.config"; -import {TypedDataDomain} from "ethers"; +import {TypedDataDomain, AbiCoder, toNumber, dataSlice} from "ethers"; import { LiquidityPoolAave, Rebalancer, Repayer } from "./typechain-types"; import { - assert, isSet, ProviderSolidity, DomainSolidity, + assert, isSet, ProviderSolidity, DomainSolidity, CCTPDomain, } from "./scripts/common"; import "hardhat-ignore-warnings"; @@ -238,6 +238,59 @@ task("sign-borrow", "Sign a Liquidity Pool borrow request for testing purposes") console.log(`signature: ${sig}`); }); +interface CCTPMessage { + attestation: string, + message: string, + eventNonce: string, +}; + +interface CCTPResponseSuccess { + messages: CCTPMessage[], +}; + +task("cctp-get-process-data", "Get burn attestation from CCTP Api to mint USDC on destination") +.addParam("txhash", "Hash of the initiate transaction") +.addOptionalParam("adapter", "Rebalancer or Repayer address", "0xA85Cf46c150db2600b1D03E437bedD5513869888") +.setAction(async ({txhash, adapter}: {txhash: string, adapter: string}, hre) => { + const {resolveProxyXAddress} = await loadTestHelpers(); + assert(txhash.length > 0, "Valid txhash should be provided."); + + const cctpAdapter = await hre.ethers.getContractAt("CCTPAdapter", await resolveProxyXAddress(adapter)); + const cctpDomain = await cctpAdapter.domainCCTP(DomainSolidity[hre.network.name as Network]); + + const url = `https://iris-api.circle.com/v1/messages/${cctpDomain}/${txhash}`; + const options = {method: "GET", headers: {"Content-Type": "application/json"}}; + const result = await (await fetch(url, options)).json(); + + if (result.error) { + console.error(result.error); + return; + } + + const success = result as CCTPResponseSuccess; + + assert(success.messages, `Messages are missing in CCTP response: ${success}`); + + if (!success.messages[0].attestation.startsWith("0x")) { + console.error("Attestation is not ready:", success.messages[0].attestation); + return; + } + + const extraDatas = success.messages.map(el => { + const destinationCCTP = toNumber(dataSlice(el.message, 8, 12)); + const destination = CCTPDomain[destinationCCTP]; + assert(destination, `Unknown CCTP domain ${destinationCCTP}`); + return { + destination, + extraData: AbiCoder.defaultAbiCoder().encode(["bytes", "bytes"], [el.message, el.attestation]), + }; + }); + + const count = extraDatas.length; + console.log(count, `message${count > 1 ? "s" : ""} found.`); + console.log(extraDatas); +}); + const accounts: string[] = isSet(process.env.PRIVATE_KEY) ? [process.env.PRIVATE_KEY || ""] : []; const config: HardhatUserConfig = { diff --git a/scripts/common.ts b/scripts/common.ts index 26dc591..eaab186 100644 --- a/scripts/common.ts +++ b/scripts/common.ts @@ -1,4 +1,5 @@ import {isAddress, getAddress} from "ethers"; +import {Network} from "../network.config"; export function assert(condition: any, message: string): asserts condition { if (!condition) { @@ -50,6 +51,15 @@ export const DomainSolidity = { POLYGON_AMOY: 11n, }; +export const CCTPDomain: { [n: number]: Network } = { + 0: Network.ETHEREUM, + 1: Network.AVALANCHE, + 2: Network.OP_MAINNET, + 3: Network.ARBITRUM_ONE, + 6: Network.BASE, + 7: Network.POLYGON_MAINNET, +}; + export const DEFAULT_PROXY_TYPE = "TransparentUpgradeableProxy"; export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; From 30bf75c3b7d494820f0f64a64b6d4209ecc7a73e Mon Sep 17 00:00:00 2001 From: Oleksii Matiiasevych Date: Thu, 19 Jun 2025 15:45:25 +0700 Subject: [PATCH 2/4] Cleanup readme --- README.md | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index cbaa28a..a5412ac 100644 --- a/README.md +++ b/README.md @@ -52,31 +52,33 @@ Manual Rebalance transaction creation through Safe UI: 2. Click New Transaction -> Transaction Builder (URL is like: https://app.safe.global/apps/open?safe=base:0x83B8D2eAda788943c3e80892f37f9c102271C1D6&appUrl=https%3A%2F%2Fapps-portal.safe.global%2Ftx-builder) 3. Enter Rebalancer address from deployments config: 0xA85Cf46c150db2600b1D03E437bedD5513869888 4. Enter initiateRebalance ABI: - [{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"sourcePool","type":"address"},{"internalType":"address","name":"destinationPool","type":"address"},{"internalType":"enum IRoute.Domain","name":"destinationDomain","type":"uint8"},{"internalType":"enum IRoute.Provider","name":"provider","type":"uint8"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"initiateRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"}] + + `[{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"sourcePool","type":"address"},{"internalType":"address","name":"destinationPool","type":"address"},{"internalType":"enum IRoute.Domain","name":"destinationDomain","type":"uint8"},{"internalType":"enum IRoute.Provider","name":"provider","type":"uint8"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"initiateRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"}]` + 5. Fill in transaction details (Base -> Base): -5.1 Amount: 100000000000 (100,000,000000 USDC with 6 decimals). -5.2 Source Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). -5.3 Destination Pool: 0xB58Bb9643884abbbad64FA7eBc874c5481E5c032 (USDC pool). -5.4 Destination Domain: 4 (Base, Reference https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L38). -5.5 Provider: 0 (Local, Reference: https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L30). -5.6 Extra Data: 0x (Depends on the selected provider). + * Amount: 100000000000 (100,000,000000 USDC with 6 decimals). + * Source Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). + * Destination Pool: 0xB58Bb9643884abbbad64FA7eBc874c5481E5c032 (USDC pool). + * Destination Domain: 4 (Base, Reference https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L38). + * Provider: 0 (Local, Reference: https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L30). + * Extra Data: 0x (Depends on the selected provider). 6. Click + Add new transaction. 7. Optionally add more transactions to the batch. 7. Fill in transaction details (Base -> Arbitrum): -7.1 Amount: 500000000000 (500,000,000000 USDC with 6 decimals). -7.2 Source Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). -7.3 Destination Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). -7.4 Destination Domain: 3 (Arbitrum One, Reference https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L38). -7.5 Provider: 1 (CCTP, Reference: https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L30). -7.6 Extra Data: 0x (Depends on the selected provider). + * Amount: 500000000000 (500,000,000000 USDC with 6 decimals). + * Source Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). + * Destination Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). + * Destination Domain: 3 (Arbitrum One, Reference https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L38). + * Provider: 1 (CCTP, Reference: https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L30). + * Extra Data: 0x (Depends on the selected provider). 8. Click Create Batch. 9. Click Simulate. 10. Click Send Batch. -=== +--- If rebalancing destination was another chain, then you will need to execute one more transaction on the destination multisig. By CCTP V1 docs it says that attestation could be produced 9-19 minutes after initial transaction, you will need a tx hash for that. @@ -86,15 +88,17 @@ By CCTP V1 docs it says that attestation could be produced 9-19 minutes after in 3. Click New Transaction -> Transaction Builder. 4. Enter Rebalancer address from deployments config: 0xA85Cf46c150db2600b1D03E437bedD5513869888 5. Enter processRebalance ABI: - [{"inputs":[{"internalType":"address","name":"destinationPool","type":"address"},{"internalType":"enum IRoute.Provider","name":"provider","type":"uint8"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"processRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"}] + + `[{"inputs":[{"internalType":"address","name":"destinationPool","type":"address"},{"internalType":"enum IRoute.Provider","name":"provider","type":"uint8"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"processRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"}]` + 6. Fill in transaction details: -6.1 Destination Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). -6.2 Provider: 1 (CCTP, Reference: https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L30). -6.3 Extra Data: take form step (1). + * Destination Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). + * Provider: 1 (CCTP, Reference: https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L30). + * Extra Data: take form step (1). 7. Click + Add new transaction. 8. Optionally add more transactions to the batch. 9. Click Create Batch. 10. Click Simulate. -11. Click Send Batch. +11. Click Send Batch. \ No newline at end of file From 33ecfe895bd9a5df42c2e254ffd9c83e5e58aea5 Mon Sep 17 00:00:00 2001 From: Oleksii Matiiasevych Date: Thu, 19 Jun 2025 16:57:52 +0700 Subject: [PATCH 3/4] Reformat README --- README.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a5412ac..d24ae30 100644 --- a/README.md +++ b/README.md @@ -52,9 +52,15 @@ Manual Rebalance transaction creation through Safe UI: 2. Click New Transaction -> Transaction Builder (URL is like: https://app.safe.global/apps/open?safe=base:0x83B8D2eAda788943c3e80892f37f9c102271C1D6&appUrl=https%3A%2F%2Fapps-portal.safe.global%2Ftx-builder) 3. Enter Rebalancer address from deployments config: 0xA85Cf46c150db2600b1D03E437bedD5513869888 4. Enter initiateRebalance ABI: - - `[{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"sourcePool","type":"address"},{"internalType":"address","name":"destinationPool","type":"address"},{"internalType":"enum IRoute.Domain","name":"destinationDomain","type":"uint8"},{"internalType":"enum IRoute.Provider","name":"provider","type":"uint8"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"initiateRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"}]` - +``` +[{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}, +{"internalType":"address","name":"sourcePool","type":"address"}, +{"internalType":"address","name":"destinationPool","type":"address"}, +{"internalType":"enum IRoute.Domain","name":"destinationDomain","type":"uint8"}, +{"internalType":"enum IRoute.Provider","name":"provider","type":"uint8"}, +{"internalType":"bytes","name":"extraData","type":"bytes"}], +"name":"initiateRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"}] +``` 5. Fill in transaction details (Base -> Base): * Amount: 100000000000 (100,000,000000 USDC with 6 decimals). * Source Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). @@ -88,9 +94,12 @@ By CCTP V1 docs it says that attestation could be produced 9-19 minutes after in 3. Click New Transaction -> Transaction Builder. 4. Enter Rebalancer address from deployments config: 0xA85Cf46c150db2600b1D03E437bedD5513869888 5. Enter processRebalance ABI: - - `[{"inputs":[{"internalType":"address","name":"destinationPool","type":"address"},{"internalType":"enum IRoute.Provider","name":"provider","type":"uint8"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"processRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"}]` - +``` +[{"inputs":[{"internalType":"address","name":"destinationPool","type":"address"}, +{"internalType":"enum IRoute.Provider","name":"provider","type":"uint8"}, +{"internalType":"bytes","name":"extraData","type":"bytes"}], +"name":"processRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"}]` +``` 6. Fill in transaction details: * Destination Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool). * Provider: 1 (CCTP, Reference: https://github.com/sprintertech/sprinter-stash-contracts/blob/main/scripts/common.ts#L30). @@ -101,4 +110,4 @@ By CCTP V1 docs it says that attestation could be produced 9-19 minutes after in 9. Click Create Batch. 10. Click Simulate. -11. Click Send Batch. \ No newline at end of file +11. Click Send Batch. From f78b8da682af47af4bfd321602d903ac4310e88c Mon Sep 17 00:00:00 2001 From: Oleksii Matiiasevych Date: Thu, 19 Jun 2025 16:58:56 +0700 Subject: [PATCH 4/4] Remove quote --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d24ae30..75fad45 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ By CCTP V1 docs it says that attestation could be produced 9-19 minutes after in [{"inputs":[{"internalType":"address","name":"destinationPool","type":"address"}, {"internalType":"enum IRoute.Provider","name":"provider","type":"uint8"}, {"internalType":"bytes","name":"extraData","type":"bytes"}], -"name":"processRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"}]` +"name":"processRebalance","outputs":[],"stateMutability":"nonpayable","type":"function"}] ``` 6. Fill in transaction details: * Destination Pool: 0x7C255279c098fdF6c3116D2BecD9978002c09f4b (AaveUSDC pool).