-
Notifications
You must be signed in to change notification settings - Fork 53
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
fix(Dataworker): Account for total required netSendAmount when executing PoolRebalanceLeaves #1933
Conversation
…RebalanceLeaves ## Context The dataworker executor functionality is supposed to detect when to call `sync()` before executing L1 PoolRebalance and RelayerRefund leaves depending on the `liquidReserves` value of l1 tokens before executing those leaves. We use pass around the `balanceAllocator` when simulating execution of the [PoolRebalanceLeaves](https://github.com/across-protocol/relayer/blob/3e9c1e4108568b39fe007f8fcd71721db4bbe090/src/dataworker/Dataworker.ts#L1491) and the [RelayerRefundLeaves](https://github.com/across-protocol/relayer/blob/3e9c1e4108568b39fe007f8fcd71721db4bbe090/src/dataworker/Dataworker.ts#L1512) in order to keep track of how many L1 tokens are withdrawn from and deposited to the HubPool following Hub-chain leaf executions. This way, we can use the `balanceAllocator` in [this function](https://github.com/across-protocol/relayer/blob/3e9c1e4108568b39fe007f8fcd71721db4bbe090/src/dataworker/Dataworker.ts#L1531) to detect when we're not going to have enough funds in LP reserves to execute a leaf [here](https://github.com/across-protocol/relayer/blob/3e9c1e4108568b39fe007f8fcd71721db4bbe090/src/dataworker/Dataworker.ts#L1823). ## Problem The problem is that when accounting for PoolRebalanceLeaf executions, we were ADDING not subtracting balance to the balanceAllocator's count of the hubpool's reserves. This means that if the current `liquidReserves` were good enough to cover execution of the Ethereum PoolRebalanceLeaf [here](https://github.com/across-protocol/relayer/blob/3e9c1e4108568b39fe007f8fcd71721db4bbe090/src/dataworker/Dataworker.ts#L1484), then the balance allocator would accidentally inflate the HubPool's balance [here](https://github.com/across-protocol/relayer/blob/3e9c1e4108568b39fe007f8fcd71721db4bbe090/src/dataworker/Dataworker.ts#L1488). This function [here](https://github.com/across-protocol/relayer/blob/3e9c1e4108568b39fe007f8fcd71721db4bbe090/src/dataworker/Dataworker.ts#L1529C40-L1529C92) would then have issues. Within this function, if any individual PoolRebalanceLeaf's `netSendAmount` was less than its liquid reserves, then a `sync` would be skipped [here](https://github.com/across-protocol/relayer/blob/3e9c1e4108568b39fe007f8fcd71721db4bbe090/src/dataworker/Dataworker.ts#L1802). This [line](https://github.com/across-protocol/relayer/blob/3e9c1e4108568b39fe007f8fcd71721db4bbe090/src/dataworker/Dataworker.ts#L1822) would then artificially inflate the hub pool's balance in the balance allocator, leading to a much more down stream simulation error when the pool rebalance leaf execution fails for unknown reasons. ## Examples of problems We saw a bundle of PoolRebalanceLeaves today fail to execute because three of the leaves, one Ethereum leaf and two non-Ethereum leaves, had a total `netSendAmount` greater than the HubPool's `liquidReserves`, but each individually had a `netSendAmount` < the `liquidReserves`. For example, the three leaves had `netSendAmounts` of: - 40 - 90 - 70 While the hubPool's liquidReserves was 180: - 40 + 90 + 70 = 200 > 180 - 40 < 180 - 90 < 180 - 70 < 180 If you take these numbers and run them through the `executePoolRebalanceLeaves` code above, you'll see how a PoolRebalanceLeaf execution was able to be submitted but then fail in simulation, without preceding the leaf executions with a `sync` transaction.
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.
Moving to draft stage as I think we can simplify this logic more #1933 (comment)
I've been thinking for a couple days now that something feels weird about including the balance allocator logic when executing pool leaves. It works when executing spoke leaves because spokes don't have a separate accounting of "liquid reserves"--all ERC20 balances are used to execute leaves, whereas the hub pool has a special accounting method.
Signed-off-by: nicholaspai <[email protected]>
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 this makes sense. I also think the balanceAllocator/liquid reserves tracking in the executor is complicated, but in general, this looks to, at worst, add extra calls and log more info, so I think it's worth trying.
…ake advantage of parallel test runs in CI
Co-authored-by: Paul <[email protected]>
Co-authored-by: Paul <[email protected]>
…D's that are invalid; add DISABLED_CHAINS unit tests to BundleDataClient unit test files Signed-off-by: nicholaspai <[email protected]>
Context
The dataworker executor functionality is supposed to detect when to call
sync()
before executing L1 PoolRebalance and RelayerRefund leaves depending on theliquidReserves
value of l1 tokens before executing those leaves.There are two important areas where we might want to call
sync
before executing any pool rebalance leaves:sync
when executing the Ethereum pool rebalance leaf and the Ethereum relayer refund leaves. Pool rebalance leaves subtractnetSendAmount
fromliquidReserves
while refund leaves addamountToReturn
to liquid reserves (because Ethereum refund leaves are on the same chain as the hub pool, thisamountToReturn
is transferred atomically). This step is done here.sync
before executing the non-Ethereum pool rebalance leaves. These all will subtract theirnetSendAmounts
from the HubPool. This step subtly takes in any updated liquid reserves value from the first step if we executed async
pre-execution of the Ethereum pool rebalance leaves. It also is aware of any used balance fromnetSendAmounts
in the first step via the BalanceAllocator.Problem
In the second step where we call
_updateExchangeRatesBeforeExecutingNonHubChainLeaves
we are not evaluating the total netSendAmount obligation of all non-Ethereum PoolRebalance leaves we want to execute. This means we can submit a transaction to execute a set of pool leaves whosenetSendAmounts
might sum greater than theliquidReserves
(plus any BalanceAllocator adjustments), but individually thenetSendAmounts
are all less thanliquidReserves
. This batch transaction would then fail in simulation.Examples of problems
We saw a bundle of PoolRebalanceLeaves today fail to execute because three of the leaves, one Ethereum leaf and two non-Ethereum leaves, had a total
netSendAmount
greater than the HubPool'sliquidReserves
, but each individually had anetSendAmount
< theliquidReserves
. For example, the three leaves hadnetSendAmounts
of:While the hubPool's liquidReserves was 180:
If you take these numbers and run them through the
executePoolRebalanceLeaves
code above, you'll see how a PoolRebalanceLeaf execution was able to be submitted but then fail in simulation, without preceding the non-Ethereum pool rebalance leaf executions with async
transaction.PR side effects
This PR also refines the logic within the various internal functions called by
executePoolRebalanceLeaves
:_updateExchangeRatesBeforeExecutingHubChainLeaves
: enqueues async
call if necessary to execute any hub chain pool leaves_executePoolRebalanceLeaves
: submitsexecuteRootBundle
calls but also adds anyloadEthForL2Calls
/transfer
calls required to pay for an Arbitrum orbit L1->L2 message_updateExchangeRatesBeforeExecutingNonHubChainLeaves
: enqueues async
call if necessary to execute any non-hub chain pool leaves. Useful after_updateExchangeRatesBeforeExecutingHubChainLeaves
which might pull Ethereum_SpokePool funds into the HubPool that need to be synced right before executing non-Hubchain leavesblockRangesAreInvalid
warning will now indicate which chain specifically requires a longer lookback.Unit tests are updated as well