Skip to content

feat(protocol): import sequential feeDataList in anchor#21360

Open
linoscope wants to merge 1 commit intol2_fee_vault_with_p_controllerfrom
l2_fee_vault_import_range
Open

feat(protocol): import sequential feeDataList in anchor#21360
linoscope wants to merge 1 commit intol2_fee_vault_with_p_controllerfrom
l2_fee_vault_import_range

Conversation

@linoscope
Copy link
Copy Markdown
Collaborator

Builds on top of the p-controller PR (#21350) which is build on top of the original L2 fee vault PR (#21214).

Problem

The original fee vault PR (#21214) tied fee-data import to proposal transitions: on the first block of each new proposal, the anchor had to import exactly one fee-data entry, and non-first blocks imported none. This coupling causes several issues:

  • Visibility gap at proposal boundaries. The first block of a new proposal may not yet have the needed Inbox proposal visible at its anchor (e.g., during a handover window when the previous preconfer has not yet landed its proposal). This leads to:
    • Liveness risk for preconfs — there may be no new fee data available to import from L1 at the first block of the proposal.
    • Stale fee data — the first block can only access the previous-previous proposal's L1 Inbox data, which may lag by an entire epoch under whitelisted fallback.
  • One-per-proposal bottleneck. A single anchor block-number update can advance the anchor far enough to expose multiple previously pending proposals in the Inbox, but importing only one entry per proposal transition causes persistent fee-data and accounting lag.

Solution

Switch to range-based fee import via feeDataList:

  • For each anchor, derivation/proof constructs a contiguous canonical range from lastImported + 1 through the latest Inbox proposal visible in the anchor block, capped by MAX_FEE_DATA_LIST_LENGTH.
    • The truncation by MAX_FEE_DATA_LIST_LENGTH exists to keep anchor execution within
      ANCHOR_GAS_LIMIT by bounding fee-data catch-up work (and payload size) per anchor transaction.

This addresses each issue above:

  • No forced import at proposal boundaries. If no new proposal is visible yet, the list is empty and anchoring still proceeds normally.
  • Batch import eliminates per-proposal lag. If multiple proposals are visible, all are imported in a single anchor.
  • Progressive backlog drain. Backlogs are drained across successive anchors (bounded per anchor by the max list length), rather than being stuck at one import per proposal transition.

Notes for Derivation/Proving

One implementation approach is to track each proposal's parent/ancestor link and its origin L1 block number. When an anchor advances past the origin block number of previously unimported proposals, those proposals are included in the anchor's feeDataList in order, up to MAX_FEE_DATA_LIST_LENGTH.

@linoscope linoscope changed the title L2 fee vault import range Move Fee-Data Import from Per-Proposal to Range-Based Catch-Up Feb 21, 2026
@linoscope linoscope changed the title Move Fee-Data Import from Per-Proposal to Range-Based Catch-Up Decouple fee data import from per-proposal Feb 21, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e2ea92e32c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +282 to +283
feeVault.importProposalFeeList(_feeDataList);
_lastImportedFeeProposalId += uint48(listLength);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Validate feeDataList proposal-id continuity before import

_importFeeDataList now forwards _feeDataList without checking IDs and then advances _lastImportedFeeProposalId by list length only; if derivation/proving ever emits a non-contiguous or shifted list (for example starting above _lastImportedFeeProposalId + 1), the vault will reimburse those entries anyway and Anchor’s counter will drift, which can both skip reimbursements for missing proposal IDs and permit duplicate reimbursements later because L2FeeVault does not enforce ordering/deduplication. The previous implementation enforced sequential progression on-chain, so this is a regression in accounting safety.

Useful? React with 👍 / 👎.

@linoscope linoscope changed the title Decouple fee data import from per-proposal feat(protocol): import sequential feeDataList in anchor Feb 21, 2026
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.

1 participant