feat(cketh): drive the sweeper transaction pipeline from its own timer task - #11237
Draft
gregorydemay wants to merge 2 commits into
Draft
feat(cketh): drive the sweeper transaction pipeline from its own timer task#11237gregorydemay wants to merge 2 commits into
gregorydemay wants to merge 2 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an independent timer-driven transaction pipeline for the ckETH sweeper address.
Changes:
- Adds the sweeper create/sign/send/resubmit/finalize driver.
- Generalizes withdrawal RPC helpers by sender and pipeline ID.
- Registers a dedicated timer guard and periodic task.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
withdraw.rs |
Generalizes shared RPC helpers. |
sweep.rs |
Implements the sweeper pipeline driver. |
state/transactions/tests.rs |
Reuses the sweeper gas-limit constant. |
state.rs |
Adds sweeper address access and task type. |
main.rs |
Registers the sweeper timer. |
lib.rs |
Exports the sweep module. |
deposit_address/mod.rs |
Exposes the sweeper derivation path internally. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| const SWEEP_TRANSACTIONS_TO_SIGN_BATCH_SIZE: usize = 5; | ||
| const SWEEP_TRANSACTIONS_TO_SEND_BATCH_SIZE: usize = 5; | ||
|
|
||
| pub async fn process_sweeper_transactions() { |
Comment on lines
+71
to
+80
| let gas_fee_estimate = match lazy_refresh_gas_fee_estimate().await { | ||
| Some(gas_fee_estimate) => gas_fee_estimate, | ||
| None => { | ||
| log!( | ||
| INFO, | ||
| "[process_sweeper_transactions]: failed retrieving gas fee estimate", | ||
| ); | ||
| return; | ||
| } | ||
| }; |
This was referenced Aug 20, 2026
gregorydemay
force-pushed
the
greg/sweeper-send-lane
branch
from
August 21, 2026 09:13
de2eb00 to
6fbf7c1
Compare
gregorydemay
force-pushed
the
greg/DEFI-2926-sweeper-send-task
branch
2 times, most recently
from
August 21, 2026 10:57
a8b30dc to
02f02c0
Compare
gregorydemay
changed the base branch from
greg/sweeper-send-lane
to
greg/sweeper-eip7702
August 21, 2026 10:57
gregorydemay
force-pushed
the
greg/DEFI-2926-sweeper-send-task
branch
from
August 21, 2026 11:12
02f02c0 to
73c453c
Compare
Four helpers in `withdraw` were implicitly about the main address: they called `minter_address()` themselves, or keyed receipts by `LedgerBurnIndex`. Reading a transaction count, broadcasting signed transactions and fetching finalized receipts are none of them specific to a sender or to what a request is keyed by. Take the sender as an argument and make the receipt fetch generic over the pipeline id, so a second pipeline sending from a different address can reuse them. `finalize_transactions_batch` keeps its behaviour: the receipt loop moves into `fetch_finalized_receipts`, which returns `None` where the loop used to return early. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The sweeper transaction pipeline exists but nothing moves requests through it. Add `sweep::process_sweeper_transactions`, running the pipeline through the same create → sign → send → resubmit → finalize cycle as withdrawals, but signing with the sweeper derivation path `[3]` and reading the sweeper address' own transaction count. It takes its own `TaskType::SweeperSend` timer guard, so a slow sweep round cannot block the withdrawal task and vice versa. `SweepRequest::Error` being `Infallible` pays off at the call site: creating a sweep transaction is destructured with `let Ok(transaction) = ...`, with no arm for a failure the type system rules out. Nothing enqueues a sweep yet — the sweep-queue source, EIP-7702 (`0x04`) first-time delegation and gating on prepaid sweep gas are follow-ups — so the task early-returns on an empty pipeline. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gregorydemay
force-pushed
the
greg/DEFI-2926-sweeper-send-task
branch
from
August 21, 2026 14:44
73c453c to
68f9246
Compare
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.
DEFI-2926, stacked on #11144 which instantiates the pipeline this drives.
Why
#11144 gives the sweeper address its own transaction pipeline, but nothing moves requests through it. This is the task that does.
What
sweep::process_sweeper_transactionsruns the sweeper pipeline through the same create → sign → send → resubmit → finalize cycle as withdrawals, signing with the sweeper derivation path[3]and reading the sweeper address' own transaction count. It takes its ownTaskType::SweeperSendtimer guard, so a slow sweep round cannot block the withdrawal task or be blocked by it — which is the point of the separate nonce sequence in the first place.The first commit is a prerequisite worth reading on its own: four RPC helpers in
withdrawwere implicitly about the main address, callingminter_address()themselves or keying receipts byLedgerBurnIndex. Reading a transaction count, broadcasting signed transactions and fetching finalized receipts are none of them specific to a sender or to what a request is keyed by, so they take the sender as an argument and the receipt fetch becomes generic over the pipeline id. Behaviour is unchanged: the receipt loop moves intofetch_finalized_receipts, which returnsNonewhere the loop used to return early.SweepRequest::ErrorbeingInfalliblepays off here: creating a sweep transaction is destructured withlet Ok(transaction) = ..., with no arm for a failure the type system rules out. That is what #11178 made possible by turning the creation error into an associated type.Scope
Nothing enqueues a
SweepRequestyet, so the task early-returns on an empty pipeline and this is inert in production. Still to come: the sweep-queue→SweepRequestsource, EIP-7702 (0x04) first-time delegation, and gating on prepaid sweep gas. EIP-1559 (0x02) only.Note for reviewers
The sweep driver and the withdrawal driver are now near-identical five-stage loops over different request types, down to a private trio of batch-size constants that are
5in both files. Deduplicating them is the obvious follow-up now that the pipeline is generic, but it would bury this change, so it is deliberately left for its own PR.