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-0A
All other cases expect no precompile to exist at the specified address
  • Loading branch information
reedsa committed Jan 23, 2025
1 parent b20cf5a commit ccb6574
Show file tree
Hide file tree
Showing 2 changed files with 341 additions and 0 deletions.
Empty file added tests/precompiles/__init__.py
Empty file.
341 changes: 341 additions & 0 deletions tests/precompiles/test_precompiles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,341 @@
import pytest

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


@pytest.mark.parametrize(
["address", "exists"],
[
("01", True),
("02", True),
("03", True),
("04", True),
("05", True),
("06", True),
("07", True),
("08", True),
("09", True),
("0A", True),
("0B", False),
("0C", False),
("0D", False),
("0E", False),
("0F", False),
("10", False),
("11", False),
("12", False),
("13", False),
("14", False),
("15", False),
("16", False),
("17", False),
("18", False),
("19", False),
("1A", False),
("1B", False),
("1C", False),
("1D", False),
("1E", False),
("1F", False),
("20", False),
("21", False),
("22", False),
("23", False),
("24", False),
("25", False),
("26", False),
("27", False),
("28", False),
("29", False),
("2A", False),
("2B", False),
("2C", False),
("2D", False),
("2E", False),
("2F", False),
("30", False),
("31", False),
("32", False),
("33", False),
("34", False),
("35", False),
("36", False),
("37", False),
("38", False),
("39", False),
("3A", False),
("3B", False),
("3C", False),
("3D", False),
("3E", False),
("3F", False),
("40", False),
("41", False),
("42", False),
("43", False),
("44", False),
("45", False),
("46", False),
("47", False),
("48", False),
("49", False),
("4A", False),
("4B", False),
("4C", False),
("4D", False),
("4E", False),
("4F", False),
("50", False),
("51", False),
("52", False),
("53", False),
("54", False),
("55", False),
("56", False),
("57", False),
("58", False),
("59", False),
("5A", False),
("5B", False),
("5C", False),
("5D", False),
("5E", False),
("5F", False),
("60", False),
("61", False),
("62", False),
("63", False),
("64", False),
("65", False),
("66", False),
("67", False),
("68", False),
("69", False),
("6A", False),
("6B", False),
("6C", False),
("6D", False),
("6E", False),
("6F", False),
("70", False),
("71", False),
("72", False),
("73", False),
("74", False),
("75", False),
("76", False),
("77", False),
("78", False),
("79", False),
("7A", False),
("7B", False),
("7C", False),
("7D", False),
("7E", False),
("7F", False),
("80", False),
("81", False),
("82", False),
("83", False),
("84", False),
("85", False),
("86", False),
("87", False),
("88", False),
("89", False),
("8A", False),
("8B", False),
("8C", False),
("8D", False),
("8E", False),
("8F", False),
("90", False),
("91", False),
("92", False),
("93", False),
("94", False),
("95", False),
("96", False),
("97", False),
("98", False),
("99", False),
("9A", False),
("9B", False),
("9C", False),
("9D", False),
("9E", False),
("9F", False),
("A0", False),
("A1", False),
("A2", False),
("A3", False),
("A4", False),
("A5", False),
("A6", False),
("A7", False),
("A8", False),
("A9", False),
("AA", False),
("AB", False),
("AC", False),
("AD", False),
("AE", False),
("AF", False),
("B0", False),
("B1", False),
("B2", False),
("B3", False),
("B4", False),
("B5", False),
("B6", False),
("B7", False),
("B8", False),
("B9", False),
("BA", False),
("BB", False),
("BC", False),
("BD", False),
("BE", False),
("BF", False),
("C0", False),
("C1", False),
("C2", False),
("C3", False),
("C4", False),
("C5", False),
("C6", False),
("C7", False),
("C8", False),
("C9", False),
("CA", False),
("CB", False),
("CC", False),
("CD", False),
("CE", False),
("CF", False),
("D0", False),
("D1", False),
("D2", False),
("D3", False),
("D4", False),
("D5", False),
("D6", False),
("D7", False),
("D8", False),
("D9", False),
("DA", False),
("DB", False),
("DC", False),
("DD", False),
("DE", False),
("DF", False),
("E0", False),
("E1", False),
("E2", False),
("E3", False),
("E4", False),
("E5", False),
("E6", False),
("E7", False),
("E8", False),
("E9", False),
("EA", False),
("EB", False),
("EC", False),
("ED", False),
("EE", False),
("EF", False),
("F0", False),
("F1", False),
("F2", False),
("F3", False),
("F4", False),
("F5", False),
("F6", False),
("F7", False),
("F8", False),
("F9", False),
("FA", False),
("FB", False),
("FC", False),
("FD", False),
("FE", False),
("FF", False),
],
)
def test_precompiles(state_test: StateTestFiller, pre: Alloc, address: str, exists: bool):
"""Test the MODEXP precompile."""
env = Environment()

address_10000 = 0x10000

input_buf = 0x1000
output_buf = 0x2000

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

gas_test = 0x20
gas_10000 = 0x40

account = pre.deploy_contract(
Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE())
+ Op.MSTORE(args_size, 0x20)
+ Op.MSTORE(input_buf, 0xFF)
+ Op.MSTORE(output_buf, 0xFF)
+ Op.MSTORE8(input_buf, 0xFF)
+ Op.MSTORE8(output_buf, 0xFF)
+ Op.BALANCE(Op.MLOAD(0))
+ Op.BALANCE(address_10000)
+ Op.MSTORE(gas_test, Op.GAS())
# Setup stack to CALL into precompile with the CALLDATA and CALL into it (+ pop value)
+ Op.CALL(
address=Op.MLOAD(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=address_10000,
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.GT(Op.MLOAD(gas_test), Op.MLOAD(gas_10000))
+ Op.JUMPI(Op.JUMPDEST(), 0x1)
+ Op.SSTORE(0, Op.SUB(Op.MLOAD(gas_test), Op.MLOAD(gas_10000)))
+ Op.SSTORE(0, Op.LT(Op.SLOAD(gas_test), 0x10))
+ Op.STOP(),
)

sender = pre.fund_eoa()

tx = Transaction(
ty=0x0,
to=account,
data=bytes.fromhex(address),
gas_limit=500000,
gas_price=10,
protected=True,
sender=sender,
)

# 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 exists else "0x01"})}

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

0 comments on commit ccb6574

Please sign in to comment.