ethereum.forks.gray_glacier.vm.instructions.environmentethereum.forks.paris.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:
33
    <snip>
42
    # STACK
43
    pass
44
45
    # GAS
46
    charge_gas(evm, GasCosts.OPCODE_ADDRESS)
47
48
    # OPERATION
49
    push(evm.stack, U256.from_be_bytes(evm.message.current_target))
50
51
    # PROGRAM COUNTER
52
    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:
56
    <snip>
65
    # STACK
66
    address = to_address_masked(pop(evm.stack))
67
68
    # GAS
69
    if address in evm.accessed_addresses:
70
        charge_gas(evm, GasCosts.WARM_ACCESS)
71
    else:
72
        evm.accessed_addresses.add(address)
73
        charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS)
74
75
    # OPERATION
76
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
77
    tx_state = evm.message.tx_env.state
78
    balance = get_account(tx_state, address).balance
79
80
    push(evm.stack, balance)
81
82
    # PROGRAM COUNTER
83
    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:
87
    <snip>
97
    # STACK
98
    pass
99
100
    # GAS
101
    charge_gas(evm, GasCosts.OPCODE_ORIGIN)
102
103
    # OPERATION
104
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
105
106
    # PROGRAM COUNTER
107
    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:
111
    <snip>
120
    # STACK
121
    pass
122
123
    # GAS
124
    charge_gas(evm, GasCosts.OPCODE_CALLER)
125
126
    # OPERATION
127
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
128
129
    # PROGRAM COUNTER
130
    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:
134
    <snip>
143
    # STACK
144
    pass
145
146
    # GAS
147
    charge_gas(evm, GasCosts.OPCODE_CALLVALUE)
148
149
    # OPERATION
150
    push(evm.stack, evm.message.value)
151
152
    # PROGRAM COUNTER
153
    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:
157
    <snip>
167
    # STACK
168
    start_index = pop(evm.stack)
169
170
    # GAS
171
    charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD)
172
173
    # OPERATION
174
    value = buffer_read(evm.message.data, start_index, U256(32))
175
176
    push(evm.stack, U256.from_be_bytes(value))
177
178
    # PROGRAM COUNTER
179
    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:
183
    <snip>
192
    # STACK
193
    pass
194
195
    # GAS
196
    charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE)
197
198
    # OPERATION
199
    push(evm.stack, U256(len(evm.message.data)))
200
201
    # PROGRAM COUNTER
202
    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:
206
    <snip>
218
    # STACK
219
    memory_start_index = pop(evm.stack)
220
    data_start_index = pop(evm.stack)
221
    size = pop(evm.stack)
222
223
    # GAS
224
    words = ceil32(Uint(size)) // Uint(32)
225
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
226
    extend_memory = calculate_gas_extend_memory(
227
        evm.memory, [(memory_start_index, size)]
228
    )
229
    charge_gas(
230
        evm,
231
        GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost,
232
    )
233
234
    # OPERATION
235
    evm.memory += b"\x00" * extend_memory.expand_by
236
    value = buffer_read(evm.message.data, data_start_index, size)
237
    memory_write(evm.memory, memory_start_index, value)
238
239
    # PROGRAM COUNTER
240
    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:
244
    <snip>
253
    # STACK
254
    pass
255
256
    # GAS
257
    charge_gas(evm, GasCosts.OPCODE_CODESIZE)
258
259
    # OPERATION
260
    push(evm.stack, U256(len(evm.code)))
261
262
    # PROGRAM COUNTER
263
    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:
267
    <snip>
279
    # STACK
280
    memory_start_index = pop(evm.stack)
281
    code_start_index = pop(evm.stack)
282
    size = pop(evm.stack)
283
284
    # GAS
285
    words = ceil32(Uint(size)) // Uint(32)
286
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
287
    extend_memory = calculate_gas_extend_memory(
288
        evm.memory, [(memory_start_index, size)]
289
    )
290
    charge_gas(
291
        evm,
292
        GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost,
293
    )
294
295
    # OPERATION
296
    evm.memory += b"\x00" * extend_memory.expand_by
297
    value = buffer_read(evm.code, code_start_index, size)
298
    memory_write(evm.memory, memory_start_index, value)
299
300
    # PROGRAM COUNTER
301
    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:
305
    <snip>
314
    # STACK
315
    pass
316
317
    # GAS
318
    charge_gas(evm, GasCosts.OPCODE_GASPRICE)
319
320
    # OPERATION
321
    push(evm.stack, U256(evm.message.tx_env.gas_price))
