Skip to content

feat(spec-specs, tests): update EIP-8037 to use source based refunds - #2999

Merged
spencer-tb merged 4 commits into
ethereum:forks/amsterdamfrom
spencer-tb:eips/amsterdam/eip-8037-source-based-refunds
Jun 18, 2026
Merged

spencer-tb merged 4 commits into
ethereum:forks/amsterdamfrom
spencer-tb:eips/amsterdam/eip-8037-source-based-refunds

Conversation

@spencer-tb

@spencer-tb spencer-tb commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

🗒️ Description

Update the EIP-8037 reservoir model so state gas refunds are source based LIFO.

🔗 Related Issues or PRs

Aligns with the second point in ethereum/EIPs#11807.

✅ Checklist

  • All: Ran fast static checks to avoid unnecessary CI fails, see also Code Standards and Enabling Pre-commit Checks:
    just static
  • All: PR title adheres to the repo standard - it will be used as the squash commit message and should start type(scope):.
  • All: Considered updating the online docs in the ./docs/ directory.
  • All: Set appropriate labels for the changes (only maintainers can apply labels).

Cute Animal Picture

Put a link to a cute animal picture inside the parenthesis-->

@spencer-tb spencer-tb added A-spec-specs Area: Specification—The Ethereum specification itself (eg. `src/ethereum/*`) C-feat Category: an improvement or new feature P-high A-tests Area: Consensus tests. labels Jun 17, 2026
@spencer-tb
spencer-tb requested a review from kclowes June 17, 2026 13:42
@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.21%. Comparing base (4d84100) to head (a941cda).
⚠️ Report is 5 commits behind head on forks/amsterdam.

Additional details and impacted files
@@               Coverage Diff                @@
##           forks/amsterdam    #2999   +/-   ##
================================================
  Coverage            93.20%   93.21%           
================================================
  Files                  620      620           
  Lines                38759    38787   +28     
  Branches              3341     3341           
================================================
+ Hits                 36127    36154   +27     
  Misses                1773     1773           
- Partials               859      860    +1     
Flag Coverage Δ
unittests 93.21% <100.00%> (+<0.01%) ⬆️

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 requested a review from SamWilsn June 17, 2026 14:47
@spencer-tb
spencer-tb force-pushed the eips/amsterdam/eip-8037-source-based-refunds branch from 8bd822f to 2d4541e Compare June 17, 2026 14:52
@spencer-tb spencer-tb self-assigned this Jun 17, 2026

@kclowes kclowes 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.

Those cats 😆

Nice work! I left a couple small comments, but looks good overall!

The comments here and here are wrong, but the tests still pass correctly afaict.

Missing test via Claude - feel free to take or leave:
Combined own-frame + child-propagated spill, then revert: No test covers the case where the parent itself spills state gas AND a successful child propagates its own state_gas_from_gas_left to the parent, and then the parent reverts. The test_top_level_failure_propagated_state_gas covers child-propagated spill only (parent charges no state gas of its own). Adding parent-level charges that also spill would exercise whether the accumulated state_gas_from_gas_left = own_spill + child_spill is correctly returned to gas_left on revert rather than reservoir.

Comment thread src/ethereum/forks/amsterdam/vm/__init__.py Outdated
Comment thread tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_create.py Outdated
Comment thread tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_create.py Outdated
@spencer-tb

Copy link
Copy Markdown
Contributor Author

Thanks @kclowes! 🙏

Used your rename suggestion, fixed the comments, and added the test scenario by folding it together with the existing test_top_level_failure_propagated_state_gas parameterised test now called test_top_level_failure_spilled_state_gas.

@spencer-tb
spencer-tb merged commit a8876ca into ethereum:forks/amsterdam Jun 18, 2026
26 checks passed
danceratopz added a commit to danceratopz/execution-specs that referenced this pull request Jun 18, 2026
The header `gas_used` is `max(block regular gas, block state gas)`.
After the source-based refund rework (ethereum#2999) and the EIP-8038
state-access repricing, the hand-rolled expectation in
`test_sstore_restoration_ancestor_revert` drifted on both terms. The
spec produces 157111 (157108 for `DELEGATECALL`) but the test wanted
163911, an excess of 6800.

That 6800 is two compensating errors that no longer cancel under the
EIP-8038 prices:

- The caller's outer `SSTORE(slot0, CALL(probe))` writes the probe's
  `0` return (the probe OOGs) into a fresh slot, a cold no-op charging
  `COLD_STORAGE_ACCESS` (3000). `regular_cost` assumed a cold set
  (`COLD_STORAGE_WRITE`, 13000), over-counting by 10000.
- `probe_burned` subtracted `COLD_ACCOUNT_ACCESS + 2 * WARM_ACCESS`.
  The probe burns its full forwarded budget (`probe_gas`) on the OOG,
  and the CALL's cold-access surcharge already sits in the caller's
  regular cost, so the subtraction under-counted by 3200.

Net: `+10000 - 3200 = +6800`.

The fix:

- Annotate the caller's outer SSTORE with no-op metadata
  (`key_warm=False`, `original_value=current_value=new_value=0`) so
  `regular_cost` prices it as the cold no-op it is.
- Use the full `probe_gas` in place of `probe_burned`.
- Drop the `expected_state` SSTORE-set term, since no set persists.
  Inner's set and clear cancel, middle reverts, the probe OOGs, and
  the outer SSTORE is a no-op, so block state gas is zero and
  `gas_used` is the regular total.

Verified by reconstructing all three call opcodes from fork-derived
components against the t8n output (`CALL` and `CALLCODE` 157111,
`DELEGATECALL` 157108). All 154 tests in `test_state_gas_sstore.py`
pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-spec-specs Area: Specification—The Ethereum specification itself (eg. `src/ethereum/*`) A-tests Area: Consensus tests. C-feat Category: an improvement or new feature P-high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants