Skip to content

fix(cketh): provision sweep gas out of the sweeper balance bound - #11342

Queued
gregorydemay wants to merge 13 commits into
masterfrom
greg/DEFI-2933-provision-sweep-gas
Queued

fix(cketh): provision sweep gas out of the sweeper balance bound#11342
gregorydemay wants to merge 13 commits into
masterfrom
greg/DEFI-2933-provision-sweep-gas

Conversation

@gregorydemay

@gregorydemay gregorydemay commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Why

  • The funding task decides whether to top the sweeper address up from a lower bound on its ETH balance, tracked from the minter's own events (feat(cketh): sweeper fee-funding task, with an end-to-end test #11086). Nothing debited that bound, which was true while nothing spent from the sweeper address — and the layers below connect the sweep queue to the pipeline that does.
  • Without a debit the bound only ever grows: fundings top the sweeper up once, sweeps spend the gas, and every counter still reports a full sweeper — amount_due declines fundings the sweeper actually needs, and sweeping stalls while looking healthy.

What

  • An accepted sweep provisions the most it can cost the sweeper address: its fee ceiling, the same ceiling every resubmission is checked against. A sweep moves its ERC-20 through call data and sends no ETH — settlement reads the finalized transaction and its receipt, asserts exactly that, hands back the fee the sweep did not pay, and records the fee it did.
  • A sweep is only accepted while the bound covers its ceiling, so every hold is backed by delivered gas. That lets the balance be checked like the main address' EthBalance instead of floored at zero: provisioning beyond deliveries is a bug to surface, not a state to tolerate (no deployed minter ever wrote a sweep event, so there is no legacy log to indulge).
  • Provisioning at acceptance rather than debiting at spend keeps the bound erring low while sweeps are in flight: a sweep whose finalization is never observed brings a funding forward rather than letting the minter believe in gas that is gone. Acceptance also happens exactly once per sweep, where a signature happens once per resubmission.
  • The holds stay out of cumulative_spent — that ETH was counted there when the funding delivered it, and counting it twice would trip the burn-first invariant (R14).
  • The sweep e2e now funds the sweeper the way production does — ckETH burned from the fee account, delivered and finalized by the funding pipeline — since a minter that trusts only its own accounting no longer sweeps on gas credited behind its back.

This is #11329 (thanks @mbjorkqvist), integrated on top of the sweep stack per the hand-off on DEFI-2933: rebased onto the sweep-queue lifecycle, whose deposit release now lives in the same finalization transition the refund settles in.

@gregorydemay gregorydemay changed the title greg/DEFI 2933 provision sweep gas fix(cketh): provision sweep gas out of the sweeper balance bound Aug 27, 2026
@gregorydemay
gregorydemay requested a balanced review from Copilot August 27, 2026 07:00
@github-actions github-actions Bot added the fix label Aug 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates ckETH sweeper funding accounting so in-flight and finalized sweep costs correctly reduce the tracked balance lower bound.

Changes:

  • Provision accepted sweeps against the sweeper balance bound.
  • Refund unused fees and failed transfer values upon finalization.
  • Add lifecycle tests, shared fixtures, and updated documentation.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
rs/ethereum/cketh/minter/src/test_fixtures.rs Adds a reusable sweep request fixture.
rs/ethereum/cketh/minter/src/state/transactions/tests.rs Reuses the shared sweep fixture.
rs/ethereum/cketh/minter/src/state/sweeper_funding/tests.rs Tests provisioning, refunds, accounting invariants, and flooring.
rs/ethereum/cketh/minter/src/state/sweeper_funding.rs Tracks provisioned and refunded sweep costs.
rs/ethereum/cketh/minter/src/state/audit.rs Wires accounting into sweep lifecycle events.
rs/ethereum/cketh/minter/src/state.rs Settles sweeper balance accounting at acceptance and finalization.
rs/ethereum/cketh/docs/deposit_from_cex.md Documents the revised lower-bound calculation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@gregorydemay
gregorydemay force-pushed the greg/DEFI-2933-provision-sweep-gas branch from 63a865b to 928e0c0 Compare August 27, 2026 07:56
@gregorydemay
gregorydemay requested a balanced review from Copilot August 27, 2026 08:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Comment thread rs/ethereum/cketh/minter/src/state/sweeper_funding.rs Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Comment thread rs/ethereum/cketh/minter/src/state/sweeper_funding.rs Outdated
Comment thread rs/ethereum/cketh/minter/src/state/sweeper_funding/tests.rs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 29 out of 29 changed files in this pull request and generated 3 comments.

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

rs/ethereum/cketh/minter/src/state/automatic_deposits/mod.rs:220

  • This literal emits large runs of spaces in the operational log message, making failure diagnostics harder to read. Use Rust line continuations so source wrapping produces single spaces.
                    "[record_finalized_sweep_transaction]: DROPPING {request:?} from the sweep                      queue: {id:?} failed and the minter does not retry. Its {:?} stays at {}, and                      reaching it again needs the pair armed afresh.",

