Skip to content

test_access_list_slot_warmth_is_address_scoped()

Documentation for tests/amsterdam/eip8038_state_access_gas_cost_increase/test_access_list_gas.py::test_access_list_slot_warmth_is_address_scoped@622620d8.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip8038_state_access_gas_cost_increase/test_access_list_gas.py::test_access_list_slot_warmth_is_address_scoped --fork Amsterdam

Access-list slot warmth is scoped to (address, slot).

Slot s of account A is listed in the access list. Reading slot s of A is warm (WARM_SLOAD); reading the same slot number of a different account B is cold (COLD_STORAGE_ACCESS).

Source code in tests/amsterdam/eip8038_state_access_gas_cost_increase/test_access_list_gas.py
218
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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
@EIPChecklist.GasCostChanges.Test.GasUpdatesMeasurement()
def test_access_list_slot_warmth_is_address_scoped(
    state_test: StateTestFiller,
    env: Environment,
    pre: Alloc,
    fork: Fork,
) -> None:
    """
    Access-list slot warmth is scoped to ``(address, slot)``.

    Slot ``s`` of account ``A`` is listed in the access list. Reading
    slot ``s`` of ``A`` is warm (``WARM_SLOAD``); reading the same slot
    number of a different account ``B`` is cold (``COLD_STORAGE_ACCESS``).
    """
    slot = 0x42
    warm_gas = Op.SLOAD(key_warm=True).gas_cost(fork)
    cold_gas = Op.SLOAD(key_warm=False).gas_cost(fork)

    # Both accounts read their own slot ``s`` with the same wrapper, so the
    # overhead that strips the operand PUSH is identical for each.
    measured_read = Op.SLOAD(slot)
    overhead = measured_read.gas_cost(fork) - cold_gas

    # B reads its own slot ``s`` (cold), storing the result in B's slot 1.
    account_b = pre.deploy_contract(
        code=CodeGasMeasure(
            code=measured_read,
            overhead_cost=overhead,
            extra_stack_items=1,
            sstore_key=1,
        ),
        storage={slot: 1},
    )

    # A reads its own slot ``s`` (warm via the access list), then calls B.
    account_a = pre.deploy_contract(
        code=CodeGasMeasure(
            code=measured_read,
            overhead_cost=overhead,
            extra_stack_items=1,
            sstore_key=1,
        )
        + Op.POP(Op.CALL(gas=200_000, address=account_b)),
        storage={slot: 1},
    )

    tx = Transaction(
        to=account_a,
        sender=pre.fund_eoa(),
        # Only A's slot is listed; B's identical slot stays cold.
        access_list=[AccessList(address=account_a, storage_keys=[slot])],
    )

    post = {
        account_a: Account(storage={1: warm_gas, slot: 1}),
        account_b: Account(storage={1: cold_gas, slot: 1}),
    }
    state_test(env=env, pre=pre, post=post, tx=tx)

Parametrized Test Cases

This test generates 1 parametrized test case across 1 fork.