Skip to content

feat(tests): pin cross-frame state gas refund placement and settlement - #3490

Merged
fselmo merged 4 commits into
ethereum:forks/amsterdamfrom
spencer-tb:tests/amsterdam/eip-8037-cross-frame-spill-coverage
Sep 1, 2026
Merged

feat(tests): pin cross-frame state gas refund placement and settlement#3490
fselmo merged 4 commits into
ethereum:forks/amsterdamfrom
spencer-tb:tests/amsterdam/eip-8037-cross-frame-spill-coverage

Conversation

@spencer-tb

Copy link
Copy Markdown
Contributor

Description

Add coverage for a state charge spilled from gas_left whose refund is credited in a different frame. Four tests pin the current placement and its settlement consequences:

  • the credit lands in the reservoir and gas_left is not repaid at the merge
  • settlement sums both pools, so the parked credit returns to the sender and the receipt carries no state term
  • the parked credit funds a later creation that still bills the full state price, so the cross-frame route opens no discount
  • the parked credit cannot fund execution work

The settlement pins are placement independent and hold unchanged under the merge-time repayment of ethereum/EIPs#12265. The placement pins flip with it: three of the four tests fail when filled against #3478.

Related Issues or PRs

Coverage baseline for ethereum/EIPs#12265. #3478 revises the flipped pins if the repayment lands.

Checklist

  • Ran fast static checks to avoid CI fails, see Code Standards & Verifying Changes: just static
  • PR title has the form <type>(<area>): <title>, where <type> and <area> come from an appropriate C-<type>, respectively A-<area>, label. The title should match the target squash commit message.

@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.90%. Comparing base (e5b6e3b) to head (1a7a3b1).
⚠️ Report is 4 commits behind head on forks/amsterdam.

Additional details and impacted files
@@               Coverage Diff                @@
##           forks/amsterdam    #3490   +/-   ##
================================================
  Coverage            93.90%   93.90%           
================================================
  Files                  624      624           
  Lines                36905    36905           
  Branches              3326     3326           
================================================
  Hits                 34655    34655           
  Misses                1569     1569           
  Partials               681      681           
Flag Coverage Δ
unittests 93.90% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@spencer-tb
spencer-tb marked this pull request as ready for review September 1, 2026 14:52
@spencer-tb
spencer-tb force-pushed the tests/amsterdam/eip-8037-cross-frame-spill-coverage branch from 209d9a5 to 4625066 Compare September 1, 2026 15:12
@marioevz
marioevz self-requested a review September 1, 2026 17:48
…pill

Test that one frame's refund both repays a different slot's borrow and
puts the excess in the reservoir, that the split state merges cleanly
on success, and that it is fully unwound on revert and halt.

@fselmo fselmo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These look good to me! I added another test after sniffing around a bit with Claude where it exercises two different paths on credit_state_gas_refund on two separate refund credits within the same frame.

@marioevz would be good if you wanted to take a pass here as well 👀

@marioevz marioevz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of nits. Thank you!

fselmo added a commit to spencer-tb/execution-specs that referenced this pull request Sep 1, 2026
@fselmo
fselmo force-pushed the tests/amsterdam/eip-8037-cross-frame-spill-coverage branch from bedff2f to 1a7a3b1 Compare September 1, 2026 19:14
@fselmo
fselmo merged commit 70c3511 into ethereum:forks/amsterdam Sep 1, 2026
17 checks passed
@fselmo
fselmo deleted the tests/amsterdam/eip-8037-cross-frame-spill-coverage branch September 1, 2026 19:19
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.
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.
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.

3 participants