improve(gasless): enforce deadline buffer before deposit submission and immediate fill#3463
improve(gasless): enforce deadline buffer before deposit submission and immediate fill#3463droplet-rl wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9535d33b56
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if ( | ||
| !fillImmediate && | ||
| !isCctpDeposit && | ||
| fillDeadline - getCurrentTime() <= GASLESS_DEADLINE_BUFFER_SECONDS | ||
| ) { |
There was a problem hiding this comment.
Allow observed deposits to continue to fill
When a standard bridge deposit is already observed on origin but its destination fill is not, _markFilledFromInitialObservation leaves it eligible for this state machine so the bot can finish the fill. With this new guard, any such deposit whose fillDeadline has less than the buffer remaining is moved to ERROR before DEPOSIT_CONFIRM can resolve the already-landed deposit, so restarts or delayed polling can strand a valid on-chain deposit even though there is still time to submit the fill. The buffer should only prevent submitting a new origin deposit, or should exempt observedDeposits[originChainId].has(depositKey).
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Good catch — addressed in 3965c03. Exempted observedDeposits[originChainId].has(depositKey) from the buffer check so deposits already landed on origin (e.g. seen via _markFilledFromInitialObservation after a restart) still proceed to a fill attempt even when the remaining fillDeadline window is short. New test Standard path: still proceeds when fillDeadline within buffer but deposit already on chain covers it.
| if ( | ||
| !fillImmediate && | ||
| !isCctpDeposit && | ||
| fillDeadline - getCurrentTime() <= GASLESS_DEADLINE_BUFFER_SECONDS | ||
| ) { |
There was a problem hiding this comment.
Apply the fill deadline buffer to immediate fills
For instantFill deposits where fillImmediate remains true, this condition skips the new fillDeadline buffer entirely, so a message with only a few seconds left before fillDeadline still submits the origin deposit and then attempts the destination fill. If that fill misses the on-chain deadline, the bot has already landed a deposit it can no longer fill, which is the same scenario the standard-path buffer is trying to avoid.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Agreed — also addressed in 3965c03. Dropped the !fillImmediate clause so the fillDeadline buffer applies to the immediate-fill path too. If fillDeadline is within the buffer and the deposit is not already on chain, the message now ERRORs before any origin submission, so we never land a deposit we cannot subsequently fill. New test Immediate fill: ERROR when fillDeadline within buffer and deposit not observed covers it.
|
@codex addressed both review items in 3965c03:
Two new tests cover the added behavior ( |
|
Codex Review: Didn't find any major issues. Breezy! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
Thanks — re-review confirms the buffer fixes are clean. No further changes. |
… immediate fill Two guards to prevent the relayer from acting on a deposit whose deadlines won't outlive the action: - Standard (non-immediate, non-CCTP) path: refuse to submit a deposit when fewer than GASLESS_DEADLINE_BUFFER_SECONDS remain on the destination fillDeadline. Otherwise the deposit may land but the subsequent fill misses the destination window. - Immediate-fill path: refuse to commit a destination fill when fewer than GASLESS_DEADLINE_BUFFER_SECONDS remain on the origin authorization (EIP-3009 validBefore or Permit2 deadline), unless the deposit is already observed on chain. The check lives inside fillImmediate() as one of the existing eligibility predicates rather than a downstream override.
784a8c3 to
6dbbeed
Compare
Summary
Hardens the gasless relayer against two failure modes where a partial action leaves the relayer holding an unrecoverable position:
fillDeadlineto be more than 2 minutes out. Otherwise the deposit may land but the subsequent fill fails for lack of time, leaving an unfillable origin deposit.validBeforeor Permit2deadline) to be more than 2 minutes out, unless the deposit has already been observed on chain. Otherwise the fill may land while the authorization expires, leaving an unreimbursable fill.When the immediate path is blocked by the authorization deadline, the message falls back to the standard path (where the
fillDeadlinecheck then applies). A single shared constant (GASLESS_DEADLINE_BUFFER_SECONDS = 120) controls both checks.The CCTP path is exempted from the
fillDeadlinecheck since there is no relayer-submitted destination fill.Test plan
yarn typecheckyarn lintyarn test --grep "Gasless"— 52 pass, including 5 new cases underDeadline buffer checksfillDeadlinelog the new warn and skip deposit submission rather than landing unfillable deposits🤖 Generated with Claude Code