Skip to content

feat(op-reth/txpool): reserve the Isthmus operator fee in pool balance check#21609

Open
asdv23 wants to merge 1 commit into
ethereum-optimism:developfrom
asdv23:fix/op-reth-txpool-operator-fee
Open

feat(op-reth/txpool): reserve the Isthmus operator fee in pool balance check#21609
asdv23 wants to merge 1 commit into
ethereum-optimism:developfrom
asdv23:fix/op-reth-txpool-operator-fee

Conversation

@asdv23

@asdv23 asdv23 commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Closes #21608.

OpTransactionValidator::apply_op_checks (rust/op-reth/crates/txpool/src/validator.rs) reserves only the L1 data fee (l1_tx_data_fee) when checking that a sender can afford a transaction, not the Isthmus operator fee. On a post-Isthmus OP chain a sender whose balance covers L2 gas + value + L1 data fee — but not the operator fee — is admitted to the pool and then fails at execution.

operator_fee did not appear anywhere in rust/op-reth/crates/txpool before this change.

op-geth already charges the operator fee in its txpool balance check (NewOperatorCostFunc / NewTotalRollupCostFunc, core/types/rollup_cost.go, combined via TotalTxCost and used in ValidateTransactionWithState), so op-reth was behind op-geth here.

Change

  • Add operator_fee_addition() and fold its result into cost_addition in apply_op_checks.
  • Guarded on Isthmus activation (via the spec resolved from chain spec + timestamp with revm_spec_by_timestamp_after_bedrock) and the presence of both operator fee params. L1BlockInfo::operator_fee_charge .expect()s the scalar and constant, so it panics when they are unset (pre-Isthmus); the guard returns zero without calling it.
  • Uses the tx gas_limit (worst-case spend), matching op-geth's tx.Gas().
  • cost() is left untouched — the operator fee stays an overlay applied at the check site, exactly like the existing L1 data fee.

Scope / safety

Pool-admission only — no block-validation / state-root / execution change, so no consensus impact. Sequencer-only concern (verifiers do not admit from the mempool). Returns to op-geth parity.

Not in scope

The cumulative pending-balance path (PoolInternalTransaction::next_cumulative_cost sums the intrinsic cost(), which omits both the L1 fee and the operator fee) is a separate concern and is not addressed here.

Sibling of the L1-info gas-limit reservation: #21546 / #21548.

Tests

Unit tests for operator_fee_addition:

  • charge applied (equals operator_fee_charge) when Isthmus active + params present;
  • zero before Isthmus;
  • zero and no panic when params unset (pre-Isthmus);
  • zero for deposit-typed (0x7E) input.

cargo test -p reth-optimism-txpool (operator_fee tests) and cargo clippy -p reth-optimism-txpool --all-targets pass; cargo +nightly fmt --check clean.

…e check

`OpTransactionValidator::apply_op_checks` reserved only the L1 data fee
(`l1_tx_data_fee`) when checking that a sender can afford a transaction, not the
Isthmus operator fee. On a post-Isthmus OP chain a sender covering
`L2 gas + value + L1 data fee` — but not the operator fee — was admitted to the
pool and then failed at execution. op-geth already charges the operator fee in
its txpool balance check (`NewOperatorCostFunc`/`NewTotalRollupCostFunc`,
`core/types/rollup_cost.go`), so op-reth was behind op-geth here.

Add `operator_fee_addition()` and fold it into `cost_addition`. It is guarded on
Isthmus activation (via the spec resolved from chain spec + timestamp) AND the
presence of both operator fee params — `L1BlockInfo::operator_fee_charge`
`.expect()`s the scalar and constant, so it would panic when they are unset —
so it returns zero (no panic) before Isthmus. Uses the tx gas limit (worst-case
spend), matching op-geth's `tx.Gas()`. Pool-admission only: no block-validation
/ state-root / execution change.

Sibling of the L1-info gas-limit reservation (ethereum-optimism#21546 / ethereum-optimism#21548).
@asdv23 asdv23 requested a review from a team as a code owner July 2, 2026 06:22
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.

op-reth tx-pool balance check omits the Isthmus operator fee (admits under-funded txs; op-geth parity)

1 participant