Skip to content

test_precompiles()

Documentation for tests/frontier/precompiles/test_precompiles.py::test_precompiles@9c2813ee.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/frontier/precompiles/test_precompiles.py::test_precompiles --fork Amsterdam

Tests the behavior of precompiled contracts in the Ethereum state test.

Parameters:

Name Type Description Default
state_test StateTestFiller

The state test filler object used to run the test.

required
address str

The address of the precompiled contract to test.

required
precompile_exists bool

A flag indicating whether the precompiled contract exists at the given address.

required
pre Alloc

The allocation object used to deploy the contract and set up the initial state.

required

This test deploys a contract that performs two CALL operations to the specified address and a fixed address (0x10000), measuring the gas used for each call. It then stores the difference in gas usage in storage slot 0. The test verifies the expected storage value based on whether the precompiled contract exists at the given address.

Source code in tests/frontier/precompiles/test_precompiles.py
 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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
@pytest.mark.ported_from(
    [
        "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stPreCompiledContracts/idPrecompsFiller.yml"
    ],
    pr=["https://github.com/ethereum/execution-spec-tests/pull/1120"],
    coverage_missed_reason=(
        "Original test saves variables to memory, loads from storage, uses "
        "calldataload to get the precompile address to call, uses lt and gt "
        "to compare the gas differences, sends non-zero data and value with "
        "the transaction, uses conditional jumps to save different values to "
        "storage."
    ),
)
@pytest.mark.valid_from("Berlin")
@pytest.mark.parametrize_by_fork(
    "address,precompile_exists", precompile_addresses
)
@pytest.mark.eels_base_coverage
def test_precompiles(
    state_test: StateTestFiller,
    address: Address,
    precompile_exists: bool,
    pre: Alloc,
) -> None:
    """
    Tests the behavior of precompiled contracts in the Ethereum state test.

    Args:
      state_test (StateTestFiller): The state test filler object used to
                                    run the test.
      address (str): The address of the precompiled contract to test.
      precompile_exists (bool): A flag indicating whether the precompiled
                                contract exists at the given address.
      pre (Alloc): The allocation object used to deploy the contract and
                   set up the initial state.

    This test deploys a contract that performs two CALL operations to the
    specified address and a fixed address (0x10000), measuring the gas used for
    each call. It then stores the difference in gas usage in storage slot 0.
    The test verifies the expected storage value based on whether the
    precompiled contract exists at the given address.

    """
    env = Environment()

    # Empty account to serve as reference
    empty_account = pre.fund_eoa(amount=0)

    # Memory
    args_offset = 0
    ret_offset = 32
    length = 32

    account = pre.deploy_contract(
        Op.MSTORE(
            args_offset, 0xFF
        )  # Pre-expand the memory and setup inputs for pre-compiles
        + Op.MSTORE(ret_offset, 0xFF)
        + Op.MSTORE8(args_offset, 0xFF)
        + Op.MSTORE8(ret_offset, 0xFF)
        + Op.POP(Op.BALANCE(empty_account))  # Warm the accounts
        + Op.POP(Op.BALANCE(address))
        + Op.GAS
        + Op.CALL(
            gas=50_000,
            address=address,
            args_offset=args_offset,
            args_size=length,
            ret_offset=ret_offset,
            ret_size=length,
        )
        + Op.POP
        + Op.SUB(Op.SWAP1, Op.GAS)
        + Op.GAS
        + Op.CALL(
            gas=50_000,
            address=empty_account,
            args_offset=args_offset,
            args_size=length,
            ret_offset=ret_offset,
            ret_size=length,
        )
        + Op.POP
        + Op.SUB(Op.SWAP1, Op.GAS)
        + Op.SWAP1
        + Op.SUB
        + Op.SSTORE(0, Op.ISZERO)
        + Op.STOP,
        storage={0: 0xDEADBEEF},
    )

    tx = Transaction(
        to=account,
        sender=pre.fund_eoa(),
        gas_limit=1_000_000,
        protected=True,
    )

    # A high gas cost will result from calling a precompile
    # Expect 0x00 when a precompile exists at the address, 0x01 otherwise
    post = {account: Account(storage={0: 0 if precompile_exists else 1})}

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

Parametrized Test Cases

This test generates 22 parametrized test cases across 8 forks.