Skip to content

test_access_list_no_fallback()

Documentation for tests/amsterdam/eip8038_state_access_gas_cost_increase/test_exact_balance_no_fallback.py::test_access_list_no_fallback@26332146.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip8038_state_access_gas_cost_increase/test_exact_balance_no_fallback.py::test_access_list_no_fallback --fork Amsterdam

Reject an access-list transaction whose gas_limit is one gas below the Amsterdam intrinsic.

EIP-8038 raises TX_ACCESS_LIST_ADDRESS and TX_ACCESS_LIST_STORAGE_KEY. A client reusing the old per-address/per-key constants would compute an intrinsic smaller by num_addresses * addr_delta + num_keys * key_delta; with the sender funded to the wei, that fallback must not slip through.

Source code in tests/amsterdam/eip8038_state_access_gas_cost_increase/test_exact_balance_no_fallback.py
 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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
@pytest.mark.inclusion_test
@EIPChecklist.GasCostChanges.Test.OutOfGas()
@pytest.mark.exception_test
@pytest.mark.parametrize(
    "num_addresses,num_keys",
    [
        pytest.param(1, 0, id="one_address"),
        pytest.param(2, 0, id="two_addresses"),
        pytest.param(1, 1, id="one_address_one_key"),
    ],
)
def test_access_list_no_fallback(
    state_test: StateTestFiller,
    pre: Alloc,
    fork: Fork,
    num_addresses: int,
    num_keys: int,
) -> None:
    """
    Reject an access-list transaction whose ``gas_limit`` is one gas
    below the Amsterdam intrinsic.

    EIP-8038 raises ``TX_ACCESS_LIST_ADDRESS`` and
    ``TX_ACCESS_LIST_STORAGE_KEY``. A client reusing the
    old per-address/per-key constants would compute an intrinsic smaller
    by ``num_addresses * addr_delta + num_keys * key_delta``; with the
    sender funded to the wei, that fallback must not slip through.
    """
    new_costs = fork.gas_costs()
    old_costs = gas_costs_before_increase(
        fork,
        lambda c: (c.TX_ACCESS_LIST_ADDRESS, c.TX_ACCESS_LIST_STORAGE_KEY),
    )
    addr_delta = (
        new_costs.TX_ACCESS_LIST_ADDRESS - old_costs.TX_ACCESS_LIST_ADDRESS
    )
    key_delta = (
        new_costs.TX_ACCESS_LIST_STORAGE_KEY
        - old_costs.TX_ACCESS_LIST_STORAGE_KEY
    )
    fallback_delta = num_addresses * addr_delta + num_keys * key_delta
    assert fallback_delta > 0

    # All storage keys live on the first listed address; the remaining
    # addresses carry no keys.
    storage_keys = list(range(num_keys))
    access_list = [
        AccessList(
            address=pre.fund_eoa(amount=0),
            storage_keys=storage_keys if index == 0 else [],
        )
        for index in range(num_addresses)
    ]

    intrinsic = fork.transaction_intrinsic_cost_calculator()(
        access_list=access_list,
        return_cost_deducted_prior_execution=True,
    )
    # One gas below the spec-correct intrinsic: a fallback client using
    # the old constants needs only `intrinsic - fallback_delta`.
    gas_limit = intrinsic - 1
    assert intrinsic - fallback_delta <= gas_limit < intrinsic

    sender = pre.fund_eoa(amount=gas_limit * GAS_PRICE)
    tx = Transaction(
        sender=sender,
        to=pre.fund_eoa(amount=0),
        access_list=access_list,
        gas_limit=gas_limit,
        gas_price=GAS_PRICE,
        error=TransactionException.INTRINSIC_GAS_TOO_LOW,
    )

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

Parametrized Test Cases

This test generates 3 parametrized test cases across 1 fork.