ethereum.shanghai.vm.instructions.environmentethereum.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:
44
    """
45
    Pushes the address of the current executing account to the stack.
46
47
    Parameters
48
    ----------
49
    evm :
50
        The current EVM frame.
51
52
    """
53
    # STACK
54
    pass
55
56
    # GAS
57
    charge_gas(evm, GAS_BASE)
58
59
    # OPERATION
60
    push(evm.stack, U256.from_be_bytes(evm.message.current_target))
61
62
    # PROGRAM COUNTER
63
    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:
67
    """
68
    Pushes the balance of the given account onto the stack.
69
70
    Parameters
71
    ----------
72
    evm :
73
        The current EVM frame.
74
75
    """
76
    # STACK
77
    address = to_address(pop(evm.stack))
78
79
    # GAS
80
    if address in evm.accessed_addresses:
81
        charge_gas(evm, GAS_WARM_ACCESS)
82
    else:
83
        evm.accessed_addresses.add(address)
84
        charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS)
85
86
    # OPERATION
87
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
88
    balance = get_account(evm.message.block_env.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(pop(evm.stack))
343
344
    # GAS
345
    if address in evm.accessed_addresses:
346
        access_gas_cost = GAS_WARM_ACCESS
347
    else:
348
        evm.accessed_addresses.add(address)
349
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
350
351
    charge_gas(evm, access_gas_cost)
352
353
    # OPERATION
354
    code = get_account(evm.message.block_env.state, address).code
355
356
    codesize = U256(len(code))
357
    push(evm.stack, codesize)
358
359
    # PROGRAM COUNTER
360
    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:
364
    """
365
    Copy a portion of an account's code to memory.
366
367
    Parameters
368
    ----------
369
    evm :
370
        The current EVM frame.
371
372
    """
373
    # STACK
374
    address = to_address(pop(evm.stack))
375
    memory_start_index = pop(evm.stack)
376
    code_start_index = pop(evm.stack)
377
    size = pop(evm.stack)
378
379
    # GAS
380
    words = ceil32(Uint(size)) // Uint(32)
381
    copy_gas_cost = GAS_COPY * words
382
    extend_memory = calculate_gas_extend_memory(
383
        evm.memory, [(memory_start_index, size)]
384
    )
385
386
    if address in evm.accessed_addresses:
387
        access_gas_cost = GAS_WARM_ACCESS
388
    else:
389
        evm.accessed_addresses.add(address)
390
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
391
392
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
393
394
    # OPERATION
395
    evm.memory += b"\x00" * extend_memory.expand_by
396
    code = get_account(evm.message.block_env.state, address).code
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
    # STACK
415
    pass
416
417
    # GAS
418
    charge_gas(evm, GAS_BASE)
419
420
    # OPERATION
421
    push(evm.stack, U256(len(evm.return_data)))
422
423
    # PROGRAM COUNTER
424
    evm.pc += Uint(1)

returndatacopy

Copies data from the return data buffer code to memory

Parameters

evm : The current EVM frame.

def returndatacopy(evm: Evm) -> None:
428
    """
429
    Copies data from the return data buffer code to memory
430
431
    Parameters
432
    ----------
433
    evm :
434
        The current EVM frame.
435
    """
436
    # STACK
437
    memory_start_index = pop(evm.stack)
438
    return_data_start_position = pop(evm.stack)
439
    size = pop(evm.stack)
440
441
    # GAS
442
    words = ceil32(Uint(size)) // Uint(32)
443
    copy_gas_cost = GAS_RETURN_DATA_COPY * words
444
    extend_memory = calculate_gas_extend_memory(
445
        evm.memory, [(memory_start_index, size)]
446
    )
447
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
448
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
449
        raise OutOfBoundsRead
450
451
    evm.memory += b"\x00" * extend_memory.expand_by
452
    value = evm.return_data[
453
        return_data_start_position : return_data_start_position + size
454
    ]
455
    memory_write(evm.memory, memory_start_index, value)
456
457
    # PROGRAM COUNTER
458
    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:
462
    """
463
    Returns the keccak256 hash of a contract’s bytecode
464
    Parameters
465
    ----------
466
    evm :
467
        The current EVM frame.
468
    """
469
    # STACK
470
    address = to_address(pop(evm.stack))
471
472
    # GAS
473
    if address in evm.accessed_addresses:
474
        access_gas_cost = GAS_WARM_ACCESS
475
    else:
476
        evm.accessed_addresses.add(address)
477
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
478
479
    charge_gas(evm, access_gas_cost)
480
481
    # OPERATION
482
    account = get_account(evm.message.block_env.state, address)
483
484
    if account == EMPTY_ACCOUNT:
485
        codehash = U256(0)
486
    else:
487
        code = account.code
488
        codehash = U256.from_be_bytes(keccak256(code))
489
490
    push(evm.stack, codehash)
491
492
    # PROGRAM COUNTER
493
    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:
497
    """
498
    Pushes the balance of the current address to the stack.
499
500
    Parameters
501
    ----------
502
    evm :
503
        The current EVM frame.
504
505
    """
506
    # STACK
507
    pass
508
509
    # GAS
510
    charge_gas(evm, GAS_FAST_STEP)
511
512
    # OPERATION
513
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
514
    balance = get_account(
515
        evm.message.block_env.state, evm.message.current_target
516
    ).balance
517
518
    push(evm.stack, balance)
519
520
    # PROGRAM COUNTER
521
    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:
525
    """
526
    Pushes the base fee of the current block on to the stack.
527
528
    Parameters
529
    ----------
530
    evm :
531
        The current EVM frame.
532
533
    """
534
    # STACK
535
    pass
536
537
    # GAS
538
    charge_gas(evm, GAS_BASE)
539
540
    # OPERATION
541
    push(evm.stack, U256(evm.message.block_env.base_fee_per_gas))
542
543
    # PROGRAM COUNTER
544
    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:
548
    """
549
    Pushes the versioned hash at a particular index on to the stack.
550
551
    Parameters
552
    ----------
553
    evm :
554
        The current EVM frame.
555
556
    """
557
    # STACK
558
    index = pop(evm.stack)
559
560
    # GAS
561
    charge_gas(evm, GAS_BLOBHASH_OPCODE)
562
563
    # OPERATION
564
    if int(index) < len(evm.message.tx_env.blob_versioned_hashes):
565
        blob_hash = evm.message.tx_env.blob_versioned_hashes[index]
566
    else:
567
        blob_hash = Bytes32(b"\x00" * 32)
568
    push(evm.stack, U256.from_be_bytes(blob_hash))
569
570
    # PROGRAM COUNTER
571
    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:
575
    """
576
    Pushes the blob base fee on to the stack.
577
578
    Parameters
579
    ----------
580
    evm :
581
        The current EVM frame.
582
583
    """
584
    # STACK
585
    pass
586
587
    # GAS
588
    charge_gas(evm, GAS_BASE)
589
590
    # OPERATION
591
    blob_base_fee = calculate_blob_gas_price(
592
        evm.message.block_env.excess_blob_gas
593
    )
594
    push(evm.stack, U256(blob_base_fee))
595
596
    # PROGRAM COUNTER
597
    evm.pc += Uint(1)