rs/ethereum/cketh/test_utils/src/anvil.rs:316

  • Blocks are searched newest-first, but transactions within each block are still searched oldest-first. With interval mining, multiple transactions from this sender can share the head block, so this can return an earlier transaction rather than the documented most recent one. Reverse the per-block iteration too.
            for transaction in transactions {

Comment thread rs/ethereum/cketh/minter/src/state.rs
Comment thread rs/ethereum/cketh/minter/cketh_minter.did
Comment thread rs/ethereum/cketh/minter/cketh_minter.did
@gregorydemay
gregorydemay force-pushed the greg/DEFI-2933-provision-sweep-gas branch from 542ceb8 to a124541 Compare August 29, 2026 10:52
@gregorydemay
gregorydemay requested a balanced review from Copilot August 29, 2026 10:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Base automatically changed from gdemay/DEFI-2926-deposit-from-cex-e2e to master August 31, 2026 10:17
gregorydemay and others added 5 commits August 31, 2026 12:17
The funding decision reads a lower bound on the sweeper address' balance,
tracked from the minter's own events. Nothing debited it, which was true while
nothing spent from that address — and the layers below have since landed the
pipeline that does. With those in place the bound only ever grows: fundings top
the sweeper up once, sweeps spend the gas, and the bound still reports a full
sweeper, so `amount_due` declines every later funding. The sweeper drains,
sweeping stalls, and every counter says it is funded.

An accepted sweep now provisions the most it can cost that address — its fee
ceiling, which caps every resubmission the pipeline makes for it — and gets back
the fee it did not pay when it finalizes. An ERC-20 sweep moves its tokens
through call data and carries no ETH value of its own, so the fee is the whole
of what it can cost, and a reverted sweep is charged for its gas like any other.

Provisioning at acceptance rather than debiting at spend is what keeps this a
bound while sweeps are in flight. Gas a committed sweep will pay stops counting
as available immediately, and a sweep whose finalization is never observed
leaves the bound too low — which delays a funding — rather than too high, which
would let the minter believe in gas that is gone. It is the discipline the
withdrawal pipeline already applies to its own fees.

The counters are kept out of `cumulative_spent`: this ETH was counted there once
already, when the funding that delivered it finalized, and counting it twice
would make spend overtake burn and trip the burn-first invariant. The bound
floors at zero rather than trapping, since an upgrade that starts the counters
from zero — or a sweeper funded before it was tracked — can legitimately leave
provisioning above deliveries, and trapping in a state transition would take the
replay of every later event with it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YK3ggw1xtE3HZTGGBu66oD
…prepaid gas

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YK3ggw1xtE3HZTGGBu66oD
@gregorydemay
gregorydemay force-pushed the greg/DEFI-2933-provision-sweep-gas branch from e9dfee9 to b254286 Compare August 31, 2026 10:17
gregorydemay and others added 8 commits August 31, 2026 13:09
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ2pJpCcJWSmYfrhLjmUZ8
@gregorydemay
gregorydemay marked this pull request as ready for review August 31, 2026 13:33
@gregorydemay
gregorydemay requested a review from a team as a code owner August 31, 2026 13:33
@github-actions github-actions Bot added the @defi label Aug 31, 2026
@zeropath-ai

zeropath-ai Bot commented Aug 31, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to 1835071.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► rs/ethereum/cketh/minter/src/state.rs
    Add record_finalized_sweeper_transaction method
► rs/ethereum/cketh/minter/src/state.rs
    Add update_sweeper_balance_upon_accepted_sweep method
► rs/ethereum/cketh/minter/src/state/audit.rs
    Call update_sweeper_balance_upon_accepted_sweep during sweep event processing
► rs/ethereum/cketh/minter/src/state/automatic_deposits/mod.rs
    Expose processed_sweep_request method
Enhancement ► rs/ethereum/cketh/minter/src/state/sweeper_funding.rs
    Introduce SweeperBalance and SweeperBalance handling (credit/debit, add_error checks)
► rs/ethereum/cketh/minter/src/state/sweeper_funding.rs
    Extend SweeperFundingAccounting with sweeper_balance, new methods record_accepted_sweep, record_finalized_sweep, total_effective_sweep_fees, sweeper_balance_lower_bound
Enhancement ► rs/ethereum/cketh/minter/src/sweep/mod.rs
    Prevent creating pending sweeps when sweeper balance cannot cover max_transaction_fee
Enhancement ► rs/ethereum/cketh/minter/src/sweep/tests.rs
    Add tests for sweeper balance behavior: should_not_accept_a_sweep_the_sweeper_gas_cannot_pay_for, should_record_the_fees_sweeps_paid, and support for finalized sweeps with replacements
Enhancement ► rs/ethereum/cketh/minter/src/test_fixtures.rs
    Add PREPAID_SWEEP_GAS constant, prepay_sweep_gas, and state_with_enqueued_sweep helpers; extend fixtures with sweep-related setup
Enhancement ► rs/ethereum/cketh/minter/tests/deposit_from_cex.rs
    Adjust test setup to use new sweep funding flow and dynamic funded gas amount
Enhancement ► rs/ethereum/cketh/test_utils/src/live.rs
    Update live test setup to reflect new sweep funding semantics and include TransactionStatus in events
Enhancement ► rs/ethereum/cketh/test_utils/src/live.rs
    Refactor new_sweep to initialize via new approach and adjust funding flow for tests
Enhancement ► rs/ethereum/cketh/minter/src/sweep/tests.rs
    Add tests for not accepting sweeps when gas cannot be covered, and related fixtures for state with enqueued sweeps

@mbjorkqvist mbjorkqvist left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks @gregorydemay!

@gregorydemay
gregorydemay added this pull request to the merge queue Aug 31, 2026
Any commits made after this event will not be merged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants