Skip to content

Commit

Permalink
Contract opcodes to compare gas cost for each precompile
Browse files Browse the repository at this point in the history
Include all test cases and expect precompiles at addresses 01-09
Only include case 0A and 0B to verify no precompile in all valid forks (except cancun)
  • Loading branch information
reedsa committed Jan 30, 2025
1 parent b22e901 commit f78c534
Showing 1 changed file with 99 additions and 0 deletions.
99 changes: 99 additions & 0 deletions tests/frontier/precompiles/test_precompiles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import pytest

from ethereum_test_tools import (
Account,
Alloc,
Environment,
StateTestFiller,
Transaction,
)
from ethereum_test_tools.code.generators import Conditional
from ethereum_test_tools.vm.opcode import Opcodes as Op


def precompile_addresses(fork: str) -> list[tuple[str, bool]]:
"""
Return the precompile addresses for the given fork.
Args:
fork (str): The fork name.
Returns:
list[tuple[str, bool]]: The precompile addresses and whether they exist.
"""
return [
("01", True),
("02", True),
("03", True),
("04", True),
("05", True),
("06", True),
("07", True),
("08", True),
("09", True),
("0A", True) if fork == "cancun" else ("0A", False),
("0B", False),
]


@pytest.mark.valid_from("Byzantium")
@pytest.mark.parametrize_by_fork("data,precompile_exists", precompile_addresses)
def test_precompiles(state_test: StateTestFiller, data: str, precompile_exists: bool, pre: Alloc):
"""Test the MODEXP precompile."""
env = Environment()

args_offset = 0x1000
args_size = 0x20
output_offset = 0x2000
output_size = 0x20

gas_test = 0x00
gas_10000 = 0x20

account = pre.deploy_contract(
Op.MSTORE(gas_test, Op.GAS())
+ Op.CALL(
address=Op.CALLDATALOAD(0),
args_offset=args_offset,
args_size=args_size,
output_offset=output_offset,
output_size=output_size,
)
+ Op.MSTORE(gas_test, Op.SUB(Op.GAS(), Op.MLOAD(gas_test)))
+ Op.MSTORE(gas_10000, Op.GAS())
+ Op.CALL(
address=0x10000,
args_offset=args_offset,
args_size=args_size,
output_offset=output_offset,
output_size=output_size,
)
+ Op.MSTORE(gas_10000, Op.SUB(Op.GAS(), Op.MLOAD(gas_10000)))
+ Op.SSTORE(
0,
Conditional(
condition=Op.GT(Op.MLOAD(gas_test), Op.MLOAD(gas_10000)),
if_true=Op.SUB(Op.MLOAD(gas_test), Op.MLOAD(gas_10000)),
if_false=Op.SUB(Op.MLOAD(gas_10000), Op.MLOAD(gas_test)),
),
)
+ Op.SSTORE(0, Op.LT(Op.SLOAD(0), 0x10))
+ Op.STOP,
storage={0: 0xDEADBEEF},
)
sender = pre.fund_eoa()

tx = Transaction(
to=account,
data=bytes.fromhex(data),
sender=sender,
gas_limit=1_000_000,
value=0,
)

# 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: "0x00" if precompile_exists else "0x01"})}

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

0 comments on commit f78c534

Please sign in to comment.