feat(spec-specs, tests): repay spilled state gas from the reservoir when a child merges - #3478
Open
spencer-tb wants to merge 3 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## forks/amsterdam #3478 +/- ##
================================================
Coverage 94.01% 94.01%
================================================
Files 624 624
Lines 36905 36912 +7
Branches 3326 3326
================================================
+ Hits 34695 34702 +7
Misses 1533 1533
Partials 677 677
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
spencer-tb
force-pushed
the
eips/amsterdam/eip-8037-merge-state-gas-return
branch
from
August 31, 2026 18:43
aab8895 to
e28e730
Compare
2 tasks
This was referenced Sep 2, 2026
spencer-tb
pushed a commit
to chfast/execution-specs
that referenced
this pull request
Sep 2, 2026
…voir Add a test where the sender pays for a reservoir that covers none, one or both of the parent's two fresh sets and the rest spill. A delegated child clears both slots and the refunded state gas lands in the reservoir. The call window, a later set and the receipt are the same in every case: the refund stays in the reservoir and the spill is not repaid. With one set covered, the refund merged from the child is larger than the outstanding spill. The existing tests in this file all start with an empty reservoir, so the merged refund never exceeds the spill there. Covering both sets and covering none are the boundaries. The expectations pin current placement. With the `src/` change of sets and `SLOT_PROBE_RESULT` rises by one state cost for `reservoir_slots=0` only. The receipt does not change. Follow-up to ethereum#3490. Coverage for ethereum/EIPs#12265 and ethereum#3478.
spencer-tb
force-pushed
the
eips/amsterdam/eip-8037-merge-state-gas-return
branch
from
September 2, 2026 13:10
e28e730 to
df8077e
Compare
chfast
added a commit
to chfast/execution-specs
that referenced
this pull request
Sep 2, 2026
Add two tests pinning where a merged state gas refund lands, swept over `with_all_call_opcodes` and `with_all_create_opcodes`. A holder contract owns the cleared slot, so a create's initcode reaches it the same way a call's child does, and the parent's spill comes from setting the slot through the holder. Each test measures a clearing window against a no-op window of identical code, so neither needs gas arithmetic. Today the refund stays in the reservoir: the two windows cost the same at a call, and at a create the second window's account creation charge draws on the parked refund, so the clearing window costs one slot's state gas more. With the `src/` change of ethereum#3478 applied, every arm flips to minus one slot's state cost. Before this, `CREATE` and `CREATE2` never merged a refunding child into a parent holding a spill: a repayment applied only at `generic_call` passed the whole suite. `CALL`, `CALLCODE` and depth 2 did reach the path, in `test_state_gas_sstore` and `test_state_gas_set_code`, but nothing there discriminates. Both tests reach the holder through an intermediate frame, so the sweep pins depth 2 as well. `STATICCALL` is excluded: a static child cannot write, so it can never refund. `test_cross_frame_refund_parks_in_reservoir` builds the same probe, so move that shape into `clearing_probe_code` and take the setting code as a parameter. Its fixtures are unchanged. Follow-up to ethereum#3490 and ethereum#3499. Coverage for ethereum/EIPs#12265 and ethereum#3478.
2 tasks
spencer-tb
force-pushed
the
eips/amsterdam/eip-8037-merge-state-gas-return
branch
from
September 2, 2026 15:17
d14e716 to
5db355e
Compare
chfast
added a commit
to chfast/execution-specs
that referenced
this pull request
Sep 3, 2026
Four tests each asserted a gas window measuring where a merged refund sits and a receipt measuring what the sender pays. The window changes under the merge-time repayment of ethereum/EIPs#12265, the receipt must not. Asserted together, the receipt could only be read from a test that change makes fail. Split each in two. The tests keeping the receipt drop the `GAS` stamps and the result slot, so one fewer slot survives and their sums stop carrying the probe overhead. With the `src/` change of ethereum#3478 applied, the failing tests are exactly the ones measuring a window, so the module docstring's claim that the two are independent is now checked. Extract what the halves share as `clearing_child_code`, `clearing_child_storage` and `delegation_to`, and name the budget leaving a storing child more than the call stipend `budget_above_sstore_stipend`. It was open-coded ten times. The two `SSTORE` metadata forms spelled out eleven times become `FRESH_SET` and `WARM_CLEAR`, and `window_cost_excess` loses its metadata parameter now that no receipt sum reads a measured frame. Fixtures for every pre-existing test are unchanged.
2 tasks
spencer-tb
force-pushed
the
eips/amsterdam/eip-8037-merge-state-gas-return
branch
from
September 3, 2026 09:23
5db355e to
94ee8b5
Compare
spencer-tb
marked this pull request as ready for review
September 3, 2026 14:13
20 tasks
2 tasks
ilitteri
pushed a commit
to lambdaclass/execution-specs
that referenced
this pull request
Sep 3, 2026
…es branch Ports execution-specs#3478 onto devnets/frames/0, which was frozen before the rule and so diverged from tests-glamsterdam-devnet@v8.1.4 on the cross-frame-refund fixtures: the two releases pinned contradictory post-states for the same tests, and no client could satisfy both. The frames branch keeps the state gas reservoir as a separate GasMeter.reservoir component rather than flat meter fields, so the repayment operates on the reservoir and runs inside the reservoir branch of incorporate_child, next to the spill and reservoir merge it completes. A frame transaction's meters carry no reservoir, so the repayment never runs for them: their state gas lives on the frame context and is never drawn from gas_left, leaving nothing to repay and nothing to repay from. The test rewrite is unchanged from ethereum#3478. Verification: the rewritten test fills 75/75 at Amsterdam and 75/75 at Bogota, and every common case matches tests-glamsterdam-devnet@v8.1.4 exactly (post-state and block hashes); the EIP-8141 suite fills unchanged (721 passed at Bogota). (cherry picked from commit 7341820, adapted)
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
Implement the merge time repayment specified in ethereum/EIPs#12265. A state charge spilled from
gas_leftcan be refunded in a different frame, where the credit lands in thestate_gas_reservoir. When a successful child merges, the reservoir now repays the merged frame's outstanding spill, capped at the spill (repay_state_gas_spill).Flips the placement pins of
test_state_gas_cross_frame_refund.py(#3490, #3498, #3499, #3506) to the repaid behaviour, adds an inner-frame probe and pins the receipt of the repaid execution. The repayment moves gas between the two pools settlement sums, so no other fixture changes and the settlement pins hold unchanged.Related Issues or PRs
Requires ethereum/EIPs#12256 & ethereum/EIPs#12265
Checklist
just static<type>(<area>): <title>, where<type>and<area>come from an appropriateC-<type>, respectivelyA-<area>, label. The title should match the target squash commit message.