Skip to content

feat(l1): conditional sequencer checkpoint rewards (PoC) - #25175

Draft
spalladino wants to merge 3 commits into
merge-train/spartanfrom
spl/conditional-checkpoint-rewards
Draft

feat(l1): conditional sequencer checkpoint rewards (PoC)#25175
spalladino wants to merge 3 commits into
merge-train/spartanfrom
spl/conditional-checkpoint-rewards

Conversation

@spalladino

@spalladino spalladino commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Proof of concept for making the sequencer's checkpoint reward conditional on a property of the validator that proposed the checkpoint. The condition is evaluated on the withdrawer of the proposer (looked up in the GSE), matching how ATP stakers register validators: the attester key is arbitrary, but the withdrawer is the ATP's staker contract.

Approach

At proof time, submitEpochRootProof already reconstructs the full committee from the end checkpoint's attestations and checks it against the stored per-epoch committee commitment. Since the committee is stable for the whole epoch, each checkpoint's proposer is derived from that same in-memory committee with one computeProposerIndex keccak — no committee sampling, no extra calldata, and no stored state. verifyAttestations now returns the committee it already built, and RewardLib uses it to compute per-checkpoint eligibility.

The eligibility test itself is a placeholder: the proposer's withdrawer must be a contract answering true to isEligible(). The probe is a gas-capped staticcall where no code, revert, or a malformed return all read as ineligible, so a hostile withdrawer cannot block proof submission.

Only what is owed is claimed from the reward distributor: the prover share for every checkpoint plus the sequencer share for eligible ones. Ineligible sequencers' shares never leave the distributor; prover rewards are unaffected. If the distributor cannot cover the full amount, both pots scale proportionally.

Gas

Measured with test/benchmark/happy.t.sol::test_100_validators (32-slot epochs, target committee size 48, 100 validators, forge gas-report averages). Baseline: propose 324,981, submitEpochRootProof 1,581,276.

Variant propose Δ (each) proof Δ Total Δ per epoch (32 proposes + 1 proof)
Re-sample committee per checkpoint at proof time 0 +5,396k +5,396k
Check at propose time, persist a bit per checkpoint +16.0k +116k / −290k¹ +629k / +215k
Derive proposers from the attestation committee (this PR) ±0 +279k / −136k¹ +279k / −136k

¹ all-eligible / all-ineligible. All-ineligible epochs are cheaper than baseline because the 32 sequencer-reward SSTOREs are skipped.

The benchmark's validators share a single withdrawer; with 32 distinct withdrawers the all-eligible proof delta grows by roughly 2.6–5k per checkpoint (cold account + storage per withdrawer), i.e. ~+400k total.

Caveats

  • Escape-hatch epochs skip attestation verification, so no committee is available and all their checkpoints read as ineligible.
  • Existing reward tests that expect unconditional sequencer rewards fail by design; no tests were added since this is a PoC.

Proof of concept: gate the sequencer share of the checkpoint reward on an
eligibility probe of the coinbase (a contract answering true to isEligible()).
Only the eligible sequencers' share is claimed from the reward distributor;
the prover share is unaffected.
…ion committee

The proposer of each checkpoint is derived at proof time from the committee
already reconstructed during attestation verification, so no committee
sampling, extra calldata, or stored state is needed. Only the sequencer
share of eligible checkpoints is claimed from the reward distributor.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant