Skip to content

Ethereum Test Base Types package

Common definitions and types.

Address

Bases: FixedSizeBytes[20]

Class that helps represent Ethereum addresses in tests.

Source code in src/ethereum_test_base_types/base_types.py
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
class Address(FixedSizeBytes[20]):  # type: ignore
    """Class that helps represent Ethereum addresses in tests."""

    label: str | None = None

    def __new__(
        cls, input_bytes: "FixedSizeBytesConvertible | Address", *, label: str | None = None
    ):
        """Create a new Address object with an optional label."""
        instance = super(Address, cls).__new__(cls, input_bytes)
        if isinstance(input_bytes, Address) and label is None:
            instance.label = input_bytes.label
        else:
            instance.label = label
        return instance

__new__(input_bytes, *, label=None)

Create a new Address object with an optional label.

Source code in src/ethereum_test_base_types/base_types.py
300
301
302
303
304
305
306
307
308
309
def __new__(
    cls, input_bytes: "FixedSizeBytesConvertible | Address", *, label: str | None = None
):
    """Create a new Address object with an optional label."""
    instance = super(Address, cls).__new__(cls, input_bytes)
    if isinstance(input_bytes, Address) and label is None:
        instance.label = input_bytes.label
    else:
        instance.label = label
    return instance

Bloom

Bases: FixedSizeBytes[256]

Class that helps represent blooms in tests.

Source code in src/ethereum_test_base_types/base_types.py
318
319
320
321
class Bloom(FixedSizeBytes[256]):  # type: ignore
    """Class that helps represent blooms in tests."""

    pass

BLSPublicKey

Bases: FixedSizeBytes[48]

Class that helps represent BLS public keys in tests.

Source code in src/ethereum_test_base_types/base_types.py
330
331
332
333
class BLSPublicKey(FixedSizeBytes[48]):  # type: ignore
    """Class that helps represent BLS public keys in tests."""

    pass

BLSSignature

Bases: FixedSizeBytes[96]

Class that helps represent BLS signatures in tests.

Source code in src/ethereum_test_base_types/base_types.py
336
337
338
339
class BLSSignature(FixedSizeBytes[96]):  # type: ignore
    """Class that helps represent BLS signatures in tests."""

    pass

Bytes

Bases: bytes, ToStringSchema

Class that helps represent bytes of variable length in tests.

Source code in src/ethereum_test_base_types/base_types.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
class Bytes(bytes, ToStringSchema):
    """Class that helps represent bytes of variable length in tests."""

    def __new__(cls, input_bytes: BytesConvertible = b""):
        """Create a new Bytes object."""
        if type(input_bytes) is cls:
            return input_bytes
        return super(Bytes, cls).__new__(cls, to_bytes(input_bytes))

    def __hash__(self) -> int:
        """Return the hash of the bytes."""
        return super(Bytes, self).__hash__()

    def __str__(self) -> str:
        """Return the hexadecimal representation of the bytes."""
        return self.hex()

    def hex(self, *args, **kwargs) -> str:
        """Return the hexadecimal representation of the bytes."""
        return "0x" + super().hex(*args, **kwargs)

    @classmethod
    def or_none(cls, input_bytes: "Bytes | BytesConvertible | None") -> "Bytes | None":
        """Convert the input to a Bytes while accepting None."""
        if input_bytes is None:
            return input_bytes
        return cls(input_bytes)

    def keccak256(self) -> "Hash":
        """Return the keccak256 hash of the opcode byte representation."""
        k = keccak.new(digest_bits=256)
        return Hash(k.update(bytes(self)).digest())

    def sha256(self) -> "Hash":
        """Return the sha256 hash of the opcode byte representation."""
        return Hash(sha256(self).digest())

__new__(input_bytes=b'')

Create a new Bytes object.

Source code in src/ethereum_test_base_types/base_types.py
137
138
139
140
141
def __new__(cls, input_bytes: BytesConvertible = b""):
    """Create a new Bytes object."""
    if type(input_bytes) is cls:
        return input_bytes
    return super(Bytes, cls).__new__(cls, to_bytes(input_bytes))

__hash__()

Return the hash of the bytes.

Source code in src/ethereum_test_base_types/base_types.py
143
144
145
def __hash__(self) -> int:
    """Return the hash of the bytes."""
    return super(Bytes, self).__hash__()

__str__()

Return the hexadecimal representation of the bytes.

Source code in src/ethereum_test_base_types/base_types.py
147
148
149
def __str__(self) -> str:
    """Return the hexadecimal representation of the bytes."""
    return self.hex()

hex(*args, **kwargs)

Return the hexadecimal representation of the bytes.

Source code in src/ethereum_test_base_types/base_types.py
151
152
153
def hex(self, *args, **kwargs) -> str:
    """Return the hexadecimal representation of the bytes."""
    return "0x" + super().hex(*args, **kwargs)

or_none(input_bytes) classmethod

Convert the input to a Bytes while accepting None.

Source code in src/ethereum_test_base_types/base_types.py
155
156
157
158
159
160
@classmethod
def or_none(cls, input_bytes: "Bytes | BytesConvertible | None") -> "Bytes | None":
    """Convert the input to a Bytes while accepting None."""
    if input_bytes is None:
        return input_bytes
    return cls(input_bytes)

keccak256()

Return the keccak256 hash of the opcode byte representation.

Source code in src/ethereum_test_base_types/base_types.py
162
163
164
165
def keccak256(self) -> "Hash":
    """Return the keccak256 hash of the opcode byte representation."""
    k = keccak.new(digest_bits=256)
    return Hash(k.update(bytes(self)).digest())

sha256()

Return the sha256 hash of the opcode byte representation.

Source code in src/ethereum_test_base_types/base_types.py
167
168
169
def sha256(self) -> "Hash":
    """Return the sha256 hash of the opcode byte representation."""
    return Hash(sha256(self).digest())

FixedSizeBytes

Bases: Bytes

Class that helps represent bytes of fixed length in tests.

Source code in src/ethereum_test_base_types/base_types.py
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
class FixedSizeBytes(Bytes):
    """Class that helps represent bytes of fixed length in tests."""

    byte_length: ClassVar[int]
    _sized_: ClassVar[Type["FixedSizeBytes"]]

    def __class_getitem__(cls, length: int) -> Type["FixedSizeBytes"]:
        """Create a new FixedSizeBytes class with the given length."""

        class Sized(cls):  # type: ignore
            byte_length = length

        Sized._sized_ = Sized
        return Sized

    def __new__(
        cls,
        input_bytes: FixedSizeBytesConvertible | T,
        *,
        left_padding: bool = False,
        right_padding: bool = False,
    ):
        """Create a new FixedSizeBytes object."""
        if type(input_bytes) is cls:
            return input_bytes
        return super(FixedSizeBytes, cls).__new__(
            cls,
            to_fixed_size_bytes(
                input_bytes,
                cls.byte_length,
                left_padding=left_padding,
                right_padding=right_padding,
            ),
        )

    def __hash__(self) -> int:
        """Return the hash of the bytes."""
        return super(FixedSizeBytes, self).__hash__()

    @classmethod
    def or_none(cls: Type[T], input_bytes: T | FixedSizeBytesConvertible | None) -> T | None:
        """Convert the input to a Fixed Size Bytes while accepting None."""
        if input_bytes is None:
            return input_bytes
        return cls(input_bytes)

    def __eq__(self, other: object) -> bool:
        """Compare two FixedSizeBytes objects to be equal."""
        if other is None:
            return False
        if not isinstance(other, FixedSizeBytes):
            assert (
                isinstance(other, str)
                or isinstance(other, int)
                or isinstance(other, bytes)
                or isinstance(other, SupportsBytes)
            )
            other = self._sized_(other)
        return super().__eq__(other)

    def __ne__(self, other: object) -> bool:
        """Compare two FixedSizeBytes objects to be not equal."""
        return not self.__eq__(other)

__class_getitem__(length)

Create a new FixedSizeBytes class with the given length.

Source code in src/ethereum_test_base_types/base_types.py
236
237
238
239
240
241
242
243
def __class_getitem__(cls, length: int) -> Type["FixedSizeBytes"]:
    """Create a new FixedSizeBytes class with the given length."""

    class Sized(cls):  # type: ignore
        byte_length = length

    Sized._sized_ = Sized
    return Sized

__new__(input_bytes, *, left_padding=False, right_padding=False)

Create a new FixedSizeBytes object.

Source code in src/ethereum_test_base_types/base_types.py
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
def __new__(
    cls,
    input_bytes: FixedSizeBytesConvertible | T,
    *,
    left_padding: bool = False,
    right_padding: bool = False,
):
    """Create a new FixedSizeBytes object."""
    if type(input_bytes) is cls:
        return input_bytes
    return super(FixedSizeBytes, cls).__new__(
        cls,
        to_fixed_size_bytes(
            input_bytes,
            cls.byte_length,
            left_padding=left_padding,
            right_padding=right_padding,
        ),
    )

__hash__()

Return the hash of the bytes.

Source code in src/ethereum_test_base_types/base_types.py
265
266
267
def __hash__(self) -> int:
    """Return the hash of the bytes."""
    return super(FixedSizeBytes, self).__hash__()

or_none(input_bytes) classmethod

Convert the input to a Fixed Size Bytes while accepting None.

Source code in src/ethereum_test_base_types/base_types.py
269
270
271
272
273
274
@classmethod
def or_none(cls: Type[T], input_bytes: T | FixedSizeBytesConvertible | None) -> T | None:
    """Convert the input to a Fixed Size Bytes while accepting None."""
    if input_bytes is None:
        return input_bytes
    return cls(input_bytes)

__eq__(other)

Compare two FixedSizeBytes objects to be equal.

Source code in src/ethereum_test_base_types/base_types.py
276
277
278
279
280
281
282
283
284
285
286
287
288
def __eq__(self, other: object) -> bool:
    """Compare two FixedSizeBytes objects to be equal."""
    if other is None:
        return False
    if not isinstance(other, FixedSizeBytes):
        assert (
            isinstance(other, str)
            or isinstance(other, int)
            or isinstance(other, bytes)
            or isinstance(other, SupportsBytes)
        )
        other = self._sized_(other)
    return super().__eq__(other)

__ne__(other)

Compare two FixedSizeBytes objects to be not equal.

Source code in src/ethereum_test_base_types/base_types.py
290
291
292
def __ne__(self, other: object) -> bool:
    """Compare two FixedSizeBytes objects to be not equal."""
    return not self.__eq__(other)

Hash

Bases: FixedSizeBytes[32]

Class that helps represent hashes in tests.

Source code in src/ethereum_test_base_types/base_types.py
312
313
314
315
class Hash(FixedSizeBytes[32]):  # type: ignore
    """Class that helps represent hashes in tests."""

    pass

HashInt

Bases: FixedSizeHexNumber[32]

Class that helps represent hashes in tests.

Source code in src/ethereum_test_base_types/base_types.py
221
222
223
224
class HashInt(FixedSizeHexNumber[32]):  # type: ignore
    """Class that helps represent hashes in tests."""

    pass

HeaderNonce

Bases: FixedSizeBytes[8]

Class that helps represent the header nonce in tests.

Source code in src/ethereum_test_base_types/base_types.py
324
325
326
327
class HeaderNonce(FixedSizeBytes[8]):  # type: ignore
    """Class that helps represent the header nonce in tests."""

    pass

HexNumber

Bases: Number

Class that helps represent an hexadecimal numbers in tests.

Source code in src/ethereum_test_base_types/base_types.py
110
111
112
113
114
115
class HexNumber(Number):
    """Class that helps represent an hexadecimal numbers in tests."""

    def __str__(self) -> str:
        """Return the string representation of the number."""
        return self.hex()

__str__()

Return the string representation of the number.

Source code in src/ethereum_test_base_types/base_types.py
113
114
115
def __str__(self) -> str:
    """Return the string representation of the number."""
    return self.hex()

Number

Bases: int, ToStringSchema

Class that helps represent numbers in tests.

Source code in src/ethereum_test_base_types/base_types.py
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
class Number(int, ToStringSchema):
    """Class that helps represent numbers in tests."""

    def __new__(cls, input_number: NumberConvertible | N):
        """Create a new Number object."""
        return super(Number, cls).__new__(cls, to_number(input_number))

    def __str__(self) -> str:
        """Return the string representation of the number."""
        return str(int(self))

    def hex(self) -> str:
        """Return the hexadecimal representation of the number."""
        return hex(self)

    @classmethod
    def or_none(cls: Type[N], input_number: N | NumberConvertible | None) -> N | None:
        """Convert the input to a Number while accepting None."""
        if input_number is None:
            return input_number
        return cls(input_number)

__new__(input_number)

Create a new Number object.

Source code in src/ethereum_test_base_types/base_types.py
46
47
48
def __new__(cls, input_number: NumberConvertible | N):
    """Create a new Number object."""
    return super(Number, cls).__new__(cls, to_number(input_number))

__str__()

Return the string representation of the number.

Source code in src/ethereum_test_base_types/base_types.py
50
51
52
def __str__(self) -> str:
    """Return the string representation of the number."""
    return str(int(self))

hex()

Return the hexadecimal representation of the number.

Source code in src/ethereum_test_base_types/base_types.py
54
55
56
def hex(self) -> str:
    """Return the hexadecimal representation of the number."""
    return hex(self)

or_none(input_number) classmethod

Convert the input to a Number while accepting None.

Source code in src/ethereum_test_base_types/base_types.py
58
59
60
61
62
63
@classmethod
def or_none(cls: Type[N], input_number: N | NumberConvertible | None) -> N | None:
    """Convert the input to a Number while accepting None."""
    if input_number is None:
        return input_number
    return cls(input_number)

Wei

Bases: Number

Class that helps represent wei that can be parsed from strings.

Source code in src/ethereum_test_base_types/base_types.py
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
class Wei(Number):
    """Class that helps represent wei that can be parsed from strings."""

    def __new__(cls, input_number: NumberConvertible | N):
        """Create a new Number object."""
        if isinstance(input_number, str):
            words = input_number.split()
            multiplier = 1
            assert len(words) <= 2
            value_str = words[0]
            if len(words) > 1:
                unit = words[1].lower()
                multiplier = cls._get_multiplier(unit)
            value: float
            if "**" in value_str:
                base, exp = value_str.split("**")
                value = float(base) ** int(exp)
            else:
                value = float(value_str)
            return super(Number, cls).__new__(cls, value * multiplier)
        return super(Number, cls).__new__(cls, to_number(input_number))

    @staticmethod
    def _get_multiplier(unit: str) -> int:
        """Return the multiplier for the given unit of wei, handling synonyms."""
        match unit:
            case "wei":
                return 1
            case "kwei" | "babbage" | "femtoether":
                return 10**3
            case "mwei" | "lovelace" | "picoether":
                return 10**6
            case "gwei" | "shannon" | "nanoether" | "nano":
                return 10**9
            case "szabo" | "microether" | "micro":
                return 10**12
            case "finney" | "milliether" | "milli":
                return 10**15
            case "ether" | "eth":
                return 10**18
            case _:
                raise ValueError(f"Invalid unit {unit}")

__new__(input_number)

Create a new Number object.

Source code in src/ethereum_test_base_types/base_types.py
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
def __new__(cls, input_number: NumberConvertible | N):
    """Create a new Number object."""
    if isinstance(input_number, str):
        words = input_number.split()
        multiplier = 1
        assert len(words) <= 2
        value_str = words[0]
        if len(words) > 1:
            unit = words[1].lower()
            multiplier = cls._get_multiplier(unit)
        value: float
        if "**" in value_str:
            base, exp = value_str.split("**")
            value = float(base) ** int(exp)
        else:
            value = float(value_str)
        return super(Number, cls).__new__(cls, value * multiplier)
    return super(Number, cls).__new__(cls, to_number(input_number))

ZeroPaddedHexNumber

Bases: HexNumber

Class that helps represent zero padded hexadecimal numbers in tests.

Source code in src/ethereum_test_base_types/base_types.py
118
119
120
121
122
123
124
125
126
127
128
class ZeroPaddedHexNumber(HexNumber):
    """Class that helps represent zero padded hexadecimal numbers in tests."""

    def hex(self) -> str:
        """Return the hexadecimal representation of the number."""
        if self == 0:
            return "0x00"
        hex_str = hex(self)[2:]
        if len(hex_str) % 2 == 1:
            return "0x0" + hex_str
        return "0x" + hex_str

hex()

Return the hexadecimal representation of the number.

Source code in src/ethereum_test_base_types/base_types.py
121
122
123
124
125
126
127
128
def hex(self) -> str:
    """Return the hexadecimal representation of the number."""
    if self == 0:
        return "0x00"
    hex_str = hex(self)[2:]
    if len(hex_str) % 2 == 1:
        return "0x0" + hex_str
    return "0x" + hex_str

AccessList

Bases: CamelModel

Access List for transactions.

Source code in src/ethereum_test_base_types/composite_types.py
456
457
458
459
460
461
462
463
464
class AccessList(CamelModel):
    """Access List for transactions."""

    address: Address
    storage_keys: List[Hash]

    def to_list(self) -> List[Address | List[Hash]]:
        """Return access list as a list of serializable elements."""
        return [self.address, self.storage_keys]

to_list()

Return access list as a list of serializable elements.

Source code in src/ethereum_test_base_types/composite_types.py
462
463
464
def to_list(self) -> List[Address | List[Hash]]:
    """Return access list as a list of serializable elements."""
    return [self.address, self.storage_keys]

Account

Bases: CamelModel

State associated with an address.

Source code in src/ethereum_test_base_types/composite_types.py
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
class Account(CamelModel):
    """State associated with an address."""

    nonce: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0)
    """
    The scalar value equal to a) the number of transactions sent by
    an Externally Owned Account, b) the amount of contracts created by a
    contract.
    """
    balance: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0)
    """
    The amount of Wei (10<sup>-18</sup> Eth) the account has.
    """
    code: Bytes = Bytes(b"")
    """
    Bytecode contained by the account.
    """
    storage: Storage = Field(default_factory=Storage)
    """
    Storage within a contract.
    """

    NONEXISTENT: ClassVar[None] = None
    """
    Sentinel object used to specify when an account should not exist in the
    state.
    """

    @dataclass(kw_only=True)
    class NonceMismatchError(Exception):
        """
        Test expected a certain nonce value for an account but a different
        value was found.
        """

        address: Address
        want: int | None
        got: int | None

        def __init__(self, address: Address, want: int | None, got: int | None, *args):
            """Initialize the exception with the address, wanted and got values."""
            super().__init__(args)
            self.address = address
            self.want = want
            self.got = got

        def __str__(self):
            """Print exception string."""
            label_str = ""
            if self.address.label is not None:
                label_str = f" ({self.address.label})"
            return (
                f"unexpected nonce for account {self.address}{label_str}: "
                + f"want {self.want}, got {self.got}"
            )

    @dataclass(kw_only=True)
    class BalanceMismatchError(Exception):
        """
        Test expected a certain balance for an account but a different
        value was found.
        """

        address: Address
        want: int | None
        got: int | None

        def __init__(self, address: Address, want: int | None, got: int | None, *args):
            """Initialize the exception with the address, wanted and got values."""
            super().__init__(args)
            self.address = address
            self.want = want
            self.got = got

        def __str__(self):
            """Print exception string."""
            label_str = ""
            if self.address.label is not None:
                label_str = f" ({self.address.label})"
            return (
                f"unexpected balance for account {self.address}{label_str}: "
                + f"want {self.want}, got {self.got}"
            )

    @dataclass(kw_only=True)
    class CodeMismatchError(Exception):
        """
        Test expected a certain bytecode for an account but a different
        one was found.
        """

        address: Address
        want: bytes | None
        got: bytes | None

        def __init__(self, address: Address, want: bytes | None, got: bytes | None, *args):
            """Initialize the exception with the address, wanted and got values."""
            super().__init__(args)
            self.address = address
            self.want = want
            self.got = got

        def __str__(self):
            """Print exception string."""
            label_str = ""
            if self.address.label is not None:
                label_str = f" ({self.address.label})"
            return (
                f"unexpected code for account {self.address}{label_str}: "
                + f"want {self.want}, got {self.got}"
            )

    def check_alloc(self: "Account", address: Address, account: "Account"):
        """
        Check the returned alloc against an expected account in post state.
        Raises exception on failure.
        """
        if "nonce" in self.model_fields_set:
            if self.nonce != account.nonce:
                raise Account.NonceMismatchError(
                    address=address,
                    want=self.nonce,
                    got=account.nonce,
                )

        if "balance" in self.model_fields_set:
            if self.balance != account.balance:
                raise Account.BalanceMismatchError(
                    address=address,
                    want=self.balance,
                    got=account.balance,
                )

        if "code" in self.model_fields_set:
            if self.code != account.code:
                raise Account.CodeMismatchError(
                    address=address,
                    want=self.code,
                    got=account.code,
                )

        if "storage" in self.model_fields_set:
            self.storage.must_be_equal(address=address, other=account.storage)

    def __bool__(self: "Account") -> bool:
        """Return True on a non-empty account."""
        return any((self.nonce, self.balance, self.code, self.storage))

    @classmethod
    def with_code(cls: Type, code: BytesConvertible) -> "Account":
        """Create account with provided `code` and nonce of `1`."""
        return Account(nonce=HexNumber(1), code=Bytes(code))

    @classmethod
    def merge(
        cls: Type, account_1: "Dict | Account | None", account_2: "Dict | Account | None"
    ) -> "Account":
        """Create a merged account from two sources."""

        def to_kwargs_dict(account: "Dict | Account | None") -> Dict:
            if account is None:
                return {}
            if isinstance(account, dict):
                return account
            elif isinstance(account, cls):
                return account.model_dump(exclude_unset=True)
            raise TypeError(f"Unexpected type for account merge: {type(account)}")

        kwargs = to_kwargs_dict(account_1)
        kwargs.update(to_kwargs_dict(account_2))

        return cls(**kwargs)

nonce: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0) class-attribute instance-attribute

The scalar value equal to a) the number of transactions sent by an Externally Owned Account, b) the amount of contracts created by a contract.

balance: ZeroPaddedHexNumber = ZeroPaddedHexNumber(0) class-attribute instance-attribute

The amount of Wei (10-18 Eth) the account has.

code: Bytes = Bytes(b'') class-attribute instance-attribute

Bytecode contained by the account.

storage: Storage = Field(default_factory=Storage) class-attribute instance-attribute

Storage within a contract.

NONEXISTENT: None = None class-attribute

Sentinel object used to specify when an account should not exist in the state.

NonceMismatchError dataclass

Bases: Exception

Test expected a certain nonce value for an account but a different value was found.

Source code in src/ethereum_test_base_types/composite_types.py
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
@dataclass(kw_only=True)
class NonceMismatchError(Exception):
    """
    Test expected a certain nonce value for an account but a different
    value was found.
    """

    address: Address
    want: int | None
    got: int | None

    def __init__(self, address: Address, want: int | None, got: int | None, *args):
        """Initialize the exception with the address, wanted and got values."""
        super().__init__(args)
        self.address = address
        self.want = want
        self.got = got

    def __str__(self):
        """Print exception string."""
        label_str = ""
        if self.address.label is not None:
            label_str = f" ({self.address.label})"
        return (
            f"unexpected nonce for account {self.address}{label_str}: "
            + f"want {self.want}, got {self.got}"
        )

__init__(address, want, got, *args)

Initialize the exception with the address, wanted and got values.

Source code in src/ethereum_test_base_types/composite_types.py
315
316
317
318
319
320
def __init__(self, address: Address, want: int | None, got: int | None, *args):
    """Initialize the exception with the address, wanted and got values."""
    super().__init__(args)
    self.address = address
    self.want = want
    self.got = got

__str__()

Print exception string.

Source code in src/ethereum_test_base_types/composite_types.py
322
323
324
325
326
327
328
329
330
def __str__(self):
    """Print exception string."""
    label_str = ""
    if self.address.label is not None:
        label_str = f" ({self.address.label})"
    return (
        f"unexpected nonce for account {self.address}{label_str}: "
        + f"want {self.want}, got {self.got}"
    )

BalanceMismatchError dataclass

Bases: Exception

Test expected a certain balance for an account but a different value was found.

Source code in src/ethereum_test_base_types/composite_types.py
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
@dataclass(kw_only=True)
class BalanceMismatchError(Exception):
    """
    Test expected a certain balance for an account but a different
    value was found.
    """

    address: Address
    want: int | None
    got: int | None

    def __init__(self, address: Address, want: int | None, got: int | None, *args):
        """Initialize the exception with the address, wanted and got values."""
        super().__init__(args)
        self.address = address
        self.want = want
        self.got = got

    def __str__(self):
        """Print exception string."""
        label_str = ""
        if self.address.label is not None:
            label_str = f" ({self.address.label})"
        return (
            f"unexpected balance for account {self.address}{label_str}: "
            + f"want {self.want}, got {self.got}"
        )

__init__(address, want, got, *args)

Initialize the exception with the address, wanted and got values.

Source code in src/ethereum_test_base_types/composite_types.py
343
344
345
346
347
348
def __init__(self, address: Address, want: int | None, got: int | None, *args):
    """Initialize the exception with the address, wanted and got values."""
    super().__init__(args)
    self.address = address
    self.want = want
    self.got = got

__str__()

Print exception string.

Source code in src/ethereum_test_base_types/composite_types.py
350
351
352
353
354
355
356
357
358
def __str__(self):
    """Print exception string."""
    label_str = ""
    if self.address.label is not None:
        label_str = f" ({self.address.label})"
    return (
        f"unexpected balance for account {self.address}{label_str}: "
        + f"want {self.want}, got {self.got}"
    )

CodeMismatchError dataclass

Bases: Exception

Test expected a certain bytecode for an account but a different one was found.

Source code in src/ethereum_test_base_types/composite_types.py
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
@dataclass(kw_only=True)
class CodeMismatchError(Exception):
    """
    Test expected a certain bytecode for an account but a different
    one was found.
    """

    address: Address
    want: bytes | None
    got: bytes | None

    def __init__(self, address: Address, want: bytes | None, got: bytes | None, *args):
        """Initialize the exception with the address, wanted and got values."""
        super().__init__(args)
        self.address = address
        self.want = want
        self.got = got

    def __str__(self):
        """Print exception string."""
        label_str = ""
        if self.address.label is not None:
            label_str = f" ({self.address.label})"
        return (
            f"unexpected code for account {self.address}{label_str}: "
            + f"want {self.want}, got {self.got}"
        )

__init__(address, want, got, *args)

Initialize the exception with the address, wanted and got values.

Source code in src/ethereum_test_base_types/composite_types.py
371
372
373
374
375
376
def __init__(self, address: Address, want: bytes | None, got: bytes | None, *args):
    """Initialize the exception with the address, wanted and got values."""
    super().__init__(args)
    self.address = address
    self.want = want
    self.got = got

__str__()

Print exception string.

Source code in src/ethereum_test_base_types/composite_types.py
378
379
380
381
382
383
384
385
386
def __str__(self):
    """Print exception string."""
    label_str = ""
    if self.address.label is not None:
        label_str = f" ({self.address.label})"
    return (
        f"unexpected code for account {self.address}{label_str}: "
        + f"want {self.want}, got {self.got}"
    )

check_alloc(address, account)

Check the returned alloc against an expected account in post state. Raises exception on failure.

Source code in src/ethereum_test_base_types/composite_types.py
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
def check_alloc(self: "Account", address: Address, account: "Account"):
    """
    Check the returned alloc against an expected account in post state.
    Raises exception on failure.
    """
    if "nonce" in self.model_fields_set:
        if self.nonce != account.nonce:
            raise Account.NonceMismatchError(
                address=address,
                want=self.nonce,
                got=account.nonce,
            )

    if "balance" in self.model_fields_set:
        if self.balance != account.balance:
            raise Account.BalanceMismatchError(
                address=address,
                want=self.balance,
                got=account.balance,
            )

    if "code" in self.model_fields_set:
        if self.code != account.code:
            raise Account.CodeMismatchError(
                address=address,
                want=self.code,
                got=account.code,
            )

    if "storage" in self.model_fields_set:
        self.storage.must_be_equal(address=address, other=account.storage)

__bool__()

Return True on a non-empty account.

Source code in src/ethereum_test_base_types/composite_types.py
420
421
422
def __bool__(self: "Account") -> bool:
    """Return True on a non-empty account."""
    return any((self.nonce, self.balance, self.code, self.storage))

with_code(code) classmethod

Create account with provided code and nonce of 1.

Source code in src/ethereum_test_base_types/composite_types.py
424
425
426
427
@classmethod
def with_code(cls: Type, code: BytesConvertible) -> "Account":
    """Create account with provided `code` and nonce of `1`."""
    return Account(nonce=HexNumber(1), code=Bytes(code))

merge(account_1, account_2) classmethod

Create a merged account from two sources.

Source code in src/ethereum_test_base_types/composite_types.py
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
@classmethod
def merge(
    cls: Type, account_1: "Dict | Account | None", account_2: "Dict | Account | None"
) -> "Account":
    """Create a merged account from two sources."""

    def to_kwargs_dict(account: "Dict | Account | None") -> Dict:
        if account is None:
            return {}
        if isinstance(account, dict):
            return account
        elif isinstance(account, cls):
            return account.model_dump(exclude_unset=True)
        raise TypeError(f"Unexpected type for account merge: {type(account)}")

    kwargs = to_kwargs_dict(account_1)
    kwargs.update(to_kwargs_dict(account_2))

    return cls(**kwargs)

Alloc

Bases: EthereumTestRootModel[Dict[Address, Account | None]]

Allocation of accounts in the state, pre and post test execution.

Source code in src/ethereum_test_base_types/composite_types.py
450
451
452
453
class Alloc(EthereumTestRootModel[Dict[Address, Account | None]]):
    """Allocation of accounts in the state, pre and post test execution."""

    root: Dict[Address, Account | None] = Field(default_factory=dict, validate_default=True)

BlobSchedule

Bases: EthereumTestRootModel[Dict[str, ForkBlobSchedule]]

Blob schedule configuration dictionary.

Source code in src/ethereum_test_base_types/composite_types.py
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
class BlobSchedule(EthereumTestRootModel[Dict[str, ForkBlobSchedule]]):
    """Blob schedule configuration dictionary."""

    root: Dict[str, ForkBlobSchedule] = Field(default_factory=dict, validate_default=True)

    def append(self, *, fork: str, schedule: Any):
        """Append a new fork schedule."""
        if not isinstance(schedule, ForkBlobSchedule):
            schedule = ForkBlobSchedule(**schedule)
        self.root[fork] = schedule

    def last(self) -> ForkBlobSchedule | None:
        """Return the last schedule."""
        if len(self.root) == 0:
            return None
        return list(self.root.values())[-1]

append(*, fork, schedule)

Append a new fork schedule.

Source code in src/ethereum_test_base_types/composite_types.py
480
481
482
483
484
def append(self, *, fork: str, schedule: Any):
    """Append a new fork schedule."""
    if not isinstance(schedule, ForkBlobSchedule):
        schedule = ForkBlobSchedule(**schedule)
    self.root[fork] = schedule

last()

Return the last schedule.

Source code in src/ethereum_test_base_types/composite_types.py
486
487
488
489
490
def last(self) -> ForkBlobSchedule | None:
    """Return the last schedule."""
    if len(self.root) == 0:
        return None
    return list(self.root.values())[-1]

ForkBlobSchedule

Bases: CamelModel

Representation of the blob schedule of a given fork.

Source code in src/ethereum_test_base_types/composite_types.py
467
468
469
470
471
472
class ForkBlobSchedule(CamelModel):
    """Representation of the blob schedule of a given fork."""

    target_blobs_per_block: HexNumber = Field(..., alias="target")
    max_blobs_per_block: HexNumber = Field(..., alias="max")
    base_fee_update_fraction: HexNumber = Field(...)

Storage

Bases: EthereumTestRootModel[Dict[StorageKeyValueType, StorageKeyValueType]]

Definition of a storage in pre or post state of a test.

Source code in src/ethereum_test_base_types/composite_types.py
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
class Storage(EthereumTestRootModel[Dict[StorageKeyValueType, StorageKeyValueType]]):
    """Definition of a storage in pre or post state of a test."""

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

    _current_slot: int = PrivateAttr(0)
    _hint_map: Dict[StorageKeyValueType, str] = PrivateAttr(default_factory=dict)

    StorageDictType: ClassVar[TypeAlias] = Dict[
        str | int | bytes | SupportsBytes, str | int | bytes | SupportsBytes
    ]
    """
    Dictionary type to be used when defining an input to initialize a storage.
    """

    @dataclass(kw_only=True)
    class InvalidTypeError(Exception):
        """Invalid type used when describing test's expected storage key or value."""

        key_or_value: Any

        def __init__(self, key_or_value: Any, *args):
            """Initialize the exception with the invalid type."""
            super().__init__(args)
            self.key_or_value = key_or_value

        def __str__(self):
            """Print exception string."""
            return f"invalid type for key/value: {self.key_or_value}"

    @dataclass(kw_only=True)
    class InvalidValueError(Exception):
        """
        Invalid value used when describing test's expected storage key or
        value.
        """

        key_or_value: Any

        def __init__(self, key_or_value: Any, *args):
            """Initialize the exception with the invalid value."""
            super().__init__(args)
            self.key_or_value = key_or_value

        def __str__(self):
            """Print exception string."""
            return f"invalid value for key/value: {self.key_or_value}"

    @dataclass(kw_only=True)
    class MissingKeyError(Exception):
        """Test expected to find a storage key set but key was missing."""

        key: int

        def __init__(self, key: int, *args):
            """Initialize the exception with the missing key."""
            super().__init__(args)
            self.key = key

        def __str__(self):
            """Print exception string."""
            return "key {0} not found in storage".format(Hash(self.key))

    @dataclass(kw_only=True)
    class KeyValueMismatchError(Exception):
        """
        Test expected a certain value in a storage key but value found
        was different.
        """

        address: Address
        key: int
        want: int
        got: int
        hint: str

        def __init__(self, address: Address, key: int, want: int, got: int, hint: str = "", *args):
            """Initialize the exception with the address, key, wanted and got values."""
            super().__init__(args)
            self.address = address
            self.key = key
            self.want = want
            self.got = got
            self.hint = hint

        def __str__(self):
            """Print exception string."""
            label_str = ""
            if self.address.label is not None:
                label_str = f" ({self.address.label})"
            return (
                f"incorrect value in address {self.address}{label_str} for "
                + f"key {Hash(self.key)}{f' ({self.hint})' if self.hint else ''}:"
                + f" want {HexNumber(self.want)} (dec:{int(self.want)}),"
                + f" got {HexNumber(self.got)} (dec:{int(self.got)})"
            )

    def __contains__(self, key: StorageKeyValueTypeConvertible | StorageKeyValueType) -> bool:
        """Check for an item in the storage."""
        return StorageKeyValueTypeAdapter.validate_python(key) in self.root

    def __getitem__(
        self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
    ) -> StorageKeyValueType:
        """Return an item from the storage."""
        return self.root[StorageKeyValueTypeAdapter.validate_python(key)]

    def __setitem__(
        self,
        key: StorageKeyValueTypeConvertible | StorageKeyValueType,
        value: StorageKeyValueTypeConvertible | StorageKeyValueType,
    ):  # noqa: SC200
        """Set an item in the storage."""
        self.root[StorageKeyValueTypeAdapter.validate_python(key)] = (
            StorageKeyValueTypeAdapter.validate_python(value)
        )

    def __delitem__(self, key: StorageKeyValueTypeConvertible | StorageKeyValueType):
        """Delete an item from the storage."""
        del self.root[StorageKeyValueTypeAdapter.validate_python(key)]

    def __iter__(self):
        """Return an iterator over the storage."""
        return iter(self.root)

    def __eq__(self, other) -> bool:
        """Return True if both storages are equal."""
        if not isinstance(other, Storage):
            return False
        return self.root == other.root

    def __ne__(self, other) -> bool:
        """Return True if both storages are not equal."""
        if not isinstance(other, Storage):
            return False
        return self.root != other.root

    def __bool__(self) -> bool:
        """Return True if the storage is not empty."""
        return any(v for v in self.root.values())

    def __add__(self, other: "Storage") -> "Storage":
        """Return a new storage that is the sum of two storages."""
        return Storage({**self.root, **other.root})

    def keys(self) -> set[StorageKeyValueType]:
        """Return the keys of the storage."""
        return set(self.root.keys())

    def set_next_slot(self, slot: int) -> "Storage":
        """Set the next slot to be used by `store_next`."""
        self._current_slot = slot
        return self

    def items(self):
        """Return the items of the storage."""
        return self.root.items()

    def store_next(
        self, value: StorageKeyValueTypeConvertible | StorageKeyValueType | bool, hint: str = ""
    ) -> StorageKeyValueType:
        """
        Store a value in the storage and returns the key where the value is stored.

        Increments the key counter so the next time this function is called,
        the next key is used.
        """
        slot = StorageKeyValueTypeAdapter.validate_python(self._current_slot)
        self._current_slot += 1
        if hint:
            self._hint_map[slot] = hint
        self[slot] = StorageKeyValueTypeAdapter.validate_python(value)
        return slot

    def peek_slot(self) -> int:
        """Peek the next slot that will be used by `store_next`."""
        return self._current_slot

    def contains(self, other: "Storage") -> bool:
        """
        Return True if self contains all keys with equal value as
        contained by second storage.
        Used for comparison with test expected post state and alloc returned
        by the transition tool.
        """
        for key in other.keys():
            if key not in self:
                return False
            if self[key] != other[key]:
                return False
        return True

    def must_contain(self, address: Address, other: "Storage"):
        """
        Succeeds only if self contains all keys with equal value as
        contained by second storage.
        Used for comparison with test expected post state and alloc returned
        by the transition tool.
        Raises detailed exception when a difference is found.
        """
        for key in other.keys():
            if key not in self:
                # storage[key]==0 is equal to missing storage
                if other[key] != 0:
                    raise Storage.MissingKeyError(key=key)
            elif self[key] != other[key]:
                raise Storage.KeyValueMismatchError(
                    address=address,
                    key=key,
                    want=self[key],
                    got=other[key],
                    hint=self._hint_map.get(key, ""),
                )

    def must_be_equal(self, address: Address, other: "Storage | None"):
        """Succeed only if "self" is equal to "other" storage."""
        # Test keys contained in both storage objects
        if other is None:
            other = Storage({})
        for key in self.keys() & other.keys():
            if self[key] != other[key]:
                raise Storage.KeyValueMismatchError(
                    address=address,
                    key=key,
                    want=self[key],
                    got=other[key],
                    hint=self._hint_map.get(key, ""),
                )

        # Test keys contained in either one of the storage objects
        for key in self.keys() ^ other.keys():
            if key in self:
                if self[key] != 0:
                    raise Storage.KeyValueMismatchError(
                        address=address,
                        key=key,
                        want=self[key],
                        got=0,
                        hint=self._hint_map.get(key, ""),
                    )

            elif other[key] != 0:
                raise Storage.KeyValueMismatchError(
                    address=address,
                    key=key,
                    want=0,
                    got=other[key],
                    hint=self._hint_map.get(key, ""),
                )

    def canary(self) -> "Storage":
        """
        Return a canary storage filled with non-zero values where the current storage expects
        zero values, to guarantee that the test overwrites the storage.
        """
        return Storage({key: HashInt(0xBA5E) for key in self.keys() if self[key] == 0})

StorageDictType: TypeAlias = Dict[str | int | bytes | SupportsBytes, str | int | bytes | SupportsBytes] class-attribute

Dictionary type to be used when defining an input to initialize a storage.

InvalidTypeError dataclass

Bases: Exception

Invalid type used when describing test's expected storage key or value.

Source code in src/ethereum_test_base_types/composite_types.py
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@dataclass(kw_only=True)
class InvalidTypeError(Exception):
    """Invalid type used when describing test's expected storage key or value."""

    key_or_value: Any

    def __init__(self, key_or_value: Any, *args):
        """Initialize the exception with the invalid type."""
        super().__init__(args)
        self.key_or_value = key_or_value

    def __str__(self):
        """Print exception string."""
        return f"invalid type for key/value: {self.key_or_value}"

__init__(key_or_value, *args)

Initialize the exception with the invalid type.

Source code in src/ethereum_test_base_types/composite_types.py
39
40
41
42
def __init__(self, key_or_value: Any, *args):
    """Initialize the exception with the invalid type."""
    super().__init__(args)
    self.key_or_value = key_or_value

__str__()

Print exception string.

Source code in src/ethereum_test_base_types/composite_types.py
44
45
46
def __str__(self):
    """Print exception string."""
    return f"invalid type for key/value: {self.key_or_value}"

InvalidValueError dataclass

Bases: Exception

Invalid value used when describing test's expected storage key or value.

Source code in src/ethereum_test_base_types/composite_types.py
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@dataclass(kw_only=True)
class InvalidValueError(Exception):
    """
    Invalid value used when describing test's expected storage key or
    value.
    """

    key_or_value: Any

    def __init__(self, key_or_value: Any, *args):
        """Initialize the exception with the invalid value."""
        super().__init__(args)
        self.key_or_value = key_or_value

    def __str__(self):
        """Print exception string."""
        return f"invalid value for key/value: {self.key_or_value}"

__init__(key_or_value, *args)

Initialize the exception with the invalid value.

Source code in src/ethereum_test_base_types/composite_types.py
57
58
59
60
def __init__(self, key_or_value: Any, *args):
    """Initialize the exception with the invalid value."""
    super().__init__(args)
    self.key_or_value = key_or_value

__str__()

Print exception string.

Source code in src/ethereum_test_base_types/composite_types.py
62
63
64
def __str__(self):
    """Print exception string."""
    return f"invalid value for key/value: {self.key_or_value}"

MissingKeyError dataclass

Bases: Exception

Test expected to find a storage key set but key was missing.

Source code in src/ethereum_test_base_types/composite_types.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
@dataclass(kw_only=True)
class MissingKeyError(Exception):
    """Test expected to find a storage key set but key was missing."""

    key: int

    def __init__(self, key: int, *args):
        """Initialize the exception with the missing key."""
        super().__init__(args)
        self.key = key

    def __str__(self):
        """Print exception string."""
        return "key {0} not found in storage".format(Hash(self.key))

__init__(key, *args)

Initialize the exception with the missing key.

Source code in src/ethereum_test_base_types/composite_types.py
72
73
74
75
def __init__(self, key: int, *args):
    """Initialize the exception with the missing key."""
    super().__init__(args)
    self.key = key

__str__()

Print exception string.

Source code in src/ethereum_test_base_types/composite_types.py
77
78
79
def __str__(self):
    """Print exception string."""
    return "key {0} not found in storage".format(Hash(self.key))

KeyValueMismatchError dataclass

Bases: Exception

Test expected a certain value in a storage key but value found was different.

Source code in src/ethereum_test_base_types/composite_types.py
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
@dataclass(kw_only=True)
class KeyValueMismatchError(Exception):
    """
    Test expected a certain value in a storage key but value found
    was different.
    """

    address: Address
    key: int
    want: int
    got: int
    hint: str

    def __init__(self, address: Address, key: int, want: int, got: int, hint: str = "", *args):
        """Initialize the exception with the address, key, wanted and got values."""
        super().__init__(args)
        self.address = address
        self.key = key
        self.want = want
        self.got = got
        self.hint = hint

    def __str__(self):
        """Print exception string."""
        label_str = ""
        if self.address.label is not None:
            label_str = f" ({self.address.label})"
        return (
            f"incorrect value in address {self.address}{label_str} for "
            + f"key {Hash(self.key)}{f' ({self.hint})' if self.hint else ''}:"
            + f" want {HexNumber(self.want)} (dec:{int(self.want)}),"
            + f" got {HexNumber(self.got)} (dec:{int(self.got)})"
        )

__init__(address, key, want, got, hint='', *args)

Initialize the exception with the address, key, wanted and got values.

Source code in src/ethereum_test_base_types/composite_types.py
 94
 95
 96
 97
 98
 99
100
101
def __init__(self, address: Address, key: int, want: int, got: int, hint: str = "", *args):
    """Initialize the exception with the address, key, wanted and got values."""
    super().__init__(args)
    self.address = address
    self.key = key
    self.want = want
    self.got = got
    self.hint = hint

__str__()

Print exception string.

Source code in src/ethereum_test_base_types/composite_types.py
103
104
105
106
107
108
109
110
111
112
113
def __str__(self):
    """Print exception string."""
    label_str = ""
    if self.address.label is not None:
        label_str = f" ({self.address.label})"
    return (
        f"incorrect value in address {self.address}{label_str} for "
        + f"key {Hash(self.key)}{f' ({self.hint})' if self.hint else ''}:"
        + f" want {HexNumber(self.want)} (dec:{int(self.want)}),"
        + f" got {HexNumber(self.got)} (dec:{int(self.got)})"
    )

