Skip to content

Commit 1155288

Browse files
marioevzjochem-brouwerdanceratopz
authored
feat(fw,tests): EIP-6110, EIP-7002, EIP-7251, EIP-7702: Pectra Devnet-4 updates (ethereum#832)
* fix(forks): Update 7002, 7251 contracts * feat(forks): Add 7685 methods * fix(fw): Remove requests from block body, add as parameters for new payload * refactor(tests): Refactor requests usages, add more 7685 tests * feat(tests): EIP-7702, #8929 changes - Incomplete * Update tests/prague/eip7702_set_code_tx/spec.py Co-authored-by: Jochem Brouwer <[email protected]> * feat(exceptions): Add invalid authorization format exception * new(tests): EIP 7702: chain id/nonce overflow tests * new(tests): EIP 7702: delegation clearing test * new(tests): EIP 7702: delegation clearing on failure test * new(tests): EIP 7702: fixup * new(tests): EIP 7702: test deployting a delegation-like contract * fix(tests): EIP 7702: remove `test_set_code_to_zero_address` * new(tests): EIP 7702: add `test_signature_s_out_of_range` * fix(forks): EIP-7002,7251 contracts * new(tests): EIP-7002: withdrawal request during fork * fix(tests): EIP-7002: fixup * fix(tests): EIP-7002: fixup * new(tests): EIP-7251: consolidation requests during fork * fix(tests): tox * github: Add devnet-4 configs * fix(github): feature devnet-4 * fix(tests): EIP-6110 conftest * fix(github): feature * fix(specs): Propagate `block.requests` to the Engine API params * fix(tests): Fix override requests comparison for empty list * fix(tox): whitelist * fix(tests): EIP-7702: note in `test_tx_validity_nonce` * new(tests): EIP-7702: Add invalid `v` (27, 28) for auth tuple test * chore(hive): update hive client config file in test summary * fix(plugins/execute): Requests * fix(rpc): Support `engine_getPayloadV4` * fix(plugins/execute): Support `engine_getPayloadV4` * fix(tests): EIP-7702: test id * fix(tests): EIP-7702: execute marks --------- Co-authored-by: Jochem Brouwer <[email protected]> Co-authored-by: danceratopz <[email protected]>
1 parent 4f31115 commit 1155288

File tree

16 files changed

+1293
-226
lines changed

16 files changed

+1293
-226
lines changed

prague/eip6110_deposits/conftest.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55

66
import pytest
77

8-
from ethereum_test_tools import Alloc, Block, BlockException, Header, Transaction
8+
from ethereum_test_forks import Fork
9+
from ethereum_test_tools import Alloc, Block, BlockException, Header, Requests, Transaction
910

1011
from .helpers import DepositInteractionBase, DepositRequest
1112

@@ -61,6 +62,7 @@ def included_requests(
6162

6263
@pytest.fixture
6364
def blocks(
65+
fork: Fork,
6466
included_requests: List[DepositRequest],
6567
block_body_override_requests: List[DepositRequest] | None,
6668
txs: List[Transaction],
@@ -71,9 +73,17 @@ def blocks(
7173
Block(
7274
txs=txs,
7375
header_verify=Header(
74-
requests_root=included_requests,
76+
requests_hash=Requests(
77+
*included_requests,
78+
max_request_type=fork.max_request_type(block_number=1, timestamp=1),
79+
),
7580
),
76-
requests=block_body_override_requests,
81+
requests=Requests(
82+
*block_body_override_requests,
83+
max_request_type=fork.max_request_type(block_number=1, timestamp=1),
84+
).requests_list
85+
if block_body_override_requests is not None
86+
else None,
7787
exception=exception,
7888
)
7989
]

prague/eip7002_el_triggerable_withdrawals/conftest.py

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
import pytest
88

9-
from ethereum_test_tools import Alloc, Block, Header
9+
from ethereum_test_forks import Fork
10+
from ethereum_test_tools import Alloc, Block, Header, Requests
1011

1112
from .helpers import WithdrawalRequest, WithdrawalRequestInteractionBase
1213
from .spec import Spec
@@ -68,25 +69,65 @@ def included_requests(
6869
return per_block_included_requests
6970

7071

72+
@pytest.fixture
73+
def timestamp() -> int:
74+
"""
75+
Return the timestamp for the first block.
76+
"""
77+
return 1
78+
79+
7180
@pytest.fixture
7281
def blocks(
82+
fork: Fork,
7383
update_pre: None, # Fixture is used for its side effects
7484
blocks_withdrawal_requests: List[List[WithdrawalRequestInteractionBase]],
7585
included_requests: List[List[WithdrawalRequest]],
86+
timestamp: int,
7687
) -> List[Block]:
7788
"""
7889
Return the list of blocks that should be included in the test.
7990
"""
80-
return [ # type: ignore
81-
Block(
82-
txs=sum((r.transactions() for r in block_requests), []),
83-
header_verify=Header(requests_root=block_included_requests),
91+
blocks: List[Block] = []
92+
93+
for block_requests, block_included_requests in zip_longest( # type: ignore
94+
blocks_withdrawal_requests,
95+
included_requests,
96+
fillvalue=[],
97+
):
98+
max_request_type = fork.max_request_type(
99+
block_number=len(blocks) + 1,
100+
timestamp=timestamp,
101+
)
102+
header_verify: Header | None = None
103+
if max_request_type > -1:
104+
header_verify = Header(
105+
requests_hash=Requests(
106+
*block_included_requests,
107+
max_request_type=max_request_type,
108+
)
109+
)
110+
else:
111+
assert not block_included_requests
112+
blocks.append(
113+
Block(
114+
txs=sum((r.transactions() for r in block_requests), []),
115+
header_verify=header_verify,
116+
timestamp=timestamp,
117+
)
84118
)
85-
for block_requests, block_included_requests in zip_longest(
86-
blocks_withdrawal_requests,
87-
included_requests,
88-
fillvalue=[],
119+
timestamp += 1
120+
121+
return blocks + [
122+
Block(
123+
header_verify=Header(
124+
requests_hash=Requests(
125+
max_request_type=fork.max_request_type(
126+
block_number=len(blocks) + 1,
127+
timestamp=timestamp,
128+
)
129+
)
130+
),
131+
timestamp=timestamp,
89132
)
90-
] + [
91-
Block(header_verify=Header(requests_root=[]))
92133
] # Add an empty block at the end to verify that no more withdrawal requests are included
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"type": "0x0",
3+
"nonce": "0x0",
4+
"to": null,
5+
"gasLimit": "0x3d090",
6+
"gasPrice": "0xe8d4a51000",
7+
"maxPriorityFeePerGas": null,
8+
"maxFeePerGas": null,
9+
"value": "0x0",
10+
"input": "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f556101f480602d5f395ff33373fffffffffffffffffffffffffffffffffffffffe1460c7573615156028575f545f5260205ff35b36603814156101f05760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f057600182026001905f5b5f821115608057810190830284830290049160010191906065565b9093900434106101f057600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060101160db575060105b5f5b81811461017f5780604c02838201600302600401805490600101805490600101549160601b83528260140152807fffffffffffffffffffffffffffffffff0000000000000000000000000000000016826034015260401c906044018160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160dd565b9101809214610191579060025561019c565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101c957505f5b6001546002828201116101de5750505f6101e4565b01600290035b5f555f600155604c025ff35b5f5ffd",
11+
"v": "0x1b",
12+
"r": "0x539",
13+
"s": "0x10e740537d4d36b9",
14+
"hash": "0x1cd8bf929988b27b07ba1c7b898b396c08c484bb0db83fdeb992aa21b5cdf0ce",
15+
"protected": false
16+
}

prague/eip7002_el_triggerable_withdrawals/spec.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
from dataclasses import dataclass
77

8+
from ethereum_test_tools import Address
9+
810

911
@dataclass(frozen=True)
1012
class ReferenceSpec:
@@ -16,7 +18,7 @@ class ReferenceSpec:
1618
version: str
1719

1820

19-
ref_spec_7002 = ReferenceSpec("EIPS/eip-7002.md", "e5af719767e789c88c0e063406c6557c8f53cfba")
21+
ref_spec_7002 = ReferenceSpec("EIPS/eip-7002.md", "9fe721f56f45bd5cf2d2958c0e6867aa81f82ebc")
2022

2123

2224
# Constants
@@ -30,7 +32,8 @@ class Spec:
3032
out.
3133
"""
3234

33-
WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = 0x00A3CA265EBCB825B45F985A16CEFB49958CE017
35+
WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = 0x09FC772D0857550724B07B850A4323F39112AAAA
36+
WITHDRAWAL_REQUEST_PREDEPLOY_SENDER = Address(0x57B8C3C2766D0623EA0A499365A6F5A26AD38B47)
3437
SYSTEM_ADDRESS = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
3538

3639
EXCESS_WITHDRAWAL_REQUESTS_STORAGE_SLOT = 0

prague/eip7002_el_triggerable_withdrawals/test_withdrawal_requests.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import pytest
1010

11+
from ethereum_test_forks import Fork
1112
from ethereum_test_tools import (
1213
Address,
1314
Alloc,
@@ -19,7 +20,7 @@
1920
Macros,
2021
)
2122
from ethereum_test_tools import Opcodes as Op
22-
from ethereum_test_tools import TestAddress, TestAddress2
23+
from ethereum_test_tools import Requests, TestAddress, TestAddress2
2324

2425
from .helpers import (
2526
WithdrawalRequest,
@@ -350,9 +351,11 @@
350351
+ [
351352
WithdrawalRequest(
352353
validator_pubkey=Spec.MAX_WITHDRAWAL_REQUESTS_PER_BLOCK,
353-
amount=Spec.MAX_AMOUNT - 1
354-
if (Spec.MAX_WITHDRAWAL_REQUESTS_PER_BLOCK - 1) % 2 == 0
355-
else 0,
354+
amount=(
355+
Spec.MAX_AMOUNT - 1
356+
if (Spec.MAX_WITHDRAWAL_REQUESTS_PER_BLOCK - 1) % 2 == 0
357+
else 0
358+
),
356359
fee=0,
357360
)
358361
],
@@ -678,6 +681,7 @@ def test_withdrawal_requests(
678681
)
679682
def test_withdrawal_requests_negative(
680683
pre: Alloc,
684+
fork: Fork,
681685
blockchain_test: BlockchainTestFiller,
682686
requests: List[WithdrawalRequestInteractionBase],
683687
block_body_override_requests: List[WithdrawalRequest],
@@ -705,9 +709,19 @@ def test_withdrawal_requests_negative(
705709
Block(
706710
txs=sum((r.transactions() for r in requests), []),
707711
header_verify=Header(
708-
requests_root=included_requests,
712+
requests_hash=Requests(
713+
*included_requests,
714+
max_request_type=fork.max_request_type(block_number=1, timestamp=1),
715+
),
716+
),
717+
requests=(
718+
Requests(
719+
*block_body_override_requests,
720+
max_request_type=fork.max_request_type(block_number=1, timestamp=1),
721+
).requests_list
722+
if block_body_override_requests is not None
723+
else None
709724
),
710-
requests=block_body_override_requests,
711725
exception=exception,
712726
)
713727
],
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
"""
2+
abstract: Tests [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002)
3+
Test execution layer triggered exits [EIP-7002: Execution layer triggerable withdrawals](https://eips.ethereum.org/EIPS/eip-7002)
4+
5+
""" # noqa: E501
6+
7+
from os.path import realpath
8+
from pathlib import Path
9+
from typing import List
10+
11+
import pytest
12+
13+
from ethereum_test_tools import (
14+
Account,
15+
Address,
16+
Alloc,
17+
Block,
18+
BlockchainTestFiller,
19+
Environment,
20+
Transaction,
21+
)
22+
23+
from .helpers import WithdrawalRequest, WithdrawalRequestTransaction
24+
from .spec import Spec, ref_spec_7002
25+
26+
REFERENCE_SPEC_GIT_PATH = ref_spec_7002.git_path
27+
REFERENCE_SPEC_VERSION = ref_spec_7002.version
28+
29+
pytestmark = pytest.mark.valid_at_transition_to("Prague")
30+
31+
BLOCKS_BEFORE_FORK = 2
32+
33+
34+
@pytest.mark.parametrize(
35+
"blocks_withdrawal_requests",
36+
[
37+
pytest.param(
38+
[
39+
[], # No withdrawal requests, but we deploy the contract
40+
[
41+
WithdrawalRequestTransaction(
42+
requests=[
43+
WithdrawalRequest(
44+
validator_pubkey=0x01,
45+
amount=0,
46+
fee=Spec.get_fee(10),
47+
# Pre-fork withdrawal request
48+
valid=False,
49+
)
50+
],
51+
),
52+
],
53+
[
54+
WithdrawalRequestTransaction(
55+
requests=[
56+
WithdrawalRequest(
57+
validator_pubkey=0x02,
58+
amount=0,
59+
fee=Spec.get_fee(10),
60+
# First post-fork withdrawal request, will not be included
61+
# because the inhibitor is cleared at the end of the block
62+
valid=False,
63+
)
64+
],
65+
),
66+
],
67+
[
68+
WithdrawalRequestTransaction(
69+
requests=[
70+
WithdrawalRequest(
71+
validator_pubkey=0x03,
72+
amount=0,
73+
fee=Spec.get_fee(0),
74+
# First withdrawal that is valid
75+
valid=True,
76+
)
77+
],
78+
),
79+
],
80+
],
81+
id="one_valid_request_second_block_after_fork",
82+
),
83+
],
84+
)
85+
@pytest.mark.parametrize("timestamp", [15_000 - BLOCKS_BEFORE_FORK], ids=[""])
86+
def test_withdrawal_requests_during_fork(
87+
blockchain_test: BlockchainTestFiller,
88+
blocks: List[Block],
89+
pre: Alloc,
90+
):
91+
"""
92+
Test making a withdrawal request to the beacon chain at the time of the fork.
93+
"""
94+
# We need to delete the deployed contract that comes by default in the pre state.
95+
pre[Spec.WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS] = Account(
96+
balance=0,
97+
code=bytes(),
98+
nonce=0,
99+
storage={},
100+
)
101+
102+
with open(Path(realpath(__file__)).parent / "contract_deploy_tx.json", mode="r") as f:
103+
deploy_tx = Transaction.model_validate_json(
104+
f.read()
105+
).with_signature_and_sender() # type: ignore
106+
107+
deployer_address = deploy_tx.sender
108+
assert deployer_address is not None
109+
assert Address(deployer_address) == Spec.WITHDRAWAL_REQUEST_PREDEPLOY_SENDER
110+
111+
tx_gas_price = deploy_tx.gas_price
112+
assert tx_gas_price is not None
113+
deployer_required_balance = deploy_tx.gas_limit * tx_gas_price
114+
115+
pre.fund_address(Spec.WITHDRAWAL_REQUEST_PREDEPLOY_SENDER, deployer_required_balance)
116+
117+
# Append the deployment transaction to the first block
118+
blocks[0].txs.append(deploy_tx)
119+
120+
blockchain_test(
121+
genesis_environment=Environment(),
122+
pre=pre,
123+
post={},
124+
blocks=blocks,
125+
)

0 commit comments

Comments
 (0)