ethereum.forks.osaka.vm.instructions.environmentethereum.forks.bpo1.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
345
    else:
346
        evm.accessed_addresses.add(address)
347
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
348
349
    charge_gas(evm, access_gas_cost)
350
351
    # OPERATION
352
    tx_state = evm.message.tx_env.state
353
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
354
355
    codesize = U256(len(code))
356
    push(evm.stack, codesize)
357
358
    # PROGRAM COUNTER
359
    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:
363
    <snip>
372
    # STACK
373
    address = to_address_masked(pop(evm.stack))
374
    memory_start_index = pop(evm.stack)
375
    code_start_index = pop(evm.stack)
376
    size = pop(evm.stack)
377
378
    # GAS
379
    words = ceil32(Uint(size)) // Uint(32)
380
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
381
    extend_memory = calculate_gas_extend_memory(
382
        evm.memory, [(memory_start_index, size)]
383
    )
384
385
    if address in evm.accessed_addresses:
386
        access_gas_cost = GasCosts.WARM_ACCESS
387
    else:
388
        evm.accessed_addresses.add(address)
389
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
390
391
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
392
393
    # OPERATION
394
    evm.memory += b"\x00" * extend_memory.expand_by
395
    tx_state = evm.message.tx_env.state
396
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
397
398
    value = buffer_read(code, code_start_index, size)
399
    memory_write(evm.memory, memory_start_index, value)
400
401
    # PROGRAM COUNTER
402
    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:
406
    <snip>
415
    # STACK
416
    pass
417
418
    # GAS
419
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
420
421
    # OPERATION
422
    push(evm.stack, U256(len(evm.return_data)))
423
424
    # PROGRAM COUNTER
425
    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:
429
    <snip>
438
    # STACK
439
    memory_start_index = pop(evm.stack)
440
    return_data_start_position = pop(evm.stack)
441
    size = pop(evm.stack)
442
443
    # GAS
444
    words = ceil32(Uint(size)) // Uint(32)
445
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
446
    extend_memory = calculate_gas_extend_memory(
447
        evm.memory, [(memory_start_index, size)]
448
    )
449
    charge_gas(
450
        evm,
451
        GasCosts.OPCODE_RETURNDATACOPY_BASE
452
        + copy_gas_cost
453
        + extend_memory.cost,
454
    )
455
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
456
        raise OutOfBoundsRead
457
458
    evm.memory += b"\x00" * extend_memory.expand_by
459
    value = evm.return_data[
460
        return_data_start_position : return_data_start_position + size
461
    ]
462
    memory_write(evm.memory, memory_start_index, value)
463
464
    # PROGRAM COUNTER
465
    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:
469
    <snip>
478
    # STACK
479
    address = to_address_masked(pop(evm.stack))
480
481
    # GAS
482
    if address in evm.accessed_addresses:
483
        access_gas_cost = GasCosts.WARM_ACCESS
484
    else:
485
        evm.accessed_addresses.add(address)
486
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
487
488
    charge_gas(evm, access_gas_cost)
489
490
    # OPERATION
491
    account = get_account(evm.message.tx_env.state, address)
492
493
    if account == EMPTY_ACCOUNT:
494
        codehash = U256(0)
495
    else:
496
        codehash = U256.from_be_bytes(account.code_hash)
497
498
    push(evm.stack, codehash)
499
500
    # PROGRAM COUNTER
501
    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:
505
    <snip>
514
    # STACK
515
    pass
516
517
    # GAS
518
    charge_gas(evm, GasCosts.FAST_STEP)
519
520
    # OPERATION
521
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
522
    balance = get_account(
523
        evm.message.tx_env.state, evm.message.current_target
524
    ).balance
525
526
    push(evm.stack, balance)
527
528
    # PROGRAM COUNTER
529
    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:
533
    <snip>
542
    # STACK
543
    pass
544
545
    # GAS
546
    charge_gas(evm, GasCosts.OPCODE_BASEFEE)
547
548
    # OPERATION
549
    push(evm.stack, U256(evm.message.block_env.base_fee_per_gas))
550
551
    # PROGRAM COUNTER
552
    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:
556
    <snip>
565
    # STACK
566
    index = pop(evm.stack)
567
568
    # GAS
569
    charge_gas(evm, GasCosts.OPCODE_BLOBHASH)
570
571
    # OPERATION
572
    if int(index) < len(evm.message.tx_env.blob_versioned_hashes):
573
        blob_hash = evm.message.tx_env.blob_versioned_hashes[index]
574
    else:
575
        blob_hash = Bytes32(b"\x00" * 32)
576
    push(evm.stack, U256.from_be_bytes(blob_hash))
577
578
    # PROGRAM COUNTER
579
    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:
583
    <snip>
592
    # STACK
593
    pass
594
595
    # GAS
596
    charge_gas(evm, GasCosts.OPCODE_BLOBBASEFEE)
597
598
    # OPERATION
599
    blob_base_fee = calculate_blob_gas_price(
600
        evm.message.block_env.excess_blob_gas
601
    )
602
    push(evm.stack, U256(blob_base_fee))
603
604
    # PROGRAM COUNTER
605
    evm.pc += Uint(1)