__contains__(key)

Check for an item in the storage.

Source code in src/ethereum_test_base_types/composite_types.py
115
116
117
def __contains__(self, key: StorageKeyValueTypeConvertible | StorageKeyValueType) -> bool:
    """Check for an item in the storage."""
    return StorageKeyValueTypeAdapter.validate_python(key) in self.root

__getitem__(key)

Return an item from the storage.

Source code in src/ethereum_test_base_types/composite_types.py
119
120
121
122
123
def __getitem__(
    self, key: StorageKeyValueTypeConvertible | StorageKeyValueType
) -> StorageKeyValueType:
    """Return an item from the storage."""
    return self.root[StorageKeyValueTypeAdapter.validate_python(key)]

__setitem__(key, value)

Set an item in the storage.

Source code in src/ethereum_test_base_types/composite_types.py
125
126
127
128
129
130
131
132
133
def __setitem__(
    self,
    key: StorageKeyValueTypeConvertible | StorageKeyValueType,
    value: StorageKeyValueTypeConvertible | StorageKeyValueType,
):  # noqa: SC200
    """Set an item in the storage."""
    self.root[StorageKeyValueTypeAdapter.validate_python(key)] = (
        StorageKeyValueTypeAdapter.validate_python(value)
    )

__delitem__(key)

Delete an item from the storage.

Source code in src/ethereum_test_base_types/composite_types.py
135
136
137
def __delitem__(self, key: StorageKeyValueTypeConvertible | StorageKeyValueType):
    """Delete an item from the storage."""
    del self.root[StorageKeyValueTypeAdapter.validate_python(key)]

__iter__()

Return an iterator over the storage.

Source code in src/ethereum_test_base_types/composite_types.py
139
140
141
def __iter__(self):
    """Return an iterator over the storage."""
    return iter(self.root)

__eq__(other)

Return True if both storages are equal.

Source code in src/ethereum_test_base_types/composite_types.py
143
144
145
146
147
def __eq__(self, other) -> bool:
    """Return True if both storages are equal."""
    if not isinstance(other, Storage):
        return False
    return self.root == other.root

__ne__(other)

Return True if both storages are not equal.

Source code in src/ethereum_test_base_types/composite_types.py
149
150
151
152
153
def __ne__(self, other) -> bool:
    """Return True if both storages are not equal."""
    if not isinstance(other, Storage):
        return False
    return self.root != other.root

__bool__()

Return True if the storage is not empty.

Source code in src/ethereum_test_base_types/composite_types.py
155
156
157
def __bool__(self) -> bool:
    """Return True if the storage is not empty."""
    return any(v for v in self.root.values())

__add__(other)

Return a new storage that is the sum of two storages.

Source code in src/ethereum_test_base_types/composite_types.py
159
160
161
def __add__(self, other: "Storage") -> "Storage":
    """Return a new storage that is the sum of two storages."""
    return Storage({**self.root, **other.root})

keys()

Return the keys of the storage.

Source code in src/ethereum_test_base_types/composite_types.py
163
164
165
def keys(self) -> set[StorageKeyValueType]:
    """Return the keys of the storage."""
    return set(self.root.keys())

set_next_slot(slot)

Set the next slot to be used by store_next.

Source code in src/ethereum_test_base_types/composite_types.py
167
168
169
170
def set_next_slot(self, slot: int) -> "Storage":
    """Set the next slot to be used by `store_next`."""
    self._current_slot = slot
    return self

items()

Return the items of the storage.

Source code in src/ethereum_test_base_types/composite_types.py
172
173
174
def items(self):
    """Return the items of the storage."""
    return self.root.items()

store_next(value, hint='')

Store a value in the storage and returns the key where the value is stored.

Increments the key counter so the next time this function is called, the next key is used.

Source code in src/ethereum_test_base_types/composite_types.py
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
def store_next(
    self, value: StorageKeyValueTypeConvertible | StorageKeyValueType | bool, hint: str = ""
) -> StorageKeyValueType:
    """
    Store a value in the storage and returns the key where the value is stored.

    Increments the key counter so the next time this function is called,
    the next key is used.
    """
    slot = StorageKeyValueTypeAdapter.validate_python(self._current_slot)
    self._current_slot += 1
    if hint:
        self._hint_map[slot] = hint
    self[slot] = StorageKeyValueTypeAdapter.validate_python(value)
    return slot

peek_slot()

Peek the next slot that will be used by store_next.

Source code in src/ethereum_test_base_types/composite_types.py
192
193
194
def peek_slot(self) -> int:
    """Peek the next slot that will be used by `store_next`."""
    return self._current_slot

contains(other)

Return True if self contains all keys with equal value as contained by second storage. Used for comparison with test expected post state and alloc returned by the transition tool.

Source code in src/ethereum_test_base_types/composite_types.py
196
197
198
199
200
201
202
203
204
205
206
207
208
def contains(self, other: "Storage") -> bool:
    """
    Return True if self contains all keys with equal value as
    contained by second storage.
    Used for comparison with test expected post state and alloc returned
    by the transition tool.
    """
    for key in other.keys():
        if key not in self:
            return False
        if self[key] != other[key]:
            return False
    return True

must_contain(address, other)

Succeeds only if self contains all keys with equal value as contained by second storage. Used for comparison with test expected post state and alloc returned by the transition tool. Raises detailed exception when a difference is found.

Source code in src/ethereum_test_base_types/composite_types.py
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
def must_contain(self, address: Address, other: "Storage"):
    """
    Succeeds only if self contains all keys with equal value as
    contained by second storage.
    Used for comparison with test expected post state and alloc returned
    by the transition tool.
    Raises detailed exception when a difference is found.
    """
    for key in other.keys():
        if key not in self:
            # storage[key]==0 is equal to missing storage
            if other[key] != 0:
                raise Storage.MissingKeyError(key=key)
        elif self[key] != other[key]:
            raise Storage.KeyValueMismatchError(
                address=address,
                key=key,
                want=self[key],
                got=other[key],
                hint=self._hint_map.get(key, ""),
            )

must_be_equal(address, other)

Succeed only if "self" is equal to "other" storage.

Source code in src/ethereum_test_base_types/composite_types.py
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
def must_be_equal(self, address: Address, other: "Storage | None"):
    """Succeed only if "self" is equal to "other" storage."""
    # Test keys contained in both storage objects
    if other is None:
        other = Storage({})
    for key in self.keys() & other.keys():
        if self[key] != other[key]:
            raise Storage.KeyValueMismatchError(
                address=address,
                key=key,
                want=self[key],
                got=other[key],
                hint=self._hint_map.get(key, ""),
            )

    # Test keys contained in either one of the storage objects
    for key in self.keys() ^ other.keys():
        if key in self:
            if self[key] != 0:
                raise Storage.KeyValueMismatchError(
                    address=address,
                    key=key,
                    want=self[key],
                    got=0,
                    hint=self._hint_map.get(key, ""),
                )

        elif other[key] != 0:
            raise Storage.KeyValueMismatchError(
                address=address,
                key=key,
                want=0,
                got=other[key],
                hint=self._hint_map.get(key, ""),
            )

canary()

Return a canary storage filled with non-zero values where the current storage expects zero values, to guarantee that the test overwrites the storage.

Source code in src/ethereum_test_base_types/composite_types.py
268
269
270
271
272
273
def canary(self) -> "Storage":
    """
    Return a canary storage filled with non-zero values where the current storage expects
    zero values, to guarantee that the test overwrites the storage.
    """
    return Storage({key: HashInt(0xBA5E) for key in self.keys() if self[key] == 0})

