Skip to content

test_child_clear_window_cost()

Documentation for tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_cross_frame_refund.py::test_child_clear_window_cost@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_child_clear_window_cost --fork Amsterdam

Test a successful clearing child repays a parent spill at the merge.

The same shape as test_child_clear_repays_own_spill_first, with the call bracketed by two GAS reads. A successful child repays one parent spill, so its window costs one state charge less than the call and child execution. A failing child repays nothing. What the sender pays is checked there.

Source code in tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_cross_frame_refund.py
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
@pytest.mark.parametrize("child_ending", ["stop", "revert", "invalid"])
@pytest.mark.valid_from("EIP8037")
def test_child_clear_window_cost(
    state_test: StateTestFiller,
    pre: Alloc,
    fork: Fork,
    child_ending: str,
) -> None:
    """
    Test a successful clearing child repays a parent spill at the merge.

    The same shape as `test_child_clear_repays_own_spill_first`, with
    the call bracketed by two `GAS` reads. A successful child repays one
    parent spill, so its window costs one state charge less than the
    call and child execution. A failing child repays nothing. What the
    sender pays is checked there.
    """
    sstore_state_gas = Op.SSTORE(new_value=1).state_cost(fork)

    child_code = clearing_child_code(child_ending)
    child = pre.deploy_contract(code=child_code)
    child_budget = budget_above_sstore_stipend(fork, child_code)

    call_window = Op.POP(
        Op.DELEGATECALL(gas=child_budget, address=child, address_warm=False)
    )
    code = (
        FRESH_SET(SLOT_X, 1)
        + FRESH_SET(SLOT_Y, 1)
        + Op.MSTORE(32, 0, new_memory_size=64, old_memory_size=0)
        + Op.MSTORE(0, Op.GAS)
        + call_window
        + Op.MSTORE(32, Op.GAS)
        + FRESH_SET(SLOT_RESULT, Op.SUB(Op.MLOAD(0), Op.MLOAD(32)))
    )
    contract = pre.deploy_contract(code=code)

    # An invalid child burns its whole budget; the others stop at the
    # end of their code.
    child_consumed = (
        child_budget
        if child_ending == "invalid"
        else child_code.execution_cost(fork)
    )
    # Gas measured between the two reads: the first stamp's store, the
    # call window, the child's consumption, and the second read itself.
    window_cost = (
        Op.MSTORE(0, Op.GAS).gas_cost(fork)
        + call_window.execution_cost(fork)
        + child_consumed
    )

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

    repaid = sstore_state_gas if child_ending == "stop" else 0
    post = {
        contract: Account(
            storage={
                **clearing_child_storage(child_ending),
                SLOT_RESULT: window_cost - repaid,
            }
        )
    }
    state_test(pre=pre, post=post, tx=tx)

Parametrized Test Cases

This test generates 3 parametrized test cases across 1 fork.