Skip to content

fix(levm): apply frame transaction gas refunds - #7046

Closed
AnkushinDaniil wants to merge 1 commit into
lambdaclass:frames-devnet-0from
AnkushinDaniil:daniil/eip8141-frame-refunds
Closed

fix(levm): apply frame transaction gas refunds#7046
AnkushinDaniil wants to merge 1 commit into
lambdaclass:frames-devnet-0from
AnkushinDaniil:daniil/eip8141-frame-refunds

Conversation

@AnkushinDaniil

@AnkushinDaniil AnkushinDaniil commented Jul 28, 2026

Copy link
Copy Markdown

Problem

EIP-8141 (Gas refunds) requires EIP-3529 storage refunds to be applied to frame transactions:

gas_used_before_refund = tx_gas_limit - tx_unused_gas
applied_refund = min(refund_counter, gas_used_before_refund // 5)
gas_used = gas_used_before_refund - applied_refund

with the refund counter accumulated across frames and the deltas of reverted frames (or frames unrolled by a failed atomic batch) discarded, and the refund "returned to the gas payer ... and added back to the block gas pool".

ethrex's frame-tx finalization ignored the accumulated refunded_gas counter entirely: the payer was charged for the gross gas used, the coinbase fee was computed on gross gas, and the execution report's gas_used/gas_spent were gross. A frame transaction that clears storage therefore reports a higher gas_used than a conformant client and charges the payer more, which breaks receipt cumulative-gas and block-gas accounting against other clients. gas_refunded in the report was also overloaded to mean "unused frame gas" rather than the EIP-3529 refund.

Change

  • Apply applied_refund = min(refunded_gas, total_gas_used / MAX_REFUND_QUOTIENT) at frame-tx finalization; substate checkpoints already discard refund deltas from reverted frames and unrolled batches.
  • Charge the payer and pay the coinbase priority fee on the net (post-refund) gas.
  • Report gas_used/gas_spent net of the refund and gas_refunded as the applied EIP-3529 refund.

Tests cover: a successful frame netting payer balance, coinbase fee and block gas; refund deltas of a reverted frame discarded; refund deltas of a reverted atomic batch discarded; and the gas_used / 5 cap binding.

Evidence

Commands run on this branch:

cargo check -p ethrex-levm                                  # pass
cargo test -p ethrex-test --test ethrex_tests levm::eip8141_tests
# 79 passed; 0 failed; 0 ignored; 751 filtered out
cargo fmt --all -- --check                                  # pass
git diff --check                                            # pass

Stack

Targets frames-devnet-0. Part of a series of independent EIP-8141 fixes, one PR per logical change, each standing alone against the same base. Siblings: #7040 (canonical low-s), #7043 (recovery id at ecrecover boundary), #7044 (intrinsic gas over payload bytes), #7045 (arbitrary-scheme verification gas), #7047 (frame receipt storage encoding), #7048 (skipped-frame status 2), #7049 (EIP-7623 calldata floor).

Consensus risk / limits

Consensus-affecting: it changes gas_used (receipts, cumulative gas, block gas accounting) and payer/coinbase balances for any frame transaction that accrues EIP-3529 refunds. Covered by unit tests only; no cross-client conformance fixture yet.

@edg-l

edg-l commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Superseded by #7004: frame-tx finalization on main applies refunded_gas capped at total_gas_used / MAX_REFUND_QUOTIENT and reports gas_used, gas_spent and gas_refunded accordingly. Main's existing frame-tx refund tests cover this behaviour. Closing as fixed; thanks.

@edg-l edg-l closed this Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants