Skip to content

Commit 805980d

Browse files
spencer-tbmarioevzdanceratopz
authored
tests/cancun/eip_4788: Update predeploy address(0xbEAC02..7d7a), add additional tests (#297)
* tests/cancun/eip_4788: Update naming to match spec. * tests/cancun/eip_4788: Update history buffer length. * tests/cancun/eip_4788: Add todo for remaining values to update. * tests/cancun/eip_4788: Add test for zero calldata value. * forks: Latest Beacon Root Update to 0xBEA...BCA * tests/cancun: Latest Beacon Root Update to 0xBEA...BCA * refactor: wrap specification params in a Spec class * tests/cancun/eip_4788|src/forks: final beacon root address update. * tests/cancun/eip_4788: add small self-destruct test. * tests/cancun/eip-4788: deployer address in spec --------- Co-authored-by: Mario Vega <[email protected]> Co-authored-by: danceratopz <[email protected]>
1 parent 789de47 commit 805980d

File tree

7 files changed

+220
-134
lines changed

7 files changed

+220
-134
lines changed

src/ethereum_test_forks/forks/forks.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -365,11 +365,11 @@ def pre_allocation(cls, block_number: int = 0, timestamp: int = 0) -> Mapping:
365365
Cancun requires pre-allocation of the beacon root contract for EIP-4788
366366
"""
367367
new_allocation = {
368-
0xBEAC00DDB15F3B6D645C48263DC93862413A222D: {
368+
0xBEAC020008AFF7331C0A389CB2AAB67597567D7A: {
369369
"nonce": 1,
370-
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5f"
371-
"fd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b620180004206"
372-
"4281555f359062018000015500",
370+
"code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5f"
371+
"fd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f"
372+
"5ffd5b62001fff42064281555f359062001fff015500",
373373
}
374374
}
375375
return new_allocation | super(Cancun, cls).pre_allocation(block_number, timestamp)

tests/cancun/eip4788_beacon_root/common.py

Lines changed: 0 additions & 53 deletions
This file was deleted.

tests/cancun/eip4788_beacon_root/conftest.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,7 @@
2020
)
2121
from ethereum_test_tools.vm.opcode import Opcodes as Op
2222

23-
from .common import (
24-
BEACON_ROOT_CONTRACT_ADDRESS,
25-
BEACON_ROOT_CONTRACT_CALL_GAS,
26-
HISTORY_BUFFER_LENGTH,
27-
SYSTEM_ADDRESS,
28-
expected_storage,
29-
)
23+
from .spec import Spec, SpecHelpers
3024

3125
BLOB_COMMITMENT_VERSION_KZG = 1
3226

@@ -88,7 +82,7 @@ def call_value() -> int: # noqa: D103
8882

8983
@pytest.fixture
9084
def call_gas() -> int: # noqa: D103
91-
return BEACON_ROOT_CONTRACT_CALL_GAS
85+
return Spec.BEACON_ROOTS_CALL_GAS
9286

9387

9488
@pytest.fixture
@@ -108,7 +102,7 @@ def contract_call_account(call_type: Op, call_value: int, call_gas: int) -> Acco
108102
0x00, # store the result of the contract call in storage[0]
109103
call_type(
110104
call_gas,
111-
BEACON_ROOT_CONTRACT_ADDRESS,
105+
Spec.BEACON_ROOTS_ADDRESS,
112106
call_value,
113107
args_start,
114108
args_length,
@@ -122,7 +116,7 @@ def contract_call_account(call_type: Op, call_value: int, call_gas: int) -> Acco
122116
0x00,
123117
call_type(
124118
call_gas,
125-
BEACON_ROOT_CONTRACT_ADDRESS,
119+
Spec.BEACON_ROOTS_ADDRESS,
126120
args_start,
127121
args_length,
128122
return_start,
@@ -197,7 +191,7 @@ def pre(
197191
caller_address: contract_call_account,
198192
}
199193
if system_address_balance > 0:
200-
pre_alloc[to_address(SYSTEM_ADDRESS)] = Account(
194+
pre_alloc[to_address(Spec.SYSTEM_ADDRESS)] = Account(
201195
nonce=0,
202196
balance=system_address_balance,
203197
)
@@ -225,10 +219,10 @@ def access_list(auto_access_list: bool, timestamp: int) -> List[AccessList]:
225219
if auto_access_list:
226220
return [
227221
AccessList(
228-
address=BEACON_ROOT_CONTRACT_ADDRESS,
222+
address=Spec.BEACON_ROOTS_ADDRESS,
229223
storage_keys=[
230224
timestamp,
231-
timestamp + HISTORY_BUFFER_LENGTH,
225+
timestamp + Spec.HISTORY_BUFFER_LENGTH,
232226
],
233227
),
234228
]
@@ -264,7 +258,7 @@ def tx(
264258
"""
265259
Prepares transaction to call the beacon root contract caller account.
266260
"""
267-
to = BEACON_ROOT_CONTRACT_ADDRESS if call_beacon_root_contract else tx_to_address
261+
to = Spec.BEACON_ROOTS_ADDRESS if call_beacon_root_contract else tx_to_address
268262
kwargs: Dict = {
269263
"ty": tx_type,
270264
"nonce": 0,
@@ -307,7 +301,7 @@ def post(
307301
"""
308302
storage = Storage()
309303
if not call_beacon_root_contract:
310-
storage = expected_storage(
304+
storage = SpecHelpers.expected_storage(
311305
beacon_root=beacon_root,
312306
valid_call=valid_call,
313307
valid_input=valid_input,
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"""
2+
Defines EIP-4788 specification constants and functions.
3+
"""
4+
from dataclasses import dataclass
5+
6+
from ethereum_test_tools import Storage
7+
8+
9+
@dataclass(frozen=True)
10+
class ReferenceSpec:
11+
"""
12+
Defines the reference spec version and git path.
13+
"""
14+
15+
git_path: str
16+
version: str
17+
18+
19+
ref_spec_4788 = ReferenceSpec("EIPS/eip-4788.md", "e7608fe8ac8a60934ca874f5aab7d5c1f4ff7782")
20+
21+
22+
# Constants
23+
@dataclass(frozen=True)
24+
class Spec:
25+
"""
26+
Parameters from the EIP-4788 specifications as defined at
27+
https://eips.ethereum.org/EIPS/eip-4788#specification
28+
"""
29+
30+
BEACON_ROOTS_ADDRESS = 0xBEAC020008AFF7331C0A389CB2AAB67597567D7A
31+
BEACON_ROOTS_CALL_GAS = 100_000
32+
BEACON_ROOTS_DEPLOYER_ADDRESS = 0x4F6DA9BA1CC8C37D9CE52311D4BAFFC43BA42D0E
33+
HISTORY_BUFFER_LENGTH = 8_191
34+
SYSTEM_ADDRESS = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
35+
FORK_TIMESTAMP = 15_000 # ShanghaiToCancun timestamp
36+
37+
38+
@dataclass(frozen=True)
39+
class SpecHelpers:
40+
"""
41+
Helper functions closely related to the EIP-4788 specification.
42+
"""
43+
44+
def timestamp_index(self, timestamp: int) -> int:
45+
"""
46+
Derive the timestamp index into the timestamp ring buffer.
47+
"""
48+
return timestamp % Spec.HISTORY_BUFFER_LENGTH
49+
50+
def root_index(self, timestamp: int) -> int:
51+
"""
52+
Derive the root index into the root ring buffer.
53+
"""
54+
return self.timestamp_index(timestamp) + Spec.HISTORY_BUFFER_LENGTH
55+
56+
@staticmethod
57+
def expected_storage(
58+
*,
59+
beacon_root: bytes,
60+
valid_call: bool,
61+
valid_input: bool,
62+
) -> Storage:
63+
"""
64+
Derives the expected storage for a given beacon root contract call
65+
dependent on:
66+
- success or failure of the call
67+
- validity of the timestamp input used within the call
68+
"""
69+
# By default assume the call is unsuccessful and all keys are zero
70+
storage = Storage({k: 0 for k in range(4)})
71+
if valid_call and valid_input:
72+
# beacon root contract call is successful
73+
storage[0] = 1
74+
storage[1] = beacon_root
75+
storage[2] = 32
76+
storage[3] = beacon_root
77+
78+
return storage

tests/cancun/eip4788_beacon_root/test_beacon_root_contract.py

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,29 @@
2727

2828
import pytest
2929

30-
from ethereum_test_tools import Environment, StateTestFiller, Transaction
30+
from ethereum_test_tools import (
31+
Account,
32+
Environment,
33+
StateTestFiller,
34+
Storage,
35+
Transaction,
36+
to_address,
37+
)
3138
from ethereum_test_tools.vm.opcode import Opcodes as Op
3239

33-
from .common import BEACON_ROOT_CONTRACT_CALL_GAS, REF_SPEC_4788_GIT_PATH, REF_SPEC_4788_VERSION
40+
from .spec import Spec, ref_spec_4788
3441

35-
REFERENCE_SPEC_GIT_PATH = REF_SPEC_4788_GIT_PATH
36-
REFERENCE_SPEC_VERSION = REF_SPEC_4788_VERSION
42+
REFERENCE_SPEC_GIT_PATH = ref_spec_4788.git_path
43+
REFERENCE_SPEC_VERSION = ref_spec_4788.version
3744

3845

3946
@pytest.mark.parametrize(
4047
"call_gas, valid_call",
4148
[
42-
pytest.param(BEACON_ROOT_CONTRACT_CALL_GAS, True),
43-
pytest.param(BEACON_ROOT_CONTRACT_CALL_GAS + 1, True),
49+
pytest.param(Spec.BEACON_ROOTS_CALL_GAS, True),
50+
pytest.param(Spec.BEACON_ROOTS_CALL_GAS + 1, True),
4451
pytest.param(
45-
BEACON_ROOT_CONTRACT_CALL_GAS - 1,
52+
Spec.BEACON_ROOTS_CALL_GAS - 1,
4653
False,
4754
marks=pytest.mark.xfail(reason="gas calculation is incorrect"), # TODO
4855
),
@@ -220,3 +227,66 @@ def test_tx_to_beacon_root_contract(
220227
txs=[tx],
221228
post=post,
222229
)
230+
231+
232+
@pytest.mark.parametrize(
233+
"tx_data",
234+
[
235+
pytest.param(int.to_bytes(0, length=32, byteorder="big"), id="zero_calldata"),
236+
],
237+
)
238+
@pytest.mark.parametrize("valid_call,valid_input", [(False, False)])
239+
@pytest.mark.parametrize("timestamp", [12])
240+
@pytest.mark.valid_from("Cancun")
241+
def test_invalid_beacon_root_calldata_value(
242+
state_test: StateTestFiller,
243+
env: Environment,
244+
pre: Dict,
245+
tx: Transaction,
246+
post: Dict,
247+
):
248+
"""
249+
Tests the beacon root contract call using invalid input values:
250+
- zero calldata.
251+
252+
Contract should revert.
253+
"""
254+
state_test(
255+
env=env,
256+
pre=pre,
257+
txs=[tx],
258+
post=post,
259+
)
260+
261+
262+
@pytest.mark.parametrize("timestamp", [12])
263+
@pytest.mark.valid_from("Cancun")
264+
def test_beacon_root_selfdestruct(
265+
state_test: StateTestFiller,
266+
env: Environment,
267+
pre: Dict,
268+
tx: Transaction,
269+
post: Dict,
270+
):
271+
"""
272+
Tests that self destructing the beacon root address transfers actors balance correctly.
273+
"""
274+
# self destruct actor
275+
pre[to_address(0x1337)] = Account(
276+
code=Op.SELFDESTRUCT(Spec.BEACON_ROOTS_ADDRESS),
277+
balance=0xBA1,
278+
)
279+
# self destruct caller
280+
pre[to_address(0xCC)] = Account(
281+
code=Op.CALL(100000, Op.PUSH20(to_address(0x1337)), 0, 0, 0, 0, 0)
282+
+ Op.SSTORE(0, Op.BALANCE(Spec.BEACON_ROOTS_ADDRESS)),
283+
)
284+
post[to_address(0xCC)] = Account(
285+
storage=Storage({0: 0xBA1}),
286+
)
287+
state_test(
288+
env=env,
289+
pre=pre,
290+
txs=[tx, Transaction(nonce=1, to=to_address(0xCC), gas_limit=100000, gas_price=10)],
291+
post=post,
292+
)

0 commit comments

Comments
 (0)