ethereum.forks.bpo5.vm.instructions.environmentethereum.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
    <snip>
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
    <snip>
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
    <snip>
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
    <snip>
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
    <snip>
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
    <snip>
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
    <snip>
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
    <snip>
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
    <snip>
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
    <snip>
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
    <snip>
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
    <snip>
339
    # STACK
340
    address = to_address_masked(pop(evm.stack))
341
342
    # GAS
343
    if address in evm.accessed_addresses:
344
        access_gas_cost = GasCosts.WARM_ACCESS
344
        charge_gas(evm, GasCosts.WARM_ACCESS)
345
    else:
346
        evm.accessed_addresses.add(address)
347
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
348
349
    charge_gas(evm, access_gas_cost)
347
        charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS)
348
349
    # OPERATION
350
    tx_state = evm.message.tx_env.state
353
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
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
    <snip>
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
391
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
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
396
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
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
    <snip>
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
    <snip>
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
    <snip>
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
491
    account = get_account(evm.message.tx_env.state, address)
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
    <snip>
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
    <snip>
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
    <snip>
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
    <snip>
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)