feat(BundleDataClient): Support refunds for pre-fills/slow-fill-requests and duplicate deposits#835
Merged
Conversation
…re-slowfill-requests ### Definitions - "pre-fill": any fill that is in a bundle that precedes the bundle containing the matched deposit - "pre-slow-fill-request": a mouthful, and any slow fill request in a bundle that precedes the bundle containing the matched deposit ## Core logic for refunding pre-fills: Evaluate all deposits in the current bundle that were not filled in the current bundle. Figure out whether the deposit was filled, by either: - Finding the fill in the spoke pool client's memory, or - Querying the fill status on-chain If there is a fill for this deposit then we need to issue a refund for this fill because the fill occurred in a previous bundle where it might not have been refunded. We need to use a similar algorithm for creating slow fill leaves for pre-slow-fill-requests ## Avoiding duplicate refunds for pre-fills We don't deterministically know whether this pre-fill was refunded in the prior bundle because we don't know for certain what kind of event search window the proposer of the prior bundle used when constructing the bundle. To illustrate this problem, imagine if a fill and a deposit are sent 10 minutes apart such that the fill is at the end of the current bundle and the deposit is at the beginning of the next. The prior bundle proposer probably would have issued a refund for this fill, but we don't know for certain. So, one way around this non-determinism is to introduce a new rule to the UMIP: ### Do not issue refunds for fills or slow fill leaves where the matched deposit is later than the current bundle block range This rule makes it always apparent which bundle should include a refund or slow fill leaf for a pre-fill or pre-slow-fill-request. This will require a UMIP change to [this PR](UMAprotocol/UMIPs#611) ## TODO I still need to update the `findFillBlock()` function to return a historical fill for a deposit, because we'll need the FilledRelay's `relayerAddress` or `msg.sender` to credit the refund to (the latter in the case where the relayer address isn't valid on the repayment chain).
bmzig
reviewed
Jan 23, 2025
Co-authored-by: bmzig <57361391+bmzig@users.noreply.github.com>
nicholaspai
added a commit
to across-protocol/relayer
that referenced
this pull request
Jan 23, 2025
This PR should be backwards compatible and deployable to production today to be paired with across-protocol/sdk#835
I think these are the changes needed but I need to consider more the impact if two deposits expire and they both create slow fill excesses, for example, or other weird edge cases.
bmzig
reviewed
Jan 23, 2025
bmzig
reviewed
Jan 23, 2025
nicholaspai
commented
Jan 24, 2025
nicholaspai
commented
Jan 31, 2025
bmzig
reviewed
Feb 1, 2025
bmzig
approved these changes
Feb 1, 2025
Try to consolidate calls to verifyFillRepayment and refactor it into some utility functions we can use as additional asserts in the BundleDataClient
bmzig
approved these changes
Feb 2, 2025
bmzig
reviewed
Feb 3, 2025
| return; | ||
| } | ||
| assert( | ||
| chainIsEvm(deposit.destinationChainId) && isValidEvmAddress(deposit.recipient), |
Contributor
There was a problem hiding this comment.
If you are adding this assert, I believe you will also need to change _canCreateSlowFillLeaf to check for a valid recipient since somebody can supply garbage to a deposit and request a slow fill for that. If that happened, we would just continuously fail on this assert.
Member
Author
There was a problem hiding this comment.
This is a good point I'm going to revert 5c32bd8
Member
Author
bmzig
approved these changes
Feb 3, 2025
nicholaspai
added a commit
to across-protocol/relayer
that referenced
this pull request
Feb 3, 2025
) * feat(Dataworker): Support pre-fill refunds This PR should be backwards compatible and deployable to production today to be paired with across-protocol/sdk#835 * Finish new tests * Update Dataworker.buildRoots.ts * Revert "Update Dataworker.buildRoots.ts" This reverts commit 40ad15f. * Add test against duplicate deposits * Add unit tests for duplicate deposits * Import beta sdk * import sdk * update import * Update package.json * Update config.yml * wip * Fix tests * Update SpokePoolUtils.ts * Update SpokePoolUtils.ts * Update Dataworker.loadData.prefill.ts * Add tests for zero value deposits * Split up tests to speed up CI * import * Update package.json * Update yarn.lock * import * Fix tests * fix * bump * Remove mocked version bump in non-prefill tests * wip * lint * bump * bump * fix * import * fix * Update Dataworker.loadData.fill.ts * Fix tests * move some bytes32 invalid test cases to pre-fills because they hit pre-fill logic * WIP * Update Dataworker.loadData.prefill.ts * update * WIP * fix * wip * update * fix * Update Dataworker.loadData.prefill.ts * fix * bump package to new duplicate refund version * Add test cases for historical deposit query when matched deposit is in future bundle * fix * Update Dataworker.loadData.fill.ts * Update Dataworker.loadData.fill.ts * pay refunds to pre-filler unless slow fill * Update Dataworker.loadData.prefill.ts * Update Dataworker.loadData.prefill.ts * fix * Add verifyFillRepayment test for pre fills * add asserts * wip * 34 * fix test * 4.0.0 * Update Constants.ts
md0x
pushed a commit
that referenced
this pull request
May 2, 2025
…sts and duplicate deposits (#835) Co-authored-by: bmzig <57361391+bmzig@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Definitions
Core logic for refunding pre-fills:
Evaluate all deposits in the current bundle that were not filled in the current bundle. Figure out whether the deposit was filled, by either:
If there is a fill for this deposit then we need to issue a refund for this fill because the fill occurred in a previous bundle where it might not have been refunded.
We need to use a similar algorithm for creating slow fill leaves for pre-slow-fill-requests with the caveat that we cannot create slow fill leaves for deposits that have expired
Non-determinism for refunding pre-fills
We don't deterministically know whether this pre-fill was refunded in the prior bundle because we don't know for certain what kind of event search window the proposer of the prior bundle used when constructing the bundle.
To illustrate this problem, imagine if a fill and a deposit are sent 10 minutes apart such that the fill is at the end of the current bundle and the deposit is at the beginning of the next. The prior bundle proposer probably would have issued a refund for this fill, but we don't know for certain.
So, one way around this non-determinism is to introduce a new rule to the UMIP:
Do not issue refunds for fills or slow fill leaves where the matched deposit is later than the current bundle block range
This rule makes it always apparent which bundle should include a refund or slow fill leaf for a pre-fill or pre-slow-fill-request.
This will require a UMIP change to this PR
findFillEvents
When we need to query
fillStatuses()on-chain to detect whether a deposit corresponds to a very old pre-fill, then we also need to locate that old fill. We assume this is rare and will use the relatively expensivefindFillEvents()function which is built off of the existingfindFillBlock()function to locate that event.Duplicate deposits
This PR also adds support for duplicate deposits that are possible to create with unsafeDeposit. Duplicate deposits are added to
bundleDepositsfor they should be included inrunningBalances. Duplicate deposits can be refunded upon expiry but for all deposits, expiry refunds cannot occur once the deposit has been filled.Due to the presence of pre-fills, we can now no longer instantly include that a deposit submitted in the current bundle that has expired is due a refund. We now need to check its relay status in the case where we don't see a matching fill in our memory.
Unit tests
Can be found here: across-protocol/relayer#2010