ethereum.forks.shanghai.vm.instructions.environmentethereum.forks.cancun.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:
35
    """
36
    Pushes the address of the current executing account to the stack.
37
38
    Parameters
39
    ----------
40
    evm :
41
        The current EVM frame.
42
43
    """
44
    # STACK
45
    pass
46
47
    # GAS
48
    charge_gas(evm, GasCosts.OPCODE_ADDRESS)
49
50
    # OPERATION
51
    push(evm.stack, U256.from_be_bytes(evm.message.current_target))
52
53
    # PROGRAM COUNTER
54
    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:
58
    """
59
    Pushes the balance of the given account onto the stack.
60
61
    Parameters
62
    ----------
63
    evm :
64
        The current EVM frame.
65
66
    """
67
    # STACK
68
    address = to_address_masked(pop(evm.stack))
69
70
    # GAS
71
    if address in evm.accessed_addresses:
72
        charge_gas(evm, GasCosts.WARM_ACCESS)
73
    else:
74
        evm.accessed_addresses.add(address)
75
        charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS)
76
77
    # OPERATION
78
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
79
    tx_state = evm.message.tx_env.state
80
    balance = get_account(tx_state, address).balance
81
82
    push(evm.stack, balance)
83
84
    # PROGRAM COUNTER
85
    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:
89
    """
90
    Pushes the address of the original transaction sender to the stack.
91
    The origin address can only be an EOA.
92
93
    Parameters
94
    ----------
95
    evm :
96
        The current EVM frame.
97
98
    """
99
    # STACK
100
    pass
101
102
    # GAS
103
    charge_gas(evm, GasCosts.OPCODE_ORIGIN)
104
105
    # OPERATION
106
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
107
108
    # PROGRAM COUNTER
109
    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:
113
    """
114
    Pushes the address of the caller onto the stack.
115
116
    Parameters
117
    ----------
118
    evm :
119
        The current EVM frame.
120
121
    """
122
    # STACK
123
    pass
124
125
    # GAS
126
    charge_gas(evm, GasCosts.OPCODE_CALLER)
127
128
    # OPERATION
129
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
130
131
    # PROGRAM COUNTER
132
    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:
136
    """
137
    Push the value (in wei) sent with the call onto the stack.
138
139
    Parameters
140
    ----------
141
    evm :
142
        The current EVM frame.
143
144
    """
145
    # STACK
146
    pass
147
148
    # GAS
149
    charge_gas(evm, GasCosts.OPCODE_CALLVALUE)
150
151
    # OPERATION
152
    push(evm.stack, evm.message.value)
153
154
    # PROGRAM COUNTER
155
    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:
159
    """
160
    Push a word (32 bytes) of the input data belonging to the current
161
    environment onto the stack.
162
163
    Parameters
164
    ----------
165
    evm :
166
        The current EVM frame.
167
168
    """
169
    # STACK
170
    start_index = pop(evm.stack)
171
172
    # GAS
173
    charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD)
174
175
    # OPERATION
176
    value = buffer_read(evm.message.data, start_index, U256(32))
177
178
    push(evm.stack, U256.from_be_bytes(value))
179
180
    # PROGRAM COUNTER
181
    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:
185
    """
186
    Push the size of input data in current environment onto the stack.
187
188
    Parameters
189
    ----------
190
    evm :
191
        The current EVM frame.
192
193
    """
194
    # STACK
195
    pass
196
197
    # GAS
198
    charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE)
199
200
    # OPERATION
201
    push(evm.stack, U256(len(evm.message.data)))
202
203
    # PROGRAM COUNTER
204
    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:
208
    """
209
    Copy a portion of the input data in current environment to memory.
210
211
    This will also expand the memory, in case that the memory is insufficient
212
    to store the data.
213
214
    Parameters
215
    ----------
216
    evm :
217
        The current EVM frame.
218
219
    """
220
    # STACK
221
    memory_start_index = pop(evm.stack)
222
    data_start_index = pop(evm.stack)
223
    size = pop(evm.stack)
224
225
    # GAS
226
    words = ceil32(Uint(size)) // Uint(32)
227
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
228
    extend_memory = calculate_gas_extend_memory(
229
        evm.memory, [(memory_start_index, size)]
230
    )
231
    charge_gas(
232
        evm,
233
        GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost,
234
    )
235
236
    # OPERATION
237
    evm.memory += b"\x00" * extend_memory.expand_by
238
    value = buffer_read(evm.message.data, data_start_index, size)
239
    memory_write(evm.memory, memory_start_index, value)
240
241
    # PROGRAM COUNTER
242
    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:
246
    """
247
    Push the size of code running in current environment onto the stack.
248
249
    Parameters
250
    ----------
251
    evm :
252
        The current EVM frame.
253
254
    """
255
    # STACK
256
    pass
257
258
    # GAS
259
    charge_gas(evm, GasCosts.OPCODE_CODESIZE)
260
261
    # OPERATION
262
    push(evm.stack, U256(len(evm.code)))
263
264
    # PROGRAM COUNTER
265
    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:
269
    """
270
    Copy a portion of the code in current environment to memory.
271
272
    This will also expand the memory, in case that the memory is insufficient
273
    to store the data.
274
275
    Parameters
276
    ----------
277
    evm :
278
        The current EVM frame.
279
280
    """
281
    # STACK
282
    memory_start_index = pop(evm.stack)
283
    code_start_index = pop(evm.stack)
284
    size = pop(evm.stack)
285
286
    # GAS
287
    words = ceil32(Uint(size)) // Uint(32)
288
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
289
    extend_memory = calculate_gas_extend_memory(
290
        evm.memory, [(memory_start_index, size)]
291
    )
292
    charge_gas(
293
        evm,
294
        GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost,
295
    )
296
297
    # OPERATION
298
    evm.memory += b"\x00" * extend_memory.expand_by
299
    value = buffer_read(evm.code, code_start_index, size)
300
    memory_write(evm.memory, memory_start_index, value)
301
302
    # PROGRAM COUNTER
303
    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:
307
    """
308
    Push the gas price used in current environment onto the stack.
309
310
    Parameters
311
    ----------
312
    evm :
313
        The current EVM frame.
314
315
    """
316
    # STACK
317
    pass
318
319
    # GAS
320
    charge_gas(evm, GasCosts.OPCODE_GASPRICE)
321
322
    # OPERATION
323
    push(evm.stack, U256(evm.message.tx_env.gas_price))
324
325
    # PROGRAM COUNTER
326
    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:
330
    """
331
    Push the code size of a given account onto the stack.
332
333
    Parameters
334
    ----------
335
    evm :
336
        The current EVM frame.
337
338
    """
339
    # STACK
340
    address = to_address_masked(pop(evm.stack))
341
342
    # GAS
343
    if address in evm.accessed_addresses:
344
        access_gas_cost = GasCosts.WARM_ACCESS
345
    else:
346
        evm.accessed_addresses.add(address)
347
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
348
349
    charge_gas(evm, access_gas_cost)
350
351
    # OPERATION
352
    tx_state = evm.message.tx_env.state
353
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
354
355
    codesize = U256(len(code))
356
    push(evm.stack, codesize)
357
358
    # PROGRAM COUNTER
359
    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:
363
    """
364
    Copy a portion of an account's code to memory.
365
366
    Parameters
367
    ----------
368
    evm :
369
        The current EVM frame.
370
371
    """
372
    # STACK
373
    address = to_address_masked(pop(evm.stack))
374
    memory_start_index = pop(evm.stack)
375
    code_start_index = pop(evm.stack)
376
    size = pop(evm.stack)
377
378
    # GAS
379
    words = ceil32(Uint(size)) // Uint(32)
380
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
381
    extend_memory = calculate_gas_extend_memory(
382
        evm.memory, [(memory_start_index, size)]
383
    )
384
385
    if address in evm.accessed_addresses:
386
        access_gas_cost = GasCosts.WARM_ACCESS
387
    else:
388
        evm.accessed_addresses.add(address)
389
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
390
391
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
392
393
    # OPERATION
394
    evm.memory += b"\x00" * extend_memory.expand_by
395
    tx_state = evm.message.tx_env.state
396
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
397
398
    value = buffer_read(code, code_start_index, size)
399
    memory_write(evm.memory, memory_start_index, value)
400
401
    # PROGRAM COUNTER
402
    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:
406
    """
407
    Pushes the size of the return data buffer onto the stack.
408
409
    Parameters
410
    ----------
411
    evm :
412
        The current EVM frame.
413
414
    """
415
    # STACK
416
    pass
417
418
    # GAS
419
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
420
421
    # OPERATION
422
    push(evm.stack, U256(len(evm.return_data)))
423
424
    # PROGRAM COUNTER
425
    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:
429
    """
430
    Copies data from the return data buffer to memory.
431
432
    Parameters
433
    ----------
434
    evm :
435
        The current EVM frame.
436
437
    """
438
    # STACK
439
    memory_start_index = pop(evm.stack)
440
    return_data_start_position = pop(evm.stack)
441
    size = pop(evm.stack)
442
443
    # GAS
444
    words = ceil32(Uint(size)) // Uint(32)
445
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
446
    extend_memory = calculate_gas_extend_memory(
447
        evm.memory, [(memory_start_index, size)]
448
    )
449
    charge_gas(
450
        evm,
451
        GasCosts.OPCODE_RETURNDATACOPY_BASE
452
        + copy_gas_cost
453
        + extend_memory.cost,
454
    )
455
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
456
        raise OutOfBoundsRead
457
458
    evm.memory += b"\x00" * extend_memory.expand_by
459
    value = evm.return_data[
460
        return_data_start_position : return_data_start_position + size
461
    ]
462
    memory_write(evm.memory, memory_start_index, value)
463
464
    # PROGRAM COUNTER
465
    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:
469
    """
470
    Returns the keccak256 hash of a contract’s bytecode.
471
472
    Parameters
473
    ----------
474
    evm :
475
        The current EVM frame.
476
477
    """
478
    # STACK
479
    address = to_address_masked(pop(evm.stack))
480
481
    # GAS
482
    if address in evm.accessed_addresses:
483
        access_gas_cost = GasCosts.WARM_ACCESS
484
    else:
485
        evm.accessed_addresses.add(address)
486
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
487
488
    charge_gas(evm, access_gas_cost)
489
490
    # OPERATION
491
    account = get_account(evm.message.tx_env.state, address)
492
493
    if account == EMPTY_ACCOUNT:
494
        codehash = U256(0)
495
    else:
496
        codehash = U256.from_be_bytes(account.code_hash)
497
498
    push(evm.stack, codehash)
499
500
    # PROGRAM COUNTER
501
    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:
505
    """
506
    Pushes the balance of the current address to the stack.
507
508
    Parameters
509
    ----------
510
    evm :
511
        The current EVM frame.
512
513
    """
514
    # STACK
515
    pass
516
517
    # GAS
518
    charge_gas(evm, GasCosts.FAST_STEP)
519
520
    # OPERATION
521
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
522
    balance = get_account(
523
        evm.message.tx_env.state, evm.message.current_target
524
    ).balance
525
526
    push(evm.stack, balance)
527
528
    # PROGRAM COUNTER
529
    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:
533
    """
534
    Pushes the base fee of the current block on to the stack.
535
536
    Parameters
537
    ----------
538
    evm :
539
        The current EVM frame.
540
541
    """
542
    # STACK
543
    pass
544
545
    # GAS
546
    charge_gas(evm, GasCosts.OPCODE_BASEFEE)
547
548
    # OPERATION
549
    push(evm.stack, U256(evm.message.block_env.base_fee_per_gas))
550
551
    # PROGRAM COUNTER
552
    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:
556
    """
557
    Pushes the versioned hash at a particular index on to the stack.
558
559
    Parameters
560
    ----------
561
    evm :
562
        The current EVM frame.
563
564
    """
565
    # STACK
566
    index = pop(evm.stack)
567
568
    # GAS
569
    charge_gas(evm, GasCosts.OPCODE_BLOBHASH)
570
571
    # OPERATION
572
    if int(index) < len(evm.message.tx_env.blob_versioned_hashes):
573
        blob_hash = evm.message.tx_env.blob_versioned_hashes[index]
574
    else:
575
        blob_hash = Bytes32(b"\x00" * 32)
576
    push(evm.stack, U256.from_be_bytes(blob_hash))
577
578
    # PROGRAM COUNTER
579
    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:
583
    """
584
    Pushes the blob base fee on to the stack.
585
586
    Parameters
587
    ----------
588
    evm :
589
        The current EVM frame.
590
591
    """
592
    # STACK
593
    pass
594
595
    # GAS
596
    charge_gas(evm, GasCosts.OPCODE_BLOBBASEFEE)
597
598
    # OPERATION
599
    blob_base_fee = calculate_blob_gas_price(
600
        evm.message.block_env.excess_blob_gas
601
    )
602
    push(evm.stack, U256(blob_base_fee))
603
604
    # PROGRAM COUNTER
605
    evm.pc += Uint(1)