From b005113b0d6511acca24c69bd89a39fbccfc88c0 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Tue, 23 Apr 2024 15:16:17 -0600 Subject: [PATCH 01/14] Validate EIP-7676 Prepare for Address Space Extension Validate ASE behaviors on legacy and EOF opcodes for ASE, when targeting EOAs, Contracts, and empty accounts. Opcodes are BALANCE, EXTCALL/CALL, EXTDELEGATECALL/DELEGATECALL, EXTSTATICCALL/STATICCALL, and CALLCODE. Signed-off-by: Danno Ferrin --- src/ethereum_test_tools/vm/opcode.py | 85 ++++--- .../__init__.py | 3 + .../eip7676_address_space_extension/spec.py | 5 + .../test_ase_opcodes.py | 219 ++++++++++++++++++ whitelist.txt | 6 +- 5 files changed, 288 insertions(+), 30 deletions(-) create mode 100644 tests/prague/eip7676_address_space_extension/__init__.py create mode 100644 tests/prague/eip7676_address_space_extension/spec.py create mode 100644 tests/prague/eip7676_address_space_extension/test_ase_opcodes.py diff --git a/src/ethereum_test_tools/vm/opcode.py b/src/ethereum_test_tools/vm/opcode.py index 8b503670c3..7cb287405d 100644 --- a/src/ethereum_test_tools/vm/opcode.py +++ b/src/ethereum_test_tools/vm/opcode.py @@ -5038,6 +5038,30 @@ class Opcodes(Opcode, Enum): """ + TXCREATE = Opcode(0xED, popped_stack_items=5, pushed_stack_items=1) + """ + !!! Note: This opcode is under development + + TXCREATE(tx_initcode_hash, value, salt, input_offset, input_size) + ---- + + Description + ---- + + Inputs + ---- + + Outputs + ---- + + Fork + ---- + + Gas + ---- + + """ + RETURNCONTRACT = Opcode( 0xEE, popped_stack_items=2, pushed_stack_items=1, data_portion_length=1 ) @@ -5316,7 +5340,7 @@ class Opcodes(Opcode, Enum): Fork ---- - Prague + EOF Fork Gas ---- @@ -5329,6 +5353,35 @@ class Opcodes(Opcode, Enum): Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) """ + RETURNDATALOAD = Opcode(0xF7, popped_stack_items=1, pushed_stack_items=1) + """ + RETURNDATALOAD(offset) = returndata + ---- + + Description + ---- + Copies 32 bytes of return data onto the operand stack + + Inputs + ---- + - offset: The offset within the return data to start copying. There must be 32 byes of return + data at that address or an exceptional halt occurs. + + Outputs + ---- + - returndata: the 32 bytes of return data at the offset + + Fork + ---- + EOF Fork + + Gas + ---- + 3 + + Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) + """ + EXTDELEGATECALL = Opcode(0xF9, popped_stack_items=3, pushed_stack_items=1) """ EXTDELEGATECALL(target_address, input_offset, input_size) = address @@ -5354,7 +5407,7 @@ class Opcodes(Opcode, Enum): Fork ---- - Prague + EOF Fork Gas ---- @@ -5400,7 +5453,7 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#FA](https://www.evm.codes/#FA) """ - EXTSTATICCALL = Opcode(0xFB, popped_stack_items=4, pushed_stack_items=1) + EXTSTATICCALL = Opcode(0xFB, popped_stack_items=3, pushed_stack_items=1) """ EXTSTATICCALL(target_address, input_offset, input_size) = address ---- @@ -5424,7 +5477,7 @@ class Opcodes(Opcode, Enum): Fork ---- - Prague + EOF Fork Gas ---- @@ -5434,30 +5487,6 @@ class Opcodes(Opcode, Enum): Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) """ - CREATE4 = Opcode(0xF7, popped_stack_items=5, pushed_stack_items=1) - """ - !!! Note: This opcode is under development - - CREATE4() - ---- - - Description - ---- - - Inputs - ---- - - Outputs - ---- - - Fork - ---- - - Gas - ---- - - """ - REVERT = Opcode(0xFD, popped_stack_items=2) """ REVERT(offset, size) diff --git a/tests/prague/eip7676_address_space_extension/__init__.py b/tests/prague/eip7676_address_space_extension/__init__.py new file mode 100644 index 0000000000..094865f879 --- /dev/null +++ b/tests/prague/eip7676_address_space_extension/__init__.py @@ -0,0 +1,3 @@ +""" +Address Space Extension Tests +""" diff --git a/tests/prague/eip7676_address_space_extension/spec.py b/tests/prague/eip7676_address_space_extension/spec.py new file mode 100644 index 0000000000..7bf760554f --- /dev/null +++ b/tests/prague/eip7676_address_space_extension/spec.py @@ -0,0 +1,5 @@ +""" +EOF V1 Constants used throughout all tests +""" + +EOF_FORK_NAME = "Prague" diff --git a/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py b/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py new file mode 100644 index 0000000000..573e1db9e8 --- /dev/null +++ b/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py @@ -0,0 +1,219 @@ +""" +Execution of CALLF, RETF opcodes within EOF V1 containers tests +""" + +import pytest + +from ethereum_test_tools import ( + Account, + Address, + Environment, + StateTestFiller, + TestAddress, + Transaction, +) +from ethereum_test_tools.common.conversions import BytesConvertible, to_bytes +from ethereum_test_tools.eof.v1 import Container, Section +from ethereum_test_tools.eof.v1.constants import NON_RETURNING_SECTION +from ethereum_test_tools.vm.opcode import Opcodes as Op + +from .spec import EOF_FORK_NAME + +REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7676.md" +REFERENCE_SPEC_VERSION = ( + "00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +) + +pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) + + +@pytest.mark.parametrize( + "target_address", + ( + b"", + b"\x10\x00", + b"\x78" * 20, + b"\xff" * 20, + b"\x01" + (b"\x00" * 20), + b"\x5a" * 28, + b"\x5a" * 32, + b"\xff" * 32, + ), + ids=["zero", "short", "mid20", "max20", "minAse", "midAse", "fullAse", "maxAse"], +) +@pytest.mark.parametrize("target_account_type", ("empty", "EOA", "Contract"), ids=lambda x: x) +def test_address_space_extension( + state_test: StateTestFiller, + target_address: BytesConvertible, + target_account_type: str, +): + """ + Test contacts with possibly extended address and fail if address is too large + """ + env = Environment() + + address_bytes = to_bytes(target_address) + ase_address = len(address_bytes) > 20 + if ase_address and address_bytes[0] == b"00": + raise ValueError("Test instrumentation requires target addresses trim leading zeros") + + pre = { + TestAddress: Account( + balance=1000000000000000000000, + nonce=1, + ), + Address(0x100): Account( + code=( + Op.MSTORE(0, Op.PUSH32(address_bytes)) + + Op.SSTORE(0, Op.CALL(50000, 0x200, 0, 0, 32, 0, 0)) + + Op.SSTORE(1, Op.CALL(50000, 0x300, 0, 0, 32, 0, 0)) + + Op.SSTORE(2, Op.CALL(50000, 0x400, 0, 0, 32, 0, 0)) + + Op.SSTORE(3, Op.CALL(50000, 0x500, 0, 0, 32, 0, 0)) + + Op.SSTORE(4, Op.CALL(50000, 0x201, 0, 0, 32, 0, 0)) + + Op.SSTORE(5, Op.CALL(50000, 0x301, 0, 0, 32, 0, 0)) + + Op.SSTORE(6, Op.CALL(50000, 0x401, 0, 0, 32, 0, 0)) + + Op.SSTORE(7, Op.CALL(50000, 0x501, 0, 0, 32, 0, 0)) + + Op.SSTORE(8, Op.CALL(50000, 0x601, 0, 0, 32, 0, 0)) + + Op.STOP() + ), + nonce=1, + ), + Address(0x200): Account( + code=Container( + sections=[ + Section.Code( + code=Op.SSTORE(0, Op.BALANCE(Op.CALLDATALOAD(0))) + Op.STOP, + code_inputs=0, + code_outputs=NON_RETURNING_SECTION, + max_stack_height=2, + ) + ], + ), + nonce=1, + ), + Address(0x201): Account( + code=Op.SSTORE(0, Op.BALANCE(Op.CALLDATALOAD(0))) + Op.STOP, + nonce=1, + ), + Address(0x300): Account( + code=Container( + sections=[ + Section.Code( + code=Op.SSTORE(0, Op.EXTCALL(Op.CALLDATALOAD(0), 0, 0, 0)) + + Op.SSTORE(1, Op.RETURNDATALOAD(0)) + + Op.STOP, + code_inputs=0, + code_outputs=NON_RETURNING_SECTION, + max_stack_height=4, + ) + ], + ), + nonce=1, + ), + Address(0x301): Account( + code=Op.SSTORE(0, Op.CALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0, 0)) + + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + + Op.SSTORE(1, Op.MLOAD(0)) + + Op.STOP, + nonce=1, + ), + Address(0x400): Account( + code=Container( + sections=[ + Section.Code( + code=Op.SSTORE(0, Op.EXTDELEGATECALL(Op.CALLDATALOAD(0), 0, 0)) + + Op.SSTORE(1, Op.RETURNDATALOAD(0)) + + Op.STOP, + code_inputs=0, + code_outputs=NON_RETURNING_SECTION, + max_stack_height=3, + ) + ], + ), + nonce=1, + ), + Address(0x401): Account( + code=Op.SSTORE(0, Op.DELEGATECALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0)) + + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + + Op.SSTORE(1, Op.MLOAD(0)) + + Op.STOP, + nonce=1, + ), + Address(0x500): Account( + code=Container( + sections=[ + Section.Code( + code=Op.SSTORE(0, Op.EXTSTATICCALL(Op.CALLDATALOAD(0), 0, 0)) + + Op.SSTORE(1, Op.RETURNDATALOAD(0)) + + Op.STOP, + code_inputs=0, + code_outputs=NON_RETURNING_SECTION, + max_stack_height=3, + ) + ], + ), + nonce=1, + ), + Address(0x501): Account( + code=Op.SSTORE(0, Op.STATICCALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0)) + + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + + Op.SSTORE(1, Op.MLOAD(0)) + + Op.STOP, + nonce=1, + ), + Address(0x601): Account( + code=Op.SSTORE(0, Op.CALLCODE(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0, 0)) + + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + + Op.SSTORE(1, Op.MLOAD(0)) + + Op.STOP, + nonce=1, + ), + } + + stripped_address = address_bytes[-20:] if ase_address else target_address + post = { + Address(0x100): Account( + storage={0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1} + if not ase_address + else {4: 1, 5: 1, 6: 1, 7: 1, 8: 1} + ) + } + match target_account_type: + case "empty": + # add no account + pass + case "EOA": + pre[Address(stripped_address)] = Account(code="", balance=10**18, nonce=9) + post[Address(0x200)] = Account(storage={} if ase_address else {0: 10**18}) + post[Address(0x201)] = Account(storage={0: 10**18}) + case "Contract": + pre[Address(stripped_address)] = Account( + code=Op.MSTORE(0, Op.ADDRESS) + Op.RETURN(0, 32), balance=0, nonce=0 + ) + # For EOF variants the EXT*CALL reverts, so no storage updates for ASE address + post[Address(0x300)] = Account(storage={} if ase_address else {1: stripped_address}) + post[Address(0x301)] = Account(storage={0: 1, 1: stripped_address}) + # EXTDELEGATECALL fails when calling legacy, so no stripped address + post[Address(0x400)] = Account(storage={} if ase_address else {0: 1}) + post[Address(0x401)] = Account(storage={0: 1, 1: 0x401}) + post[Address(0x500)] = Account(storage={} if ase_address else {1: stripped_address}) + post[Address(0x501)] = Account(storage={0: 1, 1: stripped_address}) + post[Address(0x601)] = Account(storage={0: 1, 1: 0x601}) + case _: + raise ValueError("Unknown account type: " + target_account_type) + + tx = Transaction( + nonce=1, + to=Address(0x100), + gas_limit=50000000, + gas_price=10, + protected=False, + data="", + ) + + state_test( + env=env, + pre=pre, + post=post, + tx=tx, + ) diff --git a/whitelist.txt b/whitelist.txt index c06e368730..f204bd7519 100644 --- a/whitelist.txt +++ b/whitelist.txt @@ -3,6 +3,7 @@ acl addr address address2 +ase alloc api apis @@ -244,6 +245,7 @@ repo repo's repos returndatacopy +returndataload returndatasize returncontract rlp @@ -272,7 +274,7 @@ StateTestFiller staticcalled stExample str -streetsidesoftware +streetsidesoftiware subcall subclasscheck subdirectories @@ -549,7 +551,7 @@ tstore create create2 create3 -create4 +txcreate call callcode return From 52be716543e0b4611cccd87b4363a4e284910e41 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Wed, 24 Apr 2024 13:20:58 -0600 Subject: [PATCH 02/14] Reviewer requested changes Signed-off-by: Danno Ferrin --- .../test_ase_opcodes.py | 97 +++++++++++++------ 1 file changed, 67 insertions(+), 30 deletions(-) diff --git a/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py b/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py index 573e1db9e8..bd6b83b2f3 100644 --- a/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py +++ b/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py @@ -26,6 +26,27 @@ pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) +ID_EOF_BALANCE = 0 +ID_BALANCE = 1 +ID_EXTCALL = 2 +ID_CALL = 3 +ID_EXTDELEGATE = 4 +ID_DELEGATECALL = 5 +ID_EXTSTATIC = 6 +ID_STATICALL = 7 +ID_CALLCODE = 8 + +BASE_ADDR = 100000000 +ADDR_EOF_BALANCE = Address(BASE_ADDR + ID_EOF_BALANCE) +ADDR_BALANCE = Address(BASE_ADDR + ID_BALANCE) +ADDR_EXTCALL = Address(BASE_ADDR + ID_EXTCALL) +ADDR_CALL = Address(BASE_ADDR + ID_CALL) +ADDR_EXTDELEGATE = Address(BASE_ADDR + ID_EXTDELEGATE) +ADDR_DELEGATECALL = Address(BASE_ADDR + ID_DELEGATECALL) +ADDR_EXTSTATIC = Address(BASE_ADDR + ID_EXTSTATIC) +ADDR_STATICALL = Address(BASE_ADDR + ID_STATICALL) +ADDR_CALLCODE = Address(BASE_ADDR + ID_CALLCODE) + @pytest.mark.parametrize( "target_address", @@ -65,20 +86,20 @@ def test_address_space_extension( Address(0x100): Account( code=( Op.MSTORE(0, Op.PUSH32(address_bytes)) - + Op.SSTORE(0, Op.CALL(50000, 0x200, 0, 0, 32, 0, 0)) - + Op.SSTORE(1, Op.CALL(50000, 0x300, 0, 0, 32, 0, 0)) - + Op.SSTORE(2, Op.CALL(50000, 0x400, 0, 0, 32, 0, 0)) - + Op.SSTORE(3, Op.CALL(50000, 0x500, 0, 0, 32, 0, 0)) - + Op.SSTORE(4, Op.CALL(50000, 0x201, 0, 0, 32, 0, 0)) - + Op.SSTORE(5, Op.CALL(50000, 0x301, 0, 0, 32, 0, 0)) - + Op.SSTORE(6, Op.CALL(50000, 0x401, 0, 0, 32, 0, 0)) - + Op.SSTORE(7, Op.CALL(50000, 0x501, 0, 0, 32, 0, 0)) - + Op.SSTORE(8, Op.CALL(50000, 0x601, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_EOF_BALANCE, Op.CALL(50000, ADDR_EOF_BALANCE, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_BALANCE, Op.CALL(50000, ADDR_BALANCE, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_EXTCALL, Op.CALL(50000, ADDR_EXTCALL, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_CALL, Op.CALL(50000, ADDR_CALL, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_EXTDELEGATE, Op.CALL(50000, ADDR_EXTDELEGATE, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_DELEGATECALL, Op.CALL(50000, ADDR_DELEGATECALL, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_EXTSTATIC, Op.CALL(50000, ADDR_EXTSTATIC, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_STATICALL, Op.CALL(50000, ADDR_STATICALL, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_CALLCODE, Op.CALL(50000, ADDR_CALLCODE, 0, 0, 32, 0, 0)) + Op.STOP() ), nonce=1, ), - Address(0x200): Account( + ADDR_EOF_BALANCE: Account( code=Container( sections=[ Section.Code( @@ -91,11 +112,11 @@ def test_address_space_extension( ), nonce=1, ), - Address(0x201): Account( + ADDR_BALANCE: Account( code=Op.SSTORE(0, Op.BALANCE(Op.CALLDATALOAD(0))) + Op.STOP, nonce=1, ), - Address(0x300): Account( + ADDR_EXTCALL: Account( code=Container( sections=[ Section.Code( @@ -110,14 +131,14 @@ def test_address_space_extension( ), nonce=1, ), - Address(0x301): Account( + ADDR_CALL: Account( code=Op.SSTORE(0, Op.CALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0, 0)) + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + Op.SSTORE(1, Op.MLOAD(0)) + Op.STOP, nonce=1, ), - Address(0x400): Account( + ADDR_EXTDELEGATE: Account( code=Container( sections=[ Section.Code( @@ -132,14 +153,14 @@ def test_address_space_extension( ), nonce=1, ), - Address(0x401): Account( + ADDR_DELEGATECALL: Account( code=Op.SSTORE(0, Op.DELEGATECALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0)) + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + Op.SSTORE(1, Op.MLOAD(0)) + Op.STOP, nonce=1, ), - Address(0x500): Account( + ADDR_EXTSTATIC: Account( code=Container( sections=[ Section.Code( @@ -154,14 +175,14 @@ def test_address_space_extension( ), nonce=1, ), - Address(0x501): Account( + ADDR_STATICALL: Account( code=Op.SSTORE(0, Op.STATICCALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0)) + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + Op.SSTORE(1, Op.MLOAD(0)) + Op.STOP, nonce=1, ), - Address(0x601): Account( + ADDR_CALLCODE: Account( code=Op.SSTORE(0, Op.CALLCODE(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0, 0)) + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + Op.SSTORE(1, Op.MLOAD(0)) @@ -173,9 +194,25 @@ def test_address_space_extension( stripped_address = address_bytes[-20:] if ase_address else target_address post = { Address(0x100): Account( - storage={0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1} - if not ase_address - else {4: 1, 5: 1, 6: 1, 7: 1, 8: 1} + storage={ + ID_BALANCE: 1, + ID_CALL: 1, + ID_DELEGATECALL: 1, + ID_STATICALL: 1, + ID_CALLCODE: 1, + } + if ase_address + else { + ID_EOF_BALANCE: 1, + ID_BALANCE: 1, + ID_EXTCALL: 1, + ID_CALL: 1, + ID_EXTDELEGATE: 1, + ID_DELEGATECALL: 1, + ID_EXTSTATIC: 1, + ID_STATICALL: 1, + ID_CALLCODE: 1, + } ) } match target_account_type: @@ -184,21 +221,21 @@ def test_address_space_extension( pass case "EOA": pre[Address(stripped_address)] = Account(code="", balance=10**18, nonce=9) - post[Address(0x200)] = Account(storage={} if ase_address else {0: 10**18}) - post[Address(0x201)] = Account(storage={0: 10**18}) + post[ADDR_EOF_BALANCE] = Account(storage={} if ase_address else {0: 10**18}) + post[ADDR_BALANCE] = Account(storage={0: 10**18}) case "Contract": pre[Address(stripped_address)] = Account( code=Op.MSTORE(0, Op.ADDRESS) + Op.RETURN(0, 32), balance=0, nonce=0 ) # For EOF variants the EXT*CALL reverts, so no storage updates for ASE address - post[Address(0x300)] = Account(storage={} if ase_address else {1: stripped_address}) - post[Address(0x301)] = Account(storage={0: 1, 1: stripped_address}) + post[ADDR_EXTCALL] = Account(storage={} if ase_address else {1: stripped_address}) + post[ADDR_CALL] = Account(storage={0: 1, 1: stripped_address}) # EXTDELEGATECALL fails when calling legacy, so no stripped address - post[Address(0x400)] = Account(storage={} if ase_address else {0: 1}) - post[Address(0x401)] = Account(storage={0: 1, 1: 0x401}) - post[Address(0x500)] = Account(storage={} if ase_address else {1: stripped_address}) - post[Address(0x501)] = Account(storage={0: 1, 1: stripped_address}) - post[Address(0x601)] = Account(storage={0: 1, 1: 0x601}) + post[ADDR_EXTDELEGATE] = Account(storage={} if ase_address else {0: 1}) + post[ADDR_DELEGATECALL] = Account(storage={0: 1, 1: ADDR_DELEGATECALL}) + post[ADDR_EXTSTATIC] = Account(storage={} if ase_address else {1: stripped_address}) + post[ADDR_STATICALL] = Account(storage={0: 1, 1: stripped_address}) + post[ADDR_CALLCODE] = Account(storage={0: 1, 1: ADDR_CALLCODE}) case _: raise ValueError("Unknown account type: " + target_account_type) From f5dd04a0ae70968f80f31031a6fe422886a65371 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Wed, 24 Apr 2024 14:12:09 -0600 Subject: [PATCH 03/14] formatting Signed-off-by: Danno Ferrin --- .../test_ase_opcodes.py | 84 ++++++++++--------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py b/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py index bd6b83b2f3..5a2d7442c2 100644 --- a/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py +++ b/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py @@ -30,22 +30,22 @@ ID_BALANCE = 1 ID_EXTCALL = 2 ID_CALL = 3 -ID_EXTDELEGATE = 4 +ID_EXTDELEGATECALL = 4 ID_DELEGATECALL = 5 -ID_EXTSTATIC = 6 +ID_EXTSTATICCALL = 6 ID_STATICALL = 7 ID_CALLCODE = 8 -BASE_ADDR = 100000000 -ADDR_EOF_BALANCE = Address(BASE_ADDR + ID_EOF_BALANCE) -ADDR_BALANCE = Address(BASE_ADDR + ID_BALANCE) -ADDR_EXTCALL = Address(BASE_ADDR + ID_EXTCALL) -ADDR_CALL = Address(BASE_ADDR + ID_CALL) -ADDR_EXTDELEGATE = Address(BASE_ADDR + ID_EXTDELEGATE) -ADDR_DELEGATECALL = Address(BASE_ADDR + ID_DELEGATECALL) -ADDR_EXTSTATIC = Address(BASE_ADDR + ID_EXTSTATIC) -ADDR_STATICALL = Address(BASE_ADDR + ID_STATICALL) -ADDR_CALLCODE = Address(BASE_ADDR + ID_CALLCODE) +BASE_ADDRESS = 100000000 +ADDRESS_EOF_BALANCE = Address(BASE_ADDRESS + ID_EOF_BALANCE) +ADDRESS_BALANCE = Address(BASE_ADDRESS + ID_BALANCE) +ADDRESS_EXTCALL = Address(BASE_ADDRESS + ID_EXTCALL) +ADDRESS_CALL = Address(BASE_ADDRESS + ID_CALL) +ADDRESS_EXTDELEGATE = Address(BASE_ADDRESS + ID_EXTDELEGATECALL) +ADDRESS_DELEGATECALL = Address(BASE_ADDRESS + ID_DELEGATECALL) +ADDRESS_EXTSTATIC = Address(BASE_ADDRESS + ID_EXTSTATICCALL) +ADDRESS_STATICALL = Address(BASE_ADDRESS + ID_STATICALL) +ADDRESS_CALLCODE = Address(BASE_ADDRESS + ID_CALLCODE) @pytest.mark.parametrize( @@ -86,20 +86,22 @@ def test_address_space_extension( Address(0x100): Account( code=( Op.MSTORE(0, Op.PUSH32(address_bytes)) - + Op.SSTORE(ID_EOF_BALANCE, Op.CALL(50000, ADDR_EOF_BALANCE, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_BALANCE, Op.CALL(50000, ADDR_BALANCE, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_EXTCALL, Op.CALL(50000, ADDR_EXTCALL, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_CALL, Op.CALL(50000, ADDR_CALL, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_EXTDELEGATE, Op.CALL(50000, ADDR_EXTDELEGATE, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_DELEGATECALL, Op.CALL(50000, ADDR_DELEGATECALL, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_EXTSTATIC, Op.CALL(50000, ADDR_EXTSTATIC, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_STATICALL, Op.CALL(50000, ADDR_STATICALL, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_CALLCODE, Op.CALL(50000, ADDR_CALLCODE, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_EOF_BALANCE, Op.CALL(50000, ADDRESS_EOF_BALANCE, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_BALANCE, Op.CALL(50000, ADDRESS_BALANCE, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_EXTCALL, Op.CALL(50000, ADDRESS_EXTCALL, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_CALL, Op.CALL(50000, ADDRESS_CALL, 0, 0, 32, 0, 0)) + + Op.SSTORE( + ID_EXTDELEGATECALL, Op.CALL(50000, ADDRESS_EXTDELEGATE, 0, 0, 32, 0, 0) + ) + + Op.SSTORE(ID_DELEGATECALL, Op.CALL(50000, ADDRESS_DELEGATECALL, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_EXTSTATICCALL, Op.CALL(50000, ADDRESS_EXTSTATIC, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_STATICALL, Op.CALL(50000, ADDRESS_STATICALL, 0, 0, 32, 0, 0)) + + Op.SSTORE(ID_CALLCODE, Op.CALL(50000, ADDRESS_CALLCODE, 0, 0, 32, 0, 0)) + Op.STOP() ), nonce=1, ), - ADDR_EOF_BALANCE: Account( + ADDRESS_EOF_BALANCE: Account( code=Container( sections=[ Section.Code( @@ -112,11 +114,11 @@ def test_address_space_extension( ), nonce=1, ), - ADDR_BALANCE: Account( + ADDRESS_BALANCE: Account( code=Op.SSTORE(0, Op.BALANCE(Op.CALLDATALOAD(0))) + Op.STOP, nonce=1, ), - ADDR_EXTCALL: Account( + ADDRESS_EXTCALL: Account( code=Container( sections=[ Section.Code( @@ -131,14 +133,14 @@ def test_address_space_extension( ), nonce=1, ), - ADDR_CALL: Account( + ADDRESS_CALL: Account( code=Op.SSTORE(0, Op.CALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0, 0)) + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + Op.SSTORE(1, Op.MLOAD(0)) + Op.STOP, nonce=1, ), - ADDR_EXTDELEGATE: Account( + ADDRESS_EXTDELEGATE: Account( code=Container( sections=[ Section.Code( @@ -153,14 +155,14 @@ def test_address_space_extension( ), nonce=1, ), - ADDR_DELEGATECALL: Account( + ADDRESS_DELEGATECALL: Account( code=Op.SSTORE(0, Op.DELEGATECALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0)) + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + Op.SSTORE(1, Op.MLOAD(0)) + Op.STOP, nonce=1, ), - ADDR_EXTSTATIC: Account( + ADDRESS_EXTSTATIC: Account( code=Container( sections=[ Section.Code( @@ -175,14 +177,14 @@ def test_address_space_extension( ), nonce=1, ), - ADDR_STATICALL: Account( + ADDRESS_STATICALL: Account( code=Op.SSTORE(0, Op.STATICCALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0)) + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + Op.SSTORE(1, Op.MLOAD(0)) + Op.STOP, nonce=1, ), - ADDR_CALLCODE: Account( + ADDRESS_CALLCODE: Account( code=Op.SSTORE(0, Op.CALLCODE(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0, 0)) + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + Op.SSTORE(1, Op.MLOAD(0)) @@ -207,9 +209,9 @@ def test_address_space_extension( ID_BALANCE: 1, ID_EXTCALL: 1, ID_CALL: 1, - ID_EXTDELEGATE: 1, + ID_EXTDELEGATECALL: 1, ID_DELEGATECALL: 1, - ID_EXTSTATIC: 1, + ID_EXTSTATICCALL: 1, ID_STATICALL: 1, ID_CALLCODE: 1, } @@ -221,21 +223,21 @@ def test_address_space_extension( pass case "EOA": pre[Address(stripped_address)] = Account(code="", balance=10**18, nonce=9) - post[ADDR_EOF_BALANCE] = Account(storage={} if ase_address else {0: 10**18}) - post[ADDR_BALANCE] = Account(storage={0: 10**18}) + post[ADDRESS_EOF_BALANCE] = Account(storage={} if ase_address else {0: 10**18}) + post[ADDRESS_BALANCE] = Account(storage={0: 10**18}) case "Contract": pre[Address(stripped_address)] = Account( code=Op.MSTORE(0, Op.ADDRESS) + Op.RETURN(0, 32), balance=0, nonce=0 ) # For EOF variants the EXT*CALL reverts, so no storage updates for ASE address - post[ADDR_EXTCALL] = Account(storage={} if ase_address else {1: stripped_address}) - post[ADDR_CALL] = Account(storage={0: 1, 1: stripped_address}) + post[ADDRESS_EXTCALL] = Account(storage={} if ase_address else {1: stripped_address}) + post[ADDRESS_CALL] = Account(storage={0: 1, 1: stripped_address}) # EXTDELEGATECALL fails when calling legacy, so no stripped address - post[ADDR_EXTDELEGATE] = Account(storage={} if ase_address else {0: 1}) - post[ADDR_DELEGATECALL] = Account(storage={0: 1, 1: ADDR_DELEGATECALL}) - post[ADDR_EXTSTATIC] = Account(storage={} if ase_address else {1: stripped_address}) - post[ADDR_STATICALL] = Account(storage={0: 1, 1: stripped_address}) - post[ADDR_CALLCODE] = Account(storage={0: 1, 1: ADDR_CALLCODE}) + post[ADDRESS_EXTDELEGATE] = Account(storage={} if ase_address else {0: 1}) + post[ADDRESS_DELEGATECALL] = Account(storage={0: 1, 1: ADDRESS_DELEGATECALL}) + post[ADDRESS_EXTSTATIC] = Account(storage={} if ase_address else {1: stripped_address}) + post[ADDRESS_STATICALL] = Account(storage={0: 1, 1: stripped_address}) + post[ADDRESS_CALLCODE] = Account(storage={0: 1, 1: ADDRESS_CALLCODE}) case _: raise ValueError("Unknown account type: " + target_account_type) From b88130d50919ff8c9244787f4e56843d1fc6dcde Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Wed, 24 Apr 2024 14:17:48 -0600 Subject: [PATCH 04/14] speling Signed-off-by: Danno Ferrin --- .../test_ase_opcodes.py | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py b/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py index 5a2d7442c2..5bf5f2e97c 100644 --- a/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py +++ b/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py @@ -33,7 +33,7 @@ ID_EXTDELEGATECALL = 4 ID_DELEGATECALL = 5 ID_EXTSTATICCALL = 6 -ID_STATICALL = 7 +ID_STATICCALL = 7 ID_CALLCODE = 8 BASE_ADDRESS = 100000000 @@ -41,10 +41,10 @@ ADDRESS_BALANCE = Address(BASE_ADDRESS + ID_BALANCE) ADDRESS_EXTCALL = Address(BASE_ADDRESS + ID_EXTCALL) ADDRESS_CALL = Address(BASE_ADDRESS + ID_CALL) -ADDRESS_EXTDELEGATE = Address(BASE_ADDRESS + ID_EXTDELEGATECALL) +ADDRESS_EXTDELEGATECALL = Address(BASE_ADDRESS + ID_EXTDELEGATECALL) ADDRESS_DELEGATECALL = Address(BASE_ADDRESS + ID_DELEGATECALL) -ADDRESS_EXTSTATIC = Address(BASE_ADDRESS + ID_EXTSTATICCALL) -ADDRESS_STATICALL = Address(BASE_ADDRESS + ID_STATICALL) +ADDRESS_EXTSTATICCALL = Address(BASE_ADDRESS + ID_EXTSTATICCALL) +ADDRESS_STATICCALL = Address(BASE_ADDRESS + ID_STATICCALL) ADDRESS_CALLCODE = Address(BASE_ADDRESS + ID_CALLCODE) @@ -91,11 +91,13 @@ def test_address_space_extension( + Op.SSTORE(ID_EXTCALL, Op.CALL(50000, ADDRESS_EXTCALL, 0, 0, 32, 0, 0)) + Op.SSTORE(ID_CALL, Op.CALL(50000, ADDRESS_CALL, 0, 0, 32, 0, 0)) + Op.SSTORE( - ID_EXTDELEGATECALL, Op.CALL(50000, ADDRESS_EXTDELEGATE, 0, 0, 32, 0, 0) + ID_EXTDELEGATECALL, Op.CALL(50000, ADDRESS_EXTDELEGATECALL, 0, 0, 32, 0, 0) ) + Op.SSTORE(ID_DELEGATECALL, Op.CALL(50000, ADDRESS_DELEGATECALL, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_EXTSTATICCALL, Op.CALL(50000, ADDRESS_EXTSTATIC, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_STATICALL, Op.CALL(50000, ADDRESS_STATICALL, 0, 0, 32, 0, 0)) + + Op.SSTORE( + ID_EXTSTATICCALL, Op.CALL(50000, ADDRESS_EXTSTATICCALL, 0, 0, 32, 0, 0) + ) + + Op.SSTORE(ID_STATICCALL, Op.CALL(50000, ADDRESS_STATICCALL, 0, 0, 32, 0, 0)) + Op.SSTORE(ID_CALLCODE, Op.CALL(50000, ADDRESS_CALLCODE, 0, 0, 32, 0, 0)) + Op.STOP() ), @@ -140,7 +142,7 @@ def test_address_space_extension( + Op.STOP, nonce=1, ), - ADDRESS_EXTDELEGATE: Account( + ADDRESS_EXTDELEGATECALL: Account( code=Container( sections=[ Section.Code( @@ -162,7 +164,7 @@ def test_address_space_extension( + Op.STOP, nonce=1, ), - ADDRESS_EXTSTATIC: Account( + ADDRESS_EXTSTATICCALL: Account( code=Container( sections=[ Section.Code( @@ -177,7 +179,7 @@ def test_address_space_extension( ), nonce=1, ), - ADDRESS_STATICALL: Account( + ADDRESS_STATICCALL: Account( code=Op.SSTORE(0, Op.STATICCALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0)) + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + Op.SSTORE(1, Op.MLOAD(0)) @@ -200,7 +202,7 @@ def test_address_space_extension( ID_BALANCE: 1, ID_CALL: 1, ID_DELEGATECALL: 1, - ID_STATICALL: 1, + ID_STATICCALL: 1, ID_CALLCODE: 1, } if ase_address @@ -212,7 +214,7 @@ def test_address_space_extension( ID_EXTDELEGATECALL: 1, ID_DELEGATECALL: 1, ID_EXTSTATICCALL: 1, - ID_STATICALL: 1, + ID_STATICCALL: 1, ID_CALLCODE: 1, } ) @@ -233,10 +235,12 @@ def test_address_space_extension( post[ADDRESS_EXTCALL] = Account(storage={} if ase_address else {1: stripped_address}) post[ADDRESS_CALL] = Account(storage={0: 1, 1: stripped_address}) # EXTDELEGATECALL fails when calling legacy, so no stripped address - post[ADDRESS_EXTDELEGATE] = Account(storage={} if ase_address else {0: 1}) + post[ADDRESS_EXTDELEGATECALL] = Account(storage={} if ase_address else {0: 1}) post[ADDRESS_DELEGATECALL] = Account(storage={0: 1, 1: ADDRESS_DELEGATECALL}) - post[ADDRESS_EXTSTATIC] = Account(storage={} if ase_address else {1: stripped_address}) - post[ADDRESS_STATICALL] = Account(storage={0: 1, 1: stripped_address}) + post[ADDRESS_EXTSTATICCALL] = Account( + storage={} if ase_address else {1: stripped_address} + ) + post[ADDRESS_STATICCALL] = Account(storage={0: 1, 1: stripped_address}) post[ADDRESS_CALLCODE] = Account(storage={0: 1, 1: ADDRESS_CALLCODE}) case _: raise ValueError("Unknown account type: " + target_account_type) From 2966ef598e432c87aea7f4959a5abc4135c224ba Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Mon, 13 May 2024 12:44:04 +0300 Subject: [PATCH 05/14] comment out balance from ASE checks EIP-7676 moved the critical EXTCALL sections into the main spec. EOF does not depend on a new BALANCE op, so don't test it. Signed-off-by: Danno Ferrin --- .../test_ase_opcodes.py | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py b/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py index 5bf5f2e97c..3b1df35d76 100644 --- a/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py +++ b/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py @@ -26,8 +26,8 @@ pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) -ID_EOF_BALANCE = 0 -ID_BALANCE = 1 +# ID_EOF_BALANCE = 0 +# ID_BALANCE = 1 ID_EXTCALL = 2 ID_CALL = 3 ID_EXTDELEGATECALL = 4 @@ -37,8 +37,8 @@ ID_CALLCODE = 8 BASE_ADDRESS = 100000000 -ADDRESS_EOF_BALANCE = Address(BASE_ADDRESS + ID_EOF_BALANCE) -ADDRESS_BALANCE = Address(BASE_ADDRESS + ID_BALANCE) +# ADDRESS_EOF_BALANCE = Address(BASE_ADDRESS + ID_EOF_BALANCE) +# ADDRESS_BALANCE = Address(BASE_ADDRESS + ID_BALANCE) ADDRESS_EXTCALL = Address(BASE_ADDRESS + ID_EXTCALL) ADDRESS_CALL = Address(BASE_ADDRESS + ID_CALL) ADDRESS_EXTDELEGATECALL = Address(BASE_ADDRESS + ID_EXTDELEGATECALL) @@ -86,8 +86,8 @@ def test_address_space_extension( Address(0x100): Account( code=( Op.MSTORE(0, Op.PUSH32(address_bytes)) - + Op.SSTORE(ID_EOF_BALANCE, Op.CALL(50000, ADDRESS_EOF_BALANCE, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_BALANCE, Op.CALL(50000, ADDRESS_BALANCE, 0, 0, 32, 0, 0)) + # + Op.SSTORE(ID_EOF_BALANCE, Op.CALL(50000, ADDRESS_EOF_BALANCE, 0, 0, 32, 0, 0)) + # + Op.SSTORE(ID_BALANCE, Op.CALL(50000, ADDRESS_BALANCE, 0, 0, 32, 0, 0)) + Op.SSTORE(ID_EXTCALL, Op.CALL(50000, ADDRESS_EXTCALL, 0, 0, 32, 0, 0)) + Op.SSTORE(ID_CALL, Op.CALL(50000, ADDRESS_CALL, 0, 0, 32, 0, 0)) + Op.SSTORE( @@ -103,23 +103,23 @@ def test_address_space_extension( ), nonce=1, ), - ADDRESS_EOF_BALANCE: Account( - code=Container( - sections=[ - Section.Code( - code=Op.SSTORE(0, Op.BALANCE(Op.CALLDATALOAD(0))) + Op.STOP, - code_inputs=0, - code_outputs=NON_RETURNING_SECTION, - max_stack_height=2, - ) - ], - ), - nonce=1, - ), - ADDRESS_BALANCE: Account( - code=Op.SSTORE(0, Op.BALANCE(Op.CALLDATALOAD(0))) + Op.STOP, - nonce=1, - ), + # ADDRESS_EOF_BALANCE: Account( + # code=Container( + # sections=[ + # Section.Code( + # code=Op.SSTORE(0, Op.BALANCE(Op.CALLDATALOAD(0))) + Op.STOP, + # code_inputs=0, + # code_outputs=NON_RETURNING_SECTION, + # max_stack_height=2, + # ) + # ], + # ), + # nonce=1, + # ), + # ADDRESS_BALANCE: Account( + # code=Op.SSTORE(0, Op.BALANCE(Op.CALLDATALOAD(0))) + Op.STOP, + # nonce=1, + # ), ADDRESS_EXTCALL: Account( code=Container( sections=[ @@ -199,7 +199,7 @@ def test_address_space_extension( post = { Address(0x100): Account( storage={ - ID_BALANCE: 1, + # ID_BALANCE: 1, ID_CALL: 1, ID_DELEGATECALL: 1, ID_STATICCALL: 1, @@ -207,8 +207,8 @@ def test_address_space_extension( } if ase_address else { - ID_EOF_BALANCE: 1, - ID_BALANCE: 1, + # ID_EOF_BALANCE: 1, + # ID_BALANCE: 1, ID_EXTCALL: 1, ID_CALL: 1, ID_EXTDELEGATECALL: 1, @@ -225,8 +225,8 @@ def test_address_space_extension( pass case "EOA": pre[Address(stripped_address)] = Account(code="", balance=10**18, nonce=9) - post[ADDRESS_EOF_BALANCE] = Account(storage={} if ase_address else {0: 10**18}) - post[ADDRESS_BALANCE] = Account(storage={0: 10**18}) + # post[ADDRESS_EOF_BALANCE] = Account(storage={} if ase_address else {0: 10**18}) + # post[ADDRESS_BALANCE] = Account(storage={0: 10**18}) case "Contract": pre[Address(stripped_address)] = Account( code=Op.MSTORE(0, Op.ADDRESS) + Op.RETURN(0, 32), balance=0, nonce=0 From 6c3a02866a440742775b35f66be8d4bcb2d8ef13 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Thu, 23 May 2024 07:40:56 -0600 Subject: [PATCH 06/14] move to new subfolder Signed-off-by: Danno Ferrin --- .../eip7676_address_space_extension/__init__.py | 0 .../{ => eip7692_eof_v1}/eip7676_address_space_extension/spec.py | 0 .../eip7676_address_space_extension/test_ase_opcodes.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename tests/prague/{ => eip7692_eof_v1}/eip7676_address_space_extension/__init__.py (100%) rename tests/prague/{ => eip7692_eof_v1}/eip7676_address_space_extension/spec.py (100%) rename tests/prague/{ => eip7692_eof_v1}/eip7676_address_space_extension/test_ase_opcodes.py (100%) diff --git a/tests/prague/eip7676_address_space_extension/__init__.py b/tests/prague/eip7692_eof_v1/eip7676_address_space_extension/__init__.py similarity index 100% rename from tests/prague/eip7676_address_space_extension/__init__.py rename to tests/prague/eip7692_eof_v1/eip7676_address_space_extension/__init__.py diff --git a/tests/prague/eip7676_address_space_extension/spec.py b/tests/prague/eip7692_eof_v1/eip7676_address_space_extension/spec.py similarity index 100% rename from tests/prague/eip7676_address_space_extension/spec.py rename to tests/prague/eip7692_eof_v1/eip7676_address_space_extension/spec.py diff --git a/tests/prague/eip7676_address_space_extension/test_ase_opcodes.py b/tests/prague/eip7692_eof_v1/eip7676_address_space_extension/test_ase_opcodes.py similarity index 100% rename from tests/prague/eip7676_address_space_extension/test_ase_opcodes.py rename to tests/prague/eip7692_eof_v1/eip7676_address_space_extension/test_ase_opcodes.py From 7882ef0444f3b05d6d76bc09522c01bcb49ad2bb Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Thu, 23 May 2024 10:58:45 -0600 Subject: [PATCH 07/14] Recast as EIP-7069 test Signed-off-by: Danno Ferrin --- .../eip7069_extcall/__init__.py | 3 ++ .../spec.py | 0 .../test_address_space_extension.py} | 36 ++----------------- .../__init__.py | 3 -- 4 files changed, 6 insertions(+), 36 deletions(-) create mode 100644 tests/prague/eip7692_eof_v1/eip7069_extcall/__init__.py rename tests/prague/eip7692_eof_v1/{eip7676_address_space_extension => eip7069_extcall}/spec.py (100%) rename tests/prague/eip7692_eof_v1/{eip7676_address_space_extension/test_ase_opcodes.py => eip7069_extcall/test_address_space_extension.py} (84%) delete mode 100644 tests/prague/eip7692_eof_v1/eip7676_address_space_extension/__init__.py diff --git a/tests/prague/eip7692_eof_v1/eip7069_extcall/__init__.py b/tests/prague/eip7692_eof_v1/eip7069_extcall/__init__.py new file mode 100644 index 0000000000..f4bbcd143f --- /dev/null +++ b/tests/prague/eip7692_eof_v1/eip7069_extcall/__init__.py @@ -0,0 +1,3 @@ +""" +Revamped Call Instructions Tests +""" diff --git a/tests/prague/eip7692_eof_v1/eip7676_address_space_extension/spec.py b/tests/prague/eip7692_eof_v1/eip7069_extcall/spec.py similarity index 100% rename from tests/prague/eip7692_eof_v1/eip7676_address_space_extension/spec.py rename to tests/prague/eip7692_eof_v1/eip7069_extcall/spec.py diff --git a/tests/prague/eip7692_eof_v1/eip7676_address_space_extension/test_ase_opcodes.py b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py similarity index 84% rename from tests/prague/eip7692_eof_v1/eip7676_address_space_extension/test_ase_opcodes.py rename to tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py index 3b1df35d76..6278d34905 100644 --- a/tests/prague/eip7692_eof_v1/eip7676_address_space_extension/test_ase_opcodes.py +++ b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py @@ -1,5 +1,5 @@ """ -Execution of CALLF, RETF opcodes within EOF V1 containers tests +Tests the "Address Space Extension" aspect of EXT*CALL """ import pytest @@ -19,15 +19,11 @@ from .spec import EOF_FORK_NAME -REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7676.md" -REFERENCE_SPEC_VERSION = ( - "00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" -) +REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7069.md" +REFERENCE_SPEC_VERSION = "1795943aeacc86131d5ab6bb3d65824b3b1d4cad" pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) -# ID_EOF_BALANCE = 0 -# ID_BALANCE = 1 ID_EXTCALL = 2 ID_CALL = 3 ID_EXTDELEGATECALL = 4 @@ -37,8 +33,6 @@ ID_CALLCODE = 8 BASE_ADDRESS = 100000000 -# ADDRESS_EOF_BALANCE = Address(BASE_ADDRESS + ID_EOF_BALANCE) -# ADDRESS_BALANCE = Address(BASE_ADDRESS + ID_BALANCE) ADDRESS_EXTCALL = Address(BASE_ADDRESS + ID_EXTCALL) ADDRESS_CALL = Address(BASE_ADDRESS + ID_CALL) ADDRESS_EXTDELEGATECALL = Address(BASE_ADDRESS + ID_EXTDELEGATECALL) @@ -86,8 +80,6 @@ def test_address_space_extension( Address(0x100): Account( code=( Op.MSTORE(0, Op.PUSH32(address_bytes)) - # + Op.SSTORE(ID_EOF_BALANCE, Op.CALL(50000, ADDRESS_EOF_BALANCE, 0, 0, 32, 0, 0)) - # + Op.SSTORE(ID_BALANCE, Op.CALL(50000, ADDRESS_BALANCE, 0, 0, 32, 0, 0)) + Op.SSTORE(ID_EXTCALL, Op.CALL(50000, ADDRESS_EXTCALL, 0, 0, 32, 0, 0)) + Op.SSTORE(ID_CALL, Op.CALL(50000, ADDRESS_CALL, 0, 0, 32, 0, 0)) + Op.SSTORE( @@ -103,23 +95,6 @@ def test_address_space_extension( ), nonce=1, ), - # ADDRESS_EOF_BALANCE: Account( - # code=Container( - # sections=[ - # Section.Code( - # code=Op.SSTORE(0, Op.BALANCE(Op.CALLDATALOAD(0))) + Op.STOP, - # code_inputs=0, - # code_outputs=NON_RETURNING_SECTION, - # max_stack_height=2, - # ) - # ], - # ), - # nonce=1, - # ), - # ADDRESS_BALANCE: Account( - # code=Op.SSTORE(0, Op.BALANCE(Op.CALLDATALOAD(0))) + Op.STOP, - # nonce=1, - # ), ADDRESS_EXTCALL: Account( code=Container( sections=[ @@ -199,7 +174,6 @@ def test_address_space_extension( post = { Address(0x100): Account( storage={ - # ID_BALANCE: 1, ID_CALL: 1, ID_DELEGATECALL: 1, ID_STATICCALL: 1, @@ -207,8 +181,6 @@ def test_address_space_extension( } if ase_address else { - # ID_EOF_BALANCE: 1, - # ID_BALANCE: 1, ID_EXTCALL: 1, ID_CALL: 1, ID_EXTDELEGATECALL: 1, @@ -225,8 +197,6 @@ def test_address_space_extension( pass case "EOA": pre[Address(stripped_address)] = Account(code="", balance=10**18, nonce=9) - # post[ADDRESS_EOF_BALANCE] = Account(storage={} if ase_address else {0: 10**18}) - # post[ADDRESS_BALANCE] = Account(storage={0: 10**18}) case "Contract": pre[Address(stripped_address)] = Account( code=Op.MSTORE(0, Op.ADDRESS) + Op.RETURN(0, 32), balance=0, nonce=0 diff --git a/tests/prague/eip7692_eof_v1/eip7676_address_space_extension/__init__.py b/tests/prague/eip7692_eof_v1/eip7676_address_space_extension/__init__.py deleted file mode 100644 index 094865f879..0000000000 --- a/tests/prague/eip7692_eof_v1/eip7676_address_space_extension/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -Address Space Extension Tests -""" From 988996b12a00233ccf312a0037fcad139c76c746 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Thu, 23 May 2024 11:07:38 -0600 Subject: [PATCH 08/14] use itertools.count instead of hard coded address Signed-off-by: Danno Ferrin --- .../test_address_space_extension.py | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py index 6278d34905..68e51739b1 100644 --- a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py +++ b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py @@ -1,6 +1,7 @@ """ Tests the "Address Space Extension" aspect of EXT*CALL """ +import itertools import pytest @@ -24,22 +25,23 @@ pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) -ID_EXTCALL = 2 -ID_CALL = 3 -ID_EXTDELEGATECALL = 4 -ID_DELEGATECALL = 5 -ID_EXTSTATICCALL = 6 -ID_STATICCALL = 7 -ID_CALLCODE = 8 +_call_type = itertools.count(1) +ID_EXTCALL = next(_call_type) +ID_CALL = next(_call_type) +ID_EXTDELEGATECALL = next(_call_type) +ID_DELEGATECALL = next(_call_type) +ID_EXTSTATICCALL = next(_call_type) +ID_STATICCALL = next(_call_type) +ID_CALLCODE = next(_call_type) -BASE_ADDRESS = 100000000 -ADDRESS_EXTCALL = Address(BASE_ADDRESS + ID_EXTCALL) -ADDRESS_CALL = Address(BASE_ADDRESS + ID_CALL) -ADDRESS_EXTDELEGATECALL = Address(BASE_ADDRESS + ID_EXTDELEGATECALL) -ADDRESS_DELEGATECALL = Address(BASE_ADDRESS + ID_DELEGATECALL) -ADDRESS_EXTSTATICCALL = Address(BASE_ADDRESS + ID_EXTSTATICCALL) -ADDRESS_STATICCALL = Address(BASE_ADDRESS + ID_STATICCALL) -ADDRESS_CALLCODE = Address(BASE_ADDRESS + ID_CALLCODE) +_address_allocation = itertools.count(100000000) +ADDRESS_EXTCALL = Address(next(_address_allocation)) +ADDRESS_CALL = Address(next(_address_allocation)) +ADDRESS_EXTDELEGATECALL = Address(next(_address_allocation)) +ADDRESS_DELEGATECALL = Address(next(_address_allocation)) +ADDRESS_EXTSTATICCALL = Address(next(_address_allocation)) +ADDRESS_STATICCALL = Address(next(_address_allocation)) +ADDRESS_CALLCODE = Address(next(_address_allocation)) @pytest.mark.parametrize( From 4ecae63e7cf3b7f735dad4ba40fa9f07c59ae9ea Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Tue, 28 May 2024 16:43:32 -0600 Subject: [PATCH 09/14] Review changes * Apply specific edits * Parameterize by opcode as well Signed-off-by: Danno Ferrin --- .../test_address_space_extension.py | 276 +++++++++--------- 1 file changed, 134 insertions(+), 142 deletions(-) diff --git a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py index 68e51739b1..3cdc689366 100644 --- a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py +++ b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py @@ -13,7 +13,6 @@ TestAddress, Transaction, ) -from ethereum_test_tools.common.conversions import BytesConvertible, to_bytes from ethereum_test_tools.eof.v1 import Container, Section from ethereum_test_tools.eof.v1.constants import NON_RETURNING_SECTION from ethereum_test_tools.vm.opcode import Opcodes as Op @@ -25,43 +24,53 @@ pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) -_call_type = itertools.count(1) -ID_EXTCALL = next(_call_type) -ID_CALL = next(_call_type) -ID_EXTDELEGATECALL = next(_call_type) -ID_DELEGATECALL = next(_call_type) -ID_EXTSTATICCALL = next(_call_type) -ID_STATICCALL = next(_call_type) -ID_CALLCODE = next(_call_type) - -_address_allocation = itertools.count(100000000) -ADDRESS_EXTCALL = Address(next(_address_allocation)) -ADDRESS_CALL = Address(next(_address_allocation)) -ADDRESS_EXTDELEGATECALL = Address(next(_address_allocation)) -ADDRESS_DELEGATECALL = Address(next(_address_allocation)) -ADDRESS_EXTSTATICCALL = Address(next(_address_allocation)) -ADDRESS_STATICCALL = Address(next(_address_allocation)) -ADDRESS_CALLCODE = Address(next(_address_allocation)) + +_address_allocation = itertools.count(0x10000) +address_caller = Address(next(_address_allocation)) +address_target = Address(next(_address_allocation)) + +_slot = itertools.count(1) +slot_top_level_call_status = next(_slot) +slot_target_call_status = next(_slot) +slot_target_returndata = next(_slot) + +value_legacy_success = 1 +value_eof_success = 0 +value_eof_fail = 1 @pytest.mark.parametrize( "target_address", ( - b"", - b"\x10\x00", - b"\x78" * 20, - b"\xff" * 20, - b"\x01" + (b"\x00" * 20), - b"\x5a" * 28, - b"\x5a" * 32, - b"\xff" * 32, + pytest.param(b"", id="zero"), + pytest.param(b"\xc0\xde", id="short"), + pytest.param(b"\x78" * 20, id="mid_20"), + pytest.param(b"\xff" * 20, id="max_20"), + pytest.param(b"\x01" + (b"\x00" * 20), id="min_ase"), + pytest.param(b"\x5a" * 28, id="mid_ase"), + pytest.param(b"\x5a" * 32, id="full_ase"), + pytest.param(b"\xff" * 32, id="max_ase"), + ), +) +@pytest.mark.parametrize( + "target_account_type", ("empty", "EOA", "LegacyContract", "EOFContract"), ids=lambda x: x +) +@pytest.mark.parametrize( + "target_opcode", + ( + Op.CALL, + Op.CALLCODE, + Op.STATICCALL, + Op.DELEGATECALL, + Op.EXTCALL, + Op.EXTDELEGATECALL, + Op.EXTSTATICCALL, ), - ids=["zero", "short", "mid20", "max20", "minAse", "midAse", "fullAse", "maxAse"], ) -@pytest.mark.parametrize("target_account_type", ("empty", "EOA", "Contract"), ids=lambda x: x) def test_address_space_extension( state_test: StateTestFiller, - target_address: BytesConvertible, + target_address: bytes, + target_opcode: Op, target_account_type: str, ): """ @@ -69,157 +78,140 @@ def test_address_space_extension( """ env = Environment() - address_bytes = to_bytes(target_address) - ase_address = len(address_bytes) > 20 - if ase_address and address_bytes[0] == b"00": + ase_address = len(target_address) > 20 + stripped_address = target_address[-20:] if ase_address else target_address + if ase_address and target_address[0] == b"00": raise ValueError("Test instrumentation requires target addresses trim leading zeros") + match target_opcode: + case Op.CALL | Op.CALLCODE: + call_suffix = [0, 0, 0, 0, 0] + ase_ready_opcode = False + case Op.DELEGATECALL | Op.STATICCALL: + call_suffix = [0, 0, 0, 0] + ase_ready_opcode = False + case Op.EXTCALL: + call_suffix = [0, 0, 0] + ase_ready_opcode = True + case Op.EXTDELEGATECALL | Op.EXTSTATICCALL: + call_suffix = [0, 0] + ase_ready_opcode = True + case _: + raise ValueError("Unexpected opcode ", target_opcode) + pre = { TestAddress: Account( balance=1000000000000000000000, nonce=1, ), - Address(0x100): Account( + address_caller: Account( code=( - Op.MSTORE(0, Op.PUSH32(address_bytes)) - + Op.SSTORE(ID_EXTCALL, Op.CALL(50000, ADDRESS_EXTCALL, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_CALL, Op.CALL(50000, ADDRESS_CALL, 0, 0, 32, 0, 0)) - + Op.SSTORE( - ID_EXTDELEGATECALL, Op.CALL(50000, ADDRESS_EXTDELEGATECALL, 0, 0, 32, 0, 0) - ) - + Op.SSTORE(ID_DELEGATECALL, Op.CALL(50000, ADDRESS_DELEGATECALL, 0, 0, 32, 0, 0)) + Op.MSTORE(0, Op.PUSH32(target_address)) + Op.SSTORE( - ID_EXTSTATICCALL, Op.CALL(50000, ADDRESS_EXTSTATICCALL, 0, 0, 32, 0, 0) + slot_top_level_call_status, + Op.CALL(50000, address_target, 0, 0, 32, 0, 0), ) - + Op.SSTORE(ID_STATICCALL, Op.CALL(50000, ADDRESS_STATICCALL, 0, 0, 32, 0, 0)) - + Op.SSTORE(ID_CALLCODE, Op.CALL(50000, ADDRESS_CALLCODE, 0, 0, 32, 0, 0)) + Op.STOP() ), nonce=1, ), - ADDRESS_EXTCALL: Account( - code=Container( - sections=[ - Section.Code( - code=Op.SSTORE(0, Op.EXTCALL(Op.CALLDATALOAD(0), 0, 0, 0)) - + Op.SSTORE(1, Op.RETURNDATALOAD(0)) - + Op.STOP, - code_inputs=0, - code_outputs=NON_RETURNING_SECTION, - max_stack_height=4, - ) - ], - ), - nonce=1, - ), - ADDRESS_CALL: Account( - code=Op.SSTORE(0, Op.CALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0, 0)) - + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) - + Op.SSTORE(1, Op.MLOAD(0)) - + Op.STOP, - nonce=1, - ), - ADDRESS_EXTDELEGATECALL: Account( + address_target: Account( code=Container( sections=[ Section.Code( - code=Op.SSTORE(0, Op.EXTDELEGATECALL(Op.CALLDATALOAD(0), 0, 0)) - + Op.SSTORE(1, Op.RETURNDATALOAD(0)) + code=Op.SSTORE( + slot_target_call_status, + target_opcode(Op.CALLDATALOAD(0), *call_suffix), + ) + + Op.SSTORE(slot_target_returndata, Op.RETURNDATALOAD(0)) + Op.STOP, code_inputs=0, code_outputs=NON_RETURNING_SECTION, - max_stack_height=3, + max_stack_height=1 + len(call_suffix), ) ], - ), - nonce=1, - ), - ADDRESS_DELEGATECALL: Account( - code=Op.SSTORE(0, Op.DELEGATECALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0)) - + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) - + Op.SSTORE(1, Op.MLOAD(0)) - + Op.STOP, - nonce=1, - ), - ADDRESS_EXTSTATICCALL: Account( - code=Container( - sections=[ - Section.Code( - code=Op.SSTORE(0, Op.EXTSTATICCALL(Op.CALLDATALOAD(0), 0, 0)) - + Op.SSTORE(1, Op.RETURNDATALOAD(0)) - + Op.STOP, - code_inputs=0, - code_outputs=NON_RETURNING_SECTION, - max_stack_height=3, - ) - ], - ), - nonce=1, - ), - ADDRESS_STATICCALL: Account( - code=Op.SSTORE(0, Op.STATICCALL(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0)) - + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) - + Op.SSTORE(1, Op.MLOAD(0)) - + Op.STOP, - nonce=1, - ), - ADDRESS_CALLCODE: Account( - code=Op.SSTORE(0, Op.CALLCODE(Op.GAS, Op.CALLDATALOAD(0), 0, 0, 0, 0, 0)) - + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) - + Op.SSTORE(1, Op.MLOAD(0)) + ) + if ase_ready_opcode + else Op.SSTORE( + slot_target_call_status, + target_opcode(Op.GAS, Op.CALLDATALOAD(0), *call_suffix), + ) + + Op.SSTORE(slot_target_returndata, Op.RETURNDATALOAD(0)) + Op.STOP, nonce=1, ), } - - stripped_address = address_bytes[-20:] if ase_address else target_address - post = { - Address(0x100): Account( - storage={ - ID_CALL: 1, - ID_DELEGATECALL: 1, - ID_STATICCALL: 1, - ID_CALLCODE: 1, - } - if ase_address - else { - ID_EXTCALL: 1, - ID_CALL: 1, - ID_EXTDELEGATECALL: 1, - ID_DELEGATECALL: 1, - ID_EXTSTATICCALL: 1, - ID_STATICCALL: 1, - ID_CALLCODE: 1, - } - ) - } match target_account_type: case "empty": # add no account pass case "EOA": pre[Address(stripped_address)] = Account(code="", balance=10**18, nonce=9) - case "Contract": + case "LegacyContract": pre[Address(stripped_address)] = Account( - code=Op.MSTORE(0, Op.ADDRESS) + Op.RETURN(0, 32), balance=0, nonce=0 + code=Op.MSTORE(0, Op.ADDRESS) + Op.RETURN(0, 32), + balance=0, + nonce=0, ) - # For EOF variants the EXT*CALL reverts, so no storage updates for ASE address - post[ADDRESS_EXTCALL] = Account(storage={} if ase_address else {1: stripped_address}) - post[ADDRESS_CALL] = Account(storage={0: 1, 1: stripped_address}) - # EXTDELEGATECALL fails when calling legacy, so no stripped address - post[ADDRESS_EXTDELEGATECALL] = Account(storage={} if ase_address else {0: 1}) - post[ADDRESS_DELEGATECALL] = Account(storage={0: 1, 1: ADDRESS_DELEGATECALL}) - post[ADDRESS_EXTSTATICCALL] = Account( - storage={} if ase_address else {1: stripped_address} + case "EOFContract": + pre[Address(stripped_address)] = Account( + code=Container( + sections=[ + Section.Code( + code=Op.MSTORE(0, Op.ADDRESS) + Op.RETURN(0, 32), + code_outputs=NON_RETURNING_SECTION, + max_stack_height=2, + ) + ], + ), + balance=0, + nonce=0, ) - post[ADDRESS_STATICCALL] = Account(storage={0: 1, 1: stripped_address}) - post[ADDRESS_CALLCODE] = Account(storage={0: 1, 1: ADDRESS_CALLCODE}) - case _: - raise ValueError("Unknown account type: " + target_account_type) + + target_storage = {} + match target_account_type: + case "empty": + target_storage[slot_target_call_status] = 0 if ase_ready_opcode else 1 + case "EOA": + pre[Address(stripped_address)] = Account(code="", balance=10**18, nonce=9) + target_storage[slot_target_call_status] = 0 if ase_ready_opcode else 1 + case "LegacyContract" | "EOFContract": + match target_opcode: + case Op.CALL | Op.STATICCALL: + target_storage[slot_target_call_status] = value_legacy_success + # CALL and STATICCALL call will call the stripped address + target_storage[slot_target_returndata] = stripped_address + case Op.CALLCODE | Op.DELEGATECALL: + target_storage[slot_target_call_status] = value_legacy_success + # CALLCODE and DELEGATECALL call will call the stripped address + # but will change the sender to self + target_storage[slot_target_returndata] = address_target + case Op.EXTCALL | Op.EXTSTATICCALL: + target_storage[slot_target_call_status] = value_eof_success + # EXTCALL and EXTSTATICCALL will fault if calling an ASE address + target_storage[slot_target_returndata] = 0 if ase_address else stripped_address + case Op.EXTDELEGATECALL: + if not ase_address and target_account_type == "LegacyContract": + # If calling a legacy contract EXTDELEGATECALL fails + target_storage[slot_target_call_status] = value_eof_fail + target_storage[slot_target_returndata] = 0 + else: + target_storage[slot_target_call_status] = value_eof_success + # EXTDELEGATECALL will fault if calling an ASE address + target_storage[slot_target_returndata] = ( + 0 if ase_address else address_target + ) + + post = { + address_caller: Account( + storage={slot_top_level_call_status: 0 if ase_ready_opcode and ase_address else 1} + ), + address_target: Account(storage=target_storage), + } tx = Transaction( nonce=1, - to=Address(0x100), + to=address_caller, gas_limit=50000000, gas_price=10, protected=False, From 97ed1e154fb8b28554fa8fe2b4e664d7f8d601a5 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Tue, 28 May 2024 16:50:22 -0600 Subject: [PATCH 10/14] tox fixes Signed-off-by: Danno Ferrin --- .../eip7069_extcall/test_address_space_extension.py | 2 +- whitelist.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py index 3cdc689366..028faed52e 100644 --- a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py +++ b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py @@ -168,7 +168,7 @@ def test_address_space_extension( nonce=0, ) - target_storage = {} + target_storage: dict[int, int | bytes | Address] = {} match target_account_type: case "empty": target_storage[slot_target_call_status] = 0 if ase_ready_opcode else 1 diff --git a/whitelist.txt b/whitelist.txt index 02c6ab53cb..1b61b9d0a3 100644 --- a/whitelist.txt +++ b/whitelist.txt @@ -283,6 +283,7 @@ reentrant repo repo's repos +returndata returndatacopy returndataload returndatasize From 4754460c2246e8995fb2a21b00620417865e1984 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Tue, 4 Jun 2024 14:39:44 -0600 Subject: [PATCH 11/14] remove RETURNDATALOAD from ASE tests Remove RETURNDATALOAD from ASE tests, to be moved to a different test Signed-off-by: Danno Ferrin --- .../eip7069_extcall/test_address_space_extension.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py index 028faed52e..5a8593345a 100644 --- a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py +++ b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py @@ -17,7 +17,7 @@ from ethereum_test_tools.eof.v1.constants import NON_RETURNING_SECTION from ethereum_test_tools.vm.opcode import Opcodes as Op -from .spec import EOF_FORK_NAME +from .. import EOF_FORK_NAME REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7069.md" REFERENCE_SPEC_VERSION = "1795943aeacc86131d5ab6bb3d65824b3b1d4cad" @@ -123,7 +123,8 @@ def test_address_space_extension( slot_target_call_status, target_opcode(Op.CALLDATALOAD(0), *call_suffix), ) - + Op.SSTORE(slot_target_returndata, Op.RETURNDATALOAD(0)) + + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + + Op.SSTORE(slot_target_returndata, Op.MLOAD(0)) + Op.STOP, code_inputs=0, code_outputs=NON_RETURNING_SECTION, @@ -136,7 +137,8 @@ def test_address_space_extension( slot_target_call_status, target_opcode(Op.GAS, Op.CALLDATALOAD(0), *call_suffix), ) - + Op.SSTORE(slot_target_returndata, Op.RETURNDATALOAD(0)) + + Op.RETURNDATACOPY(0, 0, Op.RETURNDATASIZE) + + Op.SSTORE(slot_target_returndata, Op.MLOAD(0)) + Op.STOP, nonce=1, ), @@ -170,10 +172,7 @@ def test_address_space_extension( target_storage: dict[int, int | bytes | Address] = {} match target_account_type: - case "empty": - target_storage[slot_target_call_status] = 0 if ase_ready_opcode else 1 - case "EOA": - pre[Address(stripped_address)] = Account(code="", balance=10**18, nonce=9) + case "empty" | "EOA": target_storage[slot_target_call_status] = 0 if ase_ready_opcode else 1 case "LegacyContract" | "EOFContract": match target_opcode: From 338ff1650ad8df6b78499f4d83da809629c8542c Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Tue, 4 Jun 2024 14:53:32 -0600 Subject: [PATCH 12/14] reviewer comments Signed-off-by: Danno Ferrin --- .../eip7692_eof_v1/eip7069_extcall/spec.py | 8 +++- .../test_address_space_extension.py | 44 ++++++++++--------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/tests/prague/eip7692_eof_v1/eip7069_extcall/spec.py b/tests/prague/eip7692_eof_v1/eip7069_extcall/spec.py index 7bf760554f..fa5023b8f4 100644 --- a/tests/prague/eip7692_eof_v1/eip7069_extcall/spec.py +++ b/tests/prague/eip7692_eof_v1/eip7069_extcall/spec.py @@ -2,4 +2,10 @@ EOF V1 Constants used throughout all tests """ -EOF_FORK_NAME = "Prague" +EOF_FORK_NAME = "CancunEIP7692" + +CALL_FAILURE = 0 +CALL_SUCCESS = 1 +EXTCALL_SUCCESS = 0 +EXTCALL_FAILURE = 1 +EXTCALL_REVERT = 2 diff --git a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py index 5a8593345a..589433c36b 100644 --- a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py +++ b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py @@ -18,26 +18,22 @@ from ethereum_test_tools.vm.opcode import Opcodes as Op from .. import EOF_FORK_NAME +from .spec import CALL_SUCCESS, EXTCALL_FAILURE, EXTCALL_SUCCESS REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7069.md" REFERENCE_SPEC_VERSION = "1795943aeacc86131d5ab6bb3d65824b3b1d4cad" pytestmark = pytest.mark.valid_from(EOF_FORK_NAME) - _address_allocation = itertools.count(0x10000) +address_entry_point = Address(next(_address_allocation)) address_caller = Address(next(_address_allocation)) -address_target = Address(next(_address_allocation)) _slot = itertools.count(1) slot_top_level_call_status = next(_slot) slot_target_call_status = next(_slot) slot_target_returndata = next(_slot) -value_legacy_success = 1 -value_eof_success = 0 -value_eof_fail = 1 - @pytest.mark.parametrize( "target_address", @@ -104,18 +100,18 @@ def test_address_space_extension( balance=1000000000000000000000, nonce=1, ), - address_caller: Account( + address_entry_point: Account( code=( Op.MSTORE(0, Op.PUSH32(target_address)) + Op.SSTORE( slot_top_level_call_status, - Op.CALL(50000, address_target, 0, 0, 32, 0, 0), + Op.CALL(50000, address_caller, 0, 0, 32, 0, 0), ) + Op.STOP() ), nonce=1, ), - address_target: Account( + address_caller: Account( code=Container( sections=[ Section.Code( @@ -173,44 +169,50 @@ def test_address_space_extension( target_storage: dict[int, int | bytes | Address] = {} match target_account_type: case "empty" | "EOA": - target_storage[slot_target_call_status] = 0 if ase_ready_opcode else 1 + target_storage[slot_target_call_status] = ( + EXTCALL_SUCCESS if ase_ready_opcode else CALL_SUCCESS + ) case "LegacyContract" | "EOFContract": match target_opcode: case Op.CALL | Op.STATICCALL: - target_storage[slot_target_call_status] = value_legacy_success + target_storage[slot_target_call_status] = CALL_SUCCESS # CALL and STATICCALL call will call the stripped address target_storage[slot_target_returndata] = stripped_address case Op.CALLCODE | Op.DELEGATECALL: - target_storage[slot_target_call_status] = value_legacy_success + target_storage[slot_target_call_status] = CALL_SUCCESS # CALLCODE and DELEGATECALL call will call the stripped address # but will change the sender to self - target_storage[slot_target_returndata] = address_target + target_storage[slot_target_returndata] = address_caller case Op.EXTCALL | Op.EXTSTATICCALL: - target_storage[slot_target_call_status] = value_eof_success + target_storage[slot_target_call_status] = EXTCALL_SUCCESS # EXTCALL and EXTSTATICCALL will fault if calling an ASE address target_storage[slot_target_returndata] = 0 if ase_address else stripped_address case Op.EXTDELEGATECALL: if not ase_address and target_account_type == "LegacyContract": # If calling a legacy contract EXTDELEGATECALL fails - target_storage[slot_target_call_status] = value_eof_fail + target_storage[slot_target_call_status] = EXTCALL_FAILURE target_storage[slot_target_returndata] = 0 else: - target_storage[slot_target_call_status] = value_eof_success + target_storage[slot_target_call_status] = EXTCALL_SUCCESS # EXTDELEGATECALL will fault if calling an ASE address target_storage[slot_target_returndata] = ( - 0 if ase_address else address_target + 0 if ase_address else address_caller ) post = { - address_caller: Account( - storage={slot_top_level_call_status: 0 if ase_ready_opcode and ase_address else 1} + address_entry_point: Account( + storage={ + slot_top_level_call_status: EXTCALL_SUCCESS + if ase_ready_opcode and ase_address + else CALL_SUCCESS + } ), - address_target: Account(storage=target_storage), + address_caller: Account(storage=target_storage), } tx = Transaction( nonce=1, - to=address_caller, + to=address_entry_point, gas_limit=50000000, gas_price=10, protected=False, From 95e5bc06338f929fa062d5b679f04d04bbdbaa87 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Thu, 6 Jun 2024 16:34:01 -0600 Subject: [PATCH 13/14] Reviewer comments Signed-off-by: Danno Ferrin --- .../eip7692_eof_v1/eip7069_extcall/spec.py | 4 +- .../test_address_space_extension.py | 66 ++++++++++++------- whitelist.txt | 2 +- 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/tests/prague/eip7692_eof_v1/eip7069_extcall/spec.py b/tests/prague/eip7692_eof_v1/eip7069_extcall/spec.py index fa5023b8f4..d0af7ecccb 100644 --- a/tests/prague/eip7692_eof_v1/eip7069_extcall/spec.py +++ b/tests/prague/eip7692_eof_v1/eip7069_extcall/spec.py @@ -7,5 +7,5 @@ CALL_FAILURE = 0 CALL_SUCCESS = 1 EXTCALL_SUCCESS = 0 -EXTCALL_FAILURE = 1 -EXTCALL_REVERT = 2 +EXTCALL_REVERT = 1 +EXTCALL_FAILED = 2 diff --git a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py index 589433c36b..188177291f 100644 --- a/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py +++ b/tests/prague/eip7692_eof_v1/eip7069_extcall/test_address_space_extension.py @@ -14,11 +14,10 @@ Transaction, ) from ethereum_test_tools.eof.v1 import Container, Section -from ethereum_test_tools.eof.v1.constants import NON_RETURNING_SECTION from ethereum_test_tools.vm.opcode import Opcodes as Op from .. import EOF_FORK_NAME -from .spec import CALL_SUCCESS, EXTCALL_FAILURE, EXTCALL_SUCCESS +from .spec import CALL_SUCCESS, EXTCALL_REVERT, EXTCALL_SUCCESS REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7069.md" REFERENCE_SPEC_VERSION = "1795943aeacc86131d5ab6bb3d65824b3b1d4cad" @@ -34,6 +33,8 @@ slot_target_call_status = next(_slot) slot_target_returndata = next(_slot) +value_exceptional_abort_canary = 0x1984 + @pytest.mark.parametrize( "target_address", @@ -110,6 +111,9 @@ def test_address_space_extension( + Op.STOP() ), nonce=1, + storage={ + slot_top_level_call_status: value_exceptional_abort_canary, + }, ), address_caller: Account( code=Container( @@ -123,7 +127,6 @@ def test_address_space_extension( + Op.SSTORE(slot_target_returndata, Op.MLOAD(0)) + Op.STOP, code_inputs=0, - code_outputs=NON_RETURNING_SECTION, max_stack_height=1 + len(call_suffix), ) ], @@ -137,6 +140,10 @@ def test_address_space_extension( + Op.SSTORE(slot_target_returndata, Op.MLOAD(0)) + Op.STOP, nonce=1, + storage={ + slot_target_call_status: value_exceptional_abort_canary, + slot_target_returndata: value_exceptional_abort_canary, + }, ), } match target_account_type: @@ -157,7 +164,6 @@ def test_address_space_extension( sections=[ Section.Code( code=Op.MSTORE(0, Op.ADDRESS) + Op.RETURN(0, 32), - code_outputs=NON_RETURNING_SECTION, max_stack_height=2, ) ], @@ -166,38 +172,50 @@ def test_address_space_extension( nonce=0, ) - target_storage: dict[int, int | bytes | Address] = {} + caller_storage: dict[int, int | bytes | Address] = {} match target_account_type: case "empty" | "EOA": - target_storage[slot_target_call_status] = ( - EXTCALL_SUCCESS if ase_ready_opcode else CALL_SUCCESS - ) + if ase_address and ase_ready_opcode: + caller_storage[slot_target_call_status] = value_exceptional_abort_canary + caller_storage[slot_target_returndata] = value_exceptional_abort_canary + elif target_opcode == Op.EXTDELEGATECALL: + caller_storage[slot_target_call_status] = EXTCALL_REVERT + caller_storage[slot_target_returndata] = 0 + else: + caller_storage[slot_target_call_status] = ( + EXTCALL_SUCCESS if ase_ready_opcode else CALL_SUCCESS + ) case "LegacyContract" | "EOFContract": match target_opcode: case Op.CALL | Op.STATICCALL: - target_storage[slot_target_call_status] = CALL_SUCCESS + caller_storage[slot_target_call_status] = CALL_SUCCESS # CALL and STATICCALL call will call the stripped address - target_storage[slot_target_returndata] = stripped_address + caller_storage[slot_target_returndata] = stripped_address case Op.CALLCODE | Op.DELEGATECALL: - target_storage[slot_target_call_status] = CALL_SUCCESS + caller_storage[slot_target_call_status] = CALL_SUCCESS # CALLCODE and DELEGATECALL call will call the stripped address # but will change the sender to self - target_storage[slot_target_returndata] = address_caller + caller_storage[slot_target_returndata] = address_caller case Op.EXTCALL | Op.EXTSTATICCALL: - target_storage[slot_target_call_status] = EXTCALL_SUCCESS # EXTCALL and EXTSTATICCALL will fault if calling an ASE address - target_storage[slot_target_returndata] = 0 if ase_address else stripped_address + if ase_address: + caller_storage[slot_target_call_status] = value_exceptional_abort_canary + caller_storage[slot_target_returndata] = value_exceptional_abort_canary + else: + caller_storage[slot_target_call_status] = EXTCALL_SUCCESS + caller_storage[slot_target_returndata] = stripped_address case Op.EXTDELEGATECALL: - if not ase_address and target_account_type == "LegacyContract": - # If calling a legacy contract EXTDELEGATECALL fails - target_storage[slot_target_call_status] = EXTCALL_FAILURE - target_storage[slot_target_returndata] = 0 + if ase_address: + caller_storage[slot_target_call_status] = value_exceptional_abort_canary + caller_storage[slot_target_returndata] = value_exceptional_abort_canary + elif target_account_type == "LegacyContract": + caller_storage[slot_target_call_status] = EXTCALL_REVERT + caller_storage[slot_target_returndata] = 0 else: - target_storage[slot_target_call_status] = EXTCALL_SUCCESS - # EXTDELEGATECALL will fault if calling an ASE address - target_storage[slot_target_returndata] = ( - 0 if ase_address else address_caller - ) + caller_storage[slot_target_call_status] = EXTCALL_SUCCESS + # EXTDELEGATECALL call will call the stripped address + # but will change the sender to self + caller_storage[slot_target_returndata] = address_caller post = { address_entry_point: Account( @@ -207,7 +225,7 @@ def test_address_space_extension( else CALL_SUCCESS } ), - address_caller: Account(storage=target_storage), + address_caller: Account(storage=caller_storage), } tx = Transaction( diff --git a/whitelist.txt b/whitelist.txt index 8e14a26bad..cfb87072fe 100644 --- a/whitelist.txt +++ b/whitelist.txt @@ -322,7 +322,7 @@ StateTestFiller staticcalled stExample str -streetsidesoftiware +streetsidesoftware subcall subclasscheck subdirectories From 8698b1fee3c90ab52069d344f450aaad38aaa754 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Thu, 6 Jun 2024 16:36:58 -0600 Subject: [PATCH 14/14] extreneous changes Signed-off-by: Danno Ferrin --- src/ethereum_test_tools/vm/opcode.py | 57 ++++++++++++---------------- whitelist.txt | 3 +- 2 files changed, 26 insertions(+), 34 deletions(-) diff --git a/src/ethereum_test_tools/vm/opcode.py b/src/ethereum_test_tools/vm/opcode.py index 316036c198..716d3c007e 100644 --- a/src/ethereum_test_tools/vm/opcode.py +++ b/src/ethereum_test_tools/vm/opcode.py @@ -5393,7 +5393,7 @@ class Opcodes(Opcode, Enum): Fork ---- - EOF Fork + Prague Gas ---- @@ -5406,35 +5406,6 @@ class Opcodes(Opcode, Enum): Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) """ - RETURNDATALOAD = Opcode(0xF7, popped_stack_items=1, pushed_stack_items=1) - """ - RETURNDATALOAD(offset) = returndata - ---- - - Description - ---- - Copies 32 bytes of return data onto the operand stack - - Inputs - ---- - - offset: The offset within the return data to start copying. There must be 32 byes of return - data at that address or an exceptional halt occurs. - - Outputs - ---- - - returndata: the 32 bytes of return data at the offset - - Fork - ---- - EOF Fork - - Gas - ---- - 3 - - Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) - """ - EXTDELEGATECALL = Opcode(0xF9, popped_stack_items=3, pushed_stack_items=1) """ EXTDELEGATECALL(target_address, input_offset, input_size) = address @@ -5460,7 +5431,7 @@ class Opcodes(Opcode, Enum): Fork ---- - EOF Fork + Prague Gas ---- @@ -5530,7 +5501,7 @@ class Opcodes(Opcode, Enum): Fork ---- - EOF Fork + Prague Gas ---- @@ -5540,6 +5511,28 @@ class Opcodes(Opcode, Enum): Source: [EIP-7069](https://eips.ethereum.org/EIPS/eip-7069) """ + RETURNDATALOAD = Opcode(0xF7, popped_stack_items=1) + """ + RETURNDATALOAD(offset) + ---- + + Description + ---- + Copy 32 bytes from returndata at offset onto the stack + + Inputs + ---- + - offset: byte offset in the return data from the last executed sub context to copy + + Fork + ---- + EOF + + Gas + ---- + 3 + """ + REVERT = Opcode(0xFD, popped_stack_items=2) """ REVERT(offset, size) diff --git a/whitelist.txt b/whitelist.txt index cfb87072fe..c35f9cbb5b 100644 --- a/whitelist.txt +++ b/whitelist.txt @@ -291,7 +291,6 @@ repo's repos returndata returndatacopy -returndataload returndatasize returncontract rlp @@ -620,7 +619,7 @@ tstore create create2 create3 -txcreate +create4 call callcode return