From 0ed27a0e1dfd70c8b175bd347ba7060b2c63e08a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 24 Oct 2024 13:38:42 +0200 Subject: [PATCH] new(tests): basic EOF execution tests (#912) - Add basic EOF execution tests migrated from ethereum/tests: EIPTests/StateTests/stEOF/stEIP3540/EOF1_Execution.json - Extend execution test of legacy invoking `EXTCODE*` instruction on EOF with the case from ethereum/tests. --- converted-ethereum-tests.txt | 2 + .../eip3540_eof_v1/test_execution.py | 78 +++++++++++++++++++ .../eip3540_eof_v1/test_extcode.py | 20 ++--- tests/osaka/eip7692_eof_v1/eof_tracker.md | 8 +- 4 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_execution.py diff --git a/converted-ethereum-tests.txt b/converted-ethereum-tests.txt index 80ecd1ec57..5a028d6990 100644 --- a/converted-ethereum-tests.txt +++ b/converted-ethereum-tests.txt @@ -19,6 +19,8 @@ EOFTests/efValidation/unreachable_code_sections_.json EOFTests/efValidation/EOF1_returncontract_invalid_.json EOFTests/efValidation/EOF1_returncontract_valid_.json +EIPTests/StateTests/stEOF/stEIP3540/EOF1_Execution.json + ([#440](https://github.com/ethereum/execution-spec-tests/pull/440)) GeneralStateTests/Cancun/stEIP1153-transientStorage/01_tloadBeginningTxn.json GeneralStateTests/Cancun/stEIP1153-transientStorage/02_tloadAfterTstore.json diff --git a/tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_execution.py b/tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_execution.py new file mode 100644 index 0000000000..64ed462d53 --- /dev/null +++ b/tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_execution.py @@ -0,0 +1,78 @@ +""" +Execution of basic EOF containers. +""" + +import pytest + +from ethereum_test_base_types import Storage +from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction +from ethereum_test_tools.eof.v1 import Container, Section +from ethereum_test_tools.vm.opcode import Opcodes as Op + +from .. import EOF_FORK_NAME + +REFERENCE_SPEC_GIT_PATH = "EIPS/eip-3540.md" +REFERENCE_SPEC_VERSION = "8dcb0a8c1c0102c87224308028632cc986a61183" + +pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) + +EXPECTED_STORAGE = (bytes.fromhex("EF"), bytes.fromhex("BADDCAFE")) +"""Expected storage (key => value) to be produced by the EOF containers""" + + +@pytest.mark.parametrize( + "container", + ( + Container( + name="store_from_push", + sections=[Section.Code(Op.SSTORE(*EXPECTED_STORAGE) + Op.STOP)], + ), + Container( + name="store_with_data", + sections=[ + Section.Code(Op.SSTORE(Op.DATALOADN[0], Op.DATALOADN[32]) + Op.STOP), + Section.Data( + EXPECTED_STORAGE[0].rjust(32, b"\x00") + EXPECTED_STORAGE[1].rjust(32, b"\x00") + ), + ], + ), + ), + ids=lambda x: x.name, +) +def test_eof_execution( + state_test: StateTestFiller, + pre: Alloc, + container: Container, +): + """ + Test simple contracts that are expected to succeed on call. + """ + env = Environment() + + storage = Storage() + sender = pre.fund_eoa() + container_address = pre.deploy_contract(container) + caller_contract = Op.SSTORE( + storage.store_next(1), Op.CALL(Op.GAS, container_address, 0, 0, 0, 0, 0) + ) + caller_address = pre.deploy_contract(caller_contract) + + tx = Transaction( + to=caller_address, + gas_limit=1_000_000, + gas_price=10, + protected=False, + sender=sender, + ) + + post = { + caller_address: Account(storage=storage), + container_address: Account(storage=dict([EXPECTED_STORAGE])), + } + + state_test( + env=env, + pre=pre, + post=post, + tx=tx, + ) diff --git a/tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_extcode.py b/tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_extcode.py index eb5dc99dda..b3edfb9273 100644 --- a/tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_extcode.py +++ b/tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_extcode.py @@ -7,7 +7,7 @@ from ethereum_test_tools import Account, Alloc, Environment from ethereum_test_tools import Opcodes as Op from ethereum_test_tools import StateTestFiller, Storage, Transaction, keccak256 -from ethereum_test_tools.eof.v1 import Container, Section +from ethereum_test_tools.eof.v1 import Container from .. import EOF_FORK_NAME @@ -23,15 +23,8 @@ def test_legacy_calls_eof_sstore( ): """Test EXTCODE* opcodes calling EOF and legacy contracts""" env = Environment() - address_eof_contract = pre.deploy_contract( - Container( - sections=[ - Section.Code( - code=Op.RJUMP[0] + Op.STOP, - ) - ] - ) - ) + eof_code = Container.Code(Op.RJUMP[0] + Op.STOP) + address_eof_contract = pre.deploy_contract(eof_code) legacy_code = Op.PUSH1(2) + Op.JUMPDEST + Op.STOP address_legacy_contract = pre.deploy_contract(legacy_code) @@ -40,7 +33,7 @@ def test_legacy_calls_eof_sstore( Op.SSTORE(storage_test.store_next(4), Op.EXTCODESIZE(address_legacy_contract)) + Op.EXTCODECOPY(address_legacy_contract, 0, 0, Op.EXTCODESIZE(address_legacy_contract)) + Op.SSTORE( - storage_test.store_next(bytes(legacy_code) + (b"\0" * (32 - len(legacy_code)))), + storage_test.store_next(bytes(legacy_code).ljust(32, b"\0")), Op.MLOAD(0), ) + Op.SSTORE( @@ -49,7 +42,10 @@ def test_legacy_calls_eof_sstore( ) + Op.SSTORE(storage_test.store_next(2), Op.EXTCODESIZE(address_eof_contract)) + Op.EXTCODECOPY(address_eof_contract, 0x20, 0, 6) - + Op.SSTORE(storage_test.store_next(b"\xef" + (b"\0" * 31)), Op.MLOAD(0x20)) + + Op.SSTORE(storage_test.store_next(b"\xef".ljust(32, b"\0")), Op.MLOAD(0x20)) + + Op.MSTORE(0x40, b"\xcc" * 32) # clobber memory slot + + Op.EXTCODECOPY(address_eof_contract, 0x40, len(eof_code) - 4, 8) # out-of-bounds "read" + + Op.SSTORE(storage_test.store_next(b"\xcc" * 24), Op.MLOAD(0x40)) + Op.SSTORE( storage_test.store_next(keccak256(b"\xef\x00")), Op.EXTCODEHASH(address_eof_contract), diff --git a/tests/osaka/eip7692_eof_v1/eof_tracker.md b/tests/osaka/eip7692_eof_v1/eof_tracker.md index e8ee5d1794..c52880ba92 100644 --- a/tests/osaka/eip7692_eof_v1/eof_tracker.md +++ b/tests/osaka/eip7692_eof_v1/eof_tracker.md @@ -81,10 +81,10 @@ ### Execution -- [ ] Execution of EOF contracts (ethereum/tests: src/EIPTestsFiller/StateTests/stEOF/stEIP3540/EOF1_ExecutionFiller.yml) -- [ ] Legacy executing EXTCODESIZE of EOF contract (ethereum/tests: src/EIPTestsFiller/StateTests/stEOF/stEIP3540/EOF1_ExecutionFiller.yml) -- [ ] Legacy executing EXTCODEHASH of EOF contract (ethereum/tests: src/EIPTestsFiller/StateTests/stEOF/stEIP3540/EOF1_ExecutionFiller.yml) -- [ ] Legacy executing EXTCODECOPY of EOF contract (ethereum/tests: src/EIPTestsFiller/StateTests/stEOF/stEIP3540/EOF1_ExecutionFiller.yml) +- [x] Execution of EOF contracts ([`tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_execution.py::test_eof_execution`](./eip3540_eof_v1/test_execution/test_eof_execution.md)) +- [x] Legacy executing EXTCODESIZE of EOF contract ([`tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_extcode.py::test_legacy_calls_eof_sstore`](./eip3540_eof_v1/test_extcode/test_legacy_calls_eof_sstore.md)) +- [x] Legacy executing EXTCODEHASH of EOF contract ([`tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_extcode.py::test_legacy_calls_eof_sstore`](./eip3540_eof_v1/test_extcode/test_legacy_calls_eof_sstore.md)) +- [x] Legacy executing EXTCODECOPY of EOF contract ([`tests/osaka/eip7692_eof_v1/eip3540_eof_v1/test_extcode.py::test_legacy_calls_eof_sstore`](./eip3540_eof_v1/test_extcode/test_legacy_calls_eof_sstore.md)) - [ ] `*CALLs` from legacy contracts to EOF contracts (ethereum/tests: src/EIPTestsFiller/StateTests/stEOF/stEIP3540/EOF1_CallsFiller.yml) - [ ] `EXT*CALLs` from EOF to legacy contracts (ethereum/tests: src/EIPTestsFiller/StateTests/stEOF/stEIP3540/EOF1_CallsFiller.yml) - [ ] EXTDELEGATECALL from EOF to EOF contract (ethereum/tests: src/EIPTestsFiller/StateTests/stEOF/stEIP3540/EOF1_CallsFiller.yml)