ethereum.forks.bpo5.vm.instructions.environmentethereum.forks.amsterdam.vm.instructions.environment

Ethereum Virtual Machine (EVM) Environmental Instructions.

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

Introduction

Implementations of the EVM environment related instructions.

address

Pushes the address of the current executing account to the stack.

Parameters

evm : The current EVM frame.

def address(evm: Evm) -> None:
42
    """
43
    Pushes the address of the current executing account to the stack.
44
45
    Parameters
46
    ----------
47
    evm :
48
        The current EVM frame.
49
50
    """
51
    # STACK
52
    pass
53
54
    # GAS
55
    charge_gas(evm, GAS_BASE)
56
57
    # OPERATION
58
    push(evm.stack, U256.from_be_bytes(evm.message.current_target))
59
60
    # PROGRAM COUNTER
61
    evm.pc += Uint(1)

balance

Pushes the balance of the given account onto the stack.

Parameters

evm : The current EVM frame.

def balance(evm: Evm) -> None:
65
    """
66
    Pushes the balance of the given account onto the stack.
67
68
    Parameters
69
    ----------
70
    evm :
71
        The current EVM frame.
72
73
    """
74
    # STACK
75
    address = to_address_masked(pop(evm.stack))
76
77
    # GAS
78
    if address in evm.accessed_addresses:
79
        charge_gas(evm, GAS_WARM_ACCESS)
80
    else:
81
        evm.accessed_addresses.add(address)
82
        charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS)
78
    is_cold_access = address not in evm.accessed_addresses
79
    gas_cost = GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS
80
    if is_cold_access:
81
        evm.accessed_addresses.add(address)
82
83
    charge_gas(evm, gas_cost)
84
85
    # OPERATION
86
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
86
    balance = get_account(evm.message.block_env.state, address).balance
87
    tx_state = evm.message.tx_env.state
88
    balance = get_account(tx_state, address).balance
89
90
    push(evm.stack, balance)
91
92
    # PROGRAM COUNTER
93
    evm.pc += Uint(1)

origin

Pushes the address of the original transaction sender to the stack. The origin address can only be an EOA.

Parameters

evm : The current EVM frame.

def origin(evm: Evm) -> None:
97
    """
98
    Pushes the address of the original transaction sender to the stack.
99
    The origin address can only be an EOA.
100
101
    Parameters
102
    ----------
103
    evm :
104
        The current EVM frame.
105
106
    """
107
    # STACK
108
    pass
109
110
    # GAS
111
    charge_gas(evm, GAS_BASE)
112
113
    # OPERATION
114
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
115
116
    # PROGRAM COUNTER
117
    evm.pc += Uint(1)

caller

Pushes the address of the caller onto the stack.

Parameters

evm : The current EVM frame.

def caller(evm: Evm) -> None:
121
    """
122
    Pushes the address of the caller onto the stack.
123
124
    Parameters
125
    ----------
126
    evm :
127
        The current EVM frame.
128
129
    """
130
    # STACK
131
    pass
132
133
    # GAS
134
    charge_gas(evm, GAS_BASE)
135
136
    # OPERATION
137
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
138
139
    # PROGRAM COUNTER
140
    evm.pc += Uint(1)

callvalue

Push the value (in wei) sent with the call onto the stack.

Parameters

evm : The current EVM frame.

def callvalue(evm: Evm) -> None:
144
    """
145
    Push the value (in wei) sent with the call onto the stack.
146
147
    Parameters
148
    ----------
149
    evm :
150
        The current EVM frame.
151
152
    """
153
    # STACK
154
    pass
155
156
    # GAS
157
    charge_gas(evm, GAS_BASE)
158
159
    # OPERATION
160
    push(evm.stack, evm.message.value)
161
162
    # PROGRAM COUNTER
163
    evm.pc += Uint(1)

calldataload

Push a word (32 bytes) of the input data belonging to the current environment onto the stack.

Parameters

evm : The current EVM frame.

def calldataload(evm: Evm) -> None:
167
    """
168
    Push a word (32 bytes) of the input data belonging to the current
169
    environment onto the stack.
170
171
    Parameters
172
    ----------
173
    evm :
174
        The current EVM frame.
175
176
    """
177
    # STACK
178
    start_index = pop(evm.stack)
179
180
    # GAS
181
    charge_gas(evm, GAS_VERY_LOW)
182
183
    # OPERATION
184
    value = buffer_read(evm.message.data, start_index, U256(32))
185
186
    push(evm.stack, U256.from_be_bytes(value))
187
188
    # PROGRAM COUNTER
189
    evm.pc += Uint(1)

calldatasize

Push the size of input data in current environment onto the stack.

Parameters

evm : The current EVM frame.

def calldatasize(evm: Evm) -> None:
193
    """
194
    Push the size of input data in current environment onto the stack.
195
196
    Parameters
197
    ----------
198
    evm :
199
        The current EVM frame.
200
201
    """
202
    # STACK
203
    pass
204
205
    # GAS
206
    charge_gas(evm, GAS_BASE)
207
208
    # OPERATION
209
    push(evm.stack, U256(len(evm.message.data)))
210
211
    # PROGRAM COUNTER
212
    evm.pc += Uint(1)

calldatacopy

Copy a portion of the input data in current environment to memory.

This will also expand the memory, in case that the memory is insufficient to store the data.

Parameters

evm : The current EVM frame.

def calldatacopy(evm: Evm) -> None:
216
    """
217
    Copy a portion of the input data in current environment to memory.
218
219
    This will also expand the memory, in case that the memory is insufficient
220
    to store the data.
221
222
    Parameters
223
    ----------
224
    evm :
225
        The current EVM frame.
226
227
    """
228
    # STACK
229
    memory_start_index = pop(evm.stack)
230
    data_start_index = pop(evm.stack)
231
    size = pop(evm.stack)
232
233
    # GAS
234
    words = ceil32(Uint(size)) // Uint(32)
235
    copy_gas_cost = GAS_COPY * words
236
    extend_memory = calculate_gas_extend_memory(
237
        evm.memory, [(memory_start_index, size)]
238
    )
239
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
240
241
    # OPERATION
242
    evm.memory += b"\x00" * extend_memory.expand_by
243
    value = buffer_read(evm.message.data, data_start_index, size)
244
    memory_write(evm.memory, memory_start_index, value)
245
246
    # PROGRAM COUNTER
247
    evm.pc += Uint(1)

codesize

Push the size of code running in current environment onto the stack.

Parameters

evm : The current EVM frame.

def codesize(evm: Evm) -> None:
251
    """
252
    Push the size of code running in current environment onto the stack.
253
254
    Parameters
255
    ----------
256
    evm :
257
        The current EVM frame.
258
259
    """
260
    # STACK
261
    pass
262
263
    # GAS
264
    charge_gas(evm, GAS_BASE)
265
266
    # OPERATION
267
    push(evm.stack, U256(len(evm.code)))
268
269
    # PROGRAM COUNTER
270
    evm.pc += Uint(1)

codecopy

Copy a portion of the code in current environment to memory.

This will also expand the memory, in case that the memory is insufficient to store the data.

Parameters

evm : The current EVM frame.

def codecopy(evm: Evm) -> None:
274
    """
275
    Copy a portion of the code in current environment to memory.
276
277
    This will also expand the memory, in case that the memory is insufficient
278
    to store the data.
279
280
    Parameters
281
    ----------
282
    evm :
283
        The current EVM frame.
284
285
    """
286
    # STACK
287
    memory_start_index = pop(evm.stack)
288
    code_start_index = pop(evm.stack)
289
    size = pop(evm.stack)
290
291
    # GAS
292
    words = ceil32(Uint(size)) // Uint(32)
293
    copy_gas_cost = GAS_COPY * words
294
    extend_memory = calculate_gas_extend_memory(
295
        evm.memory, [(memory_start_index, size)]
296
    )
297
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
298
299
    # OPERATION
300
    evm.memory += b"\x00" * extend_memory.expand_by
301
    value = buffer_read(evm.code, code_start_index, size)
302
    memory_write(evm.memory, memory_start_index, value)
303
304
    # PROGRAM COUNTER
305
    evm.pc += Uint(1)

gasprice

Push the gas price used in current environment onto the stack.

Parameters

evm : The current EVM frame.

def gasprice(evm: Evm) -> None:
309
    """
310
    Push the gas price used in current environment onto the stack.
311
312
    Parameters
313
    ----------
314
    evm :
315
        The current EVM frame.
316
317
    """
318
    # STACK
319
    pass
320
321
    # GAS
322
    charge_gas(evm, GAS_BASE)
323
324
    # OPERATION
325
    push(evm.stack, U256(evm.message.tx_env.gas_price))
326
327
    # PROGRAM COUNTER
328
    evm.pc += Uint(1)

extcodesize

Push the code size of a given account onto the stack.

Parameters

evm : The current EVM frame.

def extcodesize(evm: Evm) -> None:
332
    """
333
    Push the code size of a given account onto the stack.
334
335
    Parameters
336
    ----------
337
    evm :
338
        The current EVM frame.
339
340
    """
341
    # STACK
342
    address = to_address_masked(pop(evm.stack))
343
344
    # GAS
343
    if address in evm.accessed_addresses:
344
        access_gas_cost = GAS_WARM_ACCESS
345
    else:
346
        evm.accessed_addresses.add(address)
347
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
345
    is_cold_access = address not in evm.accessed_addresses
346
    access_gas_cost = (
347
        GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS
348
    )
349
    if is_cold_access:
350
        evm.accessed_addresses.add(address)
351
352
    charge_gas(evm, access_gas_cost)
353
354
    # OPERATION
352
    state = evm.message.block_env.state
353
    code = get_code(state, get_account(state, address).code_hash)
355
    tx_state = evm.message.tx_env.state
356
    code_hash = get_account(tx_state, address).code_hash
357
    code = get_code(tx_state, code_hash)
358
359
    codesize = U256(len(code))
360
    push(evm.stack, codesize)
361
362
    # PROGRAM COUNTER
363
    evm.pc += Uint(1)

extcodecopy

Copy a portion of an account's code to memory.

Parameters

evm : The current EVM frame.

def extcodecopy(evm: Evm) -> None:
367
    """
368
    Copy a portion of an account's code to memory.
369
370
    Parameters
371
    ----------
372
    evm :
373
        The current EVM frame.
374
375
    """
376
    # STACK
377
    address = to_address_masked(pop(evm.stack))
378
    memory_start_index = pop(evm.stack)
379
    code_start_index = pop(evm.stack)
380
    size = pop(evm.stack)
381
382
    # GAS
383
    words = ceil32(Uint(size)) // Uint(32)
384
    copy_gas_cost = GAS_COPY * words
385
    extend_memory = calculate_gas_extend_memory(
386
        evm.memory, [(memory_start_index, size)]
387
    )
388
385
    if address in evm.accessed_addresses:
386
        access_gas_cost = GAS_WARM_ACCESS
387
    else:
388
        evm.accessed_addresses.add(address)
389
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
389
    is_cold_access = address not in evm.accessed_addresses
390
    access_gas_cost = (
391
        GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS
392
    )
393
    total_gas_cost = access_gas_cost + copy_gas_cost + extend_memory.cost
394
391
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
395
    if is_cold_access:
396
        evm.accessed_addresses.add(address)
397
398
    charge_gas(evm, total_gas_cost)
399
400
    # OPERATION
401
    evm.memory += b"\x00" * extend_memory.expand_by
395
    state = evm.message.block_env.state
396
    code = get_code(state, get_account(state, address).code_hash)
402
    tx_state = evm.message.tx_env.state
403
    code_hash = get_account(tx_state, address).code_hash
404
    code = get_code(tx_state, code_hash)
405
406
    value = buffer_read(code, code_start_index, size)
407
    memory_write(evm.memory, memory_start_index, value)
408
409
    # PROGRAM COUNTER
410
    evm.pc += Uint(1)

returndatasize

Pushes the size of the return data buffer onto the stack.

Parameters

evm : The current EVM frame.

def returndatasize(evm: Evm) -> None:
414
    """
415
    Pushes the size of the return data buffer onto the stack.
416
417
    Parameters
418
    ----------
419
    evm :
420
        The current EVM frame.
421
422
    """
423
    # STACK
424
    pass
425
426
    # GAS
427
    charge_gas(evm, GAS_BASE)
428
429
    # OPERATION
430
    push(evm.stack, U256(len(evm.return_data)))
431
432
    # PROGRAM COUNTER
433
    evm.pc += Uint(1)

returndatacopy

Copies data from the return data buffer to memory.

Parameters

evm : The current EVM frame.

def returndatacopy(evm: Evm) -> None:
437
    """
438
    Copies data from the return data buffer to memory.
439
440
    Parameters
441
    ----------
442
    evm :
443
        The current EVM frame.
444
445
    """
446
    # STACK
447
    memory_start_index = pop(evm.stack)
448
    return_data_start_position = pop(evm.stack)
449
    size = pop(evm.stack)
450
451
    # GAS
452
    words = ceil32(Uint(size)) // Uint(32)
453
    copy_gas_cost = GAS_RETURN_DATA_COPY * words
454
    extend_memory = calculate_gas_extend_memory(
455
        evm.memory, [(memory_start_index, size)]
456
    )
457
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
458
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
459
        raise OutOfBoundsRead
460
461
    evm.memory += b"\x00" * extend_memory.expand_by
462
    value = evm.return_data[
463
        return_data_start_position : return_data_start_position + size
464
    ]
465
    memory_write(evm.memory, memory_start_index, value)
466
467
    # PROGRAM COUNTER
468
    evm.pc += Uint(1)

extcodehash

Returns the keccak256 hash of a contract’s bytecode.

Parameters

evm : The current EVM frame.

def extcodehash(evm: Evm) -> None:
472
    """
473
    Returns the keccak256 hash of a contract’s bytecode.
474
475
    Parameters
476
    ----------
477
    evm :
478
        The current EVM frame.
479
480
    """
481
    # STACK
482
    address = to_address_masked(pop(evm.stack))
483
484
    # GAS
477
    if address in evm.accessed_addresses:
478
        access_gas_cost = GAS_WARM_ACCESS
479
    else:
480
        evm.accessed_addresses.add(address)
481
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
485
    is_cold_access = address not in evm.accessed_addresses
486
    access_gas_cost = (
487
        GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS
488
    )
489
    if is_cold_access:
490
        evm.accessed_addresses.add(address)
491
492
    charge_gas(evm, access_gas_cost)
493
494
    # OPERATION
486
    account = get_account(evm.message.block_env.state, address)
495
    tx_state = evm.message.tx_env.state
496
    account = get_account(tx_state, address)
497
498
    if account == EMPTY_ACCOUNT:
499
        codehash = U256(0)
500
    else:
501
        codehash = U256.from_be_bytes(account.code_hash)
502
503
    push(evm.stack, codehash)
504
505
    # PROGRAM COUNTER
506
    evm.pc += Uint(1)

self_balance

Pushes the balance of the current address to the stack.

Parameters

evm : The current EVM frame.

def self_balance(evm: Evm) -> None:
510
    """
511
    Pushes the balance of the current address to the stack.
512
513
    Parameters
514
    ----------
515
    evm :
516
        The current EVM frame.
517
518
    """
519
    # STACK
520
    pass
521
522
    # GAS
523
    charge_gas(evm, GAS_FAST_STEP)
524
525
    # OPERATION
526
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
517
    balance = get_account(
518
        evm.message.block_env.state, evm.message.current_target
527
    balance = get_account(
528
        evm.message.tx_env.state, evm.message.current_target
529
    ).balance
530
531
    push(evm.stack, balance)
532
533
    # PROGRAM COUNTER
534
    evm.pc += Uint(1)

base_fee

Pushes the base fee of the current block on to the stack.

Parameters

evm : The current EVM frame.

def base_fee(evm: Evm) -> None:
538
    """
539
    Pushes the base fee of the current block on to the stack.
540
541
    Parameters
542
    ----------
543
    evm :
544
        The current EVM frame.
545
546
    """
547
    # STACK
548
    pass
549
550
    # GAS
551
    charge_gas(evm, GAS_BASE)
552
553
    # OPERATION
554
    push(evm.stack, U256(evm.message.block_env.base_fee_per_gas))
555
556
    # PROGRAM COUNTER
557
    evm.pc += Uint(1)

blob_hash

Pushes the versioned hash at a particular index on to the stack.

Parameters

evm : The current EVM frame.

def blob_hash(evm: Evm) -> None:
561
    """
562
    Pushes the versioned hash at a particular index on to the stack.
563
564
    Parameters
565
    ----------
566
    evm :
567
        The current EVM frame.
568
569
    """
570
    # STACK
571
    index = pop(evm.stack)
572
573
    # GAS
574
    charge_gas(evm, GAS_BLOBHASH_OPCODE)
575
576
    # OPERATION
577
    if int(index) < len(evm.message.tx_env.blob_versioned_hashes):
578
        blob_hash = evm.message.tx_env.blob_versioned_hashes[index]
579
    else:
580
        blob_hash = Bytes32(b"\x00" * 32)
581
    push(evm.stack, U256.from_be_bytes(blob_hash))
582
583
    # PROGRAM COUNTER
584
    evm.pc += Uint(1)

blob_base_fee

Pushes the blob base fee on to the stack.

Parameters

evm : The current EVM frame.

def blob_base_fee(evm: Evm) -> None:
588
    """
589
    Pushes the blob base fee on to the stack.
590
591
    Parameters
592
    ----------
593
    evm :
594
        The current EVM frame.
595
596
    """
597
    # STACK
598
    pass
599
600
    # GAS
601
    charge_gas(evm, GAS_BASE)
602
603
    # OPERATION
604
    blob_base_fee = calculate_blob_gas_price(
605
        evm.message.block_env.excess_blob_gas
606
    )
607
    push(evm.stack, U256(blob_base_fee))
608
609
    # PROGRAM COUNTER
610
    evm.pc += Uint(1)