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

38
@dataclass
class State:

_main_trie

44
    _main_trie: Trie[Address, Optional[Account]] = field(
45
        default_factory=lambda: Trie(secured=True, default=None)
46
    )

_storage_tries

47
    _storage_tries: Dict[Address, Trie[Bytes32, U256]] = field(
48
        default_factory=dict
49
    )

_snapshots

50
    _snapshots: List[
51
        Tuple[
52
            Trie[Address, Optional[Account]],
53
            Dict[Address, Trie[Bytes32, U256]],
54
        ]
55
    ] = field(default_factory=list)

created_accounts

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

_code_store

57
    _code_store: Dict[Hash32, Bytes] = field(
58
        default_factory=dict, compare=False
59
    )

get_code

Return the bytecode for a given code hash.Get the bytecode for a given code hash.

Return b"" for EMPTY_CODE_HASH.

def get_code(self, ​​code_hash: Hash32) -> Bytes:
62
        """
63
        Return the bytecode for a given code hash.
63
        Get the bytecode for a given code hash.
64
65
        Return ``b""`` for ``EMPTY_CODE_HASH``.
66
        """
67
        if code_hash == EMPTY_CODE_HASH:
68
            return b""
69
        return self._code_store[code_hash]

close_state

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

def close_state(state: State) -> None:
73
    """
74
    Free resources held by the state. Used by optimized implementations to
75
    release file descriptors.
76
    """
77
    del state._main_trie
78
    del state._storage_tries
79
    del state._snapshots
80
    del state.created_accounts
81
    del state._code_store

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.

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

commit_transaction

Commit a state transaction.

Parameters

state : State The state.

def commit_transaction(state: State) -> None:
106
    """
107
    Commit a state transaction.
108
109
    Parameters
110
    ----------
111
    state : State
112
        The state.
113
114
    """
115
    state._snapshots.pop()
116
    if not state._snapshots:
117
        state.created_accounts.clear()

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.

def rollback_transaction(state: State) -> None:
121
    """
122
    Rollback a state transaction, resetting the state to the point when the
123
    corresponding `begin_transaction()` call was made.
124
125
    Parameters
126
    ----------
127
    state : State
128
        The state.
129
130
    """
131
    state._main_trie, state._storage_tries = state._snapshots.pop()
132
    if not state._snapshots:
133
        state.created_accounts.clear()

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:
137
    """
138
    Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there
139
    is no account at the address.
140
141
    Use `get_account_optional()` if you care about the difference between a
142
    non-existent account and `EMPTY_ACCOUNT`.
143
144
    Parameters
145
    ----------
146
    state: `State`
147
        The state
148
    address : `Address`
149
        Address to lookup.
150
151
    Returns
152
    -------
153
    account : `Account`
154
        Account at address.
155
156
    """
157
    account = get_account_optional(state, address)
158
    if isinstance(account, Account):
159
        return account
160
    else:
161
        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]:
165
    """
166
    Get the `Account` object at an address. Returns `None` (rather than
167
    `EMPTY_ACCOUNT`) if there is no account at the address.
168
169
    Parameters
170
    ----------
171
    state: `State`
172
        The state
173
    address : `Address`
174
        Address to lookup.
175
176
    Returns
177
    -------
178
    account : `Account`
179
        Account at address.
180
181
    """
182
    account = trie_get(state._main_trie, address)
183
    return account

get_code

Return the bytecode for a given code hash.Get the bytecode for a given code hash.

Parameters

state: The current state. code_hash: The hash of the code to retrieve.Return b"" for EMPTY_CODE_HASH.

Returns

code : Bytes The bytecode for the given hash.

def get_code(state: State, ​​code_hash: Hash32) -> Bytes:
187
    """
186
    Return the bytecode for a given code hash.
188
    Get the bytecode for a given code hash.
189
188
    Parameters
189
    ----------
190
    state:
191
        The current state.
192
    code_hash:
193
        The hash of the code to retrieve.
194
195
    Returns
196
    -------
197
    code : `Bytes`
198
        The bytecode for the given hash.
199
190
    Return ``b""`` for ``EMPTY_CODE_HASH``.
191
    """
201
    return state.get_code(code_hash)
192
    if code_hash == EMPTY_CODE_HASH:
193
        return b""
194
    return state._code_store[code_hash]

store_code

Store bytecode in the code store and return its hash.Store bytecode in State and return its hash.

Parameters

state: The current state. code: The bytecode to store.

Returns

code_hash : Hash32 The keccak256 hash of the stored bytecode.

def store_code(state: State, ​​code: Bytes) -> Hash32:
198
    """
206
    Store bytecode in the code store and return its hash.
207
208
    Parameters
209
    ----------
210
    state:
211
        The current state.
212
    code:
213
        The bytecode to store.
214
215
    Returns
216
    -------
217
    code_hash : `Hash32`
218
        The keccak256 hash of the stored bytecode.
219
199
    Store bytecode in ``State`` and return its hash.
200
    """
201
    code_hash = keccak256(code)
202
    if code_hash != EMPTY_CODE_HASH:
203
        state._code_store[code_hash] = code
204
    return code_hash

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:
210
    """
211
    Set the `Account` object at an address. Setting to `None` deletes
212
    the account (but not its storage, see `destroy_account()`).
213
214
    Parameters
215
    ----------
216
    state: `State`
217
        The state
218
    address : `Address`
219
        Address to set.
220
    account : `Account`
221
        Account to set at address.
222
223
    """
224
    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:
228
    """
229
    Completely remove the account at `address` and all of its storage.
230
231
    This function is made available exclusively for the `SELFDESTRUCT`
232
    opcode. It is expected that `SELFDESTRUCT` will be disabled in a future
233
    hardfork and this function will be removed.
234
235
    Parameters
236
    ----------
237
    state: `State`
238
        The state
239
    address : `Address`
240
        Address of account to destroy.
241
242
    """
243
    destroy_storage(state, address)
244
    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:
248
    """
249
    Completely remove the storage at `address`.
250
251
    Parameters
252
    ----------
253
    state: `State`
254
        The state
255
    address : `Address`
256
        Address of account whose storage is to be deleted.
257
258
    """
259
    if address in state._storage_tries:
260
        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:
264
    """
265
    Mark an account as having been created in the current transaction.
266
    This information is used by `get_storage_original()` to handle an obscure
267
    edgecase.
268
269
    The marker is not removed even if the account creation reverts. Since the
270
    account cannot have had code prior to its creation and can't call
271
    `get_storage_original()`, this is harmless.
272
273
    Parameters
274
    ----------
275
    state: `State`
276
        The state
277
    address : `Address`
278
        Address of the account that has been created.
279
280
    """
281
    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:
285
    """
286
    Get a value at a storage key on an account. Returns `U256(0)` if the
287
    storage key has not been set previously.
288
289
    Parameters
290
    ----------
291
    state: `State`
292
        The state
293
    address : `Address`
294
        Address of the account.
295
    key : `Bytes`
296
        Key to lookup.
297
298
    Returns
299
    -------
300
    value : `U256`
301
        Value at the key.
302
303
    """
304
    trie = state._storage_tries.get(address)
305
    if trie is None:
306
        return U256(0)
307
308
    value = trie_get(trie, key)
309
310
    assert isinstance(value, U256)
311
    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:
317
    """
318
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
319
    the key.
320
321
    Parameters
322
    ----------
323
    state: `State`
324
        The state
325
    address : `Address`
326
        Address of the account.
327
    key : `Bytes`
328
        Key to set.
329
    value : `U256`
330
        Value to set at the key.
331
332
    """
333
    assert trie_get(state._main_trie, address) is not None
334
335
    trie = state._storage_tries.get(address)
336
    if trie is None:
337
        trie = Trie(secured=True, default=U256(0))
338
        state._storage_tries[address] = trie
339
    trie_set(trie, key, value)
340
    if trie._data == {}:
341
        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:
345
    """
346
    Calculate the storage root of an account.
347
348
    Parameters
349
    ----------
350
    state:
351
        The state
352
    address :
353
        Address of the account.
354
355
    Returns
356
    -------
357
    root : `Root`
358
        Storage root of the account.
359
360
    """
361
    assert not state._snapshots
362
    if address in state._storage_tries:
363
        return root(state._storage_tries[address])
364
    else:
365
        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:
369
    """
370
    Calculate the state root.
371
372
    Parameters
373
    ----------
374
    state:
375
        The current state.
376
377
    Returns
378
    -------
379
    root : `Root`
380
        The state root.
381
382
    """
383
    assert not state._snapshots
384
385
    def get_storage_root(address: Address) -> Root:
386
        return storage_root(state, address)
387
388
    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:
392
    """
393
    Checks if an account exists in the state trie.
394
395
    Parameters
396
    ----------
397
    state:
398
        The state
399
    address:
400
        Address of the account that needs to be checked.
401
402
    Returns
403
    -------
404
    account_exists : `bool`
405
        True if account exists in the state trie, False otherwise
406
407
    """
408
    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:
412
    """
413
    Checks if an account has non-zero nonce or non-empty code.
414
415
    Parameters
416
    ----------
417
    state:
418
        The state
419
    address:
420
        Address of the account that needs to be checked.
421
422
    Returns
423
    -------
424
    has_code_or_nonce : `bool`
425
        True if the account has non-zero nonce or non-empty code,
426
        False otherwise.
427
428
    """
429
    account = get_account(state, address)
430
    return account.nonce != Uint(0) or account.code_hash != EMPTY_CODE_HASH

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:
434
    """
435
    Checks if an account has storage.
436
437
    Parameters
438
    ----------
439
    state:
440
        The state
441
    address:
442
        Address of the account that needs to be checked.
443
444
    Returns
445
    -------
446
    has_storage : `bool`
447
        True if the account has storage, False otherwise.
448
449
    """
450
    return address in state._storage_tries

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:
454
    """
455
    Check whether an account is both in the state and non-empty.
456
457
    Parameters
458
    ----------
459
    state:
460
        The state
461
    address:
462
        Address of the account that needs to be checked.
463
464
    Returns
465
    -------
466
    is_alive : `bool`
467
        True if the account is alive.
468
469
    """
470
    account = get_account_optional(state, address)
471
    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:
477
    """
478
    Modify an `Account` in the `State`. If, after modification, the account
479
    exists and has zero nonce, empty code, and zero balance, it is destroyed.
480
    """
481
    set_account(state, address, modify(get_account(state, address), f))
482
483
    account = get_account_optional(state, address)
484
    account_exists_and_is_empty = (
485
        account is not None
486
        and account.nonce == Uint(0)
487
        and account.code_hash == EMPTY_CODE_HASH
488
        and account.balance == 0
489
    )
490
491
    if account_exists_and_is_empty:
492
        destroy_account(state, address)

move_ether

Move funds between accounts.

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

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

def set_account_balance(state: State, ​​address: Address, ​​amount: U256) -> None:
518
    """
519
    Sets the balance of an account.
520
521
    Parameters
522
    ----------
523
    state:
524
        The current state.
525
526
    address:
527
        Address of the account whose nonce needs to be incremented.
528
529
    amount:
530
        The amount that needs to be set in the balance.
531
532
    """
533
534
    def set_balance(account: Account) -> None:
535
        account.balance = amount
536
537
    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:
541
    """
542
    Increments the nonce of an account.
543
544
    Parameters
545
    ----------
546
    state:
547
        The current state.
548
549
    address:
550
        Address of the account whose nonce needs to be incremented.
551
552
    """
553
554
    def increase_nonce(sender: Account) -> None:
555
        sender.nonce += Uint(1)
556
557
    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:
561
    """
562
    Sets Account code.
563
564
    Parameters
565
    ----------
566
    state:
567
        The current state.
568
569
    address:
570
        Address of the account whose code needs to be updated.
571
572
    code:
573
        The bytecode that needs to be set.
574
575
    """
576
    code_hash = store_code(state, code)
577
578
    def write_code(sender: Account) -> None:
579
        sender.code_hash = code_hash
580
581
    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:
585
    """
586
    Get the original value in a storage slot i.e. the value before the current
587
    transaction began. This function reads the value from the snapshots taken
588
    before executing the transaction.
589
590
    Parameters
591
    ----------
592
    state:
593
        The current state.
594
    address:
595
        Address of the account to read the value from.
596
    key:
597
        Key of the storage slot.
598
599
    """
600
    # In the transaction where an account is created, its preexisting storage
601
    # is ignored.
602
    if address in state.created_accounts:
603
        return U256(0)
604
605
    _, original_trie = state._snapshots[0]
606
    original_account_trie = original_trie.get(address)
607
608
    if original_account_trie is None:
609
        original_value = U256(0)
610
    else:
611
        original_value = trie_get(original_account_trie, key)
612
613
    assert isinstance(original_value, U256)
614
615
    return original_value