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:
36
    <snip>
45
    # STACK
46
    pass
47
48
    # GAS
49
    charge_gas(evm, GasCosts.OPCODE_ADDRESS)
50
51
    # OPERATION
52
    push(evm.stack, U256.from_be_bytes(evm.current_target))
53
54
    # PROGRAM COUNTER
55
    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:
59
    <snip>
68
    # STACK
69
    address = to_address_masked(pop(evm.stack))
70
71
    # GAS
72
    if address in evm.accessed_addresses:
73
        charge_gas(evm, GasCosts.WARM_ACCESS)
74
    else:
75
        evm.accessed_addresses.add(address)
76
        charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS)
77
78
    # OPERATION
79
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
80
    tx_state = evm.tx_env.state
81
    balance = get_account(tx_state, address).balance
82
83
    push(evm.stack, balance)
84
85
    # PROGRAM COUNTER
86
    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:
90
    <snip>
100
    # STACK
101
    pass
102
103
    # GAS
104
    charge_gas(evm, GasCosts.OPCODE_ORIGIN)
105
106
    # OPERATION
107
    push(evm.stack, U256.from_be_bytes(evm.tx_env.origin))
108
109
    # PROGRAM COUNTER
110
    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:
114
    <snip>
123
    # STACK
124
    pass
125
126
    # GAS
127
    charge_gas(evm, GasCosts.OPCODE_CALLER)
128
129
    # OPERATION
130
    push(evm.stack, U256.from_be_bytes(evm.caller))
131
132
    # PROGRAM COUNTER
133
    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:
137
    <snip>
146
    # STACK
147
    pass
148
149
    # GAS
150
    charge_gas(evm, GasCosts.OPCODE_CALLVALUE)
151
152
    # OPERATION
153
    push(evm.stack, evm.value)
154
155
    # PROGRAM COUNTER
156
    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:
160
    <snip>
170
    # STACK
171
    start_index = pop(evm.stack)
172
173
    # GAS
174
    charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD)
175
176
    # OPERATION
177
    value = buffer_read(evm.call_data, start_index, U256(32))
178
179
    push(evm.stack, U256.from_be_bytes(value))
180
181
    # PROGRAM COUNTER
182
    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:
186
    <snip>
195
    # STACK
196
    pass
197
198
    # GAS
199
    charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE)
200
201
    # OPERATION
202
    push(evm.stack, U256(len(evm.call_data)))
203
204
    # PROGRAM COUNTER
205
    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:
209
    <snip>
221
    # STACK
222
    memory_start_index = pop(evm.stack)
223
    data_start_index = pop(evm.stack)
224
    size = pop(evm.stack)
225
226
    # GAS
227
    words = ceil32(Uint(size)) // Uint(32)
228
    copy_gas_cost = ExecutionGas(GasCosts.OPCODE_COPY_PER_WORD * words)
229
    extend_memory = calculate_gas_extend_memory(
230
        evm.memory, [(memory_start_index, size)]
231
    )
232
    charge_gas(
233
        evm,
234
        GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost,
235
    )
236
237
    # OPERATION
238
    evm.memory += b"\x00" * extend_memory.expand_by
239
    value = buffer_read(evm.call_data, data_start_index, size)
240
    memory_write(evm.memory, memory_start_index, value)
241
242
    # PROGRAM COUNTER
243
    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:
247
    <snip>
256
    # STACK
257
    pass
258
259
    # GAS
260
    charge_gas(evm, GasCosts.OPCODE_CODESIZE)
261
262
    # OPERATION
263
    push(evm.stack, U256(len(evm.code)))
264
265
    # PROGRAM COUNTER
266
    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:
270
    <snip>
282
    # STACK
283
    memory_start_index = pop(evm.stack)
284
    code_start_index = pop(evm.stack)
285
    size = pop(evm.stack)
286
287
    # GAS
288
    words = ceil32(Uint(size)) // Uint(32)
289
    copy_gas_cost = ExecutionGas(GasCosts.OPCODE_COPY_PER_WORD * words)
290
    extend_memory = calculate_gas_extend_memory(
291
        evm.memory, [(memory_start_index, size)]
292
    )
293
    charge_gas(
294
        evm,
295
        GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost,
296
    )
297
298
    # OPERATION
299
    evm.memory += b"\x00" * extend_memory.expand_by
300
    value = buffer_read(evm.code, code_start_index, size)
301
    memory_write(evm.memory, memory_start_index, value)
302
303
    # PROGRAM COUNTER
304
    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:
308
    <snip>
317
    # STACK
318
    pass
319
320
    # GAS
321
    charge_gas(evm, GasCosts.OPCODE_GASPRICE)
322
323
    # OPERATION
324
    push(evm.stack, U256(evm.tx_env.effective_gas_price))
325
326
    # PROGRAM COUNTER
327
    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:
331
    <snip>
340
    # STACK
341
    address = to_address_masked(pop(evm.stack))
342
343
    # GAS
344
    if address in evm.accessed_addresses:
345
        access_gas_cost = GasCosts.WARM_ACCESS
346
    else:
347
        evm.accessed_addresses.add(address)
348
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
349
    access_gas_cost += GasCosts.WARM_ACCESS  # Code reading cost (EIP-8038)
350
    charge_gas(evm, access_gas_cost)
351
352
    # OPERATION
353
    tx_state = evm.tx_env.state
