Skip to content

Update EIP-8037: clarify regular gas must be charged before state gas#11421

Merged
eth-bot merged 1 commit into
ethereum:masterfrom
spencer-tb:eip8037-gas-ordering
Mar 18, 2026
Merged

Update EIP-8037: clarify regular gas must be charged before state gas#11421
eth-bot merged 1 commit into
ethereum:masterfrom
spencer-tb:eip8037-gas-ordering

Conversation

@spencer-tb

Copy link
Copy Markdown
Contributor

Following the gas repricing call, cc-ing @misilva73

When an opcode requires both regular and state gas, the regular gas charge must be applied first. If regular gas OOGs, state gas is not consumed. This prevents the parent's reservoir from being inflated on child frame failure.

When an opcode requires both regular and state gas, the regular gas
charge must be applied first. If regular gas OOGs, state gas is not
consumed. This prevents the parent's reservoir from being inflated
on child frame failure.
@github-actions github-actions Bot added c-update Modifies an existing proposal s-draft This EIP is a Draft t-core labels Mar 18, 2026
@eth-bot

eth-bot commented Mar 18, 2026

Copy link
Copy Markdown
Collaborator

✅ All reviewers have approved.

@spencer-tb spencer-tb changed the title chore(eip-8037): clarify regular gas must be charged before state gas Update EIP-8037: Clarify regular gas must be charged before state gas Mar 18, 2026
@eth-bot eth-bot added the a-review Waiting on author to review label Mar 18, 2026
@eth-bot eth-bot changed the title Update EIP-8037: Clarify regular gas must be charged before state gas Update EIP-8037: clarify regular gas must be charged before state gas Mar 18, 2026

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

This look good to me. Thanks for updating. We can move out of draft.

@spencer-tb spencer-tb marked this pull request as ready for review March 18, 2026 21:13
@spencer-tb spencer-tb requested a review from eth-bot as a code owner March 18, 2026 21:13
Comment thread EIPS/eip-8037.md

- **Regular gas** charges deduct from `gas_left` only.
- **State gas** charges deduct from `state_gas_reservoir` first; when the reservoir is exhausted, from `gas_left`.
- When an opcode requires both regular and state gas, the regular gas charge MUST be applied first. If the regular gas charge triggers an out-of-gas error, the state gas charge is not applied.

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.

nit: It might help to further clarify some reasoning for this. Maybe:

Suggested change
- When an opcode requires both regular and state gas, the regular gas charge MUST be applied first. If the regular gas charge triggers an out-of-gas error, the state gas charge is not applied.
- When an opcode requires both regular and state gas, the regular gas charge MUST be applied first. If the regular gas charge triggers an out-of-gas error, the state gas charge is not applied. This prevents a regular-gas OOG from consuming state gas that would otherwise be returned to the parent frame's reservoir on exceptional halt.

Which is a bit awkward since the On **exception halt** line defined below is where this is return to the parent frame is explained. Maybe this isn't necessary or maybe this last clarifying line could be simpler:

This ensures state gas in the reservoir is not consumed for frames that fail before growing any state.

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.

I see this was already merged. I'm good with it as is :)

@eth-bot eth-bot enabled auto-merge (squash) March 18, 2026 21:51

@eth-bot eth-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

All Reviewers Have Approved; Performing Automatic Merge...

@eth-bot eth-bot merged commit 48566ad into ethereum:master Mar 18, 2026
21 of 23 checks passed
github-merge-queue Bot pushed a commit to lambdaclass/ethrex that referenced this pull request Mar 23, 2026
…#6389)

Bump execution-spec-tests fixtures from `bal@v5.4.0` to `bal@v5.5.1`.
Updates fixture URLs in CI workflows, Makefile, docs, and
`.fixtures_url_amsterdam` files.

Fix EIP-8037 state gas charging order per
[EIPs#11421](ethereum/EIPs#11421): regular gas
must be charged before state gas for SSTORE and CALL. Previously state
gas was charged first, which let spilled state gas inflate the parent's
reservoir via `incorporate_child_on_error` on regular gas OOG.

- `stack_memory_storage_flow.rs` (SSTORE): defer state gas charge until
after regular gas succeeds
- `system.rs` (CALL): peek reservoir to compute expected spill for child
gas computation, charge regular gas first, then charge state gas
- SELFDESTRUCT already had correct order, no change
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 26, 2026
Per EIP-8037 and ethereum/EIPs#11421, regular gas must be charged
before state gas. If regular gas OOGs, state gas is not consumed,
preventing parent reservoir inflation on frame failure.

Fixes:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: remove direct state gas charging before 63/64
  allocation; include in returned GasCosts instead
- CREATE/CREATE2 collision: undo account creation state gas
  charge (both tracking and budget) since EELS generic_create
  does not charge state gas on collision

Found by reservoir inflation detection tests in bal@v5.5.1.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 26, 2026
Per EIP-8037 and ethereum/EIPs#11421, regular gas must be charged
before state gas. If regular gas OOGs, state gas is not consumed,
preventing parent reservoir inflation on frame failure.

Fixes:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: remove direct state gas charging before 63/64
  allocation; include in returned GasCosts instead
- CREATE/CREATE2 collision: undo account creation state gas
  charge (both tracking and budget) since EELS generic_create
  does not charge state gas on collision

Found by reservoir inflation detection tests in bal@v5.5.1.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 26, 2026
Per EIP-8037 and ethereum/EIPs#11421, regular gas must be charged
before state gas. If regular gas OOGs, state gas is not consumed,
preventing parent reservoir inflation on frame failure.

Fixes:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- State transition: separate intrinsic gas and floor gas checks
  for Amsterdam, returning the correct error type for each

Found by reservoir inflation detection tests in bal@v5.5.1.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 26, 2026
Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)

