Skip to content

test_top_level_failure_refunds_execution_state_gas()

Documentation for tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_reservoir.py::test_top_level_failure_refunds_execution_state_gas@c74f1a67.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_reservoir.py::test_top_level_failure_refunds_execution_state_gas --fork Amsterdam

Verify top level tx failure returns execution state gas to the reservoir across revert, exceptional halt, and out of gas paths.

On top level failure no state was created, so execution state gas is credited back to the reservoir and state_gas_used is zeroed. The billing formula tx.gas - gas_left - state_gas_left sees a restored reservoir and refunds the sender. Without the refund the receipt would bill the consumed state gas despite the failure.

Source code in tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_reservoir.py
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
@pytest.mark.parametrize(
    "failure_mode",
    [
        pytest.param("revert", id="revert"),
        pytest.param("halt", id="halt"),
        pytest.param("oog", id="oog"),
    ],
)
@pytest.mark.valid_from("EIP8037")
def test_top_level_failure_refunds_execution_state_gas(
    state_test: StateTestFiller,
    pre: Alloc,
    fork: Fork,
    failure_mode: str,
) -> None:
    """
    Verify top level tx failure returns execution state gas to the
    reservoir across revert, exceptional halt, and out of gas paths.

    On top level failure no state was created, so execution state gas
    is credited back to the reservoir and `state_gas_used` is zeroed.
    The billing formula `tx.gas - gas_left - state_gas_left` sees a
    restored reservoir and refunds the sender. Without the refund the
    receipt would bill the consumed state gas despite the failure.
    """
    gas_limit_cap = fork.transaction_gas_limit_cap()
    assert gas_limit_cap is not None
    sstore_state_gas = Op.SSTORE(new_value=1).state_cost(fork)
    intrinsic_cost = fork.transaction_intrinsic_cost_calculator()()

    if failure_mode == "revert":
        code = Op.SSTORE(0, 1) + Op.REVERT(0, 0)
    elif failure_mode == "halt":
        code = Op.SSTORE(0, 1) + Op.INVALID
    else:
        # OOG: perform the SSTORE, then consume all remaining gas at
        # once (a spin loop would execute millions of ops in the EVM
        # and slow down filling).
        code = Op.SSTORE(0, 1) + Om.OOG
    contract = pre.deploy_contract(code=code)

    tx_gas = gas_limit_cap + sstore_state_gas

    if failure_mode == "revert":
        # REVERT preserves unused gas_left.
        expected_cumulative = (
            intrinsic_cost + code.gas_cost(fork) - sstore_state_gas
        )
    else:
        # Exceptional halt and out of gas zero gas_left.
        expected_cumulative = tx_gas - sstore_state_gas

    tx = Transaction(
        to=contract,
        state_gas_reservoir=sstore_state_gas,
        sender=pre.fund_eoa(),
        expected_receipt=TransactionReceipt(
            cumulative_gas_used=expected_cumulative,
        ),
    )

    state_test(pre=pre, post={contract: Account(storage={})}, tx=tx)

Parametrized Test Cases

This test generates 3 parametrized test cases across 1 fork.