Skip to content

test_warm_coinbase_call_out_of_gas()

Documentation for tests/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py::test_warm_coinbase_call_out_of_gas@2867859a.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py::test_warm_coinbase_call_out_of_gas --fork Amsterdam

Test that the coinbase is warm by accessing the COINBASE with each of the following opcodes.

  • CALL
  • CALLCODE
  • DELEGATECALL
  • STATICCALL
Source code in tests/shanghai/eip3651_warm_coinbase/test_warm_coinbase.py
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
@pytest.mark.valid_from("Shanghai")
@pytest.mark.parametrize(
    "use_sufficient_gas",
    [True, False],
    ids=["sufficient_gas", "insufficient_gas"],
)
@pytest.mark.parametrize(
    "opcode,call_opcode",
    [
        ("call", Op.CALL),
        ("callcode", Op.CALLCODE),
        ("delegatecall", Op.DELEGATECALL),
        ("staticcall", Op.STATICCALL),
    ],
    ids=["CALL", "CALLCODE", "DELEGATECALL", "STATICCALL"],
)
def test_warm_coinbase_call_out_of_gas(
    state_test: StateTestFiller,
    env: Environment,
    pre: Alloc,
    post: Alloc,
    sender: Address,
    fork: Fork,
    opcode: str,
    call_opcode: Op,
    use_sufficient_gas: bool,
) -> None:
    """
    Test that the coinbase is warm by accessing the COINBASE with each
    of the following opcodes.

    - CALL
    - CALLCODE
    - DELEGATECALL
    - STATICCALL
    """
    # Build contract code: POP(xCALL(0, COINBASE, 0, ...))
    if call_opcode in (Op.CALL, Op.CALLCODE):
        contract_under_test_code = Op.POP(
            call_opcode(0, Op.COINBASE, 0, 0, 0, 0, 0)
        )
    else:
        contract_under_test_code = Op.POP(
            call_opcode(0, Op.COINBASE, 0, 0, 0, 0)
        )

    contract_under_test_address = pre.deploy_contract(contract_under_test_code)

    # Compute exact gas: warm call cost + overhead
    # (COINBASE, PUSHes, DUPs, POP)
    warm_call_cost = call_opcode(address_warm=True).gas_cost(fork)
    # Overhead = total cost (with cold default) minus the cold call cost
    cold_call_cost = call_opcode(address_warm=False).gas_cost(fork)
    total_with_cold = contract_under_test_code.gas_cost(fork)
    call_gas_exact = warm_call_cost + (total_with_cold - cold_call_cost)

    if not use_sufficient_gas:
        call_gas_exact -= 1

    caller_code = Op.SSTORE(
        0,
        Op.CALL(call_gas_exact, contract_under_test_address, 0, 0, 0, 0, 0),
    )
    caller_address = pre.deploy_contract(caller_code)

    tx = Transaction(
        to=caller_address,
        sender=sender,
    )

    if use_sufficient_gas and fork >= Shanghai:
        post[caller_address] = Account(
            storage={
                # On shanghai and beyond, calls with only 100 gas to
                # coinbase will succeed.
                0: 1,
            }
        )
    else:
        post[caller_address] = Account(
            storage={
                # Before shanghai, calls with only 100 gas to
                # coinbase will fail.
                0: 0,
            }
        )

    state_test(
        env=env,
        pre=pre,
        post=post,
        tx=tx,
    )

Parametrized Test Cases

This test generates 8 parametrized test cases across 5 forks.