Skip to content

Commit 1e1e3cf

Browse files
authored
new(tests): EIP-7702 - Set EOA account code for one transaction (Devnet-1) (#621)
* feat(fw): Add type-4 transaction and authorization tuple type * new(tests): Add EIP-7702 folder, first test * tests: create contract * new(tests): more 7702 tests * new(tests): EIP-7702 * new(tests): EIP-7702 * typo * fix(fw): minor refactor * new(tests): parametrize sanity test with and without balance * fix(tests): fixes * fix(fw): nonce field in the auth tuple * fix(tests): fix some of the tests * fix(tests): test fixes and skips * fix(test): skip * fix(specs): output the authorization list to the fixture * nit * more tests * fix(fw): State test type-4 fix * fix(fw): Transaction type checks * fix(fixtures): Fixture transaciton type-4 test * fix(base_types): Storage methods * fix(tests): storage method usage * changelog
1 parent b85cff5 commit 1e1e3cf

File tree

11 files changed

+1216
-22
lines changed

11 files changed

+1216
-22
lines changed

docs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Test fixtures for use by clients are available for each release on the [Github r
2929
- ✨ Add tests for subcontainer kind validation from [EIP-7620: EOF Contract Creation](https://eips.ethereum.org/EIPS/eip-7620) for the cases with deeply nested containers and non-first code sections ([#676](https://github.com/ethereum/execution-spec-tests/pull/676)).
3030
- ✨ Add tests for runtime stack overflow at CALLF instruction from [EIP-4750: EOF - Functions](https://eips.ethereum.org/EIPS/eip-4750) ([#678](https://github.com/ethereum/execution-spec-tests/pull/678)).
3131
- ✨ Add tests for runtime stack overflow at JUMPF instruction from [EIP-6206: EOF - JUMPF and non-returning functions](https://eips.ethereum.org/EIPS/eip-6206) ([#690](https://github.com/ethereum/execution-spec-tests/pull/690)).
32+
- ✨ Add tests for Devnet-1 version of [EIP-7702: Set EOA account code](https://eips.ethereum.org/EIPS/eip-7702) ([#621](https://github.com/ethereum/execution-spec-tests/pull/621))
3233

3334
### 🛠️ Framework
3435

src/ethereum_test_base_types/composite_types.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22
Base composite types for Ethereum test cases.
33
"""
44
from dataclasses import dataclass
5-
from itertools import count
6-
from typing import Any, ClassVar, Dict, Iterator, SupportsBytes, Type, TypeAlias
5+
from typing import Any, ClassVar, Dict, SupportsBytes, Type, TypeAlias
76

8-
from pydantic import Field, RootModel, TypeAdapter
7+
from pydantic import Field, PrivateAttr, RootModel, TypeAdapter
98

109
from .base_types import Address, Bytes, Hash, HashInt, HexNumber, ZeroPaddedHexNumber
1110
from .conversions import BytesConvertible, NumberConvertible
@@ -24,7 +23,7 @@ class Storage(RootModel[Dict[StorageKeyValueType, StorageKeyValueType]]):
2423

2524
root: Dict[StorageKeyValueType, StorageKeyValueType] = Field(default_factory=dict)
2625

27-
_current_slot: Iterator[int] = count(0)
26+
_current_slot: int = PrivateAttr(0)
2827

2928
StorageDictType: ClassVar[TypeAlias] = Dict[
3029
str | int | bytes | SupportsBytes, str | int | bytes | SupportsBytes
@@ -161,10 +160,23 @@ def __bool__(self) -> bool:
161160
"""Returns True if the storage is not empty"""
162161
return any(v for v in self.root.values())
163162

163+
def __add__(self, other: "Storage") -> "Storage":
164+
"""
165+
Returns a new storage that is the sum of two storages.
166+
"""
167+
return Storage({**self.root, **other.root})
168+
164169
def keys(self) -> set[StorageKeyValueType]:
165170
"""Returns the keys of the storage"""
166171
return set(self.root.keys())
167172

173+
def set_next_slot(self, slot: int) -> "Storage":
174+
"""
175+
Sets the next slot to be used by `store_next`.
176+
"""
177+
self._current_slot = slot
178+
return self
179+
168180
def store_next(
169181
self, value: StorageKeyValueTypeConvertible | StorageKeyValueType | bool
170182
) -> StorageKeyValueType:
@@ -174,10 +186,17 @@ def store_next(
174186
Increments the key counter so the next time this function is called,
175187
the next key is used.
176188
"""
177-
slot = StorageKeyValueTypeAdapter.validate_python(next(self._current_slot))
189+
slot = StorageKeyValueTypeAdapter.validate_python(self._current_slot)
190+
self._current_slot += 1
178191
self[slot] = StorageKeyValueTypeAdapter.validate_python(value)
179192
return slot
180193

194+
def peek_slot(self) -> int:
195+
"""
196+
Peeks the next slot that will be used by `store_next`.
197+
"""
198+
return self._current_slot
199+
181200
def contains(self, other: "Storage") -> bool:
182201
"""
183202
Returns True if self contains all keys with equal value as

src/ethereum_test_fixtures/blockchain.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from ethereum_test_exceptions import EngineAPIError, ExceptionInstanceOrList
2727
from ethereum_test_forks import Fork
2828
from ethereum_test_types.types import (
29+
AuthorizationTupleGeneric,
2930
ConsolidationRequest,
3031
ConsolidationRequestGeneric,
3132
DepositRequest,
@@ -321,11 +322,30 @@ def from_fixture_header(
321322
return new_payload
322323

323324

325+
class FixtureAuthorizationTuple(AuthorizationTupleGeneric[ZeroPaddedHexNumber]):
326+
"""
327+
Authorization tuple for fixture transactions.
328+
"""
329+
330+
signer: Address | None = None
331+
332+
@classmethod
333+
def from_authorization_tuple(
334+
cls, auth_tuple: AuthorizationTupleGeneric
335+
) -> "FixtureAuthorizationTuple":
336+
"""
337+
Returns a FixtureAuthorizationTuple from an AuthorizationTuple.
338+
"""
339+
return cls(**auth_tuple.model_dump())
340+
341+
324342
class FixtureTransaction(TransactionFixtureConverter, TransactionGeneric[ZeroPaddedHexNumber]):
325343
"""
326344
Representation of an Ethereum transaction within a test Fixture.
327345
"""
328346

347+
authorization_list: List[FixtureAuthorizationTuple] | None = None
348+
329349
@classmethod
330350
def from_transaction(cls, tx: Transaction) -> "FixtureTransaction":
331351
"""

src/ethereum_test_fixtures/state.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from ethereum_test_exceptions import TransactionExceptionInstanceOrList
1111
from ethereum_test_types.types import (
1212
AccessList,
13+
AuthorizationTupleGeneric,
1314
CamelModel,
1415
EnvironmentGeneric,
1516
Transaction,
@@ -28,6 +29,23 @@ class FixtureEnvironment(EnvironmentGeneric[ZeroPaddedHexNumber]):
2829
prev_randao: Hash | None = Field(None, alias="currentRandom") # type: ignore
2930

3031

32+
class FixtureAuthorizationTuple(AuthorizationTupleGeneric[ZeroPaddedHexNumber]):
33+
"""
34+
Authorization tuple for fixture transactions.
35+
"""
36+
37+
signer: Address | None = None
38+
39+
@classmethod
40+
def from_authorization_tuple(
41+
cls, auth_tuple: AuthorizationTupleGeneric
42+
) -> "FixtureAuthorizationTuple":
43+
"""
44+
Returns a FixtureAuthorizationTuple from an AuthorizationTuple.
45+
"""
46+
return cls(**auth_tuple.model_dump())
47+
48+
3149
class FixtureTransaction(TransactionFixtureConverter):
3250
"""
3351
Type used to describe a transaction in a state test.
@@ -42,6 +60,7 @@ class FixtureTransaction(TransactionFixtureConverter):
4260
value: List[ZeroPaddedHexNumber]
4361
data: List[Bytes]
4462
access_lists: List[List[AccessList]] | None = None
63+
authorization_list: List[FixtureAuthorizationTuple] | None = None
4564
max_fee_per_blob_gas: ZeroPaddedHexNumber | None = None
4665
blob_versioned_hashes: Sequence[Hash] | None = None
4766
sender: Address | None = None

src/ethereum_test_fixtures/tests/test_blockchain.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@
1515
Bytes,
1616
Hash,
1717
HeaderNonce,
18+
TestPrivateKey,
1819
ZeroPaddedHexNumber,
1920
to_json,
2021
)
2122
from ethereum_test_exceptions import BlockException, EngineAPIError, TransactionException
2223
from ethereum_test_forks import Prague
2324
from ethereum_test_types import (
25+
EOA,
2426
AccessList,
27+
AuthorizationTuple,
2528
ConsolidationRequest,
2629
DepositRequest,
2730
Requests,
@@ -178,6 +181,51 @@
178181
},
179182
id="fixture_transaction_type_3_default_values",
180183
),
184+
pytest.param(
185+
True,
186+
FixtureTransaction.from_transaction(
187+
Transaction(
188+
ty=4,
189+
max_fee_per_gas=7,
190+
authorization_list=[
191+
AuthorizationTuple(
192+
chain_id=1,
193+
address=2,
194+
nonce=[3],
195+
signer=EOA(key=TestPrivateKey),
196+
)
197+
],
198+
).with_signature_and_sender()
199+
),
200+
{
201+
"type": "0x04",
202+
"chainId": "0x01",
203+
"nonce": "0x00",
204+
"to": "0x00000000000000000000000000000000000000aa",
205+
"value": "0x00",
206+
"data": "0x",
207+
"gasLimit": "0x5208",
208+
"maxPriorityFeePerGas": "0x00",
209+
"maxFeePerGas": "0x07",
210+
"accessList": [],
211+
"authorizationList": [
212+
{
213+
"chainId": "0x01",
214+
"address": Address(2).hex(),
215+
"nonce": ["0x03"],
216+
"v": "0x00",
217+
"r": "0x796b0a59fe796b5aab79259988f4b18bb7966dc9aa0a01d226859057f539d8f6",
218+
"s": "0x7456ad9b8b4e157d8a150ae7d568bb93e668bf1d5970756f7fe7b7f2472235fe",
219+
"signer": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
220+
}
221+
],
222+
"v": "0x01",
223+
"r": "0xb9f3ad929ffdb846cbe357fa25e6ab93cc6e10e76da170a12baf03f8a34ba141",
224+
"s": "0x04992060cfa252f5ac18ac1ccb340a821497d50812a225646094d2ad08b8eeaa",
225+
"sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
226+
},
227+
id="fixture_transaction_type_4",
228+
),
181229
pytest.param(
182230
True,
183231
FixtureTransaction.from_transaction(

src/ethereum_test_tools/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
EOA,
3838
AccessList,
3939
Alloc,
40+
AuthorizationTuple,
4041
ConsolidationRequest,
4142
DepositRequest,
4243
Environment,
@@ -82,6 +83,7 @@
8283
"Account",
8384
"Address",
8485
"Alloc",
86+
"AuthorizationTuple",
8587
"BaseFixture",
8688
"BaseTest",
8789
"Block",

src/ethereum_test_types/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
AccessList,
1919
Account,
2020
Alloc,
21+
AuthorizationTuple,
2122
CamelModel,
2223
ConsolidationRequest,
2324
DepositRequest,
@@ -34,6 +35,7 @@
3435
"AccessList",
3536
"Account",
3637
"Alloc",
38+
"AuthorizationTuple",
3739
"CamelModel",
3840
"ConsolidationRequest",
3941
"DepositRequest",

0 commit comments

Comments
 (0)