Skip to content

test_cross_frame_refund_repays_spill_in_inner_frame()

Documentation for tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_cross_frame_refund.py::test_cross_frame_refund_repays_spill_in_inner_frame@622620d8.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_cross_frame_refund.py::test_cross_frame_refund_repays_spill_in_inner_frame --fork Amsterdam

Test the repayment lands at an inner frame's merge.

The spill, the clearing call and both gas_left reads live in a depth-one frame, so an implementation reconciling the pools only when control returns to the top-level frame fails. Half-slot funding also checks that the inner merge repays only the spilled gas from the full-slot refund.

Source code in tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_cross_frame_refund.py
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
@pytest.mark.parametrize(
    "fund_half_slot",
    [False, True],
    ids=["empty-reservoir", "half-slot-reservoir"],
)
@pytest.mark.valid_from("EIP8037")
def test_cross_frame_refund_repays_spill_in_inner_frame(
    state_test: StateTestFiller,
    pre: Alloc,
    fork: Fork,
    fund_half_slot: bool,
) -> None:
    """
    Test the repayment lands at an inner frame's merge.

    The spill, the clearing call and both `gas_left` reads live in a
    depth-one frame, so an implementation reconciling the pools only
    when control returns to the top-level frame fails. Half-slot funding
    also checks that the inner merge repays only the spilled gas from
    the full-slot refund.
    """
    sstore_state_gas = Op.SSTORE(new_value=1).state_cost(fork)
    reservoir = sstore_state_gas // 2 if fund_half_slot else 0
    spilled = sstore_state_gas - reservoir

    clearer = pre.deploy_contract(code=Op.SSTORE(SLOT_X, 0))
    window = Op.POP(Op.DELEGATECALL(address=clearer))
    middle = pre.deploy_contract(
        code=clearing_probe_code(Op.SSTORE(SLOT_X, 1), [window] * 3)
    )
    contract = pre.deploy_contract(
        code=Op.POP(Op.DELEGATECALL(address=middle))
    )

    tx = Transaction(
        to=contract,
        state_gas_reservoir=reservoir,
        sender=pre.fund_eoa(),
    )

    post = {
        contract: Account(
            storage={
                SLOT_X: 0,
                SLOT_MARKER: 1,
                SLOT_INCREASED: 1,
                SLOT_RESULT: -spilled,
            }
        )
    }
    state_test(pre=pre, post=post, tx=tx)

Parametrized Test Cases

This test generates 2 parametrized test cases across 1 fork.