Skip to content

Commit

Permalink
new(tests): EOF - EIP-7620: EOFCREATE and RETURNDATA tests (#532)
Browse files Browse the repository at this point in the history
* EOFCREATE and RETURNDATA tests

Tests covering EOFCREATE and RETURNDATA, ported from evmone

Signed-off-by: Danno Ferrin <[email protected]>

* fix imports

Signed-off-by: Danno Ferrin <[email protected]>

* review requested changes

add canary value

Signed-off-by: Danno Ferrin <[email protected]>

* reviewer change requests

Change all magic numbers for storage into variables.

Signed-off-by: Danno Ferrin <[email protected]>

* code formatting

Signed-off-by: Danno Ferrin <[email protected]>

* fix(fw): minor nit

* refactor(tests): EIP-7620: fixes

---------

Signed-off-by: Danno Ferrin <[email protected]>
Co-authored-by: Mario Vega <[email protected]>
  • Loading branch information
shemnon and marioevz authored May 29, 2024
1 parent 98cb3f0 commit a4b68e8
Show file tree
Hide file tree
Showing 13 changed files with 1,328 additions and 25 deletions.
4 changes: 2 additions & 2 deletions src/ethereum_test_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
add_kzg_version,
ceiling_division,
compute_create2_address,
compute_create3_address,
compute_create_address,
compute_eofcreate_address,
copy_opcode_cost,
cost_memory_bytes,
eip_2028_transaction_data_cost,
Expand Down Expand Up @@ -119,7 +119,7 @@
"ceiling_division",
"compute_create_address",
"compute_create2_address",
"compute_create3_address",
"compute_eofcreate_address",
"copy_opcode_cost",
"cost_memory_bytes",
"eip_2028_transaction_data_cost",
Expand Down
4 changes: 2 additions & 2 deletions src/ethereum_test_tools/common/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
add_kzg_version,
ceiling_division,
compute_create2_address,
compute_create3_address,
compute_create_address,
compute_eofcreate_address,
copy_opcode_cost,
cost_memory_bytes,
eip_2028_transaction_data_cost,
Expand Down Expand Up @@ -83,7 +83,7 @@
"ceiling_division",
"compute_create_address",
"compute_create2_address",
"compute_create3_address",
"compute_eofcreate_address",
"copy_opcode_cost",
"cost_memory_bytes",
"eip_2028_transaction_data_cost",
Expand Down
5 changes: 2 additions & 3 deletions src/ethereum_test_tools/common/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,13 @@ def copy_opcode_cost(length: int) -> int:
return 3 + (ceiling_division(length, 32) * 3) + cost_memory_bytes(length, 0)


def compute_create3_address(
def compute_eofcreate_address(
address: FixedSizeBytesConvertible,
salt: FixedSizeBytesConvertible,
init_container: BytesConvertible,
) -> Address:
"""
Compute address of the resulting contract created using the `CREATE3`
opcode.
Compute address of the resulting contract created using the `EOFCREATE` opcode.
"""
hash = keccak256(b"\xff" + Address(address) + Hash(salt) + keccak256(Bytes(init_container)))
return Address(hash[-20:])
Expand Down
24 changes: 10 additions & 14 deletions src/ethereum_test_tools/eof/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,34 +441,30 @@ def init_container(self) -> Container:
"""
return Container(
sections=[
Section(
kind=SectionKind.CODE,
data=Op.RETURNCONTRACT(0, 0, 0),
Section.Code(
code=Op.RETURNCONTRACT[0](0, 0),
max_stack_height=2,
),
Section(
kind=SectionKind.CONTAINER,
data=bytes(self.deploy_container),
Section.Container(
container=self.deploy_container,
),
],
)

@cached_property
def bytecode(self) -> bytes:
"""
Generate legacy initcode that inits a contract with the specified code.
The initcode can be padded to a specified length for testing purposes.
Generate an EOF container performs `EOFCREATE` with the specified code.
"""
initcode = Container(
sections=[
Section(
data=Op.CREATE3(0, 0, 0, 0, len(self.deploy_container)) + Op.STOP(),
kind=SectionKind.CODE,
Section.Code(
# TODO: Pass calldata
code=Op.EOFCREATE[0](0, 0, 0, 0) + Op.STOP(),
max_stack_height=4,
),
Section(
kind=SectionKind.CONTAINER,
data=self.init_container,
Section.Container(
container=self.init_container,
),
]
)
Expand Down
4 changes: 2 additions & 2 deletions src/ethereum_test_tools/vm/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -5091,11 +5091,11 @@ class Opcodes(Opcode, Enum):
"""

CREATE3 = Opcode(0xEC, popped_stack_items=4, pushed_stack_items=1, data_portion_length=1)
EOFCREATE = Opcode(0xEC, popped_stack_items=4, pushed_stack_items=1, data_portion_length=1)
"""
!!! Note: This opcode is under development
CREATE3()
EOFCREATE[initcontainer_index](value, salt, input_offset, input_size)
----
Description
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
EOFTestFiller,
TestAddress,
Transaction,
compute_create3_address,
compute_eofcreate_address,
)
from ethereum_test_tools.eof.v1 import Container, Initcode

Expand Down Expand Up @@ -103,7 +103,7 @@ def post( # noqa: D103
container: Container,
create3_opcode_contract_address: str,
) -> Dict[Address, Account]:
create_opcode_created_contract_address = compute_create3_address(
create_opcode_created_contract_address = compute_eofcreate_address(
create3_opcode_contract_address,
0,
bytes(create3_init_container.init_container),
Expand Down
14 changes: 14 additions & 0 deletions tests/prague/eip7692_eof_v1/eip7620_eof_create/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""
EOFCREATE, RETURNCONTRACT, and container tests
evmone tests not ported
create_tx_with_eof_initcode - This calls it invalid, it is now the way to add EOF contacts to state
eofcreate_extcall_returncontract - per the new initcode mode tests you cannot have RETURNCONTRACT
in a deployed contract
eofcreate_dataloadn_referring_to_auxdata - covered by
tests.prague.eip7480_data_section.test_data_opcodes.test_data_section_succeed
eofcreate_initcontainer_return - RETURN is banned in initcode containers
eofcreate_initcontainer_stop - STOP is banned in initcode containers
All TXCREATE tests - TXCREATE has been removed from Prague
"""
88 changes: 88 additions & 0 deletions tests/prague/eip7692_eof_v1/eip7620_eof_create/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
"""
A collection of contracts used in 7620 EOF tests
"""
import itertools

from ethereum_test_tools import Address
from ethereum_test_tools import Opcodes as Op
from ethereum_test_tools import Transaction
from ethereum_test_tools.eof.v1 import Container, Section
from ethereum_test_tools.eof.v1.constants import NON_RETURNING_SECTION

"""Storage addresses for common testing fields"""
_slot = itertools.count()
next(_slot) # don't use slot 0
slot_code_worked = next(_slot)
slot_code_should_fail = next(_slot)
slot_create_address = next(_slot)
slot_calldata = next(_slot)
slot_call_result = next(_slot)
slot_returndata = next(_slot)
slot_returndata_size = next(_slot)

slot_last_slot = next(_slot)

value_code_worked = 0x2015
value_canary_should_not_change = 0x2019
value_canary_to_be_overwritten = 0x2009
value_create_failed = 0
value_call_result_success = 0

smallest_runtime_subcontainer = Container(
name="Runtime Subcontainer",
sections=[
Section.Code(
code=Op.STOP, code_inputs=0, code_outputs=NON_RETURNING_SECTION, max_stack_height=0
)
],
)

smallest_initcode_subcontainer = Container(
name="Initcode Subcontainer",
sections=[
Section.Code(
code=Op.RETURNCONTRACT[0](0, 0),
code_inputs=0,
code_outputs=NON_RETURNING_SECTION,
max_stack_height=2,
),
Section.Container(container=smallest_runtime_subcontainer),
],
)


def fixed_address(index: int) -> Address:
"""
Returns an determinstic address for testing
Parameters
----------
index - how foar off of the initial to create the address
Returns
-------
An address, unique per index and human friendly for testing
"""
return Address(0x7E570000 + index)


default_address = fixed_address(0)


def simple_transaction(
target: Address = default_address, payload: bytes = b"", gas_limit: int = 10_000_000
):
"""
Creates a simple transaction
Parameters
----------
target the target address, defaults to 0x100
payload the payload, defauls to empty
Returns
-------
a transaction instance that can be passed into state_tests
"""
return Transaction(
nonce=1, to=target, gas_limit=gas_limit, gas_price=10, protected=False, data=payload
)
5 changes: 5 additions & 0 deletions tests/prague/eip7692_eof_v1/eip7620_eof_create/spec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""
EOF V1 Constants used throughout all tests
"""

EOF_FORK_NAME = "Prague"
Loading

0 comments on commit a4b68e8

Please sign in to comment.