ethereum.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.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.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.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
        charge_gas(evm, GAS_WARM_ACCESS)
347
    else:
348
        evm.accessed_addresses.add(address)
349
        charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS)
350
351
    # OPERATION
352
    # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code.
353
    codesize = U256(len(get_account(evm.env.state, address).code))
354
355
    push(evm.stack, codesize)
356
357
    # PROGRAM COUNTER
358
    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:
362
    """
363
    Copy a portion of an account's code to memory.
364
365
    Parameters
366
    ----------
367
    evm :
368
        The current EVM frame.
369
370
    """
371
    # STACK
372
    address = to_address(pop(evm.stack))
373
    memory_start_index = pop(evm.stack)
374
    code_start_index = pop(evm.stack)
375
    size = pop(evm.stack)
376
377
    # GAS
378
    words = ceil32(Uint(size)) // Uint(32)
379
    copy_gas_cost = GAS_COPY * words
380
    extend_memory = calculate_gas_extend_memory(
381
        evm.memory, [(memory_start_index, size)]
382
    )
383
384
    if address in evm.accessed_addresses:
385
        charge_gas(evm, GAS_WARM_ACCESS + copy_gas_cost + extend_memory.cost)
386
    else:
387
        evm.accessed_addresses.add(address)
388
        charge_gas(
389
            evm, GAS_COLD_ACCOUNT_ACCESS + copy_gas_cost + extend_memory.cost
390
        )
391
392
    # OPERATION
393
    evm.memory += b"\x00" * extend_memory.expand_by
394
    code = get_account(evm.env.state, address).code
395
    value = buffer_read(code, code_start_index, size)
396
    memory_write(evm.memory, memory_start_index, value)
397
398
    # PROGRAM COUNTER
399
    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:
403
    """
404
    Pushes the size of the return data buffer onto the stack.
405
406
    Parameters
407
    ----------
408
    evm :
409
        The current EVM frame.
410
    """
411
    # STACK
412
    pass
413
414
    # GAS
415
    charge_gas(evm, GAS_BASE)
416
417
    # OPERATION
418
    push(evm.stack, U256(len(evm.return_data)))
419
420
    # PROGRAM COUNTER
421
    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:
425
    """
426
    Copies data from the return data buffer code to memory
427
428
    Parameters
429
    ----------
430
    evm :
431
        The current EVM frame.
432
    """
433
    # STACK
434
    memory_start_index = pop(evm.stack)
435
    return_data_start_position = pop(evm.stack)
436
    size = pop(evm.stack)
437
438
    # GAS
439
    words = ceil32(Uint(size)) // Uint(32)
440
    copy_gas_cost = GAS_RETURN_DATA_COPY * words
441
    extend_memory = calculate_gas_extend_memory(
442
        evm.memory, [(memory_start_index, size)]
443
    )
444
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
445
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
446
        raise OutOfBoundsRead
447
448
    evm.memory += b"\x00" * extend_memory.expand_by
449
    value = evm.return_data[
450
        return_data_start_position : return_data_start_position + size
451
    ]
452
    memory_write(evm.memory, memory_start_index, value)
453
454
    # PROGRAM COUNTER
455
    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:
459
    """
460
    Returns the keccak256 hash of a contract’s bytecode
461
    Parameters
462
    ----------
463
    evm :
464
        The current EVM frame.
465
    """
466
    # STACK
467
    address = to_address(pop(evm.stack))
468
469
    # GAS
470
    if address in evm.accessed_addresses:
471
        charge_gas(evm, GAS_WARM_ACCESS)
472
    else:
473
        evm.accessed_addresses.add(address)
474
        charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS)
475
476
    # OPERATION
477
    account = get_account(evm.env.state, address)
478
479
    if account == EMPTY_ACCOUNT:
480
        codehash = U256(0)
481
    else:
482
        codehash = U256.from_be_bytes(keccak256(account.code))
483
484
    push(evm.stack, codehash)
485
486
    # PROGRAM COUNTER
487
    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:
491
    """
492
    Pushes the balance of the current address to the stack.
493
494
    Parameters
495
    ----------
496
    evm :
497
        The current EVM frame.
498
499
    """
500
    # STACK
501
    pass
502
503
    # GAS
504
    charge_gas(evm, GAS_FAST_STEP)
505
506
    # OPERATION
507
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
508
    balance = get_account(evm.env.state, evm.message.current_target).balance
509
510
    push(evm.stack, balance)
511
512
    # PROGRAM COUNTER
513
    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:
517
    """
518
    Pushes the base fee of the current block on to the stack.
519
520
    Parameters
521
    ----------
522
    evm :
523
        The current EVM frame.
524
525
    """
526
    # STACK
527
    pass
528
529
    # GAS
530
    charge_gas(evm, GAS_BASE)
531
532
    # OPERATION
533
    push(evm.stack, U256(evm.env.base_fee_per_gas))
534
535
    # PROGRAM COUNTER
536
    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:
540
    """
541
    Pushes the versioned hash at a particular index on to the stack.
542
543
    Parameters
544
    ----------
545
    evm :
546
        The current EVM frame.
547
548
    """
549
    # STACK
550
    index = pop(evm.stack)
551
552
    # GAS
553
    charge_gas(evm, GAS_BLOBHASH_OPCODE)
554
555
    # OPERATION
556
    if int(index) < len(evm.env.blob_versioned_hashes):
557
        blob_hash = evm.env.blob_versioned_hashes[index]
558
    else:
559
        blob_hash = Bytes32(b"\x00" * 32)
560
    push(evm.stack, U256.from_be_bytes(blob_hash))
561
562
    # PROGRAM COUNTER
563
    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:
567
    """
568
    Pushes the blob base fee on to the stack.
569
570
    Parameters
571
    ----------
572
    evm :
573
        The current EVM frame.
574
575
    """
576
    # STACK
577
    pass
578
579
    # GAS
580
    charge_gas(evm, GAS_BASE)
581
582
    # OPERATION
583
    blob_base_fee = calculate_blob_gas_price(evm.env.excess_blob_gas)
584
    push(evm.stack, U256(blob_base_fee))
585
586
    # PROGRAM COUNTER
587
    evm.pc += Uint(1)