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