Skip to content

test_call_insufficient_balance_returns_reservoir()

Documentation for tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_call.py::test_call_insufficient_balance_returns_reservoir@c74f1a67.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_call.py::test_call_insufficient_balance_returns_reservoir --fork Amsterdam

Test CALL with insufficient balance returns the reservoir to parent.

A value-bearing CALL to an existing account fails the balance check before entering the child frame; gas_left and state_gas_left are returned to the parent, which can still use the reservoir for a later SSTORE. The new-account variant (where NEW_ACCOUNT is charged then refilled on the same failure) is pinned by test_call_insufficient_balance_refunds_new_account_state_gas.

Source code in tests/amsterdam/eip8037_state_creation_gas_cost_increase/test_state_gas_call.py
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
@pytest.mark.valid_from("EIP8037")
def test_call_insufficient_balance_returns_reservoir(
    state_test: StateTestFiller,
    pre: Alloc,
    fork: Fork,
) -> None:
    """
    Test CALL with insufficient balance returns the reservoir to parent.

    A value-bearing CALL to an existing account fails the balance check
    before entering the child frame; gas_left and state_gas_left are
    returned to the parent, which can still use the reservoir for a
    later SSTORE. The new-account variant (where NEW_ACCOUNT is charged
    then refilled on the same failure) is pinned by
    test_call_insufficient_balance_refunds_new_account_state_gas.
    """
    sstore_state_gas = Op.SSTORE(new_value=1).state_cost(fork)

    target = pre.deploy_contract(code=Op.STOP)
    reservoir = sstore_state_gas

    storage = Storage()
    contract = pre.deploy_contract(
        code=(
            # CALL with 1 wei — fails (contract has 0 balance)
            Op.SSTORE(
                storage.store_next(0, "call_fails"),
                Op.CALL(100_000, target, 1, 0, 0, 0, 0),
            )
            # Reservoir should be returned — SSTORE still works
            + Op.SSTORE(storage.store_next(1, "sstore_after"), 1)
        ),
    )

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

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

Parametrized Test Cases

This test generates 1 parametrized test case across 1 fork.