diff --git a/converted-ethereum-tests.txt b/converted-ethereum-tests.txt index 09a8917463a..0a0ced2934d 100644 --- a/converted-ethereum-tests.txt +++ b/converted-ethereum-tests.txt @@ -1,3 +1,7 @@ +([#1236](https://github.com/ethereum/execution-spec-tests/pull/1236)) +GeneralStateTests/VMTests/vmTests/calldataload.json +GeneralStateTests/VMTests/vmTests/calldatasize.json + ([#1056](https://github.com/ethereum/execution-spec-tests/pull/1056)) GeneralStateTests/VMTests/vmTests/calldatacopy.json diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 0d80174cf3a..d353ae899f0 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -23,6 +23,7 @@ Test fixtures for use by clients are available for each release on the [Github r ### ๐Ÿงช Test Cases - ๐Ÿ”€ Automatically apply the `zkevm` marker to all tests under `./tests/zkevm/` and `./tests/prague/eip2537_bls_12_381_precompiles/` via conftest configuration ([#1534](https://github.com/ethereum/execution-spec-tests/pull/1534)). +- โœจ Port [calldataload](https://github.com/ethereum/tests/blob/ae4791077e8fcf716136e70fe8392f1a1f1495fb/src/GeneralStateTestsFiller/VMTests/vmTests/calldatacopyFiller.yml) and [calldatasize](https://github.com/ethereum/tests/blob/81862e4848585a438d64f911a19b3825f0f4cd95/src/GeneralStateTestsFiller/VMTests/vmTests/calldatasizeFiller.yml) tests ([#1236](https://github.com/ethereum/execution-spec-tests/pull/1236)). ## [v4.4.0](https://github.com/ethereum/execution-spec-tests/releases/tag/v4.4.0) - 2025-04-29 diff --git a/tests/frontier/opcodes/test_calldataload.py b/tests/frontier/opcodes/test_calldataload.py new file mode 100644 index 00000000000..8fd90d37530 --- /dev/null +++ b/tests/frontier/opcodes/test_calldataload.py @@ -0,0 +1,92 @@ +"""test `CALLDATALOAD` opcode.""" + +import pytest + +from ethereum_test_forks import Byzantium, Fork +from ethereum_test_tools import Account, Alloc, StateTestFiller, Transaction +from ethereum_test_tools import Macros as Om +from ethereum_test_tools.vm.opcode import Opcodes as Op + + +@pytest.mark.parametrize( + "calldata,calldata_offset,expected_storage", + [ + ( + b"\x25\x60", + 0x0, + 0x2560000000000000000000000000000000000000000000000000000000000000, + ), + ( + b"\xff" * 32 + b"\x23", + 0x1, + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23, + ), + ( + bytes.fromhex("123456789ABCDEF00000000000000000000000000000000000000000000000000024"), + 0x5, + 0xBCDEF00000000000000000000000000000000000000000000000000024000000, + ), + ], + ids=[ + "two_bytes", + "word_n_byte", + "34_bytes", + ], +) +@pytest.mark.parametrize("calldata_source", ["contract", "tx"]) +def test_calldataload( + state_test: StateTestFiller, + calldata: bytes, + calldata_offset: int, + fork: Fork, + pre: Alloc, + expected_storage: Account, + calldata_source: str, +): + """ + Test `CALLDATALOAD` opcode. + + Tests two scenarios: + - calldata_source is "contract": CALLDATALOAD reads from calldata passed by another contract + - calldata_source is "tx": CALLDATALOAD reads directly from transaction calldata + + Based on https://github.com/ethereum/tests/blob/ae4791077e8fcf716136e70fe8392f1a1f1495fb/src/GeneralStateTestsFiller/VMTests/vmTests/calldatacopyFiller.yml + """ + contract_address = pre.deploy_contract( + Op.SSTORE(0, Op.CALLDATALOAD(offset=calldata_offset)) + Op.STOP, + ) + + if calldata_source == "contract": + to = pre.deploy_contract( + Om.MSTORE(calldata, 0x0) + + Op.CALL( + gas=Op.SUB(Op.GAS(), 0x100), + address=contract_address, + value=0x0, + args_offset=0x0, + args_size=len(calldata), + ret_offset=0x0, + ret_size=0x0, + ) + + Op.STOP + ) + + tx = Transaction( + data=calldata, + gas_limit=100_000, + protected=fork >= Byzantium, + sender=pre.fund_eoa(), + to=to, + ) + + else: + tx = Transaction( + data=calldata, + gas_limit=100_000, + protected=fork >= Byzantium, + sender=pre.fund_eoa(), + to=contract_address, + ) + + post = {contract_address: Account(storage={0x00: expected_storage})} + state_test(pre=pre, post=post, tx=tx) diff --git a/tests/frontier/opcodes/test_calldatasize.py b/tests/frontier/opcodes/test_calldatasize.py new file mode 100644 index 00000000000..0ff6bcbbea6 --- /dev/null +++ b/tests/frontier/opcodes/test_calldatasize.py @@ -0,0 +1,68 @@ +"""test `CALLDATASIZE` opcode.""" + +import pytest + +from ethereum_test_forks import Byzantium, Fork +from ethereum_test_tools import Account, Alloc, StateTestFiller, Transaction +from ethereum_test_tools import Macros as Om +from ethereum_test_tools.vm.opcode import Opcodes as Op + + +@pytest.mark.parametrize( + "args_size", + [0, 2, 16, 33, 257], +) +@pytest.mark.parametrize("calldata_source", ["contract", "tx"]) +def test_calldatasize( + state_test: StateTestFiller, + fork: Fork, + args_size: int, + pre: Alloc, + calldata_source: str, +): + """ + Test `CALLDATASIZE` opcode. + + Tests two scenarios: + - calldata_source is "contract": CALLDATASIZE reads from calldata passed by another contract + - calldata_source is "tx": CALLDATASIZE reads directly from transaction calldata + + Based on https://github.com/ethereum/tests/blob/81862e4848585a438d64f911a19b3825f0f4cd95/src/GeneralStateTestsFiller/VMTests/vmTests/calldatasizeFiller.yml + """ + contract_address = pre.deploy_contract(Op.SSTORE(key=0x0, value=Op.CALLDATASIZE)) + calldata = b"\x01" * args_size + + if calldata_source == "contract": + to = pre.deploy_contract( + code=( + Om.MSTORE(calldata, 0x0) + + Op.CALL( + gas=Op.SUB(Op.GAS(), 0x100), + address=contract_address, + value=0x0, + args_offset=0x0, + args_size=args_size, + ret_offset=0x0, + ret_size=0x0, + ) + ) + ) + + tx = Transaction( + gas_limit=100_000, + protected=fork >= Byzantium, + sender=pre.fund_eoa(), + to=to, + ) + + else: + tx = Transaction( + data=calldata, + gas_limit=100_000, + protected=fork >= Byzantium, + sender=pre.fund_eoa(), + to=contract_address, + ) + + post = {contract_address: Account(storage={0x00: args_size})} + state_test(pre=pre, post=post, tx=tx) diff --git a/tests/homestead/coverage/test_coverage.py b/tests/homestead/coverage/test_coverage.py index 608cd1284dc..b7240c38a31 100644 --- a/tests/homestead/coverage/test_coverage.py +++ b/tests/homestead/coverage/test_coverage.py @@ -41,6 +41,9 @@ def test_coverage( + Op.PUSH2(0x0102) + Op.PUSH3(0x010203) + Op.PUSH4(0x01020304) + + Op.PUSH32(0x0101010101010101010101010101010101010101010101010101010101010101) + + Op.MSTORE8(0x00, 0x01) + + Op.ADD(0x02, 0x03) + Op.POP(0x01) # lllc tests insert codecopy when using lll(seq()) + Op.CODECOPY(0, 16, 4), diff --git a/tests/static/state_tests/VMTests/vmTests/calldataloadFiller.yml b/tests/static/state_tests/VMTests/vmTests/calldataloadFiller.yml deleted file mode 100644 index bb3309ca13c..00000000000 --- a/tests/static/state_tests/VMTests/vmTests/calldataloadFiller.yml +++ /dev/null @@ -1,166 +0,0 @@ -calldataload: - - env: - currentCoinbase: 2adc25665018aa1fe0e6bc666dac8fc2697ff9ba - currentDifficulty: 0x20000 - currentGasLimit: 100000000 - currentNumber: 1 - currentTimestamp: 1000 - - _info: - comment: Ori Pomerantz qbzzt1@gmail.com - - pre: - - 0000000000000000000000000000000000001000: - balance: '0x0ba1a9ce0ba1a9ce' - code: | - { - (mstore8 0 0x25) - (mstore8 1 0x60) - (call 0xffffff 0x200 0 - 0x00 ; arg offest - 0x02 ; arg length - 0 0) - } - nonce: '0' - storage: {} - - - 0000000000000000000000000000000000001001: - balance: '0x0ba1a9ce0ba1a9ce' - code: | - { - [0] 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - (mstore8 0x20 0x23) - (call 0xffffff 0x201 0 - 0x00 ; arg offest - 0x21 ; arg length - 0 0) - } - nonce: '0' - storage: {} - - - - 0000000000000000000000000000000000001002: - balance: '0x0ba1a9ce0ba1a9ce' - code: | - { - [0] 0x123456789abcdef0000000000000000000000000000000000000000000000000 - (mstore8 0x20 0x00) - (mstore8 0x21 0x24) - (call 0xffffff 0x205 0 - 0x00 ; arg offest - 0x22 ; arg length - 0 0) - } - nonce: '0' - storage: {} - - - - - 0000000000000000000000000000000000000200: - balance: '0x0ba1a9ce0ba1a9ce' - code: | - { - [[0]] (calldataload 0) - } - nonce: '0' - storage: {} - - - - 0000000000000000000000000000000000000201: - balance: '0x0ba1a9ce0ba1a9ce' - code: | - { - [[0]] (calldataload 1) - } - nonce: '0' - storage: {} - - - - - 0000000000000000000000000000000000000205: - balance: '0x0ba1a9ce0ba1a9ce' - code: | - { - [[0]] (calldataload 5) - } - nonce: '0' - storage: {} - - - - cccccccccccccccccccccccccccccccccccccccc: - balance: '0x0ba1a9ce0ba1a9ce' - code: | - { - (call 0xffffff (+ 0x1000 $4) 0 0 0 0 0) - } - nonce: '0' - storage: {} - - - a94f5374fce5edbc8e2a8697c15331677e6ebf0b: - balance: '0x0ba1a9ce0ba1a9ce' - code: '0x' - nonce: '0' - storage: {} - -# The transaction to check - transaction: - data: - - :label two_bytes :abi f(uint) 0 - - :label word_n_byte :abi f(uint) 1 - - :label 34_bytes :abi f(uint) 2 - gasLimit: - - '80000000' - gasPrice: '10' - nonce: '0' - to: cccccccccccccccccccccccccccccccccccccccc - value: - - '1' - secretKey: "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - - - expect: - - indexes: - data: :label two_bytes - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000000200: - storage: - 0: 0x2560000000000000000000000000000000000000000000000000000000000000 - - - - indexes: - data: :label word_n_byte - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000000201: - storage: - 0: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23 - - - - - - indexes: - data: :label 34_bytes - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000000205: - storage: - 0: 0xbcdef00000000000000000000000000000000000000000000000000024000000 diff --git a/tests/static/state_tests/VMTests/vmTests/calldatasizeFiller.yml b/tests/static/state_tests/VMTests/vmTests/calldatasizeFiller.yml deleted file mode 100644 index 469ad5003f5..00000000000 --- a/tests/static/state_tests/VMTests/vmTests/calldatasizeFiller.yml +++ /dev/null @@ -1,171 +0,0 @@ -calldatasize: - - # Run CALLDATASIZE with various call data sizes - - env: - currentCoinbase: 2adc25665018aa1fe0e6bc666dac8fc2697ff9ba - currentDifficulty: 0x20000 - currentGasLimit: 100000000 - currentNumber: 1 - currentTimestamp: 1000 - - _info: - comment: Ori Pomerantz qbzzt1@gmail.com - - pre: - - 0000000000000000000000000000000000001000: - balance: '0x0ba1a9ce0ba1a9ce' - code: | - { - [[0]] (calldatasize) - } - nonce: '0' - storage: {} - - - - cccccccccccccccccccccccccccccccccccccccc: - balance: '0x0ba1a9ce0ba1a9ce' - code: | - { - ; Use the second parameter to decide what data to send - [0] (sha3 0 $36) - - ; Call 0x1000 with whatever value we got as a - ; parameter - (call 0xffffff 0x1000 0 0 $4 0 0) - } - nonce: '0' - storage: {} - - - a94f5374fce5edbc8e2a8697c15331677e6ebf0b: - balance: '0x0ba1a9ce0ba1a9ce' - code: '0x' - nonce: '0' - storage: {} - -# The transaction to check - transaction: - data: - - :label data1_2 :abi f(uint,uint) 0x02 1 - - :label data1_11 :abi f(uint,uint) 0x11 1 - - :label data1_21 :abi f(uint,uint) 0x21 1 - - :label data1_31 :abi f(uint,uint) 0x31 1 - - :label data1_101 :abi f(uint,uint) 0x0101 1 - - :label data2_2 :abi f(uint,uint) 0x02 2 - - :label data2_11 :abi f(uint,uint) 0x11 2 - - :label data2_21 :abi f(uint,uint) 0x21 2 - - :label data2_31 :abi f(uint,uint) 0x31 2 - - :label data2_101 :abi f(uint,uint) 0x0101 2 - - :label data3_2 :abi f(uint,uint) 0x02 3 - - :label data3_11 :abi f(uint,uint) 0x11 3 - - :label data3_21 :abi f(uint,uint) 0x21 3 - - :label data3_31 :abi f(uint,uint) 0x31 3 - - :label data3_101 :abi f(uint,uint) 0x0101 3 - - :label data4_2 :abi f(uint,uint) 0x02 4 - - :label data4_11 :abi f(uint,uint) 0x11 4 - - :label data4_21 :abi f(uint,uint) 0x21 4 - - :label data4_31 :abi f(uint,uint) 0x31 4 - - :label data4_101 :abi f(uint,uint) 0x0101 4 - gasLimit: - - '80000000' - gasPrice: '10' - nonce: '0' - to: cccccccccccccccccccccccccccccccccccccccc - value: - - '1' - secretKey: "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" - - - expect: - - indexes: - data: - - :label data1_2 - - :label data2_2 - - :label data3_2 - - :label data4_2 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001000: - storage: - # Just the length, the data is irrelevant - 0: 0x02 - - - - - indexes: - data: - - :label data1_11 - - :label data2_11 - - :label data3_11 - - :label data4_11 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001000: - storage: - # Just the length, the data is irrelevant - 0: 0x11 - - - - - - indexes: - data: - - :label data1_21 - - :label data2_21 - - :label data3_21 - - :label data4_21 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001000: - storage: - # Just the length, the data is irrelevant - 0: 0x21 - - - - - - indexes: - data: - - :label data1_31 - - :label data2_31 - - :label data3_31 - - :label data4_31 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001000: - storage: - # Just the length, the data is irrelevant - 0: 0x31 - - - - - indexes: - data: - - :label data1_101 - - :label data2_101 - - :label data3_101 - - :label data4_101 - gas: !!int -1 - value: !!int -1 - network: - - '>=Cancun' - result: - 0000000000000000000000000000000000001000: - storage: - # Just the length, the data is irrelevant - 0: 0x0101