Skip to content

Test SELFDESTRUCT Gas

Documentation for tests/amsterdam/eip8038_state_access_gas_cost_increase/test_selfdestruct_gas.py@5fa5938b.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip8038_state_access_gas_cost_increase/test_selfdestruct_gas.py --fork Amsterdam

Tests for the EIP-8038 State Access Gas Cost Increase SELFDESTRUCT regular-gas dimension.

Under EIP-8038 SELFDESTRUCT is charged, in its regular gas dimension:

  • OPCODE_SELFDESTRUCT_BASE (5,000);
  • a COLD_ACCOUNT_ACCESS (3,000) surcharge when the beneficiary is cold (a warm beneficiary adds nothing — SELFDESTRUCT has no WARM_ACCESS surcharge);
  • a net-new ACCOUNT_WRITE (8,000) when a positive balance is sent to an empty (or non-existent) beneficiary, replacing the legacy combined 25,000 regular account-creation cost.

So regular = 5,000 + (3,000 if cold) + (8,000 if creating): 13,000 warm / 16,000 cold when a new beneficiary is created, 5,000 warm / 8,000 cold otherwise.

The beneficiary account-creation charge GAS_NEW_ACCOUNT (183,600) is the EIP-8037 state dimension (charge_state_gas in the spec), covered in eip8037_state_creation_gas_cost_increase/test_state_gas_selfdestruct.py.

SELFDESTRUCT halts the frame, so it is driven via a wrapping CALL and verified through block gas_used accounting and balances. Per EIP-6780, a contract not created in the same transaction is not deleted, but its balance is still transferred and the beneficiary creation charge still applies.

The framework opcode-gas model splits the two dimensions for SELFDESTRUCT exactly as the spec does: ACCOUNT_WRITE is charged as regular gas and GAS_NEW_ACCOUNT as state gas, so Op.SELFDESTRUCT(account_new=True).regular_cost(fork) is the regular charge (16,000 cold / 13,000 warm) and .state_cost(fork) is GAS_NEW_ACCOUNT. These tests assert the regular dimension and verify account-creation via balances; the state dimension is owned by eip8037_state_creation_gas_cost_increase/test_state_gas_selfdestruct.py.

Test Functions Overview

Name Type Cases (Amsterdam) Description
test_same_tx_created_selfdestruct_self_burn state_test 1 EIP-6780: a same-tx-created contract SELFDESTRUCTs to itself, charged
test_same_tx_created_selfdestruct_to_fresh_beneficiary state_test 1 EIP-6780: a same-tx-created contract sends value to a fresh
test_selfdestruct_alive_beneficiary_no_account_write state_test 2 SELFDESTRUCT to an already-alive beneficiary charges no ACCOUNT_WRITE.
test_selfdestruct_codebearing_zero_balance_beneficiary_no_account_write state_test 2 SELFDESTRUCT to a code-bearing zero-balance beneficiary: no
test_selfdestruct_new_beneficiary_regular_gas state_test 2 SELFDESTRUCT to an empty beneficiary with balance charges
test_selfdestruct_oog_boundary state_test 2 Drive a cold SELFDESTRUCT that funds a new account at its exact total
test_selfdestruct_self_or_precompile_beneficiary state_test 2 SELFDESTRUCT to self or a precompile is warm and charges no
test_selfdestruct_zero_balance_no_account_write state_test 2 SELFDESTRUCT with a zero-balance destructor charges no ACCOUNT_WRITE.