-
Notifications
You must be signed in to change notification settings - Fork 75
feat: rebalance to hub pool script #786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: Pablo Maldonado <pablomaldonadoturci@gmail.com>
Signed-off-by: Pablo Maldonado <pablomaldonadoturci@gmail.com>
Signed-off-by: Pablo Maldonado <pablomaldonadoturci@gmail.com>
Signed-off-by: Pablo Maldonado <pablomaldonadoturci@gmail.com>
Signed-off-by: Pablo Maldonado <pablomaldonadoturci@gmail.com>
Signed-off-by: Pablo Maldonado <pablomaldonadoturci@gmail.com>
Signed-off-by: Pablo Maldonado <pablomaldonadoturci@gmail.com>
scripts/svm/utils/constants.ts
Outdated
| export const SEPOLIA_USDC_ADDRESS = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"; | ||
| export const MAINNET_USDC_ADDRESS = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better reuse TOKEN_SYMBOLS_MAP as exported in utils/constants.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean doing this?
c17299c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kindof, but better avoid putting the var in constants and not pass chainId. E.g. can pull required token for required chain dynamically, like here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are absolutely right. I fixed it here: 10a60f2
| const tx = await hubPool.connect(ethersSigner).proposeRootBundle( | ||
| [0], // bundleEvaluationBlockNumbers, not checked in this script. | ||
| 1, // poolRebalanceLeafCount, only one leaf in this script. | ||
| poolRebalanceTree.getHexRoot(), // poolRebalanceRoot. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is pool rebalance needed, cannot it be zero hash?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven’t been able to do it with a zero hash in the poolRebalanceTree. I think we need to pass at least a tree with one leaf; the leaf can be constructed with zero hashes, except for the chain ID. Otherwise, we cannot get past this line when calling executeRootBundle:
contracts/contracts/HubPool.sol
Lines 635 to 651 in 1606063
| // Verify the props provided generate a leaf that, along with the proof, are included in the merkle root. | |
| require( | |
| MerkleLib.verifyPoolRebalance( | |
| rootBundleProposal.poolRebalanceRoot, | |
| PoolRebalanceLeaf({ | |
| chainId: chainId, | |
| groupIndex: groupIndex, | |
| bundleLpFees: bundleLpFees, | |
| netSendAmounts: netSendAmounts, | |
| runningBalances: runningBalances, | |
| leafId: leafId, | |
| l1Tokens: l1Tokens | |
| }), | |
| proof | |
| ), | |
| "Bad Proof" | |
| ); |
Additionally, the chain ID needs to be valid; otherwise, this line fails:
contracts/contracts/HubPool.sol
Line 655 in 1606063
| (address adapter, address spokePool) = _getInitializedCrossChainContracts(chainId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, yes, you're totally right on this!
Signed-off-by: Pablo Maldonado <pablomaldonadoturci@gmail.com>
Signed-off-by: Pablo Maldonado <pablomaldonadoturci@gmail.com>
| } | ||
|
|
||
| // Run the bridgeLiabilityToHubPool function | ||
| bridgeLiabilityToHubPool(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this script is SUPER useful. This will basically be what the finalizer needs to do in production.
| ]); | ||
|
|
||
| const [transferLiability] = PublicKey.findProgramAddressSync( | ||
| [Buffer.from("transfer_liability"), new PublicKey(svmUsdc).toBuffer()], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
only comment I could make on this script (but I think it's fine as we do similar things all over the place) is this assumes we are working with USDC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, in many places we have dependencies on USDC, including in our smart contracts (solana adapter) and svm programs. Do you think it’s worth generalizing?
| * This script executes a previously proposed root bundle on the Hub Pool | ||
| * to rebalance USDC from the Solana Spoke Pool to the Ethereum Hub Pool. | ||
| * It handles CCTP attestations, relayer refund leaf execution, and prepares | ||
| * pending liabilities for bridging back to the Hub Pool. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just an irritating nit that like with the other scripts we have 120 chars to work with so we don't need to wrap shorter than 120.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed!
| * anchor run executeRebalanceToHubPool \ | ||
| * --provider.cluster "devnet" \ | ||
| * --provider.wallet $SOLANA_PKEY_PATH \ | ||
| * -- --netSendAmount 7 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so this is provided to re-construct the merkle leaf & proof? it also assumes that there are no relayer repayments within the leaf, right?
in practice, I don't think this is how this flow will work, right? it's assumed that the data worker will post the leafs & proofs to a public location so these can be retrieved. this particular script flow is only useful in this particular situation where you don't have any relayer repayments & we only do a net repayment.
It would be useful to be able to pass in the leafs as en env/json or something like this? this would let you take them from the script that does the proposing, save them, and then not need to re-generate them. it would also better track with what things will look like when we interface with the data worker later (executor should not need to generate leafs, just get given them)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(prehaps this is still useful if we are dealing with JUST creating leafs to pull/push tokens to/from SVM via the netSendAmount
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, exactly. The netSendAmount is merely to avoid having to pass leaves, roots, proofs, etc., between this script and proposeRebalanceToHubPool.ts. It also assumes that the poolRebalanceTree has a single leaf with empty data and the solanaChainId. Thus, both scripts are dependent on each other. I believe they do not showcase a real production scenario; they are more like helpers to test the rebalance from the SVM Spoke to the HubPool.
On the other hand, I separated bridgeLiabilityToHubPool.ts from them because this one could represent a real use case, as you pointed out. It’s essentially what the finalizer needs to do.
Signed-off-by: Pablo Maldonado <pablomaldonadoturci@gmail.com>
Changes Proposed in this PR:
This PR introduces scripts to manage the full lifecycle of a rootBundle workflow for rebalancing USDC between the SVM Spoke Pool and the Hub Pool on mainnet. The process includes proposing a rootBundle, executing it after the liveness period, bridging via CCTP, and handling liabilities. The workflow is divided into three scripts:
proposeRebalanceToHubPool: Proposes the rebalance from the Spoke Pool to the Hub Pool in the Hub Pool.executeRebalanceToHubPool: Executes the approved rebalance in the Hub Pool, bridges it via CCTP to the Spoke Pool, and processes the relayer refund leaf to create the liability.bridgeLiabilityToHubPool: Bridges any pending liability from the SVM Spoke Pool back to the Hub Pool via CCTP.