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): EIP-1014: Convert CREATE2 test from ethereum/tests #497

Merged
merged 7 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions converted-ethereum-tests.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
([#497](https://github.com/ethereum/execution-spec-tests/pull/497))
GeneralStateTests/stCreate2/call_outsize_then_create2_successful_then_returndatasize.json
GeneralStateTests/stCreate2/call_then_create2_successful_then_returndatasize.json

([#647](https://github.com/ethereum/execution-spec-tests/pull/647))
EOFTests/efValidation/EOF1_returncontract_invalid_.json
EOFTests/efValidation/EOF1_returncontract_valid_.json
Expand Down
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Test fixtures for use by clients are available for each release on the [Github r

### 🧪 Test Cases

- ✨ Port create2 return data test ([#497](https://github.com/ethereum/execution-spec-tests/pull/497)).
- ✨ Add tests for eof container's section bytes position smart fuzzing ([#592](https://github.com/ethereum/execution-spec-tests/pull/592)).
- ✨ Add `test_create_selfdestruct_same_tx_increased_nonce` which tests self-destructing a contract with a nonce > 1 ([#478](https://github.com/ethereum/execution-spec-tests/pull/478)).
- ✨ Add `test_double_kill` and `test_recreate` which test resurrection of accounts killed with `SELFDESTRUCT` ([#488](https://github.com/ethereum/execution-spec-tests/pull/488)).
Expand Down
25 changes: 25 additions & 0 deletions tests/constantinople/eip1014_create2/spec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""
Defines EIP-1014 specification constants and functions.
"""
from dataclasses import dataclass


@dataclass(frozen=True)
class ReferenceSpec:
"""
Defines the reference spec version and git path.
"""

git_path: str
version: str


ref_spec_1014 = ReferenceSpec("EIPS/eip-1014.md", "0a3c1015a07958523bb3ef48c2f230c9ba9605d9")


@dataclass(frozen=True)
class Spec:
"""
Parameters from the EIP-1014 specifications as defined at
https://eips.ethereum.org/EIPS/eip-1014
"""
135 changes: 135 additions & 0 deletions tests/constantinople/eip1014_create2/test_create_returndata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
"""
Return data management around create2
Port call_outsize_then_create2_successful_then_returndatasizeFiller.json test
Port call_then_create2_successful_then_returndatasizeFiller.json test
"""

import pytest
from ethereum.crypto.hash import keccak256

from ethereum_test_tools import Account, Alloc, Environment, StateTestFiller, Transaction
from ethereum_test_tools.vm.opcode import Opcodes as Op

from .spec import ref_spec_1014

REFERENCE_SPEC_GIT_PATH = ref_spec_1014.git_path
REFERENCE_SPEC_VERSION = ref_spec_1014.version


@pytest.mark.valid_from("Istanbul")
@pytest.mark.parametrize("call_return_size", [35, 32, 0])
@pytest.mark.parametrize("create_type", [Op.CREATE, Op.CREATE2])
@pytest.mark.parametrize("return_type", [Op.RETURN, Op.REVERT])
@pytest.mark.parametrize("return_type_in_create", [Op.RETURN, Op.REVERT])
def test_create2_return_data(
call_return_size: int,
create_type: Op,
return_type: Op,
return_type_in_create: Op,
pre: Alloc,
state_test: StateTestFiller,
):
"""
Validate that create2 return data does not interfere with previously existing memory
"""
# Storage vars
slot_returndatasize_before_create = 0
slot_returndatasize_after_create = 1
slot_return_data_hash_before_create = 2
slot_return_data_hash_after_create = 3
slot_code_worked = 4
slot_returndatacopy_before_create = 5
slot_returndatacopy_before_create_2 = 6
slot_returndatacopy_after_create = 7
slot_begin_memory_after_create = 8

# CREATE2 Initcode
create2_salt = 1
return_data_in_create = 0xFFFAFB
initcode = Op.MSTORE(0, return_data_in_create) + return_type_in_create(0, 32)
call_return_data_value = 0x1122334455667788991011121314151617181920212223242526272829303132
expected_call_return_data = int.to_bytes(call_return_data_value, 32, byteorder="big").ljust(
call_return_size, b"\0"
)[0:call_return_size]
expected_returndatacopy = expected_call_return_data[0:32]
empty_data = b""

address_call = pre.deploy_contract(
code=Op.MSTORE(0, call_return_data_value)
+ Op.MSTORE(32, 0xFFFFFFFF)
+ return_type(0, call_return_size),
storage={},
)
address_to = pre.deploy_contract(
balance=100_000_000,
code=Op.JUMPDEST()
+ Op.MSTORE(0x100, Op.CALLDATALOAD(0))
+ Op.CALL(0x0900000000, address_call, 0, 0, 0, 0, call_return_size)
#
#
+ Op.SSTORE(slot_returndatasize_before_create, Op.RETURNDATASIZE())
+ Op.RETURNDATACOPY(0x200, 0, call_return_size)
+ Op.SSTORE(slot_returndatacopy_before_create, Op.MLOAD(0x200))
+ Op.SSTORE(slot_returndatacopy_before_create_2, Op.MLOAD(0x220))
+ Op.SSTORE(slot_return_data_hash_before_create, Op.SHA3(0, call_return_size))
#
#
+ create_type(offset=0x100, size=Op.CALLDATASIZE(), salt=create2_salt)
+ Op.SSTORE(slot_returndatasize_after_create, Op.RETURNDATASIZE())
+ Op.RETURNDATACOPY(0x300, 0, Op.RETURNDATASIZE())
+ Op.SSTORE(slot_returndatacopy_after_create, Op.MLOAD(0x300))
+ Op.SSTORE(slot_return_data_hash_after_create, Op.SHA3(0x300, Op.RETURNDATASIZE()))
+ Op.SSTORE(slot_begin_memory_after_create, Op.MLOAD(0))
+ Op.SSTORE(slot_code_worked, 1)
+ Op.STOP(),
storage={
slot_returndatasize_before_create: 0xFF,
slot_returndatasize_after_create: 0xFF,
slot_return_data_hash_before_create: 0xFF,
slot_return_data_hash_after_create: 0xFF,
slot_returndatacopy_before_create: 0xFF,
slot_returndatacopy_before_create_2: 0xFF,
slot_begin_memory_after_create: 0xFF,
slot_begin_memory_after_create: 0xFF,
},
)

post = {
address_to: Account(
storage={
slot_code_worked: 1,
slot_returndatacopy_before_create: expected_returndatacopy,
slot_returndatacopy_before_create_2: 0,
#
# the actual bytes returned by returndatacopy opcode after create
slot_returndatacopy_after_create: return_data_in_create
if return_type_in_create == Op.REVERT
else 0,
slot_returndatasize_before_create: call_return_size,
#
# return datasize value after create
slot_returndatasize_after_create: 0x20
if return_type_in_create == Op.REVERT
else 0,
#
slot_return_data_hash_before_create: keccak256(expected_call_return_data),
slot_return_data_hash_after_create: keccak256(empty_data)
if return_type_in_create == Op.RETURN
else keccak256(int.to_bytes(return_data_in_create, 32, byteorder="big")),
#
# check that create 2 didn't mess up with initial memory space declared for return
slot_begin_memory_after_create: expected_returndatacopy,
} # type: ignore
)
}

tx = Transaction(
sender=pre.fund_eoa(),
to=address_to,
protected=False,
data=initcode,
gas_limit=0x0A00000000,
value=0,
) # type: ignore

state_test(env=Environment(), pre=pre, post=post, tx=tx)
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
from ethereum_test_tools import Opcodes as Op
from ethereum_test_tools import Transaction, Yul, compute_create2_address

from .spec import ref_spec_1014

REFERENCE_SPEC_GIT_PATH = ref_spec_1014.git_path
REFERENCE_SPEC_VERSION = ref_spec_1014.version


@pytest.mark.parametrize("recreate_on_separate_block", [True, False])
@pytest.mark.valid_from("Constantinople")
Expand Down
4 changes: 3 additions & 1 deletion tests/homestead/coverage/test_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ def test_coverage(
+ Op.PUSH2(0x0102)
+ Op.PUSH3(0x010203)
+ Op.PUSH4(0x01020304)
+ Op.POP(0x01),
+ Op.POP(0x01)
# lllc tests insert codecopy when using lll(seq())
+ Op.CODECOPY(0, 16, 4),
storage={},
)
address_to = pre.deploy_contract(
Expand Down
Loading