Skip to content

CALL* does not refund the NEW_ACCOUNT state-gas charge when the call fails before entering the frame (EIP-8037) #3020

Description

@misilva73

Metadata

  • Hardfork: amsterdam

What was wrong?

The EIP-8037 conditional NEW_ACCOUNT state-gas charge for the CALL* family is not refunded when the call fails before entering the child frame, contradicting EIP-8037 and creating an asymmetry with CREATE/CREATE2 (which refund correctly on the analogous failures).

NEW_ACCOUNT is charged conditionally in call/callcode/etc. at src/ethereum/forks/amsterdam/vm/instructions/system.py:460-461:

if value != 0 and not is_account_alive(tx_state, to):
    charge_state_gas(evm, StateGasCosts.NEW_ACCOUNT)

…but it is never credited back on the two pre-frame failure exits:

  • Insufficient sender balancesystem.py:481-485 restores only call_state_gas_reservoir, which is captured after the NEW_ACCOUNT deduction, so the charge (and any portion that spilled into gas_left) is lost.
  • Stack-depth limitgeneric_call, system.py:338-342 restores params.gas / params.state_gas_reservoir only.

Neither branch calls credit_state_gas_refund. Compare generic_create, which does refund on its analogous pre-frame failures (system.py:112-119).

Impact: the sender of a value-bearing CALL to a non-existent/empty account is over-charged STATE_BYTES_PER_NEW_ACCOUNT × CPSB when the call fails on insufficient balance or the stack-depth limit, even though no account is created.

Sources

  • EIP-8037 — account-creation charging for the CALL* family:

    If the operation is unsuccessful before entering the call frame (e.g., due to insufficient balance or due to the stack depth), or if the child frame reverts or halts exceptionally, the charged state-gas is refilled in LIFO order and execution_state_gas_used decreases by the same amount.

  • Update EIP-8037: resolve EIP-7928 conflict and route state-gas refills to origin EIPs#11807 — the PR that clarifies the CALL* (conditional) vs CREATE/CREATE2 (unconditional) charging split, where this requirement is spelled out.

Additional Context

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: this is a bug, deviation, or other problem

    Type

    No type

    Fields

    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