CREATE2 collision — track burned regular gas:
- On address collision, record the burned child regular gas
  in GasUsed.RegularGasUsed so txRegular properly accounts
  for it in 2D block gas (cumulativeRegular)
- Without this, gp.Used() = max(txRegular, txState) vastly
  underestimates block gas for collision scenarios
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 26, 2026
Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)

Gas validation ordering for Amsterdam:
1. Total intrinsic must fit in tx gas limit (ErrIntrinsicGas)
2. max(regular, floor) must fit in MaxTxGas (ErrIntrinsicGas)
3. Calldata floor must fit in tx gas limit (ErrFloorDataGas)
Pre-Amsterdam Prague floor check moved to else branch.

CREATE2 collision — track burned regular gas:
- On address collision, record the burned child regular gas
  in GasUsed.RegularGasUsed so txRegular properly accounts
  for it in 2D block gas (cumulativeRegular)
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 26, 2026
…tion

Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: compute state gas spillover for 63/64 calculation WITHOUT
  charging state gas directly. Include state gas in returned GasCosts
  so the interpreter charges atomically (regular first). Prevents
  parent reservoir inflation when child regular gas OOGs.

Gas validation ordering for Amsterdam:
1. Total intrinsic must fit in tx gas limit (ErrIntrinsicGas)
2. max(regular, floor) must fit in MaxTxGas (ErrIntrinsicGas)
3. Calldata floor must fit in tx gas limit (ErrFloorDataGas)

CREATE2 collision — track burned regular gas in GasUsed.RegularGasUsed
so txRegular properly accounts for it in 2D block gas accounting.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 26, 2026
…tion

Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: compute state gas spillover for 63/64 calculation WITHOUT
  charging state gas directly. Include state gas in returned GasCosts
  so the interpreter charges atomically (regular first). Prevents
  parent reservoir inflation when child regular gas OOGs.

Gas validation ordering for Amsterdam:
1. Total intrinsic must fit in tx gas limit (ErrIntrinsicGas)
2. max(regular, floor) must fit in MaxTxGas (ErrIntrinsicGas)
3. Calldata floor must fit in tx gas limit (ErrFloorDataGas)

CREATE2 collision — track burned regular gas in GasUsed.RegularGasUsed
so txRegular properly accounts for it in 2D block gas accounting.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 26, 2026
…tion

Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: compute state gas spillover for 63/64 calculation WITHOUT
  charging state gas directly. Include state gas in returned GasCosts
  so the interpreter charges atomically (regular first). Prevents
  parent reservoir inflation when child regular gas OOGs.

Gas validation ordering for Amsterdam:
1. Total intrinsic must fit in tx gas limit (ErrIntrinsicGas)
2. max(regular, floor) must fit in MaxTxGas (ErrIntrinsicGas)
3. Calldata floor must fit in tx gas limit (ErrFloorDataGas)

CREATE2 collision — track burned regular gas in GasUsed.RegularGasUsed
so txRegular properly accounts for it in 2D block gas accounting.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 26, 2026
…tion

Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: compute state gas spillover for 63/64 calculation WITHOUT
  charging state gas directly. Include state gas in returned GasCosts
  so the interpreter charges atomically (regular first). Prevents
  parent reservoir inflation when child regular gas OOGs.

Gas validation ordering for Amsterdam:
1. Total intrinsic must fit in tx gas limit (ErrIntrinsicGas)
2. max(regular, floor) must fit in MaxTxGas (ErrIntrinsicGas)
3. Calldata floor must fit in tx gas limit (ErrFloorDataGas)

CREATE2 collision — track burned regular gas in GasUsed.RegularGasUsed
so txRegular properly accounts for it in 2D block gas accounting.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 27, 2026
…tion

Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: compute state gas spillover for 63/64 calculation WITHOUT
  charging state gas directly. Include state gas in returned GasCosts
  so the interpreter charges atomically (regular first). Prevents
  parent reservoir inflation when child regular gas OOGs.

Gas validation ordering for Amsterdam:
1. Total intrinsic must fit in tx gas limit (ErrIntrinsicGas)
2. max(regular, floor) must fit in MaxTxGas (ErrIntrinsicGas)
3. Calldata floor must fit in tx gas limit (ErrFloorDataGas)

