ethereum.forks.bpo5.stateethereum.forks.amsterdam.state

State.

.. contents:: Table of Contents :backlinks: none :local:

Introduction

The state contains all information that is preserved between transactions.

It consists of a main account trie and storage tries for each contract.

There is a distinction between an account that does not exist and EMPTY_ACCOUNT.

State

Contains all information that is preserved between transactions.

33
@dataclass
class State:

_main_trie

39
    _main_trie: Trie[Address, Optional[Account]] = field(
40
        default_factory=lambda: Trie(secured=True, default=None)
41
    )

_storage_tries

42
    _storage_tries: Dict[Address, Trie[Bytes32, U256]] = field(
43
        default_factory=dict
44
    )

_snapshots

45
    _snapshots: List[
46
        Tuple[
47
            Trie[Address, Optional[Account]],
48
            Dict[Address, Trie[Bytes32, U256]],
49
        ]
50
    ] = field(default_factory=list)

created_accounts

51
    created_accounts: Set[Address] = field(default_factory=set)

TransientStorage

Contains all information that is preserved between message calls within a transaction.

54
@dataclass
class TransientStorage:

_tries

61
    _tries: Dict[Address, Trie[Bytes32, U256]] = field(default_factory=dict)

_snapshots

62
    _snapshots: List[Dict[Address, Trie[Bytes32, U256]]] = field(
63
        default_factory=list
64
    )

close_state

Free resources held by the state. Used by optimized implementations to release file descriptors.

def close_state(state: State) -> None:
68
    """
69
    Free resources held by the state. Used by optimized implementations to
70
    release file descriptors.
71
    """
72
    del state._main_trie
73
    del state._storage_tries
74
    del state._snapshots
75
    del state.created_accounts

begin_transaction

Start a state transaction.

Transactions are entirely implicit and can be nested. It is not possible to calculate the state root during a transaction.

Parameters

state : State The state. transient_storage : TransientStorage The transient storage of the transaction.

def begin_transaction(state: State, ​​transient_storage: TransientStorage) -> None:
81
    """
82
    Start a state transaction.
83
84
    Transactions are entirely implicit and can be nested. It is not possible to
85
    calculate the state root during a transaction.
86
87
    Parameters
88
    ----------
89
    state : State
90
        The state.
91
    transient_storage : TransientStorage
92
        The transient storage of the transaction.
93
94
    """
95
    state._snapshots.append(
96
        (
97
            copy_trie(state._main_trie),
98
            {k: copy_trie(t) for (k, t) in state._storage_tries.items()},
99
        )
100
    )
101
    transient_storage._snapshots.append(
102
        {k: copy_trie(t) for (k, t) in transient_storage._tries.items()}
103
    )

commit_transaction

Commit a state transaction.

Parameters

state : State The state. transient_storage : TransientStorage The transient storage of the transaction.

def commit_transaction(state: State, ​​transient_storage: TransientStorage) -> None:
109
    """
110
    Commit a state transaction.
111
112
    Parameters
113
    ----------
114
    state : State
115
        The state.
116
    transient_storage : TransientStorage
117
        The transient storage of the transaction.
118
119
    """
120
    state._snapshots.pop()
121
    if not state._snapshots:
122
        state.created_accounts.clear()
123
124
    transient_storage._snapshots.pop()

rollback_transaction

Rollback a state transaction, resetting the state to the point when the corresponding begin_transaction() call was made.

Parameters

state : State The state. transient_storage : TransientStorage The transient storage of the transaction.

def rollback_transaction(state: State, ​​transient_storage: TransientStorage) -> None:
130
    """
131
    Rollback a state transaction, resetting the state to the point when the
132
    corresponding `begin_transaction()` call was made.
133
134
    Parameters
135
    ----------
136
    state : State
137
        The state.
138
    transient_storage : TransientStorage
139
        The transient storage of the transaction.
140
141
    """
142
    state._main_trie, state._storage_tries = state._snapshots.pop()
143
    if not state._snapshots:
144
        state.created_accounts.clear()
145
146
    transient_storage._tries = transient_storage._snapshots.pop()

get_account

Get the Account object at an address. Returns EMPTY_ACCOUNT if there is no account at the address.

Use get_account_optional() if you care about the difference between a non-existent account and EMPTY_ACCOUNT.

Parameters

state: State The state address : Address Address to lookup.

Returns

account : Account Account at address.

def get_account(state: State, ​​address: Address) -> Account:
150
    """
151
    Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there
152
    is no account at the address.
153
154
    Use `get_account_optional()` if you care about the difference between a
155
    non-existent account and `EMPTY_ACCOUNT`.
156
157
    Parameters
158
    ----------
159
    state: `State`
160
        The state
161
    address : `Address`
162
        Address to lookup.
163
164
    Returns
165
    -------
166
    account : `Account`
167
        Account at address.
168
169
    """
170
    account = get_account_optional(state, address)
171
    if isinstance(account, Account):
172
        return account
173
    else:
174
        return EMPTY_ACCOUNT

get_account_optional

Get the Account object at an address. Returns None (rather than EMPTY_ACCOUNT) if there is no account at the address.

Parameters

state: State The state address : Address Address to lookup.

Returns

account : Account Account at address.

def get_account_optional(state: State, ​​address: Address) -> Optional[Account]:
178
    """
179
    Get the `Account` object at an address. Returns `None` (rather than
180
    `EMPTY_ACCOUNT`) if there is no account at the address.
181
182
    Parameters
183
    ----------
184
    state: `State`
185
        The state
186
    address : `Address`
187
        Address to lookup.
188
189
    Returns
190
    -------
191
    account : `Account`
192
        Account at address.
193
194
    """
195
    account = trie_get(state._main_trie, address)
196
    return account

set_account

Set the Account object at an address. Setting to None deletes the account (but not its storage, see destroy_account()).

Parameters

state: State The state address : Address Address to set. account : Account Account to set at address.

def set_account(state: State, ​​address: Address, ​​account: Optional[Account]) -> None:
202
    """
203
    Set the `Account` object at an address. Setting to `None` deletes
204
    the account (but not its storage, see `destroy_account()`).
205
206
    Parameters
207
    ----------
208
    state: `State`
209
        The state
210
    address : `Address`
211
        Address to set.
212
    account : `Account`
213
        Account to set at address.
214
215
    """
216
    trie_set(state._main_trie, address, account)

destroy_account

Completely remove the account at address and all of its storage.

This function is made available exclusively for the SELFDESTRUCT opcode. It is expected that SELFDESTRUCT will be disabled in a future hardfork and this function will be removed.

Parameters

state: State The state address : Address Address of account to destroy.

def destroy_account(state: State, ​​address: Address) -> None:
220
    """
221
    Completely remove the account at `address` and all of its storage.
222
223
    This function is made available exclusively for the `SELFDESTRUCT`
224
    opcode. It is expected that `SELFDESTRUCT` will be disabled in a future
225
    hardfork and this function will be removed.
226
227
    Parameters
228
    ----------
229
    state: `State`
230
        The state
231
    address : `Address`
232
        Address of account to destroy.
233
234
    """
235
    destroy_storage(state, address)
236
    set_account(state, address, None)

destroy_storage

Completely remove the storage at address.

Parameters

state: State The state address : Address Address of account whose storage is to be deleted.

def destroy_storage(state: State, ​​address: Address) -> None:
240
    """
241
    Completely remove the storage at `address`.
242
243
    Parameters
244
    ----------
245
    state: `State`
246
        The state
247
    address : `Address`
248
        Address of account whose storage is to be deleted.
249
250
    """
251
    if address in state._storage_tries:
252
        del state._storage_tries[address]

mark_account_created

Mark an account as having been created in the current transaction. This information is used by get_storage_original() to handle an obscure edgecase, and to respect the constraints added to SELFDESTRUCT by EIP-6780.

The marker is not removed even if the account creation reverts. Since the account cannot have had code prior to its creation and can't call get_storage_original(), this is harmless.

Parameters

state: State The state address : Address Address of the account that has been created.

def mark_account_created(state: State, ​​address: Address) -> None:
256
    """
257
    Mark an account as having been created in the current transaction.
258
    This information is used by `get_storage_original()` to handle an obscure
259
    edgecase, and to respect the constraints added to SELFDESTRUCT by
260
    EIP-6780.
261
262
    The marker is not removed even if the account creation reverts. Since the
263
    account cannot have had code prior to its creation and can't call
264
    `get_storage_original()`, this is harmless.
265
266
    Parameters
267
    ----------
268
    state: `State`
269
        The state
270
    address : `Address`
271
        Address of the account that has been created.
272
273
    """
274
    state.created_accounts.add(address)

get_storage

Get a value at a storage key on an account. Returns U256(0) if the storage key has not been set previously.

Parameters

state: State The state address : Address Address of the account. key : Bytes Key to lookup.

Returns

value : U256 Value at the key.

def get_storage(state: State, ​​address: Address, ​​key: Bytes32) -> U256:
278
    """
279
    Get a value at a storage key on an account. Returns `U256(0)` if the
280
    storage key has not been set previously.
281
282
    Parameters
283
    ----------
284
    state: `State`
285
        The state
286
    address : `Address`
287
        Address of the account.
288
    key : `Bytes`
289
        Key to lookup.
290
291
    Returns
292
    -------
293
    value : `U256`
294
        Value at the key.
295
296
    """
297
    trie = state._storage_tries.get(address)
298
    if trie is None:
299
        return U256(0)
300
301
    value = trie_get(trie, key)
302
303
    assert isinstance(value, U256)
304
    return value

set_storage

Set a value at a storage key on an account. Setting to U256(0) deletes the key.

Parameters

state: State The state address : Address Address of the account. key : Bytes Key to set. value : U256 Value to set at the key.

def set_storage(state: State, ​​address: Address, ​​key: Bytes32, ​​value: U256) -> None:
310
    """
311
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
312
    the key.
313
314
    Parameters
315
    ----------
316
    state: `State`
317
        The state
318
    address : `Address`
319
        Address of the account.
320
    key : `Bytes`
321
        Key to set.
322
    value : `U256`
323
        Value to set at the key.
324
325
    """
326
    assert trie_get(state._main_trie, address) is not None
327
328
    trie = state._storage_tries.get(address)
329
    if trie is None:
330
        trie = Trie(secured=True, default=U256(0))
331
        state._storage_tries[address] = trie
332
    trie_set(trie, key, value)
333
    if trie._data == {}:
334
        del state._storage_tries[address]

storage_root

Calculate the storage root of an account.

Parameters

state: The state address : Address of the account.

Returns

root : Root Storage root of the account.

def storage_root(state: State, ​​address: Address) -> Root:
338
    """
339
    Calculate the storage root of an account.
340
341
    Parameters
342
    ----------
343
    state:
344
        The state
345
    address :
346
        Address of the account.
347
348
    Returns
349
    -------
350
    root : `Root`
351
        Storage root of the account.
352
353
    """
354
    assert not state._snapshots
355
    if address in state._storage_tries:
356
        return root(state._storage_tries[address])
357
    else:
358
        return EMPTY_TRIE_ROOT

state_root

Calculate the state root.

Parameters

state: The current state.

Returns

root : Root The state root.

def state_root(state: State) -> Root:
362
    """
363
    Calculate the state root.
364
365
    Parameters
366
    ----------
367
    state:
368
        The current state.
369
370
    Returns
371
    -------
372
    root : `Root`
373
        The state root.
374
375
    """
