fix(tests): measure on-chain SSTORE regular gas and warm the warm rows#7
Merged
marioevz merged 3 commits intoJun 23, 2026
Conversation
`test_sstore_regular_gas` never measured the executed `SSTORE` cost. It
only cross-checked the gas model against a hand-derived formula and
asserted post-state `{slot: new}`. Warmth came solely from the prep
`SSTORE` (emitted when `current != original`), so the four `key_warm`
rows with `current == original` ran cold on-chain, producing fixtures
identical to their cold siblings.
Wrap the measured write in `CodeGasMeasure` and assert its stored cost
equals `expected_regular`, and warm the `key_warm` rows via the access
list. Leave `gas_limit` unset so the state-gas reservoir lands above the
EIP-7825 cap and `Op.GAS` measures regular gas only. Correct the false
comment and the function docstring.
Every `test_sstore_regular_gas` row now carries an explicit suffix instead of hiding warmth in the parameter tuple. Clean rows (current == original) are `_cold` or `_warm`; dirty rows (current != original) are `_dirty`, since a prior in-frame SSTORE necessarily warms the slot. Add a legend defining the scheme. The clean/dirty terms are existing repo vocabulary; `tests/benchmark/stateful/bloatnet/test_single_opcode.py` documents the same EIP-2200 distinction, "clean (original==current) vs dirty (original!=current)".
marioevz
reviewed
Jun 23, 2026
marioevz
left a comment
There was a problem hiding this comment.
Two comments on these changes, thanks!
| measured = measured_bare(data_slot, new) | ||
|
|
||
| # Cross-check the oracle agrees with the hand-derived formula. | ||
| assert measured.regular_cost(fork) - 2 * very_low == expected_regular |
There was a problem hiding this comment.
This kinda defeats the purpose of gas_cost(fork)/regular_cost(fork)/state_cost(fork), and forces us to have to update this particular test if the gas price formula changes in the future.
We should simply:
expected_regular = measured_bare.regular_cost(fork)and remove other gas calculations from this function.
There was a problem hiding this comment.
My comment should really be in the expected_regular = access_cost + write_cost line, but it also applies here that we should not assert the cost of the push opcodes via 2 * very_low either.
| # Warm the slot for ``key_warm`` rows that have no prep to warm it; | ||
| # harmless for prep rows (warmth is set membership). Built after | ||
| # ``deploy_contract`` so the address exists. | ||
| access_list = ( |
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.
Stacked on ethereum#3033. This PR targets its
eip-8038-testsbranch and only changestests/amsterdam/eip8038_state_access_gas_cost_increase/test_sstore_gas.py, fixing thetest_sstore_regular_gascase that PR adds.Why
test_sstore_regular_gasasserts the EIP-8038 regularSSTOREschedule, but it never measured the executed cost. It only cross-checked the framework gas model against a hand-derived formula (a closed tautology, since both come from the samegas_costs) and asserted post-state{slot: new}, which is independent of the gas charged. Separately, slot warmth came only as a side effect of a prepSSTOREemitted whencurrent != original, so the fourkey_warm=Truerows withcurrent == original(00x_warm,xx0,xxy_warm,xxx) ran cold on-chain and produced fixtures identical to their cold siblings. The warm storage-access price was never exercised in execution.What changed
SSTOREinCodeGasMeasureand assert its executed regular cost equalsexpected_regular. The model cross-check is kept as a secondary guard.key_warmrows via the transaction access list instead of relying on an incidental prep write.gas_limitunset so the EIP-8037 state-gas reservoir lands above the EIP-7825 cap andOp.GASmeasures regular gas only. The priorgas_limit=1_000_000was below the cap, which zeroes the reservoir and spills the zero-to-nonzero rows' state gas (97920) into the measurement; with it unset the reservoir absorbs the state gas, matchingtest_create_regular_gas._cold/_warm/_dirtysuffix plus a legend._dirty(current != original) reuses the clean/dirty vocabulary already documented intests/benchmark/stateful/bloatnet/test_single_opcode.py.After the fix the warm and cold rows genuinely diverge.
00x_warmandxxy_warmmeasure 10100 against 13000 for their cold siblings,xxx_warmmeasures 100 against 3000, andxx0_warmis a real warm clear at 10100.Verification
uv run fill --fork Amsterdam tests/amsterdam/eip8038_state_access_gas_cost_increase/test_sstore_gas.pypasses (30/30).just staticis clean.Per-row facts from a trace dump (
--traces --evm-dump-dir). Across all rowsmeasured regequalsstored@0equalsexpected. The 97920measured stateon the00xrows is charged on the state dimension and excluded frommeasured reg(no spill), and the_dirtyrows show their unmeasured prep write.00x_cold00x_warm0x0_dirtyxx0_warmxxy_coldxxy_warmxyz_dirtyxyx_dirtyxxx_warmxxx_cold🔗 Related Issues or PRs
Fix-up to ethereum#3033 (EIP-8038 state-access gas-cost test suite), which introduced this test.