354
    code_hash = get_account(tx_state, address).code_hash
355
    code = get_code(tx_state, code_hash)
356
357
    codesize = U256(len(code))
358
    push(evm.stack, codesize)
359
360
    # PROGRAM COUNTER
361
    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:
365
    <snip>
374
    # STACK
375
    address = to_address_masked(pop(evm.stack))
376
    memory_start_index = pop(evm.stack)
377
    code_start_index = pop(evm.stack)
378
    size = pop(evm.stack)
379
380
    # GAS
381
    words = ceil32(Uint(size)) // Uint(32)
382
    copy_gas_cost = ExecutionGas(GasCosts.OPCODE_COPY_PER_WORD * words)
383
    extend_memory = calculate_gas_extend_memory(
384
        evm.memory, [(memory_start_index, size)]
385
    )
386
387
    if address in evm.accessed_addresses:
388
        access_gas_cost = GasCosts.WARM_ACCESS
389
    else:
390
        evm.accessed_addresses.add(address)
391
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
392
    access_gas_cost += GasCosts.WARM_ACCESS  # Code reading cost (EIP-8038)
393
394
    total_gas_cost = access_gas_cost + copy_gas_cost + extend_memory.cost
395
396
    charge_gas(evm, total_gas_cost)
397
398
    # OPERATION
399
    evm.memory += b"\x00" * extend_memory.expand_by
400
    tx_state = evm.tx_env.state
401
    code_hash = get_account(tx_state, address).code_hash
402
    code = get_code(tx_state, code_hash)
403
404
    value = buffer_read(code, code_start_index, size)
405
    memory_write(evm.memory, memory_start_index, value)
406
407
    # PROGRAM COUNTER
408
    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:
412
    <snip>
421
    # STACK
422
    pass
423
424
    # GAS
425
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
426
427
    # OPERATION
428
    push(evm.stack, U256(len(evm.return_data)))
429
430
    # PROGRAM COUNTER
431
    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:
435
    <snip>
444
    # STACK
445
    memory_start_index = pop(evm.stack)
446
    return_data_start_position = pop(evm.stack)
447
    size = pop(evm.stack)
448
449
    # GAS
450
    words = ceil32(Uint(size)) // Uint(32)
451
    copy_gas_cost = ExecutionGas(
452
        GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
453
    )
454
    extend_memory = calculate_gas_extend_memory(
455
        evm.memory, [(memory_start_index, size)]
456
    )
457
    charge_gas(
458
        evm,
459
        GasCosts.OPCODE_RETURNDATACOPY_BASE
460
        + copy_gas_cost
461
        + extend_memory.cost,
462
    )
463
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
464
        raise OutOfBoundsRead
465
466
    evm.memory += b"\x00" * extend_memory.expand_by
467
    value = evm.return_data[
468
        return_data_start_position : return_data_start_position + size
469
    ]
470
    memory_write(evm.memory, memory_start_index, value)
471
472
    # PROGRAM COUNTER
473
    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:
477
    <snip>
486
    # STACK
487
    address = to_address_masked(pop(evm.stack))
488
489
    # GAS
490
    if address in evm.accessed_addresses:
491
        access_gas_cost = GasCosts.WARM_ACCESS
492
    else:
493
        evm.accessed_addresses.add(address)
494
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
495
496
    charge_gas(evm, access_gas_cost)
497
498
    # OPERATION
499
    tx_state = evm.tx_env.state
500
    account = get_account(tx_state, address)
501
502
    if account == EMPTY_ACCOUNT:
503
        codehash = U256(0)
504
    else:
505
        codehash = U256.from_be_bytes(account.code_hash)
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
    <snip>
523
    # STACK
524
    pass
525
526
    # GAS
527
    charge_gas(evm, GasCosts.FAST_STEP)
528
529
    # OPERATION
530
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
531
    balance = get_account(evm.tx_env.state, evm.current_target).balance
532
533
    push(evm.stack, balance)
534
535
    # PROGRAM COUNTER
536
    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:
540
    <snip>
549
    # STACK
550
    pass
551
552
    # GAS
553
    charge_gas(evm, GasCosts.OPCODE_BASEFEE)
554
555
    # OPERATION
556
    push(evm.stack, U256(evm.block_env.base_fee_per_gas))
557
558
    # PROGRAM COUNTER
559
    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:
563
    <snip>
572
    # STACK
573
    index = pop(evm.stack)
574
575
    # GAS
576
    charge_gas(evm, GasCosts.OPCODE_BLOBHASH)
577
578
    # OPERATION
579
    if int(index) < len(evm.tx_env.blob_versioned_hashes):
580
        blob_hash = evm.tx_env.blob_versioned_hashes[index]
581
    else:
582
        blob_hash = Bytes32(b"\x00" * 32)
583
    push(evm.stack, U256.from_be_bytes(blob_hash))
584
585
    # PROGRAM COUNTER
586
    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:
590
    <snip>
599
    # STACK
600
    pass
601
602
    # GAS
603
    charge_gas(evm, GasCosts.OPCODE_BLOBBASEFEE)
604
605
    # OPERATION
606
    blob_base_fee = calculate_blob_gas_price(evm.block_env.excess_blob_gas)
607
    push(evm.stack, U256(blob_base_fee))
608
609
    # PROGRAM COUNTER
610
    evm.pc += Uint(1)