322
323
    # PROGRAM COUNTER
324
    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:
328
    <snip>
337
    # STACK
338
    address = to_address_masked(pop(evm.stack))
339
340
    # GAS
341
    if address in evm.accessed_addresses:
342
        access_gas_cost = GasCosts.WARM_ACCESS
343
    else:
344
        evm.accessed_addresses.add(address)
345
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
346
347
    charge_gas(evm, access_gas_cost)
348
349
    # OPERATION
350
    tx_state = evm.message.tx_env.state
351
    account = get_account(tx_state, address)
352
    code = get_code(tx_state, account.code_hash)
351
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
352
353
    codesize = U256(len(code))
354
    push(evm.stack, codesize)
355
356
    # PROGRAM COUNTER
357
    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:
361
    <snip>
370
    # STACK
371
    address = to_address_masked(pop(evm.stack))
372
    memory_start_index = pop(evm.stack)
373
    code_start_index = pop(evm.stack)
374
    size = pop(evm.stack)
375
376
    # GAS
377
    words = ceil32(Uint(size)) // Uint(32)
378
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
379
    extend_memory = calculate_gas_extend_memory(
380
        evm.memory, [(memory_start_index, size)]
381
    )
382
383
    if address in evm.accessed_addresses:
384
        access_gas_cost = GasCosts.WARM_ACCESS
385
    else:
386
        evm.accessed_addresses.add(address)
387
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
388
389
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
390
391
    # OPERATION
392
    evm.memory += b"\x00" * extend_memory.expand_by
393
    tx_state = evm.message.tx_env.state
395
    account = get_account(tx_state, address)
396
    code = get_code(tx_state, account.code_hash)
394
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
395
396
    value = buffer_read(code, code_start_index, size)
397
    memory_write(evm.memory, memory_start_index, value)
398
399
    # PROGRAM COUNTER
400
    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:
404
    <snip>
413
    # STACK
414
    pass
415
416
    # GAS
417
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
418
419
    # OPERATION
420
    push(evm.stack, U256(len(evm.return_data)))
421
422
    # PROGRAM COUNTER
423
    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:
427
    <snip>
436
    # STACK
437
    memory_start_index = pop(evm.stack)
438
    return_data_start_position = pop(evm.stack)
439
    size = pop(evm.stack)
440
441
    # GAS
442
    words = ceil32(Uint(size)) // Uint(32)
443
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
444
    extend_memory = calculate_gas_extend_memory(
445
        evm.memory, [(memory_start_index, size)]
446
    )
447
    charge_gas(
448
        evm,
449
        GasCosts.OPCODE_RETURNDATACOPY_BASE
450
        + copy_gas_cost
451
        + extend_memory.cost,
452
    )
453
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
454
        raise OutOfBoundsRead
455
456
    evm.memory += b"\x00" * extend_memory.expand_by
457
    value = evm.return_data[
458
        return_data_start_position : return_data_start_position + size
459
    ]
460
    memory_write(evm.memory, memory_start_index, value)
461
462
    # PROGRAM COUNTER
463
    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:
467
    <snip>
476
    # STACK
477
    address = to_address_masked(pop(evm.stack))
478
479
    # GAS
480
    if address in evm.accessed_addresses:
481
        access_gas_cost = GasCosts.WARM_ACCESS
482
    else:
483
        evm.accessed_addresses.add(address)
484
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
485
486
    charge_gas(evm, access_gas_cost)
487
488
    # OPERATION
489
    account = get_account(evm.message.tx_env.state, address)
490
491
    if account == EMPTY_ACCOUNT:
492
        codehash = U256(0)
493
    else:
494
        codehash = U256.from_be_bytes(account.code_hash)
495
496
    push(evm.stack, codehash)
497
498
    # PROGRAM COUNTER
499
    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:
503
    <snip>
512
    # STACK
513
    pass
514
515
    # GAS
516
    charge_gas(evm, GasCosts.FAST_STEP)
517
518
    # OPERATION
519
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
520
    balance = get_account(
521
        evm.message.tx_env.state, evm.message.current_target
522
    ).balance
523
524
    push(evm.stack, balance)
525
526
    # PROGRAM COUNTER
527
    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:
531
    <snip>
540
    # STACK
541
    pass
542
543
    # GAS
544
    charge_gas(evm, GasCosts.OPCODE_BASEFEE)
545
546
    # OPERATION
547
    push(evm.stack, U256(evm.message.block_env.base_fee_per_gas))
548
549
    # PROGRAM COUNTER
550
    evm.pc += Uint(1)