Skip to content

EIP-8037: Add tests for three missing gas-validation and code-deposit edge cases #2426

@benaadams

Description

@benaadams

Summary

While implementing EIP-8037 (two-dimensional gas accounting) in Nethermind, we found three real gas-accounting edge cases that were not covered by the current execution-spec tests. All three involve interactions between EIP-8037's state-gas reservoir and existing gas rules.

We would like to suggest adding execution-spec test coverage for these scenarios.

1. Intrinsic gas validation must include state gas for CREATE / setcode transactions

Under EIP-8037, some intrinsic costs are split into regular and state components.

Examples:

  • contract creation: CreateRegular + CreateState
  • EIP-7702 setcode/auth transactions: regular per-auth cost + state per-auth cost

A transaction whose gasLimit covers only the regular intrinsic component, but not regular + state, should fail intrinsic gas validation.

Suggested tests

  • CREATE transaction with:
  • gasLimit = 21000 + CreateRegular + calldata_cost
  • omitting CreateState
  • expected result:
  • rejected as below intrinsic gas

Similarly for EIP-7702 setcode/auth transactions:

  • gasLimit covers only the regular per-auth intrinsic cost
  • expected result:
  • rejected as below intrinsic gas

2. EIP-7623 floor gas must still be enforced when EIP-8037 is active

Amsterdam inherits EIP-7623 floor gas.

The minimum required gas is:

max(regular + state, floor)

A transaction where floor > regular + state must still be rejected if gasLimit < floor, even if it satisfies regular + state.

Suggested test

Send a transaction with 100 non-zero calldata bytes to an existing account:

  • tokens = 100 * 4 = 400
  • regular_intrinsic = 21000 + 400 * 4 = 22600
  • state = 0
  • floor = 21000 + 400 * 10 = 25000

Cases:

  • gasLimit = 23000
  • expected result: rejected
  • gasLimit = 25000
  • expected result: accepted

3. Nested CREATE code deposit must not borrow caller gas via state spill

When a CREATE returns initcode output, code deposit under EIP-8037 has:

  • a regular component: CodeDepositRegularPerWord * words
  • a state component: CostPerStateByte * bytes

If the child frame's state reservoir is insufficient, the shortfall spills into regular gas.

The important invariant is:

  • the child frame's own regular gas must cover both:
  • the regular code deposit cost
  • any spill from missing state gas

It must not be possible for the deposit charge to succeed by consuming the caller's retained gas after the child frame has been merged back.

Suggested test

A contract called via CALL performs CREATE of a 1-byte contract.

Because the parent frame has no state reservoir, the child also has no state reservoir, so the full code-deposit state cost spills into regular gas.

Tune gas so that after initcode execution the child ends with:

  • enough gas to satisfy the regular deposit check in isolation
  • enough gas to satisfy the state-cost check in isolation
  • but not enough gas to pay both together once state spill is accounted for

For a 1-byte deployed contract:

  • regularDepositCost = 6
  • stateDepositCost = 1174
  • total regular required = 1180

A child ending with 1175 gas should fail code deposit.

Expected result:

  • nested CREATE fails
  • caller gas is not used to make the child code deposit succeed

Context

These cases were found during Nethermind's Amsterdam / EIP-8037 implementation.

Nethermind fixes and regression tests: NethermindEth/nethermind#10712

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions