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:
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
        charge_gas(evm, GasCosts.WARM_ACCESS)
345
    else:
346
        evm.accessed_addresses.add(address)
347
        charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS)
348
349
    # OPERATION
350
    tx_state = evm.message.tx_env.state
351
    code_hash = get_account(tx_state, address).code_hash
352
    code = get_code(tx_state, code_hash)
353
354
    codesize = U256(len(code))
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_masked(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 = GasCosts.OPCODE_COPY_PER_WORD * 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
        access_gas_cost = GasCosts.WARM_ACCESS
386
    else:
387
        evm.accessed_addresses.add(address)
388
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
389
390
    total_gas_cost = access_gas_cost + copy_gas_cost + extend_memory.cost
391
392
    charge_gas(evm, total_gas_cost)
393
394
    # OPERATION
395
    evm.memory += b"\x00" * extend_memory.expand_by
396
    tx_state = evm.message.tx_env.state
397
    code_hash = get_account(tx_state, address).code_hash
398
    code = get_code(tx_state, code_hash)
399
400
    value = buffer_read(code, code_start_index, size)
401
    memory_write(evm.memory, memory_start_index, value)
402
403
    # PROGRAM COUNTER
404
    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:
408
    """
409
    Pushes the size of the return data buffer onto the stack.
410
411
    Parameters
412
    ----------
413
    evm :
414
        The current EVM frame.
415
416
    """
417
    # STACK
418
    pass
419
420
    # GAS
421
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
422
423
    # OPERATION
424
    push(evm.stack, U256(len(evm.return_data)))
425
426
    # PROGRAM COUNTER
427
    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:
431
    """
432
    Copies data from the return data buffer to memory.
433
434
    Parameters
435
    ----------
436
    evm :
437
        The current EVM frame.
438
439
    """
440
    # STACK
441
    memory_start_index = pop(evm.stack)
442
    return_data_start_position = pop(evm.stack)
443
    size = pop(evm.stack)
444
445
    # GAS
446
    words = ceil32(Uint(size)) // Uint(32)
447
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
448
    extend_memory = calculate_gas_extend_memory(
449
        evm.memory, [(memory_start_index, size)]
450
    )
451
    charge_gas(
452
        evm,
453
        GasCosts.OPCODE_RETURNDATACOPY_BASE
454
        + copy_gas_cost
455
        + extend_memory.cost,
456
    )
457
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
458
        raise OutOfBoundsRead
459
460
    evm.memory += b"\x00" * extend_memory.expand_by
461
    value = evm.return_data[
462
        return_data_start_position : return_data_start_position + size
463
    ]
464
    memory_write(evm.memory, memory_start_index, value)
465
466
    # PROGRAM COUNTER
467
    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:
471
    """
472
    Returns the keccak256 hash of a contract’s bytecode.
473
474
    Parameters
475
    ----------
476
    evm :
477
        The current EVM frame.
478
479
    """
480
    # STACK
481
    address = to_address_masked(pop(evm.stack))
482
483
    # GAS
484
    if address in evm.accessed_addresses:
485
        access_gas_cost = GasCosts.WARM_ACCESS
486
    else:
487
        evm.accessed_addresses.add(address)
488
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
489
490
    charge_gas(evm, access_gas_cost)
491
492
    # OPERATION
493
    tx_state = evm.message.tx_env.state
494
    account = get_account(tx_state, address)
495
496
    if account == EMPTY_ACCOUNT:
497
        codehash = U256(0)
498
    else:
499
        codehash = U256.from_be_bytes(account.code_hash)
500
501
    push(evm.stack, codehash)
502
503
    # PROGRAM COUNTER
504
    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:
508
    """
509
    Pushes the balance of the current address to the stack.
510
511
    Parameters
512
    ----------
513
    evm :
514
        The current EVM frame.
515
516
    """
517
    # STACK
518
    pass
519
520
    # GAS
521
    charge_gas(evm, GasCosts.FAST_STEP)
522
523
    # OPERATION
524
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
525
    balance = get_account(
526
        evm.message.tx_env.state, evm.message.current_target
527
    ).balance
528
529
    push(evm.stack, balance)
530
531
    # PROGRAM COUNTER
532
    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:
536
    """
537
    Pushes the base fee of the current block on to the stack.
538
539
    Parameters
540
    ----------
541
    evm :
542
        The current EVM frame.
543
544
    """
545
    # STACK
546
    pass
547
548
    # GAS
549
    charge_gas(evm, GasCosts.OPCODE_BASEFEE)
550
551
    # OPERATION
552
    push(evm.stack, U256(evm.message.block_env.base_fee_per_gas))
553
554
    # PROGRAM COUNTER
555
    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:
559
    """
560
    Pushes the versioned hash at a particular index on to the stack.
561
562
    Parameters
563
    ----------
564
    evm :
565
        The current EVM frame.
566
567
    """
568
    # STACK
569
    index = pop(evm.stack)
570
571
    # GAS
572
    charge_gas(evm, GasCosts.OPCODE_BLOBHASH)
573
574
    # OPERATION
575
    if int(index) < len(evm.message.tx_env.blob_versioned_hashes):
576
        blob_hash = evm.message.tx_env.blob_versioned_hashes[index]
577
    else:
578
        blob_hash = Bytes32(b"\x00" * 32)
579
    push(evm.stack, U256.from_be_bytes(blob_hash))
580
581
    # PROGRAM COUNTER
582
    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:
586
    """
587
    Pushes the blob base fee on to the stack.
588
589
    Parameters
590
    ----------
591
    evm :
592
        The current EVM frame.
593
594
    """
595
    # STACK
596
    pass
597
598
    # GAS
599
    charge_gas(evm, GasCosts.OPCODE_BLOBBASEFEE)
600
601
    # OPERATION
602
    blob_base_fee = calculate_blob_gas_price(
603
        evm.message.block_env.excess_blob_gas
604
    )
605
    push(evm.stack, U256(blob_base_fee))
606
607
    # PROGRAM COUNTER
608
    evm.pc += Uint(1)