Conversation
`TLOAD` and `TSTORE` (EIP-1153) were charged via `WARM_ACCESS` because the two costs happened to coincide at 100 gas. Give them dedicated `OPCODE_TLOAD` and `OPCODE_TSTORE` constants so that state-access repricing does not implicitly reprice transient storage, which is in-memory only. Values are unchanged; EIP-7971 proposes new values for these operations and can update the constants in place when it lands.
Reprice state-access operations per EIP-8038 with provisional values (flat 3x of the legacy schedule, pending final benchmark results): - `WARM_ACCESS` 100 -> 300, `COLD_ACCOUNT_ACCESS` 2600 -> 7800, `COLD_STORAGE_ACCESS` 2100 -> 6300. - New `STORAGE_WRITE` (8400) replaces `COLD_STORAGE_WRITE`: `SSTORE` now always charges the access cost (cold or warm) and additionally charges `STORAGE_WRITE` on the first change to a slot; restoring the original value refunds `STORAGE_WRITE`. `REFUND_STORAGE_CLEAR` 4800 -> 14400. - New `ACCOUNT_WRITE` (20100): `CALL_VALUE` is redefined as `ACCOUNT_WRITE` + `CALL_STIPEND` (22400), and `SELFDESTRUCT` charges `ACCOUNT_WRITE` when a positive balance is sent to an empty account. - New `CREATE_ACCESS` (21000) replaces `REGULAR_GAS_CREATE` for `CREATE`/`CREATE2` and contract-creation transactions. - `EXTCODESIZE`/`EXTCODECOPY` charge an additional `WARM_ACCESS` for the second database read (the code). - Access list costs: `TX_ACCESS_LIST_ADDRESS` 2400 -> 7200, `TX_ACCESS_LIST_STORAGE_KEY` 1900 -> 5700. - EIP-7702 authorizations: the per-authorization intrinsic regular gas is `ACCOUNT_WRITE` + `REGULAR_PER_AUTH_BASE_COST` (replacing `PER_AUTH_BASE_COST`), and `ACCOUNT_WRITE` is refunded to the refund counter when the authority's account leaf already exists. Deviations of provisional values from the EIP's derivation formulas (`CREATE_ACCESS`, `REFUND_STORAGE_CLEAR`, access list costs) are flagged with comments at the constant definitions.
…load Mirror the spec-side change in the EEST fork gas model: `TLOAD` and `TSTORE` were priced via `WARM_SLOAD` because the two costs happened to coincide at 100 gas. Add dedicated `OPCODE_TLOAD` and `OPCODE_TSTORE` gas cost fields, set by the EIP-1153 mixin, so that state-access repricing does not implicitly reprice transient storage. Values are unchanged for all forks.
…as model Fold the EIP-8038 repricing into the EEST EIP-8037 mixin: the two EIPs ship together in Amsterdam and share one gas schedule, and the EIP-8037 compound constants (`AUTH_PER_EMPTY_ACCOUNT`, `TX_CREATE`, `STORAGE_SET`) are derived from the EIP-8038 parameters. Values are provisional (flat 3x), matching the spec. - Reprice the access, storage, call value, refund, and access list constants; model the new `SSTORE` formula (access cost always charged, `STORAGE_WRITE` on first change, refunded on restore). - Expose `ACCOUNT_WRITE` as a new `GasCosts` field (0 before the repricing): tests need it to model the capped regular-gas refund for EIP-7702 authorities with an existing account leaf, separately from the uncapped state refill (`REFUND_AUTH_PER_EXISTING_ACCOUNT`). - `EXTCODESIZE`/`EXTCODECOPY` charge an extra `WARM_ACCESS` for the second database read (the code). - `SELFDESTRUCT` charges `ACCOUNT_WRITE` when a positive balance is sent to an empty account.
Mirror the provisional EIP-8038 values in the test-side constants: - `REGULAR_GAS_CREATE` 9000 -> 21000: the spec's new `CREATE_ACCESS`. - `PER_AUTH_BASE_COST` 7500 -> 33116: total regular intrinsic per EIP-7702 authorization, `ACCOUNT_WRITE` (20100) + `REGULAR_PER_AUTH_BASE_COST` (13016 = 1616 calldata + 3000 ecRecover + 7800 cold account read + 2 x 300 warm writes). - `GAS_COLD_STORAGE_WRITE` 5000 -> 14700: `COLD_STORAGE_ACCESS` (6300) + `STORAGE_WRITE` (8400).
EIP-8038 splits the existing-authority adjustment for EIP-7702 authorizations into two channels with different cap semantics: - The new-account *state* portion is refilled directly to the state gas reservoir (`REFUND_AUTH_PER_EXISTING_ACCOUNT`, uncapped), as before. - The worst-case `ACCOUNT_WRITE` (20100) charged at intrinsic time is refunded via the regular refund counter, subject to the standard 1/5 refund cap. The cap typically binds: per-auth gas used before refund is well below 5 x 20100. Update the tests that model existing-authority refunds accordingly: - `test_auth_refund_block_gas_accounting`: receipt `cumulative_gas_used` subtracts `min(gas_used_before_refund // 5, ACCOUNT_WRITE)` for the `existing_leaf`/`existing_delegation` variants. Header `gas_used` is unchanged: EIP-7778 excludes refund-counter refunds from block accounting. - `test_auth_sender_billing_after_failure`: same capped term; the refund survives the top-level REVERT because delegations (and their refunds) are applied before execution. - EIP-7976 `max_refund` fixture: existing-authority refunds now contribute `ACCOUNT_WRITE` to the capped refund counter under EIP-8037/8038 (previously nothing; pre-8037 the full `REFUND_AUTH_PER_EXISTING_ACCOUNT`). - EIP-7778 `build_refund_tx`: add `ACCOUNT_WRITE` per authorization to the refund counter, outside the revert guard for the same reason as the sender-billing test.
EIP-8038 charges `ACCOUNT_WRITE` (20100) in regular gas when SELFDESTRUCT sends a positive balance to an empty account, alongside the EIP-8037 account-creation state gas. - Rework `test_selfdestruct_new_beneficiary_no_regular_account_creation_cost` into `test_selfdestruct_new_beneficiary_account_write_cost`: the old premise (no regular charge, asserted via a tight budget with 20000 slack) inverted, since `ACCOUNT_WRITE` exceeds the slack and the transaction ran out of gas. The reworked test tags the opcode with `account_new=True` so the framework folds `ACCOUNT_WRITE` plus the state gas into the budget, and tightens the slack to 4000, below the legacy 25000 minus `ACCOUNT_WRITE`: any regular draw beyond `ACCOUNT_WRITE` still runs out of gas, proving the charge is exactly the new parameter and not the legacy combined cost. - `test_selfdestruct_in_create_tx_initcode`: the budget left only 1000 slack above the account-creation state gas, so the new charge made the creation transaction halt. Tag `account_new=True` and drop the now redundant explicit `NEW_ACCOUNT` term.
Under the EIP-8038 SSTORE formula the access cost is always charged and the write cost is added only on the first change to a slot. A cold no-op store therefore costs `COLD_STORAGE_ACCESS` flat; the legacy formula charged cold plus warm (warm was the "else" branch of the write cost). The halt-path gas simulation in `test_parent_state_gas_after_child_failure` kept the legacy `+ WARM_ACCESS` for the factory's cold no-op SSTORE, overstating the expected receipt by exactly 300. The revert variants were unaffected: they compute the same bytecode via `bytecode.gas_cost(fork)`, which uses the framework formula.
The EIP-8037 state-access repricing lifted the `STORAGE_CLEAR` prefix (a single `SSTORE` clear) to 14706 gas, whose minimum post-refund execution cost (28642) now exceeds the data floor (21384) produced by sizing calldata to `intrinsic_gas_data_floor_minimum_delta = 250`. The `execution_gas_used` fixture asserts the floor sits above that cost so both the below-floor and above-floor refund scenarios stay reachable; that precondition no longer held, and the fixture's own assert diagnosed it. Raise `intrinsic_gas_data_floor_minimum_delta` 250 -> 11000. The floor grows 64/byte against 16/byte intrinsic, so ~9.7k of delta closes the gap; 11000 leaves margin. No test semantics change.
EIP-7981 tripled the access-list intrinsic cost (address 2400 -> 7200, key 1900 -> 5700). `test_below_amsterdam_floor_with_access_list_exact_balance` pins `gas_limit` to the midpoint between the data floor without and with the access list, then asserts `intrinsic_regular <= gas_limit < floor`. At 1000 nonzero bytes the regular intrinsic cost (122960) now sits above that midpoint (95880), so the premise is unsatisfiable. Raise the smaller calldata parameter 1000 -> 1700 nonzero bytes. Each nonzero byte adds 64 gas to the floor (hence to the midpoint) but only 16 to the intrinsic cost, closing the gap by 48/byte; the premise needs at least 1565 bytes. No test semantics change.
`test_code_deposit_oog_preserves_parent_reservoir` forwards a fixed `child_gas` to the factory via `Op.CALL`. After the factory's CREATE takes 63/64, the retained 1/64 (~15k from 1M) no longer covers its repriced post-CREATE SSTOREs (~21k), so the factory halted before its `parent_sstore` and the expected storage write disappeared. Raise the in-bytecode `child_gas` 1000000 -> 1500000; the factory then retains ~23k. The code-deposit OOG premise (deploy size 4096, deposit state gas 6.27M) is unaffected. PR ethereum#2969 auto-sizes the transaction gas limit but not a `CALL` gas argument inside contract code, so this budget is re-tuned by hand.
The repricing pushed the six cold zero-to-nonzero SSTOREs in `test_delegatecall_child_spill_not_double_charged` to 6 x (14700 regular + 97920 state) = 675720, which the hardcoded `gas_limit=700_000` no longer covered once intrinsic and call overhead were added, so the delegatecall hit OOG and rolled back its writes. The premise needs the top-level frame to start with no state gas reservoir, which holds only while `tx.gas` stays at or below the `TX_MAX_GAS_LIMIT` cap (16777216); leaving the limit unset would let the filler assign the block gas limit and seed a large implicit reservoir instead. Drop the hardcoded limit and set `state_gas_reservoir=0`, which pins the gas limit to exactly the cap with a zero reservoir. This preserves the premise with ~16M of headroom, is robust to further repricing, and matches the reservoir idiom used by the sibling tests in the same module.
Replace the provisional flat-3x placeholders with the final benchmark-derived values from the updated EIP-8038 spec, across the spec, the EEST fork gas model, and the Amsterdam tests: - `WARM_ACCESS` stays 100, `COLD_ACCOUNT_ACCESS` 3000, `COLD_STORAGE_ACCESS` 3000, `STORAGE_WRITE` 10000, `ACCOUNT_WRITE` 8000, `CALL_VALUE` 10300. - `CREATE_ACCESS` 11000, `REFUND_STORAGE_CLEAR` 12480, `TX_ACCESS_LIST_ADDRESS` 3000, `TX_ACCESS_LIST_STORAGE_KEY` 3000. - Test constants follow suit: `REGULAR_GAS_CREATE` 11000, `PER_AUTH_BASE_COST` 15816, `GAS_COLD_STORAGE_WRITE` 13000. The derived parameters now match the EIP derivation formulas exactly, so the provisional deviation comments are dropped. Ref: ethereum/EIPs#11802
The EIP-7702 account-warming gas tests hardcoded the EIP-2929 cold and warm account access costs (`2600` and `100`) when computing the expected per-account access gas they assert through `SSTORE`. The EIP-8038 state-access repricing raises `COLD_ACCOUNT_ACCESS` `2600 -> 3000` at Amsterdam while `WARM_ACCESS` stays `100`, so the measured access cost no longer matched the baked-in expectation: a cold access followed by a warm delegated read measured `3100` against an expected `2700`. These tests are `valid_from` Prague, so they must keep the pre-repricing values at Prague and Osaka while picking up the repriced values at Amsterdam. Derive `cold_account_cost` and `warm_account_cost` from `fork.gas_costs().COLD_ACCOUNT_ACCESS` and `.WARM_ACCESS` in: - `test_gas.py::test_account_warming`: the cold/warm constants that feed `addresses_to_check`. - `test_gas.py::test_self_set_code_cost`: the pre-authorized self-delegation cost, now `cold + warm` (`2700`), and the in-transaction case `2 x warm` (`200`). - `test_set_code_txs.py::test_set_code_address_and_authority_warm_state`: the set-code-address and authority access costs, now `cold` / `warm`, `2 x warm` (`200`), and `warm + cold` (`2700`). The derived values equal the previous literals at Prague and Osaka (`cold = 2600`, `warm = 100`) and the repriced values at Amsterdam (`cold = 3000`). No test semantics change.
`test_selfdestruct_after_create2_collision` forwards a gas budget to a deployer contract whose colliding `CREATE2` returns `0`. A colliding create consumes 63/64 of the forwarded gas (the account-creation state gas is charged then refunded on collision under EIP-8037), leaving the deployer only 1/64 to record the result with an `SSTORE`. The EIP-8038 state-access repricing raised that cold `SSTORE` to `COLD_STORAGE_WRITE` = 13,000 at Amsterdam (5,000 before), which now exceeds the surviving 1/64 of the old budget (`500_000 + NEW_ACCOUNT + SSTORE state cost`), so the deployer `CALL` hit `OutOfGasError` and `create2_call_success` read `0` instead of `1`. Size the forwarded budget as `500_000 + 64 x COLD_STORAGE_WRITE` so the 1/64 that survives the collision burn always covers the deployer's cold `SSTORE`. The value is fork-derived: it tracks `COLD_STORAGE_WRITE` (5,000 at Cancun/Osaka, 13,000 at Amsterdam) and the budget is forwarded, so the extra headroom is returned unused on the cheaper forks. No test semantics change: the `CREATE2` still collides and returns `0`.
`test_tstore_rollback_on_failed_create` recorded each failed create's
result with `SSTORE(slot, result)` over a pre-stored `{0:1, 1:1}` to
prove the writes happened. A failed create (code-too-large ->
`OutOfGasError`) consumes its full 63/64 gas forward. Under the EIP-8037
transaction gas-limit cap the top-frame regular gas is capped at
`TX_MAX_GAS_LIMIT` (16,777,216), so two sequential failed creates leave
only `16.74M / 64^2` ~ 3,750 regular gas, while the EIP-8038 repricing
raised the warm `1->0` `SSTORE` to 10,100 (2,200 before). The second
`SSTORE` therefore hit `OutOfGasError` and the whole transaction
reverted, leaving the pre-state intact (`want {0:0, 1:0}, got
{0:1, 1:1}`). The regular budget is capped, so no `gas_limit` or
`state_gas_reservoir` choice can raise it; the test passes pre-Amsterdam
only because the cheaper `SSTORE` fits the same leftover.
Drop the result `SSTORE`s and assert in the post-state that the created
address is non-existent, checking the same rollback property without a
write in the gas-starved frame:
- The caller runs the two creates and stops; its nonce advancing to 3
confirms both attempts executed.
- `CREATE2` targets one deterministic address for both attempts;
`CREATE` targets the nonce-derived addresses. If `TSTORE` is rolled
back the second create fails and nothing is deployed; if it were not,
the second `CREATE2` would deploy a contract there.
This matches the sibling `test_contract_creation` idiom (compute the
created address, check its account). A positive control (forcing the
initcode to succeed) confirms the assertion still fails when a contract
is deployed, so the regression coverage is preserved. Verified at
Amsterdam, Cancun, and Osaka.
`stEIP2930/test_storage_costs.py` measures the regular gas consumed by storage accesses via `Op.GAS` and stores it to a slot. The Amsterdam enhancement added a single `sstore_set_delta` baked against provisional EIP-8038 parameters (`state_cost(fork) - 17100`), and commit `ef7fe9bebb8` updated those parameters to their final values, leaving every measured access wrong: fresh `SSTORE`-sets were off by 7200, and the cold `SLOAD`, cold value-unchanged `SSTORE`, and storage clear/reset entries received no delta at all (off by 900, 800, and 7200/8000 respectively). Replace the single delta with six fork-derived deltas, each computed from the fork's own opcode gas model as `Op.SSTORE.with_metadata(<transition>).gas_cost(fork) - <Cancun pure cost>` (or `gas_costs().COLD_STORAGE_ACCESS - 2100` for the cold `SLOAD`). Each is exactly 0 pre-EIP-8037 and tracks the final Amsterdam parameters: `+88020`/`+88820` for warm/cold fresh sets, `+7200`/`+8000` for warm/cold writes to existing slots (clear/reset), `+800` for cold value-unchanged `SSTORE`s, and `+900` for cold `SLOAD`s. Apply each to its matching expect entry; warm reads and no-op `SSTORE`s are unchanged. No test semantics change: the post-state still asserts the exact measured gas, now correct at every fork. Fills clean across Cancun -> Amsterdam (432 passed).
`stPreCompiledContracts/test_precomps_eip2929_cancun.py` measures the regular gas of a `CALL` to an inactive precompile and isolates three cost components across its `no`/`new`/`all` parametrizations. The Amsterdam enhancement modelled only the new-account shift via a shared `new_account_delta` (`create_state_gas() - 25000`), so after commit `ef7fe9bebb8` the cold-account-access reprice (`COLD_ACCOUNT_ACCESS` 2600 -> 3000) was unaccounted for: the `no` entries (cold access only) and `all` entries (new account plus cold access) were each off by 400, while the `new` entries (new account only) were correct. Derive a separate `cold_account_delta` (`COLD_ACCOUNT_ACCESS - 2600`, 0 pre-Amsterdam) alongside the unchanged `new_account_delta` and apply them per class: `no` entries gain the cold delta, `new` entries keep the account delta, and `all` entries gain both. Both deltas come from the fork's gas model, so they stay 0 pre-EIP-8037 and track future parameter changes. No test semantics change: the post-state still asserts the exact measured gas, now correct at every fork. Fills clean across Cancun -> Amsterdam (5544 passed).
`stEIP2930/test_varied_context.py` measures gas around SSTORE, CALL, and SELFDESTRUCT in many access-list contexts. The Amsterdam enhancement used a single `sstore_set_delta` (`state_cost - 17100`) for both warm and cold sets and folded it into `suicide_write_delta`; after commit `ef7fe9bebb8` updated the final parameters, every measured access was off. Cold SLOADs, cold value-unchanged accesses, and the SELFDESTRUCT `ACCOUNT_WRITE`/cold-reprice components were unmodelled, and the `*ValidGas` parametrizations forward a fixed in-bytecode gas budget that the higher EIP-8038 SSTORE-write cost made insufficient, flipping their success path to OOG. Replace the single delta with per-transition deltas derived from the fork's own gas model (warm/cold fresh sets, cold account access, cold storage access, and the SELFDESTRUCT-to-non-alive composite of new-account spill plus `ACCOUNT_WRITE` plus cold reprice). Apply each to its matching expect entry: cold accesses gain the cold deltas, the suicide-read/write entries gain the SELFDESTRUCT composite, and the cold "invalid" suicide variants add the cold account and cold-set components traced at their ops. Bump the two `*ValidGas` forwarded-gas budgets by the inner SSTORE-write increase, preserving the Cancun margin so the warm success path stays funded while the colder invalid path still OOGs. All deltas are 0 pre-EIP-8037. No test semantics change: the post-state still asserts the exact measured gas (or success/OOG), now correct at every fork. Fills clean across Cancun -> Amsterdam (432 passed).
`stEIP2930/test_manual_create.py` measures the regular gas of a fresh SSTORE-set inside a CREATE-deployed contract. The Amsterdam enhancement used a single `sstore_set_delta` (`state_cost - 17100`) for both the declared (warm) and undeclared (cold) sets, and commit `ef7fe9bebb8` updated the final parameters, leaving the warm entry off by 7200 and the cold entries off by 8000. Replace the single delta with warm and cold fresh-set deltas derived from the fork's own gas model (`Op.SSTORE.with_metadata(...).gas_cost( fork) - <Cancun pure cost>`), each 0 pre-EIP-8037. Apply the warm delta to the declared-key entry and the cold delta to the undeclared-key entries. No test semantics change: the post-state still asserts the exact measured gas, now correct at every fork. Fills clean across Cancun -> Amsterdam.
`stCreateTest/test_create_address_warm_after_fail.py` records the measured cost of accessing a create address after a failed CREATE: a cold account access hardcoded at 2828 (2600 plus opcode overhead). EIP-8038 reprices a cold account access from 2600 to 3000, so commit `ef7fe9bebb8` left every such measurement 400 low at Amsterdam. Derive `cold_account_delta` (`COLD_ACCOUNT_ACCESS - 2600`, 0 pre-Amsterdam) from the fork's gas model and add it to each cold-access measurement, so the post-state tracks the final parameters and stays correct pre-fork. No test semantics change. Fills clean across Cancun -> Amsterdam (the successful-create parametrizations remain in the skip list).
The `stEIP150singleCodeGasPrices` ported tests measure, via `Op.GAS`, the regular gas of EIP-2929 account and storage accesses and store it to a slot, asserting hardcoded Cancun-era values. EIP-8038 reprices those accesses (cold account 2600 -> 3000, cold storage 2100 -> 3000, plus a flat `WARM_ACCESS` surcharge on the `EXTCODESIZE`/`EXTCODECOPY` code read on both warm and cold forms, and the SSTORE state-gas spill), so the literals were wrong at Amsterdam. Express each measured value as `<Cancun literal> + <fork-derived delta>`, where every delta comes from the fork's own gas model (`gas_costs().COLD_ACCOUNT_ACCESS - 2600`, `COLD_STORAGE_ACCESS - 2100`, `Op.EXTCODESIZE.gas_cost(fork)` etc., and `Op.SSTORE.with_metadata(...)` for writes) and is exactly 0 pre-EIP-8037. `test_eip2929` is rewritten to size each data index from a Cancun base table plus a fork-derived per-operation access simulator. Banners mark each file manually-enhanced. No test semantics change: the post-state still asserts the exact measured gas, now correct at every fork. Fills clean across Cancun -> Amsterdam.
`test_address_opcodes` measures the regular gas of `BALANCE`, `EXTCODESIZE`, `EXTCODEHASH`, and `EXTCODECOPY` on a first (cold or pre-warmed) and a second (warm) access; the coinbase tests measure a CALL that transfers value to the warm coinbase. EIP-8038 reprices the cold account access (2600 -> 3000), adds a flat `WARM_ACCESS` surcharge to the `EXTCODESIZE`/`EXTCODECOPY` code read, and reprices the CALL value transfer (9000 -> 10300), so the hardcoded Cancun values were wrong at Amsterdam. Split the combined entries per opcode and per access and add each opcode's own warm or cold `(Amsterdam - Cancun)` delta taken from the fork gas model; the coinbase value uses `CALL_VALUE - 9000`. Every delta is exactly 0 pre-EIP-8037. No test semantics change. Fills clean across Cancun -> Amsterdam.
`stBadOpcode/test_measure_gas` and `test_operation_diff_gas` measure the regular gas of account-touching opcodes (`EXTCODESIZE`/`EXTCODECOPY` and the CALL family) and store it. EIP-8038 reprices the cold account access (2600 -> 3000) and adds a flat `WARM_ACCESS` surcharge to the EXTCODE code read, so the hardcoded values were wrong at Amsterdam. Add each opcode's fork-derived warm or cold cost delta (`Op.<NAME>.gas_cost(fork)` minus the Cancun cost, or `COLD_ACCOUNT_ACCESS - 2600`), matching whether the measured iteration runs the access warm or cold; each delta is 0 pre-EIP-8037. The CREATE and CREATE2 parametrizations remain in the skip list. No test semantics change. Fills clean across Cancun -> Amsterdam.
The `stEIP158Specific` CALL-to-suicide and EXTCODESIZE tests measure the regular gas of a CALL (optionally with value) to a cold contract that may SELFDESTRUCT, and of EXTCODESIZE on a non-existent account. EIP-8038 reprices the cold account access (2600 -> 3000), the CALL value transfer (9000 -> 10300), the EXTCODESIZE code-read surcharge, and the SSTORE write, so the hardcoded values were wrong at Amsterdam. Express each measured value as the Cancun literal plus the fork-derived sum of the components it touches (`COLD_ACCOUNT_ACCESS - 2600`, `CALL_VALUE - 9000`, the EXTCODESIZE delta, and `Op.SSTORE.with_metadata` deltas), each 0 pre-EIP-8037. No test semantics change. Fills clean across Cancun -> Amsterdam.
`stEIP150Specific/test_suicide_to_existing_contract` and `test_suicide_to_not_existing_contract` measure the regular gas of a CALL that SELFDESTRUCTs to an existing or new beneficiary. EIP-8038 reprices the cold account access (2600 -> 3000) on the CALL target and, for the new-beneficiary case, the SELFDESTRUCT beneficiary, so the hardcoded values were 400 (one cold access) and 800 (two cold accesses) low at Amsterdam. Add the fork-derived `COLD_ACCOUNT_ACCESS - 2600` delta once or twice per the accesses each test makes; each is 0 pre-EIP-8037. No test semantics change. Fills clean across Cancun -> Amsterdam.
The `stNonZeroCallsTest` tests measure the regular gas of a CALL/CALLCODE that sends nonzero value to a cold account, then writes a result slot. EIP-8038 reprices the cold account access (2600 -> 3000), the CALL value transfer (9000 -> 10300), and the value-unchanged cold SSTORE, summing to 2500 at Amsterdam. Express the measured value as the Cancun literal plus the fork-derived sum of those components, each 0 pre-EIP-8037. No test semantics change. Fills clean across Cancun -> Amsterdam.
`stSpecialTest/test_eoa_empty_paris` measures the regular gas of CALLs to an empty account, with and without value. EIP-8038 reprices the cold account access (2600 -> 3000) and the CALL value transfer (9000 -> 10300), so the value-bearing measurements were 1300 low and the value-zero cold measurements 400 low at Amsterdam. Add the fork-derived `CALL_VALUE - 9000` and `COLD_ACCOUNT_ACCESS - 2600` deltas to the matching slots; each is 0 pre-EIP-8037. The value-0 warm literals are unchanged. No test semantics change. Fills clean across Cancun -> Amsterdam.
`stMemoryTest/test_oog` forwards a fixed in-bytecode gas budget to a nested value-0 CALL to a cold contract; EIP-8038's cold account reprice (2600 -> 3000) consumed the slack and made the RETURNDATACOPY success path run out of gas, flipping its expected result. Bump only that one forwarded calldata budget by the fork-derived `COLD_ACCOUNT_ACCESS - 2600` (0 pre-EIP-8037). The companion failure-case budget is left untouched and still runs out of gas as intended, so the test still exercises both branches. No test semantics change. Fills clean across Cancun -> Amsterdam.
`stEIP1153_transientStorage/test_14_revert_after_nested_staticcall` has the caller write four fresh storage slots before a nested STATICCALL. EIP-8037/8038 spill each fresh SSTORE's state gas into regular gas (empty reservoir), pushing total consumption past the original transaction budget so the final SSTORE ran out of gas and reverted the whole call. Bump the transaction `gas_limit` by the summed fork-derived SSTORE increases (`Op.SSTORE.with_metadata(...).gas_cost(fork)` deltas for the three sets and one clear), which is 0 pre-EIP-8037. The inner STATICCALL budget is untouched, preserving the static-violation semantics. No test semantics change. Fills clean across Cancun -> Amsterdam.
The `stRefundTest` tests assert the sender balance, which equals its start minus the paid `gas_used * gas_price`. EIP-8038 raises SSTORE clear/reset charges (cold clear 5000 -> 13000, etc.), so `gas_used` rises and the hardcoded Cancun balances were wrong at Amsterdam. Derive the per-SSTORE charge delta from the fork gas model (`Op.SSTORE.with_metadata(...).gas_cost(fork)` minus the Cancun charge, 0 pre-EIP-8037) and adjust each balance by `gas_price * gas_used_delta`. Where the EIP-3529 refund cap (`gas_used // 5`) binds at both forks the extra charge raises `gas_used` by four fifths of itself; partial-cap cases reconstruct `gas_used` as `gross - min(refund, gross // 5)` from a fork-invariant base plus the fork-derived charge and refund. The OOG-cascade case (`test_refund_no_oog_1`) also lifts the tx gas so its clear still succeeds. No test semantics change: the balances now track gas_used at every fork. Fills clean across Cancun -> Amsterdam.
The `stTransactionTest` store-clears tests run ten (and an inner ten) SSTORE clears. EIP-8038 raises each cold clear charge from 5000 to 13000, so the original tx gas_limit (and the inner CALL gas budget) no longer covered the clears and the success path ran out of gas, changing the post-state. Bump the tx `gas_limit` and inner CALL gas by the fork-derived per-clear charge delta (`Op.SSTORE.with_metadata(...).gas_cost(fork) - 5000`) times the number of clears each frame performs (accounting for the 63/64 rule on the inner CALL). The delta is 0 pre-EIP-8037, so earlier forks keep the original budgets. No test semantics change. Fills clean across Cancun -> Amsterdam.
`vmTests/test_suicide` asserts, for the `caller` case, a sender balance that reflects `gas_used`. EIP-8038 reprices the outer CALL's cold account access (2600 -> 3000), raising gas_used, so the hardcoded balance was 400 per access low at Amsterdam. Adjust that balance by `gas_price` times the fork-derived `COLD_ACCOUNT_ACCESS - 2600` per access (0 pre-EIP-8037). The `random` and `myself` cases assert non-gas-dependent balances and are unchanged. No test semantics change. Fills clean across Cancun -> Amsterdam.
The CREATE/CREATE2 "out of gas after init code" tests forward a tx gas budget tuned so one parametrization runs out of gas after the init code and another just clears the deploy threshold. EIP-8038 shifts that threshold (the NEW_ACCOUNT cost becomes a spilling state-gas charge and `OPCODE_CREATE_BASE` drops), so the previously-hardcoded Amsterdam window constants were stale and the success parametrization wrongly ran out of gas (a missing created account). Replace the magic constants with `fork.oog_budget_lift(...)` (the state gas EIP-8037 spills into regular gas, 0 pre-EIP-8037) plus the fork-derived `OPCODE_CREATE_BASE` drop and code-deposit adjustment, so the budget tracks the parameters: the out-of-gas parametrization still runs out and the success one still deploys. `test_create2_smart_init_code` lifts its success budget by the full spilled state gas (`creates_before_oog=3, sstores_before_oog=2`). No test semantics change. Fills clean across Cancun -> Amsterdam (the out-of-gas case stays NONEXISTENT, the success case deploys).
`stRevertTest/test_revert_opcode_calls` d3 success path ends in a fresh SSTORE-set in the transaction frame. EIP-8037 spills that set's state gas into regular gas (empty reservoir), so the original `tx_gas[0]` ran out at the final SSTORE and the stored result never landed. Lift the g0 budget by `fork.oog_budget_lift(sstores_before_oog=1)` (the spilled state gas, 0 pre-EIP-8037); g1 is unchanged. No test semantics change. Fills clean across Cancun -> Amsterdam.
danceratopz
force-pushed
the
8038
branch
2 times, most recently
from
June 18, 2026 16:08
eb8fb34 to
4f2db09
Compare
Merged
4 tasks
Owner
|
This was PR'd as ethereum#3017. |
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
Fix remaining ported static tests for EIP-8038.
🔗 Related Issues or PRs
N/A.
✅ Checklist
toxchecks to avoid unnecessary CI fails, see also Code Standards and Enabling Pre-commit Checks:uvx tox -e statictype(scope):.mkdocs servelocally and verified the auto-generated docs for new tests in the Test Case Reference are correctly formatted.@ported_frommarker.Cute Animal Picture