feat(spec-specs): EIP-8037 - move CREATE state gas charge after initcode size validation#2608
Merged
spencer-tb merged 2 commits intoApr 2, 2026
Conversation
Move charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) from create()/create2() into generic_create(), after the MAX_INIT_CODE_SIZE check. Previously, state gas was charged before the initcode size check, so a CREATE with oversized initcode would persist state_gas_used equal to the account creation state gas cost (STATE_BYTES_PER_NEW_ACCOUNT * cost_per_state_byte) even though no account was ever created and no state was touched. Reported by @AskDragan (reth): ethereum#2578 (comment)
Move the is_static check from generic_create() into create() and create2(), before stack pops and charge_gas(). This is consistent with SSTORE, CALL, and SELFDESTRUCT which all check static context before any gas charging.
cec523c to
bb76ce3
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## eips/amsterdam/eip-8037 #2608 +/- ##
==========================================================
Coverage ? 88.17%
==========================================================
Files ? 524
Lines ? 31088
Branches ? 3036
==========================================================
Hits ? 27412
Misses ? 3161
Partials ? 515
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
kclowes
approved these changes
Apr 1, 2026
kclowes
left a comment
Contributor
There was a problem hiding this comment.
This code lgtm! 🚀 Is the test fail expected?
b9f0afa
into
ethereum:eips/amsterdam/eip-8037
19 of 20 checks passed
Contributor
Author
Thanks! Yeah its expected :D |
github-merge-queue Bot
pushed a commit
to erigontech/erigon
that referenced
this pull request
Apr 7, 2026
…s ordering (#20290) - Fix two uint64 underflow bugs in EIP-8037 multidimensional gas accounting that caused incorrect receipt `gasUsed` when child frames reverted with a state gas reservoir that grew beyond its initial value (via sub-child reverts) - Move CREATE/CREATE2 state gas charge (account creation) from the dynamic gas functions into opCreate/opCreate2, after the static-context and initcode-size checks, so state gas is not consumed on early failures where no state is created (aligns with ethereum/execution-specs#2608) - Update execution-spec-tests submodule to [bal@v5.6.1](https://github.com/ethereum/execution-spec-tests/releases/tag/bal%40v5.6.1) - Skip 2 BAL tests where coinbase==target exposes a separate `TxIn` bug in exec3_parallel finalize (TODO) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: info@weblogix.biz <admin@10gbps.weblogix.it>
github-merge-queue Bot
pushed a commit
to erigontech/erigon
that referenced
this pull request
Apr 8, 2026
…s ordering (#20290) - Fix two uint64 underflow bugs in EIP-8037 multidimensional gas accounting that caused incorrect receipt `gasUsed` when child frames reverted with a state gas reservoir that grew beyond its initial value (via sub-child reverts) - Move CREATE/CREATE2 state gas charge (account creation) from the dynamic gas functions into opCreate/opCreate2, after the static-context and initcode-size checks, so state gas is not consumed on early failures where no state is created (aligns with ethereum/execution-specs#2608) - Update execution-spec-tests submodule to [bal@v5.6.1](https://github.com/ethereum/execution-spec-tests/releases/tag/bal%40v5.6.1) - Skip 2 BAL tests where coinbase==target exposes a separate `TxIn` bug in exec3_parallel finalize (TODO) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: info@weblogix.biz <admin@10gbps.weblogix.it>
github-merge-queue Bot
pushed a commit
to erigontech/erigon
that referenced
this pull request
Apr 8, 2026
…s ordering (#20290) - Fix two uint64 underflow bugs in EIP-8037 multidimensional gas accounting that caused incorrect receipt `gasUsed` when child frames reverted with a state gas reservoir that grew beyond its initial value (via sub-child reverts) - Move CREATE/CREATE2 state gas charge (account creation) from the dynamic gas functions into opCreate/opCreate2, after the static-context and initcode-size checks, so state gas is not consumed on early failures where no state is created (aligns with ethereum/execution-specs#2608) - Update execution-spec-tests submodule to [bal@v5.6.1](https://github.com/ethereum/execution-spec-tests/releases/tag/bal%40v5.6.1) - Skip 2 BAL tests where coinbase==target exposes a separate `TxIn` bug in exec3_parallel finalize (TODO) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: info@weblogix.biz <admin@10gbps.weblogix.it>
marioevz
pushed a commit
that referenced
this pull request
Apr 9, 2026
…ode size validation (#2608) * fix(spec): charge CREATE state gas after initcode size validation Move charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) from create()/create2() into generic_create(), after the MAX_INIT_CODE_SIZE check. Previously, state gas was charged before the initcode size check, so a CREATE with oversized initcode would persist state_gas_used equal to the account creation state gas cost (STATE_BYTES_PER_NEW_ACCOUNT * cost_per_state_byte) even though no account was ever created and no state was touched. Reported by @AskDragan (reth): #2578 (comment) * fix(spec): check static context before gas in CREATE/CREATE2 Move the is_static check from generic_create() into create() and create2(), before stack pops and charge_gas(). This is consistent with SSTORE, CALL, and SELFDESTRUCT which all check static context before any gas charging.
5 tasks
github-merge-queue Bot
pushed a commit
to lambdaclass/ethrex
that referenced
this pull request
Apr 10, 2026
…ing (#6447) Bump BAL fixtures from v5.5.1 to v5.6.1 across Makefile, CI workflows, docs, and fixture URL files. Fix two EIP-8037 correctness issues in `system.rs`: move the `is_static` check to CREATE/CREATE2 handlers (Amsterdam+ only) before stack pops and gas charging, matching ethereum/execution-specs#2608; move `increase_state_gas(STATE_GAS_NEW_ACCOUNT)` into `generic_create()` after `MAX_INIT_CODE_SIZE` validation so oversized CREATE doesn't burn state gas for an account never created. Fix per-tx gas check in `levm/mod.rs` to use `block_regular_gas_used` instead of `max(regular, state)` per ethereum/execution-specs#2583, and apply `min(TX_MAX_GAS_LIMIT, tx.gas)` cap per EIP-7825. Applied across `execute_block`, `execute_block_pipeline`, and `execute_block_parallel`. Update `payload.rs` to track `remaining_gas` using regular gas capacity only for Amsterdam. All 1103 BAL consume-engine tests pass. Along with ethereum/execution-specs#2632
marioevz
pushed a commit
that referenced
this pull request
Apr 10, 2026
…ode size validation (#2608) * fix(spec): charge CREATE state gas after initcode size validation Move charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) from create()/create2() into generic_create(), after the MAX_INIT_CODE_SIZE check. Previously, state gas was charged before the initcode size check, so a CREATE with oversized initcode would persist state_gas_used equal to the account creation state gas cost (STATE_BYTES_PER_NEW_ACCOUNT * cost_per_state_byte) even though no account was ever created and no state was touched. Reported by @AskDragan (reth): #2578 (comment) * fix(spec): check static context before gas in CREATE/CREATE2 Move the is_static check from generic_create() into create() and create2(), before stack pops and charge_gas(). This is consistent with SSTORE, CALL, and SELFDESTRUCT which all check static context before any gas charging.
chfast
pushed a commit
to ipsilon/evmone
that referenced
this pull request
Apr 13, 2026
charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) was called before MAX_INIT_CODE_SIZE validation. A CREATE with oversized initcode would persist state_gas_used for an account that was never created. Also moved is_static check before gas charging, consistent with SSTORE, CALL, and SELFDESTRUCT. Matches spec fix ethereum/execution-specs#2608. Ported from erigontech/zevmone@amsterdam-giulio.
felix314159
pushed a commit
to felix314159/execution-specs
that referenced
this pull request
Apr 14, 2026
…ode size validation (ethereum#2608) * fix(spec): charge CREATE state gas after initcode size validation Move charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) from create()/create2() into generic_create(), after the MAX_INIT_CODE_SIZE check. Previously, state gas was charged before the initcode size check, so a CREATE with oversized initcode would persist state_gas_used equal to the account creation state gas cost (STATE_BYTES_PER_NEW_ACCOUNT * cost_per_state_byte) even though no account was ever created and no state was touched. Reported by @AskDragan (reth): ethereum#2578 (comment) * fix(spec): check static context before gas in CREATE/CREATE2 Move the is_static check from generic_create() into create() and create2(), before stack pops and charge_gas(). This is consistent with SSTORE, CALL, and SELFDESTRUCT which all check static context before any gas charging.
chfast
pushed a commit
to ipsilon/evmone
that referenced
this pull request
Apr 15, 2026
charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) was called before MAX_INIT_CODE_SIZE validation. A CREATE with oversized initcode would persist state_gas_used for an account that was never created. Also moved is_static check before gas charging, consistent with SSTORE, CALL, and SELFDESTRUCT. Matches spec fix ethereum/execution-specs#2608. Ported from erigontech/zevmone@amsterdam-giulio.
felix314159
pushed a commit
that referenced
this pull request
Apr 16, 2026
…ode size validation (#2608) * fix(spec): charge CREATE state gas after initcode size validation Move charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) from create()/create2() into generic_create(), after the MAX_INIT_CODE_SIZE check. Previously, state gas was charged before the initcode size check, so a CREATE with oversized initcode would persist state_gas_used equal to the account creation state gas cost (STATE_BYTES_PER_NEW_ACCOUNT * cost_per_state_byte) even though no account was ever created and no state was touched. Reported by @AskDragan (reth): #2578 (comment) * fix(spec): check static context before gas in CREATE/CREATE2 Move the is_static check from generic_create() into create() and create2(), before stack pops and charge_gas(). This is consistent with SSTORE, CALL, and SELFDESTRUCT which all check static context before any gas charging.
spencer-tb
added a commit
that referenced
this pull request
Apr 17, 2026
…ode size validation (#2608) * fix(spec): charge CREATE state gas after initcode size validation Move charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) from create()/create2() into generic_create(), after the MAX_INIT_CODE_SIZE check. Previously, state gas was charged before the initcode size check, so a CREATE with oversized initcode would persist state_gas_used equal to the account creation state gas cost (STATE_BYTES_PER_NEW_ACCOUNT * cost_per_state_byte) even though no account was ever created and no state was touched. Reported by @AskDragan (reth): #2578 (comment) * fix(spec): check static context before gas in CREATE/CREATE2 Move the is_static check from generic_create() into create() and create2(), before stack pops and charge_gas(). This is consistent with SSTORE, CALL, and SELFDESTRUCT which all check static context before any gas charging.
spencer-tb
added a commit
to spencer-tb/execution-specs
that referenced
this pull request
Apr 19, 2026
Ported from closed PR ethereum#2639. Covers the PR ethereum#2608 ordering requirement: the MAX_INITCODE_SIZE check must run before the account-creation state gas charge. test_oversized_initcode_tx_no_state_gas (parametrized `at_max`, `over_max`) Creation tx whose initcode is exactly MAX_INITCODE_SIZE (accepted) or one byte over (rejected with INITCODE_SIZE_EXCEEDED). If state gas were charged before the size check, block_state_gas_used would include a spurious GAS_NEW_ACCOUNT for an account never created. test_oversized_initcode_opcode_no_state_gas (parametrized `at_max`, `over_max`, `CREATE`, `CREATE2`) Factory calls CREATE/CREATE2 opcode with initcode exceeding the limit; the opcode returns 0 with no state gas consumed.
4 tasks
marioevz
pushed a commit
that referenced
this pull request
Apr 20, 2026
…ode size validation (#2608) * fix(spec): charge CREATE state gas after initcode size validation Move charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) from create()/create2() into generic_create(), after the MAX_INIT_CODE_SIZE check. Previously, state gas was charged before the initcode size check, so a CREATE with oversized initcode would persist state_gas_used equal to the account creation state gas cost (STATE_BYTES_PER_NEW_ACCOUNT * cost_per_state_byte) even though no account was ever created and no state was touched. Reported by @AskDragan (reth): #2578 (comment) * fix(spec): check static context before gas in CREATE/CREATE2 Move the is_static check from generic_create() into create() and create2(), before stack pops and charge_gas(). This is consistent with SSTORE, CALL, and SELFDESTRUCT which all check static context before any gas charging.
spencer-tb
added a commit
to spencer-tb/execution-specs
that referenced
this pull request
Apr 20, 2026
Ported from closed PR ethereum#2639. Covers the PR ethereum#2608 ordering requirement: the MAX_INITCODE_SIZE check must run before the account-creation state gas charge. test_oversized_initcode_tx_no_state_gas (parametrized `at_max`, `over_max`) Creation tx whose initcode is exactly MAX_INITCODE_SIZE (accepted) or one byte over (rejected with INITCODE_SIZE_EXCEEDED). If state gas were charged before the size check, block_state_gas_used would include a spurious GAS_NEW_ACCOUNT for an account never created. test_oversized_initcode_opcode_no_state_gas (parametrized `at_max`, `over_max`, `CREATE`, `CREATE2`) Factory calls CREATE/CREATE2 opcode with initcode exceeding the limit; the opcode returns 0 with no state gas consumed.
spencer-tb
added a commit
that referenced
this pull request
Apr 20, 2026
…ode size validation (#2608) * fix(spec): charge CREATE state gas after initcode size validation Move charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) from create()/create2() into generic_create(), after the MAX_INIT_CODE_SIZE check. Previously, state gas was charged before the initcode size check, so a CREATE with oversized initcode would persist state_gas_used equal to the account creation state gas cost (STATE_BYTES_PER_NEW_ACCOUNT * cost_per_state_byte) even though no account was ever created and no state was touched. Reported by @AskDragan (reth): #2578 (comment) * fix(spec): check static context before gas in CREATE/CREATE2 Move the is_static check from generic_create() into create() and create2(), before stack pops and charge_gas(). This is consistent with SSTORE, CALL, and SELFDESTRUCT which all check static context before any gas charging.
spencer-tb
added a commit
that referenced
this pull request
Apr 21, 2026
…ode size validation (#2608) * fix(spec): charge CREATE state gas after initcode size validation Move charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) from create()/create2() into generic_create(), after the MAX_INIT_CODE_SIZE check. Previously, state gas was charged before the initcode size check, so a CREATE with oversized initcode would persist state_gas_used equal to the account creation state gas cost (STATE_BYTES_PER_NEW_ACCOUNT * cost_per_state_byte) even though no account was ever created and no state was touched. Reported by @AskDragan (reth): #2578 (comment) * fix(spec): check static context before gas in CREATE/CREATE2 Move the is_static check from generic_create() into create() and create2(), before stack pops and charge_gas(). This is consistent with SSTORE, CALL, and SELFDESTRUCT which all check static context before any gas charging.
chfast
pushed a commit
to ipsilon/evmone
that referenced
this pull request
Apr 28, 2026
charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) was called before MAX_INIT_CODE_SIZE validation. A CREATE with oversized initcode would persist state_gas_used for an account that was never created. Also moved is_static check before gas charging, consistent with SSTORE, CALL, and SELFDESTRUCT. Matches spec fix ethereum/execution-specs#2608. Ported from erigontech/zevmone@amsterdam-giulio.
fselmo
pushed a commit
that referenced
this pull request
May 5, 2026
…ode size validation (#2608) * fix(spec): charge CREATE state gas after initcode size validation Move charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) from create()/create2() into generic_create(), after the MAX_INIT_CODE_SIZE check. Previously, state gas was charged before the initcode size check, so a CREATE with oversized initcode would persist state_gas_used equal to the account creation state gas cost (STATE_BYTES_PER_NEW_ACCOUNT * cost_per_state_byte) even though no account was ever created and no state was touched. Reported by @AskDragan (reth): #2578 (comment) * fix(spec): check static context before gas in CREATE/CREATE2 Move the is_static check from generic_create() into create() and create2(), before stack pops and charge_gas(). This is consistent with SSTORE, CALL, and SELFDESTRUCT which all check static context before any gas charging.
spencer-tb
added a commit
to spencer-tb/execution-specs
that referenced
this pull request
May 22, 2026
…ode size validation (ethereum#2608) * fix(spec): charge CREATE state gas after initcode size validation Move charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT) from create()/create2() into generic_create(), after the MAX_INIT_CODE_SIZE check. Previously, state gas was charged before the initcode size check, so a CREATE with oversized initcode would persist state_gas_used equal to the account creation state gas cost (STATE_BYTES_PER_NEW_ACCOUNT * cost_per_state_byte) even though no account was ever created and no state was touched. Reported by @AskDragan (reth): ethereum#2578 (comment) * fix(spec): check static context before gas in CREATE/CREATE2 Move the is_static check from generic_create() into create() and create2(), before stack pops and charge_gas(). This is consistent with SSTORE, CALL, and SELFDESTRUCT which all check static context before any gas charging.
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
Spec Fix 1: State gas after initcode size check
Move
charge_state_gas(STATE_BYTES_PER_NEW_ACCOUNT)fromcreate()/create2()intogeneric_create(), after theMAX_INIT_CODE_SIZEvalidation.Previously, state gas was charged before the initcode size check, so a CREATE with oversized initcode would persist
state_gas_usedequal to the account creation state gas cost (STATE_BYTES_PER_NEW_ACCOUNT * cost_per_state_byte) even though no account was ever created and no state was touched.Spec Fix 2: Static context check before gas charging
Move the
is_staticcheck fromgeneric_create()intocreate()andcreate2(), before stack pops andcharge_gas(). Previously, regular and state gas were charged before checking static context. This is now consistent with SSTORE, CALL, and SELFDESTRUCT which all check static context before any gas charging.Tests
Existing
test_max_initcode_size_via_create[over_max]cases (CREATE and CREATE2) intests/amsterdam/eip7954_increase_max_contract_size/test_max_initcode_size.pyalready cover the state gas ordering fix. They only need a re-fill after this spec fix, no test code changes required.🔗 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):.