Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new(tests): EOF - EIP-7620: EOFCREATE and RETURNDATA tests #532

Merged
merged 10 commits into from
May 29, 2024
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
Loading