ethereum.forks.bpo5.vmethereum.forks.amsterdam.vm

Ethereum Virtual Machine (EVM).

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

Introduction

The abstract computer which runs the code stored in an .fork_types.Account.

__all__

33
__all__ = ("Environment", "Evm", "Message")

TRANSFER_TOPIC

34
TRANSFER_TOPIC = keccak256(b"Transfer(address,address,uint256)")

BURN_TOPIC

35
BURN_TOPIC = keccak256(b"Burn(address,uint256)")

SYSTEM_ADDRESS

36
SYSTEM_ADDRESS = Address(
37
    bytes.fromhex("fffffffffffffffffffffffffffffffffffffffe")
38
)

CALL_SUCCESS

39
CALL_SUCCESS = U256(1)

BlockEnvironment

Items external to the virtual machine itself, provided by the environment.

42
@dataclass
class BlockEnvironment:

chain_id

48
    chain_id: U64

state

41
    state: State
49
    state: BlockState

block_gas_limit

50
    block_gas_limit: Uint

block_hashes

51
    block_hashes: List[Hash32]

coinbase

52
    coinbase: Address

number

53
    number: Uint

base_fee_per_gas

54
    base_fee_per_gas: Uint

time

55
    time: U256

prev_randao

56
    prev_randao: Bytes32

excess_blob_gas

57
    excess_blob_gas: U64

parent_beacon_block_root

58
    parent_beacon_block_root: Hash32

block_access_list_builder

59
    block_access_list_builder: BlockAccessListBuilder

slot_number

60
    slot_number: U64

BlockOutput

Output from applying the block body to the present state.

Contains the following:

block_gas_used : ethereum.base_types.Uint Gas used for executing all transactions. block_state_gas_used : ethereum.base_types.Uint State gas used for executing all transactions. cumulative_gas_used : ethereum.base_types.Uint Cumulative gas paid by users (post-refund, post-floor). transactions_trie : ethereum.fork_types.Root Trie of all the transactions in the block. receipts_trie : ethereum.fork_types.Root Trie root of all the receipts in the block. receipt_keys : Keys of all the receipts in the block. block_logs : Bloom Logs bloom of all the logs included in all the transactions of the block. withdrawals_trie : ethereum.fork_types.Root Trie root of all the withdrawals in the block. blob_gas_used : ethereum.base_types.U64 Total blob gas used in the block. requests : Bytes Hash of all the requests in the block. block_access_list: BlockAccessList The block access list for the block.

63
@dataclass
class BlockOutput:

block_gas_used

95
    block_gas_used: Uint = Uint(0)

block_state_gas_used

96
    block_state_gas_used: Uint = Uint(0)

cumulative_gas_used

97
    cumulative_gas_used: Uint = Uint(0)

transactions_trie

80
    transactions_trie: Trie[Bytes, Optional[Bytes | LegacyTransaction]] = (
81
        field(default_factory=lambda: Trie(secured=False, default=None))
98
    transactions_trie: Trie[Bytes, Optional[Bytes | LegacyTransaction]] = (
99
        field(default_factory=lambda: Trie(secured=False, default=None))
100
    )

receipts_trie

83
    receipts_trie: Trie[Bytes, Optional[Bytes | Receipt]] = field(
84
        default_factory=lambda: Trie(secured=False, default=None)
101
    receipts_trie: Trie[Bytes, Optional[Bytes | Receipt]] = field(
102
        default_factory=lambda: Trie(secured=False, default=None)
103
    )

receipt_keys

104
    receipt_keys: Tuple[Bytes, ...] = field(default_factory=tuple)

block_logs

105
    block_logs: Tuple[Log, ...] = field(default_factory=tuple)

withdrawals_trie

88
    withdrawals_trie: Trie[Bytes, Optional[Bytes | Withdrawal]] = field(
89
        default_factory=lambda: Trie(secured=False, default=None)
106
    withdrawals_trie: Trie[Bytes, Optional[Bytes | Withdrawal]] = field(
107
        default_factory=lambda: Trie(secured=False, default=None)
108
    )

blob_gas_used

109
    blob_gas_used: U64 = U64(0)

requests

110
    requests: List[Bytes] = field(default_factory=list)

block_access_list

111
    block_access_list: BlockAccessList = field(default_factory=list)

TransactionEnvironment

Items that are used by contract creation or message call.

114
@dataclass
class TransactionEnvironment:

origin

120
    origin: Address

gas_price

121
    gas_price: Uint

gas

122
    gas: Uint

state_gas_reservoir

123
    state_gas_reservoir: Uint

access_list_addresses

124
    access_list_addresses: Set[Address]

access_list_storage_keys

125
    access_list_storage_keys: Set[Tuple[Address, Bytes32]]

transient_storage

106
    transient_storage: TransientStorage

state

126
    state: TransactionState

blob_versioned_hashes

127
    blob_versioned_hashes: Tuple[VersionedHash, ...]

authorizations

128
    authorizations: Tuple[Authorization, ...]

index_in_block

129
    index_in_block: Optional[Uint]

tx_hash

130
    tx_hash: Optional[Hash32]

intrinsic_regular_gas

131
    intrinsic_regular_gas: Uint

intrinsic_state_gas

132
    intrinsic_state_gas: Uint

Message

Items that are used by contract creation or message call.

135
@dataclass
class Message:

block_env

141
    block_env: BlockEnvironment

tx_env

142
    tx_env: TransactionEnvironment

caller

143
    caller: Address

target

144
    target: Bytes0 | Address

current_target

145
    current_target: Address

gas

146
    gas: Uint

state_gas_reservoir

147
    state_gas_reservoir: Uint

value

148
    value: U256

data

149
    data: Bytes

code_address

150
    code_address: Optional[Address]

code

151
    code: Bytes

depth

152
    depth: Uint

should_transfer_value

153
    should_transfer_value: bool

is_static

154
    is_static: bool

accessed_addresses

155
    accessed_addresses: Set[Address]

accessed_storage_keys

156
    accessed_storage_keys: Set[Tuple[Address, Bytes32]]

disable_precompiles

157
    disable_precompiles: bool

parent_evm

158
    parent_evm: Optional["Evm"]

Evm

The internal state of the virtual machine.

161
@dataclass
class Evm:

pc

165
    pc: Uint

stack

166
    stack: List[U256]

memory

167
    memory: bytearray

code

168
    code: Bytes

gas_left

169
    gas_left: Uint

state_gas_left

170
    state_gas_left: Uint

valid_jump_destinations

171
    valid_jump_destinations: Set[Uint]

logs

172
    logs: Tuple[Log, ...]

refund_counter

173
    refund_counter: int

running

174
    running: bool

message

175
    message: Message

output

176
    output: Bytes

accounts_to_delete

177
    accounts_to_delete: Set[Address]

return_data

178
    return_data: Bytes

error

179
    error: Optional[EthereumException]

accessed_addresses

180
    accessed_addresses: Set[Address]

accessed_storage_keys

181
    accessed_storage_keys: Set[Tuple[Address, Bytes32]]

regular_gas_used

182
    regular_gas_used: Uint = Uint(0)

state_gas_used

183
    state_gas_used: Uint = Uint(0)

state_gas_refund

184
    state_gas_refund: Uint = Uint(0)

state_gas_refund_pending

185
    state_gas_refund_pending: Uint = Uint(0)

credit_state_gas_refund

Credit an inline state gas refund to evm.state_gas_left.

Clamp the applied portion to this frame's state_gas_used — the matching charge may sit in an ancestor sharing storage via CALLCODE/DELEGATECALL. Track it in state_gas_refund so incorporate_child_on_error can undo the inflation, and defer the unapplied remainder in state_gas_refund_pending for propagation on success.

Parameters

evm : The frame crediting the refund. amount : The refund amount to credit.

def credit_state_gas_refund(evm: Evm, ​​amount: Uint) -> None:
189
    """
190
    Credit an inline state gas refund to `evm.state_gas_left`.
191
192
    Clamp the applied portion to this frame's `state_gas_used` — the
193
    matching charge may sit in an ancestor sharing storage via
194
    CALLCODE/DELEGATECALL.  Track it in `state_gas_refund` so
195
    `incorporate_child_on_error` can undo the inflation, and defer the
196
    unapplied remainder in `state_gas_refund_pending` for propagation
197
    on success.
198
199
    Parameters
200
    ----------
201
    evm :
202
        The frame crediting the refund.
203
    amount :
204
        The refund amount to credit.
205
206
    """
207
    applied = min(amount, evm.state_gas_used)
208
    evm.state_gas_left += applied
209
    evm.state_gas_used -= applied
210
    evm.state_gas_refund += applied
211
    evm.state_gas_refund_pending += amount - applied

incorporate_child_on_success

Incorporate the state of a successful child_evm into the parent evm.

Propagate state_gas_refund (inline credits the child applied) so an ancestor revert can undo the inflation, and apply state_gas_refund_pending (the unapplied remainder) to the parent via credit_state_gas_refund; any leftover propagates further up.

Parameters

evm : The parent EVM. child_evm : The child evm to incorporate.

def incorporate_child_on_success(evm: Evm, ​​child_evm: Evm) -> None:
215
    """
216
    Incorporate the state of a successful `child_evm` into the parent `evm`.
217
218
    Propagate `state_gas_refund` (inline credits the child applied) so
219
    an ancestor revert can undo the inflation, and apply
220
    `state_gas_refund_pending` (the unapplied remainder) to the parent
221
    via `credit_state_gas_refund`; any leftover propagates further up.
222
223
    Parameters
224
    ----------
225
    evm :
226
        The parent `EVM`.
227
    child_evm :
228
        The child evm to incorporate.
229
230
    """
231
    evm.gas_left += child_evm.gas_left
232
    evm.state_gas_left += child_evm.state_gas_left
233
    evm.logs += child_evm.logs
234
    evm.refund_counter += child_evm.refund_counter
235
    evm.accounts_to_delete.update(child_evm.accounts_to_delete)
236
    evm.accessed_addresses.update(child_evm.accessed_addresses)
177
    evm.accessed_storage_keys.update(child_evm.accessed_storage_keys)
237
    evm.accessed_storage_keys.update(child_evm.accessed_storage_keys)
238
    evm.regular_gas_used += child_evm.regular_gas_used
239
    evm.state_gas_used += child_evm.state_gas_used
240
    evm.state_gas_refund += child_evm.state_gas_refund
241
    credit_state_gas_refund(evm, child_evm.state_gas_refund_pending)

incorporate_child_on_error

Incorporate the state of an unsuccessful child_evm into the parent evm.

On failure (revert or exceptional halt) state changes are rolled back, so no state was actually grown. All state gas, both reservoir and any that spilled into gas_left, is restored to the parent's reservoir and the child's state_gas_used is not accumulated.

Inline state-gas refunds (SSTORE 0 to x to 0, CREATE silent failure) credited by the child inflated its state_gas_left; subtract state_gas_refund from the amount returned to the parent's reservoir so the inflation does not leak across the error boundary. state_gas_refund_pending is discarded with the child frame.

Parameters

evm : The parent EVM. child_evm : The child evm to incorporate.

def incorporate_child_on_error(evm: Evm, ​​child_evm: Evm) -> None:
248
    """
249
    Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.
250
251
    On failure (revert or exceptional halt) state changes are rolled back,
252
    so no state was actually grown.  All state gas, both reservoir and any
253
    that spilled into `gas_left`, is restored to the parent's reservoir and
254
    the child's `state_gas_used` is not accumulated.
255
256
    Inline state-gas refunds (SSTORE 0 to x to 0, CREATE silent failure)
257
    credited by the child inflated its `state_gas_left`; subtract
258
    `state_gas_refund` from the amount returned to the parent's
259
    reservoir so the inflation does not leak across the error boundary.
260
    `state_gas_refund_pending` is discarded with the child frame.
261
262
    Parameters
263
    ----------
264
    evm :
265
        The parent `EVM`.
266
    child_evm :
267
        The child evm to incorporate.
268
269
    """
192
    evm.gas_left += child_evm.gas_left
270
    evm.gas_left += child_evm.gas_left
271
    evm.state_gas_left += (
272
        child_evm.state_gas_used
273
        + child_evm.state_gas_left
274
        - child_evm.state_gas_refund
275
    )
276
    evm.regular_gas_used += child_evm.regular_gas_used

emit_transfer_log

Emit a LOG3 for all ETH transfers satisfying EIP-7708.

Parameters

evm : The state of the ethereum virtual machine sender : The account address sending the transfer recipient : The account address receiving the transfer transfer_amount : The amount of ETH transacted

def emit_transfer_log(evm: Evm, ​​sender: Address, ​​recipient: Address, ​​transfer_amount: U256) -> None:
285
    """
286
    Emit a LOG3 for all ETH transfers satisfying EIP-7708.
287
288
    Parameters
289
    ----------
290
    evm :
291
        The state of the ethereum virtual machine
292
    sender :
293
        The account address sending the transfer
294
    recipient :
295
        The account address receiving the transfer
296
    transfer_amount :
297
        The amount of ETH transacted
298
299
    """
300
    if transfer_amount == 0:
301
        return
302
303
    padded_sender = left_pad_zero_bytes(sender, 32)
304
    padded_recipient = left_pad_zero_bytes(recipient, 32)
305
    log_entry = Log(
306
        address=SYSTEM_ADDRESS,
307
        topics=(
308
            TRANSFER_TOPIC,
309
            Hash32(padded_sender),
310
            Hash32(padded_recipient),
311
        ),
312
        data=transfer_amount.to_be_bytes32(),
313
    )
314
315
    evm.logs = evm.logs + (log_entry,)

emit_burn_log

Emit a LOG2 for ETH burn per EIP-7708.

Parameters

evm : The state of the ethereum virtual machine account : The account address whose ETH is being burned amount : The amount of ETH being burned

def emit_burn_log(evm: Evm, ​​account: Address, ​​amount: U256) -> None:
323
    """
324
    Emit a LOG2 for ETH burn per EIP-7708.
325
326
    Parameters
327
    ----------
328
    evm :
329
        The state of the ethereum virtual machine
330
    account :
331
        The account address whose ETH is being burned
332
    amount :
333
        The amount of ETH being burned
334
335
    """
336
    if amount == 0:
337
        return
338
339
    padded_account = left_pad_zero_bytes(account, 32)
340
    log_entry = Log(
341
        address=SYSTEM_ADDRESS,
342
        topics=(
343
            BURN_TOPIC,
344
            Hash32(padded_account),
345
        ),
346
        data=amount.to_be_bytes32(),
347
    )
348
349
    evm.logs = evm.logs + (log_entry,)