Skip to content

test_top_frame_state_charge()

Documentation for tests/amsterdam/eip2780_reduce_intrinsic_tx_gas/test_top_frame_charges.py::test_top_frame_state_charge@c74f1a67.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip2780_reduce_intrinsic_tx_gas/test_top_frame_charges.py::test_top_frame_state_charge --fork Amsterdam

Recipient is empty and the transaction transfers a non-zero value, so the top-frame fires the NEW_ACCOUNT state-gas charge.

  • oog: gas limit is one short of covering the state charge. The transaction passes the intrinsic check, enters process_message, and out-of-gases on charge_state_gas(NEW_ACCOUNT) before any EVM bytecode runs. The sender pays the full gas_limit and no value is transferred.
  • success: gas limit covers the state charge. The value transfer brings the recipient into existence and the recipient ends the transaction holding the transferred balance.
Source code in tests/amsterdam/eip2780_reduce_intrinsic_tx_gas/test_top_frame_charges.py
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
@pytest.mark.parametrize("outcome", ["oog", "success"])
def test_top_frame_state_charge(
    fork: Fork,
    pre: Alloc,
    state_test: StateTestFiller,
    outcome: str,
) -> None:
    """
    Recipient is empty and the transaction transfers a non-zero value,
    so the top-frame fires the ``NEW_ACCOUNT`` state-gas charge.

    - ``oog``: gas limit is one short of covering the state charge.
      The transaction passes the intrinsic check, enters
      ``process_message``, and out-of-gases on
      ``charge_state_gas(NEW_ACCOUNT)`` before any EVM bytecode runs.
      The sender pays the full ``gas_limit`` and no value is
      transferred.
    - ``success``: gas limit covers the state charge. The value
      transfer brings the recipient into existence and the recipient
      ends the transaction holding the transferred balance.
    """
    sender_initial_balance = 10**18
    sender = pre.fund_eoa(sender_initial_balance)
    target = pre.fund_eoa(amount=0)

    value = 1
    intrinsic_gas = fork.transaction_intrinsic_cost_calculator()(
        sends_value=True,
        recipient_type=RecipientType.EMPTY_ACCOUNT,
        return_cost_deducted_prior_execution=True,
    )
    top_frame_state_gas = fork.transaction_top_frame_state_gas(
        sends_value=True,
        recipient_type=RecipientType.EMPTY_ACCOUNT,
    )
    assert top_frame_state_gas > 0, (
        "top-frame state gas must be non-zero for this scenario"
    )

    gas_price = 1_000_000_000
    if outcome == "oog":
        gas_limit = intrinsic_gas + top_frame_state_gas - 1
        sender_final_balance = sender_initial_balance - gas_limit * gas_price
        expected_target: Account | None = None
    else:
        total_gas_cost = intrinsic_gas + top_frame_state_gas
        gas_limit = total_gas_cost + 1000
        sender_final_balance = (
            sender_initial_balance - value - total_gas_cost * gas_price
        )
        expected_target = Account(balance=value)

    tx = Transaction(
        sender=sender,
        to=target,
        value=value,
        gas_limit=gas_limit,
        gas_price=gas_price,
    )

    post = {
        sender: Account(nonce=1, balance=sender_final_balance),
        target: expected_target,
    }

    state_test(pre=pre, tx=tx, post=post)

Parametrized Test Cases

This test generates 2 parametrized test cases across 1 fork.