376
    assert not state._snapshots
377
378
    def get_storage_root(address: Address) -> Root:
379
        return storage_root(state, address)
380
381
    return root(state._main_trie, get_storage_root=get_storage_root)

account_exists

Checks if an account exists in the state trie.

Parameters

state: The state address: Address of the account that needs to be checked.

Returns

account_exists : bool True if account exists in the state trie, False otherwise

def account_exists(state: State, ​​address: Address) -> bool:
385
    """
386
    Checks if an account exists in the state trie.
387
388
    Parameters
389
    ----------
390
    state:
391
        The state
392
    address:
393
        Address of the account that needs to be checked.
394
395
    Returns
396
    -------
397
    account_exists : `bool`
398
        True if account exists in the state trie, False otherwise
399
400
    """
401
    return get_account_optional(state, address) is not None

account_has_code_or_nonce

Checks if an account has non-zero nonce or non-empty code.

Parameters

state: The state address: Address of the account that needs to be checked.

Returns

has_code_or_nonce : bool True if the account has non-zero nonce or non-empty code, False otherwise.

def account_has_code_or_nonce(state: State, ​​address: Address) -> bool:
405
    """
406
    Checks if an account has non-zero nonce or non-empty code.
407
408
    Parameters
409
    ----------
410
    state:
411
        The state
412
    address:
413
        Address of the account that needs to be checked.
414
415
    Returns
416
    -------
417
    has_code_or_nonce : `bool`
418
        True if the account has non-zero nonce or non-empty code,
419
        False otherwise.
420
421
    """
422
    account = get_account(state, address)
423
    return account.nonce != Uint(0) or account.code != b""

account_has_storage

Checks if an account has storage.

Parameters

state: The state address: Address of the account that needs to be checked.

Returns

has_storage : bool True if the account has storage, False otherwise.

def account_has_storage(state: State, ​​address: Address) -> bool:
427
    """
428
    Checks if an account has storage.
429
430
    Parameters
431
    ----------
432
    state:
433
        The state
434
    address:
435
        Address of the account that needs to be checked.
436
437
    Returns
438
    -------
439
    has_storage : `bool`
440
        True if the account has storage, False otherwise.
441
442
    """
443
    return address in state._storage_tries

account_exists_and_is_empty

Checks if an account exists and has zero nonce, empty code and zero balance.

Parameters

state: The state address: Address of the account that needs to be checked.

Returns

exists_and_is_empty : bool True if an account exists and has zero nonce, empty code and zero balance, False otherwise.

def account_exists_and_is_empty(state: State, ​​address: Address) -> bool:
447
    """
448
    Checks if an account exists and has zero nonce, empty code and zero
449
    balance.
450
451
    Parameters
452
    ----------
453
    state:
454
        The state
455
    address:
456
        Address of the account that needs to be checked.
457
458
    Returns
459
    -------
460
    exists_and_is_empty : `bool`
461
        True if an account exists and has zero nonce, empty code and zero
462
        balance, False otherwise.
463
464
    """
465
    account = get_account_optional(state, address)
466
    return (
467
        account is not None
468
        and account.nonce == Uint(0)
469
        and account.code == b""
470
        and account.balance == 0
471
    )

is_account_alive

Check whether an account is both in the state and non-empty.

Parameters

state: The state address: Address of the account that needs to be checked.

Returns

is_alive : bool True if the account is alive.

def is_account_alive(state: State, ​​address: Address) -> bool:
475
    """
476
    Check whether an account is both in the state and non-empty.
477
478
    Parameters
479
    ----------
480
    state:
481
        The state
482
    address:
483
        Address of the account that needs to be checked.
484
485
    Returns
486
    -------
487
    is_alive : `bool`
488
        True if the account is alive.
489
490
    """
491
    account = get_account_optional(state, address)
492
    return account is not None and account != EMPTY_ACCOUNT

modify_state

Modify an Account in the State. If, after modification, the account exists and has zero nonce, empty code, and zero balance, it is destroyed.

def modify_state(state: State, ​​address: Address, ​​f: Callable[[Account], None]) -> None:
498
    """
499
    Modify an `Account` in the `State`. If, after modification, the account
500
    exists and has zero nonce, empty code, and zero balance, it is destroyed.
501
    """
502
    set_account(state, address, modify(get_account(state, address), f))
472
473
    account = get_account_optional(state, address)
474
    account_exists_and_is_empty = (
475
        account is not None
476
        and account.nonce == Uint(0)
477
        and account.code == b""
478
        and account.balance == 0
479
    )
480
481
    if account_exists_and_is_empty:
503
    if account_exists_and_is_empty(state, address):
504
        destroy_account(state, address)

move_ether

Move funds between accounts.

Parameters

state: The current state. sender_address: Address of the sender. recipient_address: Address of the recipient. amount: The amount to transfer.

def move_ether(state: State, ​​sender_address: Address, ​​recipient_address: Address, ​​amount: U256) -> None:
513
    """
514
    Move funds between accounts.
515
516
    Parameters
517
    ----------
518
    state:
519
        The current state.
520
    sender_address:
521
        Address of the sender.
522
    recipient_address:
523
        Address of the recipient.
524
    amount:
525
        The amount to transfer.
526
527
    """
528
529
    def reduce_sender_balance(sender: Account) -> None:
530
        if sender.balance < amount:
531
            raise AssertionError
532
        sender.balance -= amount
533
534
    def increase_recipient_balance(recipient: Account) -> None:
535
        recipient.balance += amount
536
537
    modify_state(state, sender_address, reduce_sender_balance)
538
    modify_state(state, recipient_address, increase_recipient_balance)

set_account_balance

Sets the balance of an account.

Parameters

state: The current state.

address: Address of the account whose nonce needs to be incremented.Address of the account whose balance needs to be set.

amount: The amount that needs to be set in the balance.

def set_account_balance(state: State, ​​address: Address, ​​amount: U256) -> None:
542
    """
543
    Sets the balance of an account.
544
545
    Parameters
546
    ----------
547
    state:
548
        The current state.
549
550
    address:
517
        Address of the account whose nonce needs to be incremented.
551
        Address of the account whose balance needs to be set.
552
553
    amount:
554
        The amount that needs to be set in the balance.
555
556
    """
557
558
    def set_balance(account: Account) -> None:
559
        account.balance = amount
560
561
    modify_state(state, address, set_balance)

increment_nonce

Increments the nonce of an account.

Parameters

state: The current state.

address: Address of the account whose nonce needs to be incremented.

def increment_nonce(state: State, ​​address: Address) -> None:
565
    """
566
    Increments the nonce of an account.
567
568
    Parameters
569
    ----------
570
    state:
571
        The current state.
572
573
    address:
574
        Address of the account whose nonce needs to be incremented.
575
576
    """
577
578
    def increase_nonce(sender: Account) -> None:
579
        sender.nonce += Uint(1)
580
581
    modify_state(state, address, increase_nonce)

set_code

Sets Account code.

Parameters

state: The current state.

address: Address of the account whose code needs to be updated.

code: The bytecode that needs to be set.

def set_code(state: State, ​​address: Address, ​​code: Bytes) -> None:
585
    """
586
    Sets Account code.
587
588
    Parameters
589
    ----------
590
    state:
591
        The current state.
592
593
    address:
594
        Address of the account whose code needs to be updated.
595
596
    code:
597
        The bytecode that needs to be set.
598
599
    """
600
601
    def write_code(sender: Account) -> None:
602
        sender.code = code
603
604
    modify_state(state, address, write_code)

set_authority_code

Sets authority account code for EIP-7702 delegation.

This function is used specifically for setting authority code within EIP-7702 Set Code Transactions.

Parameters

state: The current state.

address: Address of the authority account whose code needs to be set.

code: The delegation designation bytecode to set.

def set_authority_code(state: State, ​​address: Address, ​​code: Bytes) -> None:
608
    """
609
    Sets authority account code for EIP-7702 delegation.
610
611
    This function is used specifically for setting authority code within
612
    EIP-7702 Set Code Transactions.
613
614
    Parameters
615
    ----------
616
    state:
617
        The current state.
618
619
    address:
620
        Address of the authority account whose code needs to be set.
621
622
    code:
623
        The delegation designation bytecode to set.
624
625
    """
626
627
    def write_code(sender: Account) -> None:
628
        sender.code = code
629
630
    modify_state(state, address, write_code)

get_storage_original

Get the original value in a storage slot i.e. the value before the current transaction began. This function reads the value from the snapshots taken before executing the transaction.

Parameters

state: The current state. address: Address of the account to read the value from. key: Key of the storage slot.

def get_storage_original(state: State, ​​address: Address, ​​key: Bytes32) -> U256:
634
    """
635
    Get the original value in a storage slot i.e. the value before the current
636
    transaction began. This function reads the value from the snapshots taken
637
    before executing the transaction.
638
639
    Parameters
640
    ----------
641
    state:
642
        The current state.
643
    address:
644
        Address of the account to read the value from.
645
    key:
646
        Key of the storage slot.
647
648
    """
649
    # In the transaction where an account is created, its preexisting storage
650
    # is ignored.
651
    if address in state.created_accounts:
652
        return U256(0)
653
654
    _, original_trie = state._snapshots[0]
655
    original_account_trie = original_trie.get(address)
656
657
    if original_account_trie is None:
658
        original_value = U256(0)
659
    else:
660
        original_value = trie_get(original_account_trie, key)
661
662
    assert isinstance(original_value, U256)
663
664
    return original_value

get_transient_storage

Get a value at a storage key on an account from transient storage. Returns U256(0) if the storage key has not been set previously.

Parameters

transient_storage: TransientStorage The transient storage address : Address Address of the account. key : Bytes Key to lookup.

Returns

value : U256 Value at the key.

def get_transient_storage(transient_storage: TransientStorage, ​​address: Address, ​​key: Bytes32) -> U256:
670
    """
671
    Get a value at a storage key on an account from transient storage.
672
    Returns `U256(0)` if the storage key has not been set previously.
673
674
    Parameters
675
    ----------
676
    transient_storage: `TransientStorage`
677
        The transient storage
678
    address : `Address`
679
        Address of the account.
680
    key : `Bytes`
681
        Key to lookup.
682
683
    Returns
684
    -------
685
    value : `U256`
686
        Value at the key.
687
688
    """
689
    trie = transient_storage._tries.get(address)
690
    if trie is None:
691
        return U256(0)
692
693
    value = trie_get(trie, key)
694
695
    assert isinstance(value, U256)
696
    return value

set_transient_storage

Set a value at a storage key on an account. Setting to U256(0) deletes the key.

Parameters

transient_storage: TransientStorage The transient storage address : Address Address of the account. key : Bytes Key to set. value : U256 Value to set at the key.

def set_transient_storage(transient_storage: TransientStorage, ​​address: Address, ​​key: Bytes32, ​​value: U256) -> None:
705
    """
706
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
707
    the key.
708
709
    Parameters
710
    ----------
711
    transient_storage: `TransientStorage`
712
        The transient storage
713
    address : `Address`
714
        Address of the account.
715
    key : `Bytes`
716
        Key to set.
717
    value : `U256`
718
        Value to set at the key.
719
720
    """
721
    trie = transient_storage._tries.get(address)
722
    if trie is None:
723
        trie = Trie(secured=True, default=U256(0))
724
        transient_storage._tries[address] = trie
725
    trie_set(trie, key, value)
726
    if trie._data == {}:
727
        del transient_storage._tries[address]