-
Notifications
You must be signed in to change notification settings - Fork 75
feat(HubPool): Add initial L1->L2 call plumbing #19
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
chrismaree
commented
Feb 3, 2022
- nit
- nit
- nit
- Update contracts/HubPool.sol
- review nit
- review nit
- feat(hubpool): Refactor hub pool to use 1D bitmap integer
- nit
- WIP
- review nit
- review nit
- nit
- nit
- nit
- nit
- nit
- nit
- WIP
- nit
- nit
Co-authored-by: Matt Rice <matthewcrice32@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
Signed-off-by: chrismaree <christopher.maree@gmail.com>
contracts/HubPool.sol
Outdated
| _sendTokensToTargetChain(poolRebalance, refundRequestId); | ||
| _executeRelayerRefundOnTargetChain(poolRebalance, refundRequestId); |
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.
all the logic of sending tokens to the chains and sending the L1->L2 calls is wrapped into these two functions :)
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.
On L2, what happens if the relayer refund method on the spoke pool is executed before tokens arrive there?
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.
it'll revert as there is not enough money to pay everyone.
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.
Let me be sure I have the right understanding here:
- This will just send over a verified root that will be saved on the L2. No funds get automatically distributed.
- If funds haven't arrived and someone tried to distribute on the L2, their transaction will revert.
Is my understanding correct? In no situation should the L2 side of the _executeRelayerRefundOnTargetChain transaction revert, right?
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 is exactly right @mrice32
| if (refundRequest.unclaimedPoolRebalanceLeafCount == 0) | ||
| bondToken.safeTransfer(refundRequest.proposer, bondAmount); | ||
| } |
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.
it's better to only pay the relayer back their bond one all bundles are executed.
contracts/HubPool.sol
Outdated
| AdapterInterface adapter = crossChainContracts[poolRebalance.chainId].adapter; | ||
| adapter.relayMessage( | ||
| address(adapter), | ||
| abi.encodeWithSignature("initializeRelayerRefund(address)", refundRequest.destinationDistributionRoot) |
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 should be "bytes32" not "address" right?
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.
it should! fixed.
| emit FilledRelay(relayHash, relayFills[relayHash], repaymentChain, amountToSend, msg.sender, relayData); | ||
| } | ||
|
|
||
| function initializeRelayerRefund(bytes32 relayerRepaymentDistributionProof) public {} |
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.
nit to give me the required interface. @nicholaspai 's PR implements this actual logic.
| @@ -0,0 +1,81 @@ | |||
| import { expect } from "chai"; | |||
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 have split the HubPool rebalance unit tests into 3 separate files: Initialization,Execution and Dispute.
test/HubPool.RefundExecution.ts
Outdated
| await hubPool.connect(liquidityProvider).addLiquidity(dai.address, consts.amountToLp.mul(10)); | ||
| }); | ||
|
|
||
| it("Execute relayer refund correctly produces the refund bundle call and sends cross-chain repayment actions", async function () { |
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 test covers the main logic added in this PR. please read through it to see how the leafs are created, tree constructed, refund initiated and finally executed.
| const { defaultAbiCoder, keccak256 } = ethers.utils; | ||
| import { BigNumber, Signer, Contract } from "ethers"; | ||
|
|
||
| export interface PoolRebalance { |
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.
these interfaces were moved to here to from test/MerkleLib.Proofs.ts.
| return ethers.utils.getAddress(ethers.utils.hexlify(ethers.utils.randomBytes(20))); | ||
| } | ||
|
|
||
| export async function getParamType(contractName: string, functionName: string, paramName: string) { |
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.
new function to return the types of a function's parameters. used when building Merkle trees.
|
|
||
| export function randomAddress() { | ||
| return ethers.utils.hexlify(ethers.utils.randomBytes(20)); | ||
| return ethers.utils.getAddress(ethers.utils.hexlify(ethers.utils.randomBytes(20))); |
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.
using the .getAddress call checksum cases the address.
| @@ -0,0 +1,66 @@ | |||
| import { expect } from "chai"; | |||
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.
nothing changed here, just moved and cut down on redundant imports/method calls.
| @@ -1,91 +1,35 @@ | |||
| import { expect } from "chai"; | |||
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.
nothing changed here, just moved and cut down on redundant imports/method calls.
mrice32
left a comment
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.
There are a few commend threads that still need to be resolved, but otherwise, LGTM!
contracts/MerkleLib.sol
Outdated
| // The following arrays are required to be the same length. They are parallel arrays for the given chainId and should be ordered by the `l1Token` field. | ||
| // All whitelisted tokens with nonzero relays on this chain in this bundle in the order of whitelisting. | ||
| address[] tokenAddresses; | ||
| address[] l1Token; |
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.
| address[] l1Token; | |
| address[] l1Tokens; |
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.
if we make this change should we make all the arrays plural? netSendAmounts runningBalances?
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 think arrays should always be plural
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, I agree. If we didn't do so before in our structs (which could be my fault), I think we should update.
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.
ok will update accordingly on all variables in all places.
| address indexed disputer, | ||
| SkinnyOptimisticOracleInterface.Request ooPriceRequest, | ||
| RefundRequest refundRequest | ||
| event RelayerRefundExecuted( |
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.
are any of these events indexable?
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.
yup. will index appropriate ones.
| ).deploy(weth.address, 0, parentFixtureOutput.timer.address); | ||
| await hubPool.setCrossChainContracts(repaymentChainId, mockAdapter.address, mockSpoke.address); | ||
|
|
||
| // Deploy mock l2 tokens for each token created before and whitelist the routes. |
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.
nit: is there any benefit to running all these async funcs in parallel? I know the test network is already super fast but we could possibly get even faster?
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 dont think really. I think optimising for readability is the most important thing in fixtures IMHO.
test/HubPool.RefundExecution.ts
Outdated
| // two token to one chain Id with simple lpFee, netSend and running balance amounts. | ||
| const wethToSend = toBNWei(100); | ||
| const daiToSend = toBNWei(1000); | ||
| const leafs = buildPoolRebalanceLeafs( |
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.
Useful function +1
contracts/HubPool.sol
Outdated
|
|
||
| function executeRelayerRefund( | ||
| uint256 relayerRefundRequestId, | ||
| uint256 refundRequestId, |
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.
As discussed offline, i think we can remove refundRequestId, rename poolRebalance to poolRebalanceLeaf and rename proof to inclusionProof
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.
yup!
| bytes32 poolRebalanceRoot, | ||
| bytes32 destinationDistributionRoot | ||
| ) public onlyIfNoActiveRequest { | ||
| ) public noActiveRequests { |
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.
As discussed IRL:
- consider adding a comment that after
initiateRelayerRefundis called, if thepoolRebalanceRoot,destinationDistributionRoot,poolRebalanceLeafCount, andbundleEvaluationBlockNumbersset is disputable then this can be challenged. Once the challenge period passes, then the roots are no longer disputable, and onlyexecuteRelayerRefundcan be called andinitiateRelayerRefundcan't be called again until all leafs are executed. - Examples of some characteristics of these roots that could be disputed:
poolRebalanceRoot.netSendAmount != destinationDistributionRoot.amountToReturnfor example
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.
Motivation is updated comments + interface for the spoke pool distributeRelayerRefund in my PR: 8fb750a
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.
will do!