Skip to content

Commit

Permalink
new(tests): EIP-7069: Different RETURNDATACOPY oob
Browse files Browse the repository at this point in the history
  • Loading branch information
pdobacz committed Jun 10, 2024
1 parent 5c590c6 commit 70c5447
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""
EOF tests for EIP-7069 RETURNDATACOPY changes
"""
11 changes: 11 additions & 0 deletions tests/prague/eip7692_eof_v1/eip7069_returndatacopy/spec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""
EOF V1 Constants used throughout all tests
"""

EOF_FORK_NAME = "CancunEIP7692"

CALL_FAILURE = 0
CALL_SUCCESS = 1
EXTCALL_SUCCESS = 0
EXTCALL_REVERT = 1
EXTCALL_FAILED = 2
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
"""
RETURNDATACOPY tests covering changes in behavior in EOF.
"""
import itertools

import pytest

from ethereum_test_tools import Account, StateTestFiller
from ethereum_test_tools.common.base_types import Address
from ethereum_test_tools.common.constants import TestAddress
from ethereum_test_tools.common.types import Environment, Transaction
from ethereum_test_tools.eof.v1 import Container, Section
from ethereum_test_tools.vm.opcode import Opcodes as Op

from .. import EOF_FORK_NAME
from .spec import CALL_FAILURE, CALL_SUCCESS, EXTCALL_FAILED, EXTCALL_SUCCESS

REFERENCE_SPEC_GIT_PATH = "EIPS/eip-7069.md"
REFERENCE_SPEC_VERSION = "73f68e76dd92486d13e27375cbb468a2be445a9f"

pytestmark = pytest.mark.valid_from(EOF_FORK_NAME)

_slot = itertools.count(1)
slot_eof_target_call_status = next(_slot)
slot_legacy_target_call_status = next(_slot)
slot_eof_target_returndata = next(_slot)
slot_eof_target_returndatasize = next(_slot)
slot_legacy_target_returndatasize = next(_slot)

_address_allocation = itertools.count(0x10000)
address_entry_point = Address(next(_address_allocation))
address_callee_eof = Address(next(_address_allocation))
address_callee_legacy = Address(next(_address_allocation))

pre_storage = {
slot_eof_target_call_status: "0xdd",
slot_eof_target_returndata: "0xdd",
slot_eof_target_returndatasize: "0xdd",
slot_legacy_target_call_status: "0xdd",
slot_legacy_target_returndatasize: "0xdd",
}

# Both codes below make an OOB (out-of-bounds) RETURNDATACOPY of one byte,
# which they then attempt to return (Legacy should exceptionally halt on RETURNDATACOPY).
code_eof_oob_returndatacopy = Container(
sections=[
Section.Code(
code=Op.RETURNDATACOPY(0, 0, 1) + Op.RETURN(0, 1),
max_stack_height=3,
)
]
)
code_legacy_oob_returndatacopy = Op.RETURNDATACOPY(0, 0, 1) + Op.RETURN(0, 1)


@pytest.mark.parametrize("top_level", ("LegacyContract", "EOFContract"), ids=lambda x: x)
def test_returndatacopy_oob(
state_test: StateTestFiller,
top_level: str,
):
"""Test RETURNDATACOPY correct oob behavior"""
env = Environment()

address_entry_point = Address(0x100)
address_callee_eof = Address(0x200)
address_callee_legacy = Address(0x300)

pre = {
address_entry_point: Account(
code=Op.SSTORE(
slot_eof_target_call_status, Op.CALL(Op.GAS, address_callee_eof, 0, 0, 0, 0, 0)
)
+ Op.SSTORE(slot_eof_target_returndatasize, Op.RETURNDATASIZE)
+ Op.SSTORE(slot_eof_target_returndata, Op.RETURNDATACOPY(0, 0, 1) + Op.MLOAD(0))
+ Op.SSTORE(
slot_legacy_target_call_status,
Op.CALL(Op.GAS, Address(address_callee_legacy), 0, 0, 0, 0, 0),
)
+ Op.SSTORE(slot_legacy_target_returndatasize, Op.RETURNDATASIZE)
if top_level == "LegacyContract"
else Container(
sections=[
Section.Code(
code=Op.SSTORE(
slot_eof_target_call_status, Op.EXTCALL(address_callee_eof, 0, 0, 0)
)
+ Op.SSTORE(slot_eof_target_returndatasize, Op.RETURNDATASIZE)
+ Op.SSTORE(
slot_eof_target_returndata, Op.RETURNDATACOPY(0, 0, 1) + Op.MLOAD(0)
)
+ Op.SSTORE(
slot_legacy_target_call_status,
Op.EXTCALL(Address(address_callee_legacy), 0, 0, 0),
)
+ Op.SSTORE(slot_legacy_target_returndatasize, Op.RETURNDATASIZE)
+ Op.STOP,
max_stack_height=4,
),
],
),
storage=pre_storage,
),
address_callee_eof: Account(code=code_eof_oob_returndatacopy),
address_callee_legacy: Account(code=code_legacy_oob_returndatacopy),
TestAddress: Account(balance=1_000_000_000_000_000_000_000, nonce=0),
}

tx = Transaction(
to=address_entry_point,
gas_limit=50000000,
gas_price=10,
protected=False,
data="",
)

post = {
Address(address_entry_point): Account(
storage={
slot_eof_target_call_status: CALL_SUCCESS,
slot_eof_target_returndata: "0x00",
slot_eof_target_returndatasize: "0x01",
slot_legacy_target_call_status: CALL_FAILURE,
slot_legacy_target_returndatasize: "0x00",
}
if top_level == "LegacyContract"
else {
slot_eof_target_call_status: EXTCALL_SUCCESS,
slot_eof_target_returndata: "0x00",
slot_eof_target_returndatasize: "0x01",
slot_legacy_target_call_status: EXTCALL_FAILED,
slot_legacy_target_returndatasize: "0x00",
}
)
}

state_test(
env=env,
pre=pre,
post=post,
tx=tx,
)
1 change: 1 addition & 0 deletions whitelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ num
number
ommer
ommers
oob
opc
oprypin
origin
Expand Down

0 comments on commit 70c5447

Please sign in to comment.