Skip to content

test_access_list_warms_storage_slot()

Documentation for tests/amsterdam/eip8038_state_access_gas_cost_increase/test_access_list_gas.py::test_access_list_warms_storage_slot@87aba1a3.

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_warms_storage_slot --fork Amsterdam

A storage slot named in the access list is warm on first access.

The first runtime SLOAD/SSTORE of an access-list slot pays the warm cost: WARM_SLOAD for SLOAD; for SSTORE an overwrite of a non-zero original to a new non-zero value pays WARM_SLOAD + STORAGE_WRITE.

Source code in tests/amsterdam/eip8038_state_access_gas_cost_increase/test_access_list_gas.py
204
205
206
207
208
209
210
211
212
213
214
215
216
217
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
@EIPChecklist.GasCostChanges.Test.GasUpdatesMeasurement()
@pytest.mark.parametrize("op", ["SLOAD", "SSTORE"], ids=["sload", "sstore"])
def test_access_list_warms_storage_slot(
    state_test: StateTestFiller,
    env: Environment,
    pre: Alloc,
    fork: Fork,
    op: str,
) -> None:
    """
    A storage slot named in the access list is warm on first access.

    The first runtime ``SLOAD``/``SSTORE`` of an access-list slot pays
    the warm cost: ``WARM_SLOAD`` for ``SLOAD``; for ``SSTORE`` an
    overwrite of a non-zero original to a new non-zero value pays
    ``WARM_SLOAD + STORAGE_WRITE``.
    """
    gas_costs = fork.gas_costs()
    very_low = gas_costs.VERY_LOW
    slot = 0x42

    if op == "SLOAD":
        measured_code: Bytecode = Op.SLOAD(slot)
        # Overhead is just the single PUSH (key); the stored value is the
        # bare warm SLOAD access cost.
        overhead_cost = 1 * very_low
        extra_stack_items = 1
        expected_gas = Op.SLOAD(key_warm=True).gas_cost(fork)
    else:
        measured_code = Op.SSTORE(slot, 2)
        # Overhead is the two PUSHes (key, value); the stored value is
        # the bare warm SSTORE regular cost (overwrite of a non-zero
        # original, no state gas).
        overhead_cost = 2 * very_low
        extra_stack_items = 0
        expected_gas = (
            Op.SSTORE.with_metadata(
                key_warm=True,
                original_value=1,
                current_value=1,
                new_value=2,
            )(slot, 2).regular_cost(fork)
            - 2 * very_low
        )

    code = CodeGasMeasure(
        code=measured_code,
        overhead_cost=overhead_cost,
        extra_stack_items=extra_stack_items,
        sstore_key=1,
    )
    contract = pre.deploy_contract(code=code, storage={slot: 1})

    tx = Transaction(
        to=contract,
        sender=pre.fund_eoa(),
        access_list=[AccessList(address=contract, storage_keys=[slot])],
    )

    # Slot 1 holds the measured warm cost. The data slot ends at its
    # original (SLOAD) or the written value (SSTORE).
    final_slot_value = 1 if op == "SLOAD" else 2
    post = {
        contract: Account(storage={1: expected_gas, slot: final_slot_value})
    }
    state_test(env=env, pre=pre, post=post, tx=tx)

Parametrized Test Cases

This test generates 2 parametrized test cases across 1 fork.