ethereum.shanghai.stateethereum.cancun.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.

29
@dataclass
class State:

_main_trie

35
    _main_trie: Trie[Address, Optional[Account]] = field(
36
        default_factory=lambda: Trie(secured=True, default=None)
37
    )

_storage_tries

38
    _storage_tries: Dict[Address, Trie[Bytes, U256]] = field(
39
        default_factory=dict
40
    )

_snapshots

41
    _snapshots: List[
42
        Tuple[
43
            Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]]
44
        ]
45
    ] = field(default_factory=list)

created_accounts

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

TransientStorage

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

49
@dataclass
class TransientStorage:

_tries

56
    _tries: Dict[Address, Trie[Bytes, U256]] = field(default_factory=dict)

_snapshots

57
    _snapshots: List[Dict[Address, Trie[Bytes, U256]]] = field(
58
        default_factory=list
59
    )

close_state

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

def close_state(state: State) -> None:
63
    """
64
    Free resources held by the state. Used by optimized implementations to
65
    release file descriptors.
66
    """
67
    del state._main_trie
68
    del state._storage_tries
69
    del state._snapshots
70
    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:
76
    """
77
    Start a state transaction.
78
79
    Transactions are entirely implicit and can be nested. It is not possible to
80
    calculate the state root during a transaction.
81
82
    Parameters
83
    ----------
84
    state : State
85
        The state.
86
    transient_storage : TransientStorage
87
        The transient storage of the transaction.
88
    """
89
    state._snapshots.append(
90
        (
91
            copy_trie(state._main_trie),
92
            {k: copy_trie(t) for (k, t) in state._storage_tries.items()},
93
        )
94
    )
95
    transient_storage._snapshots.append(
96
        {k: copy_trie(t) for (k, t) in transient_storage._tries.items()}
97
    )

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:
103
    """
104
    Commit a state transaction.
105
106
    Parameters
107
    ----------
108
    state : State
109
        The state.
110
    transient_storage : TransientStorage
111
        The transient storage of the transaction.
112
    """
113
    state._snapshots.pop()
114
    if not state._snapshots:
91
        state.created_accounts.clear()
115
        state.created_accounts.clear()
116
117
    transient_storage._snapshots.pop()

rollback_transaction

Rollback a state transaction, resetting the state to the point when the corresponding start_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:
123
    """
124
    Rollback a state transaction, resetting the state to the point when the
125
    corresponding `start_transaction()` call was made.
126
127
    Parameters
128
    ----------
129
    state : State
130
        The state.
131
    transient_storage : TransientStorage
132
        The transient storage of the transaction.
133
    """
134
    state._main_trie, state._storage_tries = state._snapshots.pop()
135
    if not state._snapshots:
106
        state.created_accounts.clear()
136
        state.created_accounts.clear()
137
138
    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:
142
    """
143
    Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there
144
    is no account at the address.
145
146
    Use `get_account_optional()` if you care about the difference between a
147
    non-existent account and `EMPTY_ACCOUNT`.
148
149
    Parameters
150
    ----------
151
    state: `State`
152
        The state
153
    address : `Address`
154
        Address to lookup.
155
156
    Returns
157
    -------
158
    account : `Account`
159
        Account at address.
160
    """
161
    account = get_account_optional(state, address)
162
    if isinstance(account, Account):
163
        return account
164
    else:
165
        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]:
169
    """
170
    Get the `Account` object at an address. Returns `None` (rather than
171
    `EMPTY_ACCOUNT`) if there is no account at the address.
172
173
    Parameters
174
    ----------
175
    state: `State`
176
        The state
177
    address : `Address`
178
        Address to lookup.
179
180
    Returns
181
    -------
182
    account : `Account`
183
        Account at address.
184
    """
185
    account = trie_get(state._main_trie, address)
186
    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:
192
    """
193
    Set the `Account` object at an address. Setting to `None` deletes
194
    the account (but not its storage, see `destroy_account()`).
195
196
    Parameters
197
    ----------
198
    state: `State`
199
        The state
200
    address : `Address`
201
        Address to set.
202
    account : `Account`
203
        Account to set at address.
204
    """
205
    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:
209
    """
210
    Completely remove the account at `address` and all of its storage.
211
212
    This function is made available exclusively for the `SELFDESTRUCT`
213
    opcode. It is expected that `SELFDESTRUCT` will be disabled in a future
214
    hardfork and this function will be removed.
215
216
    Parameters
217
    ----------
218
    state: `State`
219
        The state
220
    address : `Address`
221
        Address of account to destroy.
222
    """
223
    destroy_storage(state, address)
224
    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:
228
    """
229
    Completely remove the storage at `address`.
230
231
    Parameters
232
    ----------
233
    state: `State`
234
        The state
235
    address : `Address`
236
        Address of account whose storage is to be deleted.
237
    """
238
    if address in state._storage_tries:
239
        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.

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:
243
    """
244
    Mark an account as having been created in the current transaction.
245
    This information is used by `get_storage_original()` to handle an obscure
246
    edgecase.
247
248
    The marker is not removed even if the account creation reverts. Since the
249
    account cannot have had code prior to its creation and can't call
250
    `get_storage_original()`, this is harmless.
251
252
    Parameters
253
    ----------
254
    state: `State`
255
        The state
256
    address : `Address`
257
        Address of the account that has been created.
258
    """
259
    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: Bytes) -> U256:
263
    """
264
    Get a value at a storage key on an account. Returns `U256(0)` if the
265
    storage key has not been set previously.
266
267
    Parameters
268
    ----------
269
    state: `State`
270
        The state
271
    address : `Address`
272
        Address of the account.
273
    key : `Bytes`
274
        Key to lookup.
275
276
    Returns
277
    -------
278
    value : `U256`
279
        Value at the key.
280
    """
281
    trie = state._storage_tries.get(address)
282
    if trie is None:
283
        return U256(0)
284
285
    value = trie_get(trie, key)
286
287
    assert isinstance(value, U256)
288
    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: Bytes, ​​value: U256) -> None:
294
    """
295
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
296
    the key.
297
298
    Parameters
299
    ----------
300
    state: `State`
301
        The state
302
    address : `Address`
303
        Address of the account.
304
    key : `Bytes`
305
        Key to set.
306
    value : `U256`
307
        Value to set at the key.
308
    """
309
    assert trie_get(state._main_trie, address) is not None
310
311
    trie = state._storage_tries.get(address)
312
    if trie is None:
313
        trie = Trie(secured=True, default=U256(0))
314
        state._storage_tries[address] = trie
315
    trie_set(trie, key, value)
316
    if trie._data == {}:
317
        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:
321
    """
322
    Calculate the storage root of an account.
323
324
    Parameters
325
    ----------
326
    state:
327
        The state
328
    address :
329
        Address of the account.
330
331
    Returns
332
    -------
333
    root : `Root`
334
        Storage root of the account.
335
    """
336
    assert not state._snapshots
337
    if address in state._storage_tries:
338
        return root(state._storage_tries[address])
339
    else:
340
        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:
344
    """
345
    Calculate the state root.
346
347
    Parameters
348
    ----------
349
    state:
350
        The current state.
351
352
    Returns
353
    -------
354
    root : `Root`
355
        The state root.
356
    """
357
    assert not state._snapshots
358
359
    def get_storage_root(address: Address) -> Root:
360
        return storage_root(state, address)
361
362
    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:
366
    """
367
    Checks if an account exists in the state trie
368
369
    Parameters
370
    ----------
371
    state:
372
        The state
373
    address:
374
        Address of the account that needs to be checked.
375
376
    Returns
377
    -------
378
    account_exists : `bool`
379
        True if account exists in the state trie, False otherwise
380
    """
381
    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 if an account has non zero nonce or non empty code, False otherwise.

def account_has_code_or_nonce(state: State, ​​address: Address) -> bool:
385
    """
386
    Checks if an account has non zero nonce or non empty code
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
    has_code_or_nonce : `bool`
398
        True if if an account has non zero nonce or non empty code,
399
        False otherwise.
400
    """
401
    account = get_account(state, address)
402
    return account.nonce != Uint(0) or account.code != b""

is_account_empty

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

Parameters

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

Returns

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

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

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:
431
    """
432
    Checks if an account exists and has zero nonce, empty code and zero
433
    balance.
434
435
    Parameters
436
    ----------
437
    state:
438
        The state
439
    address:
440
        Address of the account that needs to be checked.
441
442
    Returns
443
    -------
444
    exists_and_is_empty : `bool`
445
        True if an account exists and has zero nonce, empty code and zero
446
        balance, False otherwise.
447
    """
448
    account = get_account_optional(state, address)
449
    return (
450
        account is not None
451
        and account.nonce == Uint(0)
452
        and account.code == b""
453
        and account.balance == 0
454
    )

is_account_alive

Check whether is 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:
458
    """
459
    Check whether is an account is both in the state and non empty.
460
461
    Parameters
462
    ----------
463
    state:
464
        The state
465
    address:
466
        Address of the account that needs to be checked.
467
468
    Returns
469
    -------
470
    is_alive : `bool`
471
        True if the account is alive.
472
    """
473
    account = get_account_optional(state, address)
474
    if account is None:
475
        return False
476
    else:
477
        return not (
478
            account.nonce == Uint(0)
479
            and account.code == b""
480
            and account.balance == 0
481
        )

modify_state

Modify an Account in the State.

def modify_state(state: State, ​​address: Address, ​​f: Callable[[Account], None]) -> None:
487
    """
488
    Modify an `Account` in the `State`.
489
    """
490
    set_account(state, address, modify(get_account(state, address), f))

move_ether

Move funds between accounts.

def move_ether(state: State, ​​sender_address: Address, ​​recipient_address: Address, ​​amount: U256) -> None:
499
    """
500
    Move funds between accounts.
501
    """
502
503
    def reduce_sender_balance(sender: Account) -> None:
504
        if sender.balance < amount:
505
            raise AssertionError
506
        sender.balance -= amount
507
508
    def increase_recipient_balance(recipient: Account) -> None:
509
        recipient.balance += amount
510
511
    modify_state(state, sender_address, reduce_sender_balance)
512
    modify_state(state, recipient_address, increase_recipient_balance)

process_withdrawal

Increase the balance of the withdrawing account.

def process_withdrawal(state: State, ​​wd: Withdrawal) -> None:
519
    """
520
    Increase the balance of the withdrawing account.
521
    """
522
523
    def increase_recipient_balance(recipient: Account) -> None:
524
        recipient.balance += wd.amount * 10**9
525
526
    modify_state(state, wd.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.

amount: The amount that needs to set in balance.

def set_account_balance(state: State, ​​address: Address, ​​amount: U256) -> None:
530
    """
531
    Sets the balance of an account.
532
533
    Parameters
534
    ----------
535
    state:
536
        The current state.
537
538
    address:
539
        Address of the account whose nonce needs to be incremented.
540
541
    amount:
542
        The amount that needs to set in balance.
543
    """
544
545
    def set_balance(account: Account) -> None:
546
        account.balance = amount
547
548
    modify_state(state, address, set_balance)

touch_account

Initializes an account to state.

Parameters

state: The current state.

address: The address of the account that need to initialised.

def touch_account(state: State, ​​address: Address) -> None:
552
    """
553
    Initializes an account to state.
554
555
    Parameters
556
    ----------
557
    state:
558
        The current state.
559
560
    address:
561
        The address of the account that need to initialised.
562
    """
563
    if not account_exists(state, address):
564
        set_account(state, address, EMPTY_ACCOUNT)

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:
568
    """
569
    Increments the nonce of an account.
570
571
    Parameters
572
    ----------
573
    state:
574
        The current state.
575
576
    address:
577
        Address of the account whose nonce needs to be incremented.
578
    """
579
580
    def increase_nonce(sender: Account) -> None:
581
        sender.nonce += 1
582
583
    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 update.

code: The bytecode that needs to be set.

def set_code(state: State, ​​address: Address, ​​code: Bytes) -> None:
587
    """
588
    Sets Account code.
589
590
    Parameters
591
    ----------
592
    state:
593
        The current state.
594
595
    address:
596
        Address of the account whose code needs to be update.
597
598
    code:
599
        The bytecode that needs to be set.
600
    """
601
602
    def write_code(sender: Account) -> None:
603
        sender.code = code
604
605
    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: Bytes) -> U256:
609
    """
610
    Get the original value in a storage slot i.e. the value before the current
611
    transaction began. This function reads the value from the snapshots taken
612
    before executing the transaction.
613
614
    Parameters
615
    ----------
616
    state:
617
        The current state.
618
    address:
619
        Address of the account to read the value from.
620
    key:
621
        Key of the storage slot.
622
    """
623
    # In the transaction where an account is created, its preexisting storage
624
    # is ignored.
625
    if address in state.created_accounts:
626
        return U256(0)
627
628
    _, original_trie = state._snapshots[0]
629
    original_account_trie = original_trie.get(address)
630
631
    if original_account_trie is None:
632
        original_value = U256(0)
633
    else:
634
        original_value = trie_get(original_account_trie, key)
635
636
    assert isinstance(original_value, U256)
637
638
    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: Bytes) -> U256:
644
    """
645
    Get a value at a storage key on an account from transient storage.
646
    Returns `U256(0)` if the storage key has not been set previously.
647
    Parameters
648
    ----------
649
    transient_storage: `TransientStorage`
650
        The transient storage
651
    address : `Address`
652
        Address of the account.
653
    key : `Bytes`
654
        Key to lookup.
655
    Returns
656
    -------
657
    value : `U256`
658
        Value at the key.
659
    """
660
    trie = transient_storage._tries.get(address)
661
    if trie is None:
662
        return U256(0)
663
664
    value = trie_get(trie, key)
665
666
    assert isinstance(value, U256)
667
    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: Bytes, ​​value: U256) -> None:
676
    """
677
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
678
    the key.
679
    Parameters
680
    ----------
681
    transient_storage: `TransientStorage`
682
        The transient storage
683
    address : `Address`
684
        Address of the account.
685
    key : `Bytes`
686
        Key to set.
687
    value : `U256`
688
        Value to set at the key.
689
    """
690
    trie = transient_storage._tries.get(address)
691
    if trie is None:
692
        trie = Trie(secured=True, default=U256(0))
693
        transient_storage._tries[address] = trie
694
    trie_set(trie, key, value)
695
    if trie._data == {}:
696
        del transient_storage._tries[address]

destroy_touched_empty_accounts

Destroy all touched accounts that are empty. Parameters

state: State The current state. touched_accounts: Iterable[Address] All the accounts that have been touched in the current transaction.

def destroy_touched_empty_accounts(state: State, ​​touched_accounts: Iterable[Address]) -> None:
702
    """
703
    Destroy all touched accounts that are empty.
704
    Parameters
705
    ----------
706
    state: `State`
707
        The current state.
708
    touched_accounts: `Iterable[Address]`
709
        All the accounts that have been touched in the current transaction.
710
    """
711
    for address in touched_accounts:
712
        if account_exists_and_is_empty(state, address):
713
            destroy_account(state, address)