CREATE2 collision — track burned regular gas in GasUsed.RegularGasUsed
so txRegular properly accounts for it in 2D block gas accounting.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 27, 2026
…tion

Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: compute state gas spillover for 63/64 calculation WITHOUT
  charging state gas directly. Include state gas in returned GasCosts
  so the interpreter charges atomically (regular first). Prevents
  parent reservoir inflation when child regular gas OOGs.

Gas validation ordering for Amsterdam:
1. Total intrinsic must fit in tx gas limit (ErrIntrinsicGas)
2. max(regular, floor) must fit in MaxTxGas (ErrIntrinsicGas)
3. Calldata floor must fit in tx gas limit (ErrFloorDataGas)

CREATE2 collision — track burned regular gas in GasUsed.RegularGasUsed
so txRegular properly accounts for it in 2D block gas accounting.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 27, 2026
…tion

Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: compute state gas spillover for 63/64 calculation WITHOUT
  charging state gas directly. Include state gas in returned GasCosts
  so the interpreter charges atomically (regular first). Prevents
  parent reservoir inflation when child regular gas OOGs.

Gas validation ordering for Amsterdam:
1. Total intrinsic must fit in tx gas limit (ErrIntrinsicGas)
2. max(regular, floor) must fit in MaxTxGas (ErrIntrinsicGas)
3. Calldata floor must fit in tx gas limit (ErrFloorDataGas)

CREATE2 collision — track burned regular gas in GasUsed.RegularGasUsed
so txRegular properly accounts for it in 2D block gas accounting.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 27, 2026
…tion

Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: compute state gas spillover for 63/64 calculation WITHOUT
  charging state gas directly. Include state gas in returned GasCosts
  so the interpreter charges atomically (regular first). Prevents
  parent reservoir inflation when child regular gas OOGs.

Gas validation ordering for Amsterdam:
1. Total intrinsic must fit in tx gas limit (ErrIntrinsicGas)
2. max(regular, floor) must fit in MaxTxGas (ErrIntrinsicGas)
3. Calldata floor must fit in tx gas limit (ErrFloorDataGas)

CREATE2 collision — track burned regular gas in GasUsed.RegularGasUsed
so txRegular properly accounts for it in 2D block gas accounting.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 27, 2026
…tion

Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: compute state gas spillover for 63/64 calculation WITHOUT
  charging state gas directly. Include state gas in returned GasCosts
  so the interpreter charges atomically (regular first). Prevents
  parent reservoir inflation when child regular gas OOGs.

Gas validation ordering for Amsterdam:
1. Total intrinsic must fit in tx gas limit (ErrIntrinsicGas)
2. max(regular, floor) must fit in MaxTxGas (ErrIntrinsicGas)
3. Calldata floor must fit in tx gas limit (ErrFloorDataGas)

CREATE2 collision — track burned regular gas in GasUsed.RegularGasUsed
so txRegular properly accounts for it in 2D block gas accounting.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 27, 2026
…tion

Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: compute state gas spillover for 63/64 calculation WITHOUT
  charging state gas directly. Include state gas in returned GasCosts
  so the interpreter charges atomically (regular first). Prevents
  parent reservoir inflation when child regular gas OOGs.

Gas validation ordering for Amsterdam:
1. Total intrinsic must fit in tx gas limit (ErrIntrinsicGas)
2. max(regular, floor) must fit in MaxTxGas (ErrIntrinsicGas)
3. Calldata floor must fit in tx gas limit (ErrFloorDataGas)

CREATE2 collision — track burned regular gas in GasUsed.RegularGasUsed
so txRegular properly accounts for it in 2D block gas accounting.
spencer-tb added a commit to spencer-tb/go-ethereum that referenced this pull request Mar 27, 2026
…tion

Per EIP-8037 and ethereum/EIPs#11421:

Gas ordering — regular gas must be charged before state gas:
- SSTORE: return both regular and state gas in GasCosts; the
  interpreter charges regular first via Underflow check
- Code deposit: charge regular gas (keccak256 words) before
  state gas (storage bytes)
- CALL: compute state gas spillover for 63/64 calculation WITHOUT
  charging state gas directly. Include state gas in returned GasCosts
  so the interpreter charges atomically (regular first). Prevents
  parent reservoir inflation when child regular gas OOGs.

Gas validation ordering for Amsterdam:
1. Total intrinsic must fit in tx gas limit (ErrIntrinsicGas)
2. max(regular, floor) must fit in MaxTxGas (ErrIntrinsicGas)
3. Calldata floor must fit in tx gas limit (ErrFloorDataGas)

CREATE2 collision — track burned regular gas in GasUsed.RegularGasUsed
so txRegular properly accounts for it in 2D block gas accounting.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a-review Waiting on author to review c-update Modifies an existing proposal s-draft This EIP is a Draft t-core

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants