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:
45
    """
46
    Pushes the address of the current executing account to the stack.
47
48
    Parameters
49
    ----------
50
    evm :
51
        The current EVM frame.
52
53
    """
54
    # STACK
55
    pass
56
57
    # GAS
58
    charge_gas(evm, GAS_BASE)
59
60
    # OPERATION
61
    push(evm.stack, U256.from_be_bytes(evm.message.current_target))
62
63
    # PROGRAM COUNTER
64
    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:
68
    """
69
    Pushes the balance of the given account onto the stack.
70
71
    Parameters
72
    ----------
73
    evm :
74
        The current EVM frame.
75
76
    """
77
    # STACK
78
    address = to_address_masked(pop(evm.stack))
79
80
    # GAS
79
    if address in evm.accessed_addresses:
80
        charge_gas(evm, GAS_WARM_ACCESS)
81
    else:
82
        evm.accessed_addresses.add(address)
83
        charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS)
81
    is_cold_access = address not in evm.accessed_addresses
82
    gas_cost = GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS
83
    if is_cold_access:
84
        evm.accessed_addresses.add(address)
85
86
    charge_gas(evm, gas_cost)
87
88
    # OPERATION
89
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
87
    balance = get_account(evm.message.block_env.state, address).balance
90
    state = evm.message.block_env.state
91
    balance = get_account(state, address).balance
92
    track_address(evm.state_changes, address)
93
94
    push(evm.stack, balance)
95
96
    # PROGRAM COUNTER
97
    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:
101
    """
102
    Pushes the address of the original transaction sender to the stack.
103
    The origin address can only be an EOA.
104
105
    Parameters
106
    ----------
107
    evm :
108
        The current EVM frame.
109
110
    """
111
    # STACK
112
    pass
113
114
    # GAS
115
    charge_gas(evm, GAS_BASE)
116
117
    # OPERATION
118
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
119
120
    # PROGRAM COUNTER
121
    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:
125
    """
126
    Pushes the address of the caller onto the stack.
127
128
    Parameters
129
    ----------
130
    evm :
131
        The current EVM frame.
132
133
    """
134
    # STACK
135
    pass
136
137
    # GAS
138
    charge_gas(evm, GAS_BASE)
139
140
    # OPERATION
141
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
142
143
    # PROGRAM COUNTER
144
    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:
148
    """
149
    Push the value (in wei) sent with the call onto the stack.
150
151
    Parameters
152
    ----------
153
    evm :
154
        The current EVM frame.
155
156
    """
157
    # STACK
158
    pass
159
160
    # GAS
161
    charge_gas(evm, GAS_BASE)
162
163
    # OPERATION
164
    push(evm.stack, evm.message.value)
165
166
    # PROGRAM COUNTER
167
    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:
171
    """
172
    Push a word (32 bytes) of the input data belonging to the current
173
    environment onto the stack.
174
175
    Parameters
176
    ----------
177
    evm :
178
        The current EVM frame.
179
180
    """
181
    # STACK
182
    start_index = pop(evm.stack)
183
184
    # GAS
185
    charge_gas(evm, GAS_VERY_LOW)
186
187
    # OPERATION
188
    value = buffer_read(evm.message.data, start_index, U256(32))
189
190
    push(evm.stack, U256.from_be_bytes(value))
191
192
    # PROGRAM COUNTER
193
    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:
197
    """
198
    Push the size of input data in current environment onto the stack.
199
200
    Parameters
201
    ----------
202
    evm :
203
        The current EVM frame.
204
205
    """
206
    # STACK
207
    pass
208
209
    # GAS
210
    charge_gas(evm, GAS_BASE)
211
212
    # OPERATION
213
    push(evm.stack, U256(len(evm.message.data)))
214
215
    # PROGRAM COUNTER
216
    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:
220
    """
221
    Copy a portion of the input data in current environment to memory.
222
223
    This will also expand the memory, in case that the memory is insufficient
224
    to store the data.
225
226
    Parameters
227
    ----------
228
    evm :
229
        The current EVM frame.
230
231
    """
232
    # STACK
233
    memory_start_index = pop(evm.stack)
234
    data_start_index = pop(evm.stack)
235
    size = pop(evm.stack)
236
237
    # GAS
238
    words = ceil32(Uint(size)) // Uint(32)
239
    copy_gas_cost = GAS_COPY * words
240
    extend_memory = calculate_gas_extend_memory(
241
        evm.memory, [(memory_start_index, size)]
242
    )
243
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
244
245
    # OPERATION
246
    evm.memory += b"\x00" * extend_memory.expand_by
247
    value = buffer_read(evm.message.data, data_start_index, size)
248
    memory_write(evm.memory, memory_start_index, value)
249
250
    # PROGRAM COUNTER
251
    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:
255
    """
256
    Push the size of code running in current environment onto the stack.
257
258
    Parameters
259
    ----------
260
    evm :
261
        The current EVM frame.
262
263
    """
264
    # STACK
265
    pass
266
267
    # GAS
268
    charge_gas(evm, GAS_BASE)
269
270
    # OPERATION
271
    push(evm.stack, U256(len(evm.code)))
272
273
    # PROGRAM COUNTER
274
    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:
278
    """
279
    Copy a portion of the code in current environment to memory.
280
281
    This will also expand the memory, in case that the memory is insufficient
282
    to store the data.
283
284
    Parameters
285
    ----------
286
    evm :
287
        The current EVM frame.
288
289
    """
290
    # STACK
291
    memory_start_index = pop(evm.stack)
292
    code_start_index = pop(evm.stack)
293
    size = pop(evm.stack)
294
295
    # GAS
296
    words = ceil32(Uint(size)) // Uint(32)
297
    copy_gas_cost = GAS_COPY * words
298
    extend_memory = calculate_gas_extend_memory(
299
        evm.memory, [(memory_start_index, size)]
300
    )
301
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
302
303
    # OPERATION
304
    evm.memory += b"\x00" * extend_memory.expand_by
305
    value = buffer_read(evm.code, code_start_index, size)
306
    memory_write(evm.memory, memory_start_index, value)
307
308
    # PROGRAM COUNTER
309
    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:
313
    """
314
    Push the gas price used in current environment onto the stack.
315
316
    Parameters
317
    ----------
318
    evm :
319
        The current EVM frame.
320
321
    """
322
    # STACK
323
    pass
324
325
    # GAS
326
    charge_gas(evm, GAS_BASE)
327
328
    # OPERATION
329
    push(evm.stack, U256(evm.message.tx_env.gas_price))
330
331
    # PROGRAM COUNTER
332
    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:
336
    """
337
    Push the code size of a given account onto the stack.
338
339
    Parameters
340
    ----------
341
    evm :
342
        The current EVM frame.
343
344
    """
345
    # STACK
346
    address = to_address_masked(pop(evm.stack))
347
348
    # GAS
344
    if address in evm.accessed_addresses:
345
        access_gas_cost = GAS_WARM_ACCESS
346
    else:
347
        evm.accessed_addresses.add(address)
348
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
349
    is_cold_access = address not in evm.accessed_addresses
350
    access_gas_cost = (
351
        GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS
352
    )
353
    if is_cold_access:
354
        evm.accessed_addresses.add(address)
355
356
    charge_gas(evm, access_gas_cost)
357
358
    # OPERATION
353
    code = get_account(evm.message.block_env.state, address).code
359
    state = evm.message.block_env.state
360
    code = get_account(state, address).code
361
    track_address(evm.state_changes, address)
362
363
    codesize = U256(len(code))
364
    push(evm.stack, codesize)
365
366
    # PROGRAM COUNTER
367
    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:
371
    """
372
    Copy a portion of an account's code to memory.
373
374
    Parameters
375
    ----------
376
    evm :
377
        The current EVM frame.
378
379
    """
380
    # STACK
381
    address = to_address_masked(pop(evm.stack))
382
    memory_start_index = pop(evm.stack)
383
    code_start_index = pop(evm.stack)
384
    size = pop(evm.stack)
385
386
    # GAS
387
    words = ceil32(Uint(size)) // Uint(32)
388
    copy_gas_cost = GAS_COPY * words
389
    extend_memory = calculate_gas_extend_memory(
390
        evm.memory, [(memory_start_index, size)]
391
    )
392
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
393
    is_cold_access = address not in evm.accessed_addresses
394
    access_gas_cost = (
395
        GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS
396
    )
397
    total_gas_cost = access_gas_cost + copy_gas_cost + extend_memory.cost
398
391
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
399
    if is_cold_access:
400
        evm.accessed_addresses.add(address)
401
402
    charge_gas(evm, total_gas_cost)
403
404
    # OPERATION
405
    evm.memory += b"\x00" * extend_memory.expand_by
395
    code = get_account(evm.message.block_env.state, address).code
406
    state = evm.message.block_env.state
407
    code = get_account(state, address).code
408
    track_address(evm.state_changes, address)
409
410
    value = buffer_read(code, code_start_index, size)
411
    memory_write(evm.memory, memory_start_index, value)
412
413
    # PROGRAM COUNTER
414
    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:
418
    """
419
    Pushes the size of the return data buffer onto the stack.
420
421
    Parameters
422
    ----------
423
    evm :
424
        The current EVM frame.
425
426
    """
427
    # STACK
428
    pass
429
430
    # GAS
431
    charge_gas(evm, GAS_BASE)
432
433
    # OPERATION
434
    push(evm.stack, U256(len(evm.return_data)))
435
436
    # PROGRAM COUNTER
437
    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:
441
    """
442
    Copies data from the return data buffer to memory.
443
444
    Parameters
445
    ----------
446
    evm :
447
        The current EVM frame.
448
449
    """
450
    # STACK
451
    memory_start_index = pop(evm.stack)
452
    return_data_start_position = pop(evm.stack)
453
    size = pop(evm.stack)
454
455
    # GAS
456
    words = ceil32(Uint(size)) // Uint(32)
457
    copy_gas_cost = GAS_RETURN_DATA_COPY * words
458
    extend_memory = calculate_gas_extend_memory(
459
        evm.memory, [(memory_start_index, size)]
460
    )
461
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
462
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
463
        raise OutOfBoundsRead
464
465
    evm.memory += b"\x00" * extend_memory.expand_by
466
    value = evm.return_data[
467
        return_data_start_position : return_data_start_position + size
468
    ]
469
    memory_write(evm.memory, memory_start_index, value)
470
471
    # PROGRAM COUNTER
472
    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:
476
    """
477
    Returns the keccak256 hash of a contract’s bytecode.
478
479
    Parameters
480
    ----------
481
    evm :
482
        The current EVM frame.
483
484
    """
485
    # STACK
486
    address = to_address_masked(pop(evm.stack))
487
488
    # GAS
476
    if address in evm.accessed_addresses:
477
        access_gas_cost = GAS_WARM_ACCESS
478
    else:
479
        evm.accessed_addresses.add(address)
480
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
489
    is_cold_access = address not in evm.accessed_addresses
490
    access_gas_cost = (
491
        GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS
492
    )
493
    if is_cold_access:
494
        evm.accessed_addresses.add(address)
495
496
    charge_gas(evm, access_gas_cost)
497
498
    # OPERATION
485
    account = get_account(evm.message.block_env.state, address)
499
    state = evm.message.block_env.state
500
    account = get_account(state, address)
501
    track_address(evm.state_changes, address)
502
503
    if account == EMPTY_ACCOUNT:
504
        codehash = U256(0)
505
    else:
506
        code = account.code
507
        codehash = U256.from_be_bytes(keccak256(code))
508
509
    push(evm.stack, codehash)
510
511
    # PROGRAM COUNTER
512
    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:
516
    """
517
    Pushes the balance of the current address to the stack.
518
519
    Parameters
520
    ----------
521
    evm :
522
        The current EVM frame.
523
524
    """
525
    # STACK
526
    pass
527
528
    # GAS
529
    charge_gas(evm, GAS_FAST_STEP)
530
531
    # OPERATION
532
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
533
    balance = get_account(
534
        evm.message.block_env.state, evm.message.current_target
535
    ).balance
536
537
    push(evm.stack, balance)
538
539
    # PROGRAM COUNTER
540
    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:
544
    """
545
    Pushes the base fee of the current block on to the stack.
546
547
    Parameters
548
    ----------
549
    evm :
550
        The current EVM frame.
551
552
    """
553
    # STACK
554
    pass
555
556
    # GAS
557
    charge_gas(evm, GAS_BASE)
558
559
    # OPERATION
560
    push(evm.stack, U256(evm.message.block_env.base_fee_per_gas))
561
562
    # PROGRAM COUNTER
563
    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:
567
    """
568
    Pushes the versioned hash at a particular index on to the stack.
569
570
    Parameters
571
    ----------
572
    evm :
573
        The current EVM frame.
574
575
    """
576
    # STACK
577
    index = pop(evm.stack)
578
579
    # GAS
580
    charge_gas(evm, GAS_BLOBHASH_OPCODE)
581
582
    # OPERATION
583
    if int(index) < len(evm.message.tx_env.blob_versioned_hashes):
584
        blob_hash = evm.message.tx_env.blob_versioned_hashes[index]
585
    else:
586
        blob_hash = Bytes32(b"\x00" * 32)
587
    push(evm.stack, U256.from_be_bytes(blob_hash))
588
589
    # PROGRAM COUNTER
590
    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:
594
    """
595
    Pushes the blob base fee on to the stack.
596
597
    Parameters
598
    ----------
599
    evm :
600
        The current EVM frame.
601
602
    """
603
    # STACK
604
    pass
605
606
    # GAS
607
    charge_gas(evm, GAS_BASE)
608
609
    # OPERATION
610
    blob_base_fee = calculate_blob_gas_price(
611
        evm.message.block_env.excess_blob_gas
612
    )
613
    push(evm.stack, U256(blob_base_fee))
614
615
    # PROGRAM COUNTER
616
    evm.pc += Uint(1)