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

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)

close_state

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

def close_state(state: State) -> None:
50
    """
51
    Free resources held by the state. Used by optimized implementations to
52
    release file descriptors.
53
    """
54
    del state._main_trie
55
    del state._storage_tries
56
    del state._snapshots
57
    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.

def begin_transaction(state: State) -> None:
61
    """
62
    Start a state transaction.
63
64
    Transactions are entirely implicit and can be nested. It is not possible to
65
    calculate the state root during a transaction.
66
67
    Parameters
68
    ----------
69
    state : State
70
        The state.
71
    """
72
    state._snapshots.append(
73
        (
74
            copy_trie(state._main_trie),
75
            {k: copy_trie(t) for (k, t) in state._storage_tries.items()},
76
        )
77
    )

commit_transaction

Commit a state transaction.

Parameters

state : State The state.

def commit_transaction(state: State) -> None:
81
    """
82
    Commit a state transaction.
83
84
    Parameters
85
    ----------
86
    state : State
87
        The state.
88
    """
89
    state._snapshots.pop()
90
    if not state._snapshots:
91
        state.created_accounts.clear()

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.

def rollback_transaction(state: State) -> None:
95
    """
96
    Rollback a state transaction, resetting the state to the point when the
97
    corresponding `start_transaction()` call was made.
98
99
    Parameters
100
    ----------
101
    state : State
102
        The state.
103
    """
104
    state._main_trie, state._storage_tries = state._snapshots.pop()
105
    if not state._snapshots:
106
        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:
110
    """
111
    Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there
112
    is no account at the address.
113
114
    Use `get_account_optional()` if you care about the difference between a
115
    non-existent account and `EMPTY_ACCOUNT`.
116
117
    Parameters
118
    ----------
119
    state: `State`
120
        The state
121
    address : `Address`
122
        Address to lookup.
123
124
    Returns
125
    -------
126
    account : `Account`
127
        Account at address.
128
    """
129
    account = get_account_optional(state, address)
130
    if isinstance(account, Account):
131
        return account
132
    else:
133
        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]:
137
    """
138
    Get the `Account` object at an address. Returns `None` (rather than
139
    `EMPTY_ACCOUNT`) if there is no account at the address.
140
141
    Parameters
142
    ----------
143
    state: `State`
144
        The state
145
    address : `Address`
146
        Address to lookup.
147
148
    Returns
149
    -------
150
    account : `Account`
151
        Account at address.
152
    """
153
    account = trie_get(state._main_trie, address)
154
    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:
160
    """
161
    Set the `Account` object at an address. Setting to `None` deletes
162
    the account (but not its storage, see `destroy_account()`).
163
164
    Parameters
165
    ----------
166
    state: `State`
167
        The state
168
    address : `Address`
169
        Address to set.
170
    account : `Account`
171
        Account to set at address.
172
    """
173
    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:
177
    """
178
    Completely remove the account at `address` and all of its storage.
179
180
    This function is made available exclusively for the `SELFDESTRUCT`
181
    opcode. It is expected that `SELFDESTRUCT` will be disabled in a future
182
    hardfork and this function will be removed.
183
184
    Parameters
185
    ----------
186
    state: `State`
187
        The state
188
    address : `Address`
189
        Address of account to destroy.
190
    """
191
    destroy_storage(state, address)
192
    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:
196
    """
197
    Completely remove the storage at `address`.
198
199
    Parameters
200
    ----------
201
    state: `State`
202
        The state
203
    address : `Address`
204
        Address of account whose storage is to be deleted.
205
    """
206
    if address in state._storage_tries:
207
        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:
211
    """
212
    Mark an account as having been created in the current transaction.
213
    This information is used by `get_storage_original()` to handle an obscure
214
    edgecase.
215
216
    The marker is not removed even if the account creation reverts. Since the
217
    account cannot have had code prior to its creation and can't call
218
    `get_storage_original()`, this is harmless.
219
220
    Parameters
221
    ----------
222
    state: `State`
223
        The state
224
    address : `Address`
225
        Address of the account that has been created.
226
    """
227
    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:
231
    """
232
    Get a value at a storage key on an account. Returns `U256(0)` if the
233
    storage key has not been set previously.
234
235
    Parameters
236
    ----------
237
    state: `State`
238
        The state
239
    address : `Address`
240
        Address of the account.
241
    key : `Bytes`
242
        Key to lookup.
243
244
    Returns
245
    -------
246
    value : `U256`
247
        Value at the key.
248
    """
249
    trie = state._storage_tries.get(address)
250
    if trie is None:
251
        return U256(0)
252
253
    value = trie_get(trie, key)
254
255
    assert isinstance(value, U256)
256
    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:
262
    """
263
    Set a value at a storage key on an account. Setting to `U256(0)` deletes
264
    the key.
265
266
    Parameters
267
    ----------
268
    state: `State`
269
        The state
270
    address : `Address`
271
        Address of the account.
272
    key : `Bytes`
273
        Key to set.
274
    value : `U256`
275
        Value to set at the key.
276
    """
277
    assert trie_get(state._main_trie, address) is not None
278
279
    trie = state._storage_tries.get(address)
280
    if trie is None:
281
        trie = Trie(secured=True, default=U256(0))
282
        state._storage_tries[address] = trie
283
    trie_set(trie, key, value)
284
    if trie._data == {}:
285
        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:
289
    """
290
    Calculate the storage root of an account.
291
292
    Parameters
293
    ----------
294
    state:
295
        The state
296
    address :
297
        Address of the account.
298
299
    Returns
300
    -------
301
    root : `Root`
302
        Storage root of the account.
303
    """
304
    assert not state._snapshots
305
    if address in state._storage_tries:
306
        return root(state._storage_tries[address])
307
    else:
308
        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:
312
    """
313
    Calculate the state root.
314
315
    Parameters
316
    ----------
317
    state:
318
        The current state.
319
320
    Returns
321
    -------
322
    root : `Root`
323
        The state root.
324
    """
325
    assert not state._snapshots
326
327
    def get_storage_root(address: Address) -> Root:
328
        return storage_root(state, address)
329
330
    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:
334
    """
335
    Checks if an account exists in the state trie
336
337
    Parameters
338
    ----------
339
    state:
340
        The state
341
    address:
342
        Address of the account that needs to be checked.
343
344
    Returns
345
    -------
346
    account_exists : `bool`
347
        True if account exists in the state trie, False otherwise
348
    """
349
    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:
353
    """
354
    Checks if an account has non zero nonce or non empty code
355
356
    Parameters
357
    ----------
358
    state:
359
        The state
360
    address:
361
        Address of the account that needs to be checked.
362
363
    Returns
364
    -------
365
    has_code_or_nonce : `bool`
366
        True if if an account has non zero nonce or non empty code,
367
        False otherwise.
368
    """
369
    account = get_account(state, address)
370
    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:
374
    """
375
    Checks if an account has zero nonce, empty code and zero balance.
376
377
    Parameters
378
    ----------
379
    state:
380
        The state
381
    address:
382
        Address of the account that needs to be checked.
383
384
    Returns
385
    -------
386
    is_empty : `bool`
387
        True if if an account has zero nonce, empty code and zero balance,
388
        False otherwise.
389
    """
390
    account = get_account(state, address)
391
    return (
392
        account.nonce == Uint(0)
393
        and account.code == b""
394
        and account.balance == 0
395
    )

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:
399
    """
400
    Checks if an account exists and has zero nonce, empty code and zero
401
    balance.
402
403
    Parameters
404
    ----------
405
    state:
406
        The state
407
    address:
408
        Address of the account that needs to be checked.
409
410
    Returns
411
    -------
412
    exists_and_is_empty : `bool`
413
        True if an account exists and has zero nonce, empty code and zero
414
        balance, False otherwise.
415
    """
416
    account = get_account_optional(state, address)
417
    return (
418
        account is not None
419
        and account.nonce == Uint(0)
420
        and account.code == b""
421
        and account.balance == 0
422
    )

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:
426
    """
427
    Check whether is an account is both in the state and non empty.
428
429
    Parameters
430
    ----------
431
    state:
432
        The state
433
    address:
434
        Address of the account that needs to be checked.
435
436
    Returns
437
    -------
438
    is_alive : `bool`
439
        True if the account is alive.
440
    """
441
    account = get_account_optional(state, address)
442
    if account is None:
443
        return False
444
    else:
445
        return not (
446
            account.nonce == Uint(0)
447
            and account.code == b""
448
            and account.balance == 0
449
        )

modify_state

Modify an Account in the State.

def modify_state(state: State, ​​address: Address, ​​f: Callable[[Account], None]) -> None:
455
    """
456
    Modify an `Account` in the `State`.
457
    """
458
    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:
467
    """
468
    Move funds between accounts.
469
    """
470
471
    def reduce_sender_balance(sender: Account) -> None:
472
        if sender.balance < amount:
473
            raise AssertionError
474
        sender.balance -= amount
475
476
    def increase_recipient_balance(recipient: Account) -> None:
477
        recipient.balance += amount
478
479
    modify_state(state, sender_address, reduce_sender_balance)
480
    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:
487
    """
488
    Increase the balance of the withdrawing account.
489
    """
490
491
    def increase_recipient_balance(recipient: Account) -> None:
492
        recipient.balance += wd.amount * 10**9
493
494
    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:
498
    """
499
    Sets the balance of an account.
500
501
    Parameters
502
    ----------
503
    state:
504
        The current state.
505
506
    address:
507
        Address of the account whose nonce needs to be incremented.
508
509
    amount:
510
        The amount that needs to set in balance.
511
    """
512
513
    def set_balance(account: Account) -> None:
514
        account.balance = amount
515
516
    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:
520
    """
521
    Initializes an account to state.
522
523
    Parameters
524
    ----------
525
    state:
526
        The current state.
527
528
    address:
529
        The address of the account that need to initialised.
530
    """
531
    if not account_exists(state, address):
532
        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:
536
    """
537
    Increments the nonce of an account.
538
539
    Parameters
540
    ----------
541
    state:
542
        The current state.
543
544
    address:
545
        Address of the account whose nonce needs to be incremented.
546
    """
547
548
    def increase_nonce(sender: Account) -> None:
549
        sender.nonce += 1
550
551
    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:
555
    """
556
    Sets Account code.
557
558
    Parameters
559
    ----------
560
    state:
561
        The current state.
562
563
    address:
564
        Address of the account whose code needs to be update.
565
566
    code:
567
        The bytecode that needs to be set.
568
    """
569
570
    def write_code(sender: Account) -> None:
571
        sender.code = code
572
573
    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:
577
    """
578
    Get the original value in a storage slot i.e. the value before the current
579
    transaction began. This function reads the value from the snapshots taken
580
    before executing the transaction.
581
582
    Parameters
583
    ----------
584
    state:
585
        The current state.
586
    address:
587
        Address of the account to read the value from.
588
    key:
589
        Key of the storage slot.
590
    """
591
    # In the transaction where an account is created, its preexisting storage
592
    # is ignored.
593
    if address in state.created_accounts:
594
        return U256(0)
595
596
    _, original_trie = state._snapshots[0]
597
    original_account_trie = original_trie.get(address)
598
599
    if original_account_trie is None:
600
        original_value = U256(0)
601
    else:
602
        original_value = trie_get(original_account_trie, key)
603
604
    assert isinstance(original_value, U256)
605
606
    return original_value