feat(spec-specs, tests): EIP-8037 - 0 to x to 0 SSTORE refunds to state gas#2698
Merged
spencer-tb merged 3 commits intoApr 19, 2026
Conversation
e2d1f15 to
5eae4df
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## eips/amsterdam/eip-8037 #2698 +/- ##
==========================================================
Coverage ? 88.18%
==========================================================
Files ? 524
Lines ? 31120
Branches ? 3036
==========================================================
Hits ? 27444
Misses ? 3161
Partials ? 515
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
3e1d7c4 to
44b47cc
Compare
5eae4df to
9e8698a
Compare
3f40123 to
3b0e0c4
Compare
3b0e0c4 to
e001d16
Compare
5450513
into
ethereum:eips/amsterdam/eip-8037
11 of 16 checks passed
This was referenced Apr 19, 2026
Merged
| new_value=0, | ||
| )(i, 0) | ||
| tx_regular = ( | ||
| intrinsic_gas + code.gas_cost(fork) - num_cycles * sstore_state_gas |
Member
There was a problem hiding this comment.
I think this won´t work as the refund max will be hit (1/5 refund max) 🤔
marioevz
pushed a commit
that referenced
this pull request
Apr 20, 2026
4 tasks
spencer-tb
added a commit
that referenced
this pull request
Apr 20, 2026
spencer-tb
added a commit
to spencer-tb/execution-specs
that referenced
this pull request
Apr 21, 2026
spencer-tb
added a commit
to spencer-tb/execution-specs
that referenced
this pull request
Apr 21, 2026
spencer-tb
added a commit
that referenced
this pull request
Apr 21, 2026
9 tasks
fselmo
pushed a commit
that referenced
this pull request
May 5, 2026
spencer-tb
added a commit
to spencer-tb/execution-specs
that referenced
this pull request
May 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🗒️ Description
Implements SSTORE 0 to x to 0 refunds state gas directly to
state_gas_reservoirinstead ofrefund_counter, with frame scoped rollback on revert or exceptional halt (mirrorsrefund_countersemantics). Extends the journaling to the CREATE silent failure refunds introduced in #2704.EIP text change: ethereum/EIPs#11532 (merged) + ethereum/EIPs#11548 (clarification).
Spec change: 1628020
When a storage slot is restored to its original zero value (0 to x to 0), the net state growth is zero. Refund
32 * cost_per_state_bytedirectly to the reservoir instead of throughrefund_counter. The regular gas write cost refund still goes throughrefund_counter. The refund happens immediately after the x to 0 change.A new
state_gas_refundcounter on theEvmtracks inline reservoir refunds so they can be unwound with the frame:sstoreincrementsstate_gas_refundalongside thestate_gas_left += .../state_gas_used -= ...mutations.generic_createalso incrementsstate_gas_refundat all three silent-failure sites (insufficient balance / nonce / depth, address collision, child error) so feat(spec-specs, tests): EIP-8037 - CREATE failure refunds state gas to reservoir #2704's CREATE refunds follow the same rollback rule.incorporate_child_on_successpropagatesstate_gas_refundto the parent (refund is recursively inheritable up the call stack on clean returns).incorporate_child_on_errorsubtractsstate_gas_refundfrom the amount returned to the parent's reservoir and does not propagate it (refund is dropped with any reverting ancestor).Net state growth is zero so
block_state_gas_usedexcludes the refunded state gas.Existing test update: fd49b8a
test_block_gas_refund_eip7778_no_block_reduction, expected block headergas_usednow reflects the state gas refund reducingblock_state_gas_used. Regular gas refund still excluded from block accounting per EIP-7778.New tests: e001d16
Twelve tests in
test_state_gas_sstore.pycovering happy-path accounting, cross-frame propagation, and the rollback semantics on revert / exceptional halt:test_sstore_restoration_block_state_gas_zero, parametrizednum_cycles=[1, 50]. Verifies block state gas is zero for 0 to x to 0 cycles.test_sstore_restoration_mixed_with_genuine_sstore, parametrizednum_cycles=[1, 10]. Mixes restoration cycles with a genuine 0 to x, block state gas reflects only the genuine SSTORE.test_sstore_restoration_intermediate_values, 0 to x to y to 0 still triggers refund, independent of intermediate values.test_sstore_restoration_then_reset, 0 to 1 to 0 to 1 correctly charges once net (refund then re-charge).test_sstore_restoration_reservoir_replenished_inline, inline refund at x to 0 allows a subsequent 0 to x to succeed.test_sstore_restoration_reservoir_spillover, tx gas at the cap (reservoir zero), 0 to x state gas spills intogas_left, x to 0 refund goes to reservoir.test_sstore_restoration_cross_frame, parametrized overCALL/CALLCODE/DELEGATECALLviawith_all_call_opcodes. Callee performs the full 0 to x to 0 cycle; slot lives in callee's storage forCALLand in caller's forCALLCODE/DELEGATECALL; the tx-level reservoir is refunded in every case.test_sstore_restoration_sub_frame_revert, same call-opcode parametrization. Sub-call does 0 to x to 0 thenREVERT; a single-SSTORE probe sized to OOG by 1 detects any leaked refund.test_sstore_restoration_ancestor_revert, inner frame applies the refund and returns successfully, middle frameREVERTs; exercises the recursive propagation rule (successincorporate_child_on_successthen ancestorincorporate_child_on_error).test_sstore_restoration_create_init_revert, parametrized overCREATE/CREATE2viawith_all_create_opcodes. CREATE init does 0 to x to 0 thenREVERT, wrapped in an outer reverting frame so both the SSTORE refund and the feat(spec-specs, tests): EIP-8037 - CREATE failure refunds state gas to reservoir #2704 CREATE silent-failure refund must unwind together.test_sstore_restoration_create_init_success, parametrized overCREATE/CREATE2. Positive mirror: init writes and clears slot 0, returns empty runtime, CREATE succeeds.🔗 Related Issues or PRs
✅ Checklist
just statictype(scope):.