fix(l1): bump BAL fixtures to v5.5.1 and fix state gas charging order#6389
Conversation
Update execution-spec-tests fixtures from bal@v5.4.0 to bal@v5.5.1. Fix EIP-8037 state gas charging order per EIPs#11421: regular gas must be charged before state gas for SSTORE and CALL. Previously state gas was charged first, which allowed spilled state gas to inflate the parent's reservoir via incorporate_child_on_error on regular gas OOG. - SSTORE: defer state gas charge until after regular gas succeeds - CALL: peek reservoir to compute expected spill for child gas computation, charge regular gas first, then charge state gas - SELFDESTRUCT: already had correct order (no change)
🤖 Kimi Code ReviewThe PR implements a critical fix for EIP-8037 state gas charging order to comply with ethereum/EIPs#11421. The changes ensure that regular gas is consumed before state gas, preventing state gas from being consumed when regular gas OOG occurs (which would incorrectly inflate the parent's reservoir on frame failure). Security & Correctnesscrates/vm/levm/src/opcode_handlers/system.rs:92-107
crates/vm/levm/src/opcode_handlers/stack_memory_storage_flow.rs:287-306
This ordering is consensus-critical—if state gas were charged first and the subsequent regular gas charge failed, the consumed state gas would leak from the reservoir incorrectly. Suggestions
VerificationThe fixture bump from Verdict: Correct and safe implementation of the EIP clarification. The reordering prevents an edge case where failed calls could incorrectly consume state gas while preserving the state gas reservoir semantics for successful operations. Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
🤖 Codex Code Review
I did not find an obvious functional bug in the code change itself. The fixture URL bumps and the reordered charging logic look internally consistent with the surrounding EIP-8037 handling; the main gap is missing regression tests for a subtle gas-accounting rule. Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
🤖 Kimi Code ReviewReview Summary The PR updates EIP-8037 (Amsterdam) state gas charging to follow the corrected ordering per ethereum/EIPs#11421: regular gas must be charged before state gas. This prevents state gas from being consumed (and spilling into the parent's reservoir) when regular gas OOG occurs. EVM Opcode Changes
The
The
Minor Style Note: The Safety Checks: Proper use of Fixture Updates The fixture URL updates from
Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
🤖 Claude Code ReviewNow I have enough context for a thorough review. PR Review: fix(l1): bump BAL fixtures to v5.5.1 and fix state gas charging orderSummaryThis PR fixes a consensus-critical ordering bug in EIP-8037 state gas charging and bumps the Amsterdam fixture suite from CorrectnessSSTORE ( The refactor is clean:
If CALL ( The "spill peek" approach at lines 99-103 is sound: the computation mirrors the internals of However, lines 99-100 duplicate the arithmetic that // vm.rs:553-555 inside increase_state_gas:
let from_reservoir = self.state_gas_reservoir.min(gas);
let spill = gas - from_reservoir;This coupling means that if Note on CREATE/CREATE2 ( Regular gas is charged first ( SELFDESTRUCT — no change, already correct (as documented in the PR description). SecurityThe bug being fixed is consensus-critical: in the old ordering, a failed CALL or SSTORE (regular gas OOG) would allow previously spent state gas to re-enter the parent's reservoir, making more state gas available than legitimately earned. This could be exploited to perform state-writing operations at below-expected cost by carefully crafting calls that trigger OOG after state gas consumption. The fix closes this window. Minor Issues
VerdictThe fix is correct and safe. The reordering precisely targets the identified bug, preserves the semantics for success cases, and the fixture bump is consistent across all relevant locations. The one structural concern (duplicated spill arithmetic) is worth a follow-up but is not a blocker. Automated review by Claude (Anthropic) · sonnet · custom prompt |
🤖 Codex Code Review
Beyond that, the change looks directionally right: charging regular gas before Amsterdam state gas matches the stated EELS ordering intent, and I did not see another obvious correctness or security regression in the diff. I could not run Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
🤖 Claude Code ReviewHere is my review of PR #6389: PR Review: fix(l1): bump BAL fixtures to v5.5.1 and fix state gas charging orderSummaryThis PR addresses two related ordering bugs in EIP-8037 (Amsterdam+) state gas handling, per EIPs#11421. The spec mandates that regular gas must be charged before state gas — the previous code did the opposite, allowing spilled state gas to incorrectly inflate the parent's reservoir when regular gas OOG occurred. The fixture bump is mechanical.
|
Greptile SummaryThis PR bumps the Amsterdam EIP test fixtures from Key changes:
Confidence Score: 5/5
|
| Filename | Overview |
|---|---|
| crates/vm/levm/src/opcode_handlers/stack_memory_storage_flow.rs | Defers SSTORE state gas (EIP-8037) until after regular gas succeeds; needs_state_gas correctly captures the 0→nonzero slot condition, and the storage mutation path is unchanged. |
| crates/vm/levm/src/opcode_handlers/system.rs | CALL handler pre-computes expected state gas spill (peeking reservoir) to preserve child gas limit computation, charges regular gas first, then state gas; logic and OOG ordering are correct. |
| .github/workflows/daily_hive_report.yaml | Bumps Amsterdam fixtures URL from bal@v5.4.0 to bal@v5.5.1. |
| .github/workflows/pr-main_l1.yaml | Bumps Amsterdam fixtures URL from bal@v5.4.0 to bal@v5.5.1. |
| Makefile | Updates AMSTERDAM_FIXTURES_URL default to bal@v5.5.1. |
| tooling/ef_tests/blockchain/.fixtures_url_amsterdam | URL updated to bal@v5.5.1 (percent-encoded). |
| tooling/ef_tests/state/.fixtures_url_amsterdam | URL updated to bal@v5.5.1 (percent-encoded). |
| docs/developers/l1/testing/hive.md | Documentation updated to reference bal@v5.5.1 in all three locations where the version appears. |
Sequence Diagram
sequenceDiagram
participant Parent as Parent Frame
participant RegGas as Regular Gas
participant StateGas as State Gas (EIP-8037)
participant Child as Child Frame
Note over Parent,Child: SSTORE (new slot: 0→nonzero)
Parent->>RegGas: increase_consumed_gas(sstore_cost) [OOG exits here]
Parent->>StateGas: increase_state_gas(STATE_GAS_STORAGE_SET) [OOG exits here]
Parent->>Parent: mutate storage slot
Note over Parent,Child: CALL (empty account + value)
Parent->>Parent: peek reservoir → compute expected spill
Parent->>Parent: gas_left = gas_remaining − spill (for 63/64 child limit)
Parent->>RegGas: increase_consumed_gas(call_cost + eip7702) [OOG exits here]
Parent->>StateGas: increase_state_gas(STATE_GAS_NEW_ACCOUNT) [OOG exits here]
Parent->>Child: generic_call(gas_limit) — state_gas_used_snapshot recorded
alt Child reverts
Child-->>Parent: incorporate_child_on_error: reservoir += child_state_gas_used
else Child succeeds
Child-->>Parent: merge state
end
Last reviewed commit: "fix(l1): bump BAL fi..."
…ation The needs_state_gas branch was reading raw gas_remaining instead of the eip7702-adjusted gas_left, giving the child frame slightly more gas than intended when EIP-7702 delegation is involved.
Lines of code reportTotal lines added: Detailed view |
Benchmark Results ComparisonBenchmark Results: Fibonacci
Detailed ResultsBenchmark Results: BubbleSort
Benchmark Results: ERC20Approval
Benchmark Results: ERC20Mint
Benchmark Results: ERC20Transfer
Benchmark Results: Factorial
Benchmark Results: FactorialRecursive
Benchmark Results: Fibonacci
Benchmark Results: FibonacciRecursive
Benchmark Results: ManyHashes
Benchmark Results: MstoreBench
Benchmark Results: Push
Benchmark Results: SstoreBench_no_opt
|
Bump execution-spec-tests fixtures from
bal@v5.4.0tobal@v5.5.1. Updates fixture URLs in CI workflows, Makefile, docs, and.fixtures_url_amsterdamfiles.Fix EIP-8037 state gas charging order per EIPs#11421: regular gas must be charged before state gas for SSTORE and CALL. Previously state gas was charged first, which let spilled state gas inflate the parent's reservoir via
incorporate_child_on_erroron regular gas OOG.stack_memory_storage_flow.rs(SSTORE): defer state gas charge until after regular gas succeedssystem.rs(CALL): peek reservoir to compute expected spill for child gas computation, charge regular gas first, then charge state gas