to_bytes(input_bytes)

Convert multiple types into bytes.

Source code in src/ethereum_test_base_types/conversions.py
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
def to_bytes(input_bytes: BytesConvertible) -> bytes:
    """Convert multiple types into bytes."""
    if input_bytes is None:
        raise Exception("Cannot convert `None` input to bytes")

    if (
        isinstance(input_bytes, SupportsBytes)
        or isinstance(input_bytes, bytes)
        or isinstance(input_bytes, list)
    ):
        return bytes(input_bytes)

    if isinstance(input_bytes, str):
        # We can have a hex representation of bytes with spaces for readability
        input_bytes = sub(r"\s+", "", input_bytes)
        if input_bytes.startswith("0x"):
            input_bytes = input_bytes[2:]
        if len(input_bytes) % 2 == 1:
            input_bytes = "0" + input_bytes
        return bytes.fromhex(input_bytes)

    raise Exception("invalid type for `bytes`")

to_hex(input_bytes)

Convert multiple types into a bytes hex string.

Source code in src/ethereum_test_base_types/conversions.py
87
88
89
def to_hex(input_bytes: BytesConvertible) -> str:
    """Convert multiple types into a bytes hex string."""
    return "0x" + to_bytes(input_bytes).hex()

to_json(input_model)

Convert a model to its json data representation.

Source code in src/ethereum_test_base_types/json.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
def to_json(
    input_model: (
        EthereumTestBaseModel
        | EthereumTestRootModel
        | AnyStr
        | List[EthereumTestBaseModel | EthereumTestRootModel | AnyStr]
    ),
) -> Any:
    """Convert a model to its json data representation."""
    if isinstance(input_model, list):
        return [to_json(item) for item in input_model]
    elif isinstance(input_model, (EthereumTestBaseModel, EthereumTestRootModel)):
        return input_model.model_dump(mode="json", by_alias=True, exclude_none=True)
    else:
        return str(input_model)

CamelModel

Bases: CopyValidateModel

A base model that converts field names to camel case when serializing.

For example, the field name current_timestamp in a Python model will be represented as currentTimestamp when it is serialized to json.

Source code in src/ethereum_test_base_types/pydantic.py
35
36
37
38
39
40
41
42
43
44
45
46
47
class CamelModel(CopyValidateModel):
    """
    A base model that converts field names to camel case when serializing.

    For example, the field name `current_timestamp` in a Python model will be represented
    as `currentTimestamp` when it is serialized to json.
    """

    model_config = ConfigDict(
        alias_generator=to_camel,
        populate_by_name=True,
        validate_default=True,
    )

EthereumTestBaseModel

Bases: BaseModel, ModelCustomizationsMixin

Base model for all models for Ethereum tests.

Source code in src/ethereum_test_base_types/pydantic.py
15
16
17
18
class EthereumTestBaseModel(BaseModel, ModelCustomizationsMixin):
    """Base model for all models for Ethereum tests."""

    pass

EthereumTestRootModel

Bases: RootModel[RootModelRootType], ModelCustomizationsMixin

Base model for all models for Ethereum tests.

Source code in src/ethereum_test_base_types/pydantic.py
21
22
23
24
class EthereumTestRootModel(RootModel[RootModelRootType], ModelCustomizationsMixin):
    """Base model for all models for Ethereum tests."""

    root: Any

ReferenceSpec

Reference Specification Description Abstract Class.

Source code in src/ethereum_test_base_types/reference_spec/reference_spec.py
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
class ReferenceSpec:
    """Reference Specification Description Abstract Class."""

    @abstractmethod
    def name(self) -> str:
        """Return the name of the spec."""
        pass

    @abstractmethod
    def has_known_version(self) -> bool:
        """Return true if the reference spec object is hard-coded with a latest known version."""
        pass

    @abstractmethod
    def known_version(self) -> str:
        """Return the latest known version in the reference."""
        pass

    @abstractmethod
    def api_url(self) -> str:
        """Return the URL required to poll the version from an API, if needed."""
        pass

    @abstractmethod
    def latest_version(self) -> str:
        """Return a digest that points to the latest version of the spec."""
        pass

    @abstractmethod
    def is_outdated(self) -> bool:
        """
        Check whether the reference specification has been updated since the
        test was last updated.
        """
        pass

    @abstractmethod
    def write_info(self, info: Dict[str, str]):
        """Write info about the reference specification used into the output fixture."""
        pass

    @staticmethod
    @abstractmethod
    def parseable_from_module(module_dict: Dict[str, Any]) -> bool:
        """Check whether the module's dict contains required reference spec information."""
        pass

    @staticmethod
    @abstractmethod
    def parse_from_module(module_dict: Dict[str, Any]) -> "ReferenceSpec":
        """Parse the module's dict into a reference spec."""
        pass

name() abstractmethod

Return the name of the spec.

Source code in src/ethereum_test_base_types/reference_spec/reference_spec.py
32
33
34
35
@abstractmethod
def name(self) -> str:
    """Return the name of the spec."""
    pass

has_known_version() abstractmethod

Return true if the reference spec object is hard-coded with a latest known version.

Source code in src/ethereum_test_base_types/reference_spec/reference_spec.py
37
38
39
40
@abstractmethod
def has_known_version(self) -> bool:
    """Return true if the reference spec object is hard-coded with a latest known version."""
    pass

known_version() abstractmethod

Return the latest known version in the reference.

Source code in src/ethereum_test_base_types/reference_spec/reference_spec.py
42
43
44
45
@abstractmethod
def known_version(self) -> str:
    """Return the latest known version in the reference."""
    pass

api_url() abstractmethod

Return the URL required to poll the version from an API, if needed.

Source code in src/ethereum_test_base_types/reference_spec/reference_spec.py
47
48
49
50
@abstractmethod
def api_url(self) -> str:
    """Return the URL required to poll the version from an API, if needed."""
    pass

latest_version() abstractmethod

Return a digest that points to the latest version of the spec.

Source code in src/ethereum_test_base_types/reference_spec/reference_spec.py
52
53
54
55
@abstractmethod
def latest_version(self) -> str:
    """Return a digest that points to the latest version of the spec."""
    pass

is_outdated() abstractmethod

Check whether the reference specification has been updated since the test was last updated.

Source code in src/ethereum_test_base_types/reference_spec/reference_spec.py
57
58
59
60
61
62
63
@abstractmethod
def is_outdated(self) -> bool:
    """
    Check whether the reference specification has been updated since the
    test was last updated.
    """
    pass

write_info(info) abstractmethod

Write info about the reference specification used into the output fixture.

Source code in src/ethereum_test_base_types/reference_spec/reference_spec.py
65
66
67
68
@abstractmethod
def write_info(self, info: Dict[str, str]):
    """Write info about the reference specification used into the output fixture."""
    pass

parseable_from_module(module_dict) abstractmethod staticmethod

Check whether the module's dict contains required reference spec information.

Source code in src/ethereum_test_base_types/reference_spec/reference_spec.py
70
71
72
73
74
@staticmethod
@abstractmethod
def parseable_from_module(module_dict: Dict[str, Any]) -> bool:
    """Check whether the module's dict contains required reference spec information."""
    pass

parse_from_module(module_dict) abstractmethod staticmethod

Parse the module's dict into a reference spec.

Source code in src/ethereum_test_base_types/reference_spec/reference_spec.py
76
77
78
79
80
@staticmethod
@abstractmethod
def parse_from_module(module_dict: Dict[str, Any]) -> "ReferenceSpec":
    """Parse the module's dict into a reference spec."""
    pass