Skip to content

test_selfdestruct_state_gas_refilled_on_ancestor_revert()

Documentation for tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_selfdestruct.py::test_selfdestruct_state_gas_refilled_on_ancestor_revert@5c024cbb.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_selfdestruct.py::test_selfdestruct_state_gas_refilled_on_ancestor_revert --fork Amsterdam

Verify SELFDESTRUCT state gas is refilled when an ancestor reverts.

The inner frame spills the NEW_ACCOUNT charge and self-destructs successfully, then the caller reverts: the beneficiary creation rolls back and the spilled state charge is refilled. The EIP-8038 regular account-write charge for the attempted empty-account value transfer remains billed.

Source code in tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_selfdestruct.py
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
@pytest.mark.valid_from("EIP8037")
def test_selfdestruct_state_gas_refilled_on_ancestor_revert(
    state_test: StateTestFiller,
    pre: Alloc,
    fork: Fork,
) -> None:
    """
    Verify SELFDESTRUCT state gas is refilled when an ancestor reverts.

    The inner frame spills the NEW_ACCOUNT charge and self-destructs
    successfully, then the caller reverts: the beneficiary creation
    rolls back and the spilled state charge is refilled. The EIP-8038
    regular account-write charge for the attempted empty-account value
    transfer remains billed.
    """
    beneficiary = 0xDEAD
    inner_code = Op.SELFDESTRUCT(beneficiary)
    inner = pre.deploy_contract(code=inner_code, balance=1)
    caller_code = Op.POP(Op.CALL(gas=Op.GAS, address=inner)) + Op.REVERT(0, 0)
    caller = pre.deploy_contract(code=caller_code)

    expected_regular = (
        fork.transaction_intrinsic_cost_calculator()()
        + caller_code.gas_cost(fork)
        + inner_code.gas_cost(fork)
        + fork.gas_costs().ACCOUNT_WRITE
    )
    tx = Transaction(to=caller, sender=pre.fund_eoa())

    state_test(
        pre=pre,
        post={beneficiary: Account.NONEXISTENT, inner: Account(balance=1)},
        tx=tx,
        blockchain_test_header_verify=Header(gas_used=expected_regular),
    )

Parametrized Test Cases

This test generates 1 parametrized test case across 1 fork.