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:
29
    <snip>
38
    # STACK
39
    pass
40
41
    # GAS
42
    charge_gas(evm, GasCosts.OPCODE_ADDRESS)
43
44
    # OPERATION
45
    push(evm.stack, U256.from_be_bytes(evm.message.current_target))
46
47
    # PROGRAM COUNTER
48
    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:
52
    <snip>
61
    # STACK
62
    address = to_address_masked(pop(evm.stack))
63
64
    # GAS
65
    if address in evm.accessed_addresses:
66
        charge_gas(evm, GasCosts.WARM_ACCESS)
67
    else:
68
        evm.accessed_addresses.add(address)
69
        charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS)
70
71
    # OPERATION
72
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
73
    tx_state = evm.message.tx_env.state
74
    balance = get_account(tx_state, address).balance
75
76
    push(evm.stack, balance)
77
78
    # PROGRAM COUNTER
79
    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:
83
    <snip>
93
    # STACK
94
    pass
95
96
    # GAS
97
    charge_gas(evm, GasCosts.OPCODE_ORIGIN)
98
99
    # OPERATION
100
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
101
102
    # PROGRAM COUNTER
103
    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:
107
    <snip>
116
    # STACK
117
    pass
118
119
    # GAS
120
    charge_gas(evm, GasCosts.OPCODE_CALLER)
121
122
    # OPERATION
123
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
124
125
    # PROGRAM COUNTER
126
    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:
130
    <snip>
139
    # STACK
140
    pass
141
142
    # GAS
143
    charge_gas(evm, GasCosts.OPCODE_CALLVALUE)
144
145
    # OPERATION
146
    push(evm.stack, evm.message.value)
147
148
    # PROGRAM COUNTER
149
    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:
153
    <snip>
163
    # STACK
164
    start_index = pop(evm.stack)
165
166
    # GAS
167
    charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD)
168
169
    # OPERATION
170
    value = buffer_read(evm.message.data, start_index, U256(32))
171
172
    push(evm.stack, U256.from_be_bytes(value))
173
174
    # PROGRAM COUNTER
175
    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:
179
    <snip>
188
    # STACK
189
    pass
190
191
    # GAS
192
    charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE)
193
194
    # OPERATION
195
    push(evm.stack, U256(len(evm.message.data)))
196
197
    # PROGRAM COUNTER
198
    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:
202
    <snip>
214
    # STACK
215
    memory_start_index = pop(evm.stack)
216
    data_start_index = pop(evm.stack)
217
    size = pop(evm.stack)
218
219
    # GAS
220
    words = ceil32(Uint(size)) // Uint(32)
221
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
222
    extend_memory = calculate_gas_extend_memory(
223
        evm.memory, [(memory_start_index, size)]
224
    )
225
    charge_gas(
226
        evm,
227
        GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost,
228
    )
229
230
    # OPERATION
231
    evm.memory += b"\x00" * extend_memory.expand_by
232
    value = buffer_read(evm.message.data, data_start_index, size)
233
    memory_write(evm.memory, memory_start_index, value)
234
235
    # PROGRAM COUNTER
236
    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:
240
    <snip>
249
    # STACK
250
    pass
251
252
    # GAS
253
    charge_gas(evm, GasCosts.OPCODE_CODESIZE)
254
255
    # OPERATION
256
    push(evm.stack, U256(len(evm.code)))
257
258
    # PROGRAM COUNTER
259
    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:
263
    <snip>
275
    # STACK
276
    memory_start_index = pop(evm.stack)
277
    code_start_index = pop(evm.stack)
278
    size = pop(evm.stack)
279
280
    # GAS
281
    words = ceil32(Uint(size)) // Uint(32)
282
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
283
    extend_memory = calculate_gas_extend_memory(
284
        evm.memory, [(memory_start_index, size)]
285
    )
286
    charge_gas(
287
        evm,
288
        GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost,
289
    )
290
291
    # OPERATION
292
    evm.memory += b"\x00" * extend_memory.expand_by
293
    value = buffer_read(evm.code, code_start_index, size)
294
    memory_write(evm.memory, memory_start_index, value)
295
296
    # PROGRAM COUNTER
297
    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:
301
    <snip>
310
    # STACK
311
    pass
312
313
    # GAS
314
    charge_gas(evm, GasCosts.OPCODE_GASPRICE)
315
316
    # OPERATION
317
    push(evm.stack, U256(evm.message.tx_env.gas_price))
318
319
    # PROGRAM COUNTER
320
    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:
324
    <snip>
333
    # STACK
334
    address = to_address_masked(pop(evm.stack))
335
336
    # GAS
337
    if address in evm.accessed_addresses:
338
        access_gas_cost = GasCosts.WARM_ACCESS
339
    else:
340
        evm.accessed_addresses.add(address)
341
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
342
343
    charge_gas(evm, access_gas_cost)
344
345
    # OPERATION
346
    tx_state = evm.message.tx_env.state
347
    account = get_account(tx_state, address)
348
    code = get_code(tx_state, account.code_hash)
347
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
348
349
    codesize = U256(len(code))
350
    push(evm.stack, codesize)
351
352
    # PROGRAM COUNTER
353
    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:
357
    <snip>
366
    # STACK
367
    address = to_address_masked(pop(evm.stack))
368
    memory_start_index = pop(evm.stack)
369
    code_start_index = pop(evm.stack)
370
    size = pop(evm.stack)
371
372
    # GAS
373
    words = ceil32(Uint(size)) // Uint(32)
374
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
375
    extend_memory = calculate_gas_extend_memory(
376
        evm.memory, [(memory_start_index, size)]
377
    )
378
379
    if address in evm.accessed_addresses:
380
        access_gas_cost = GasCosts.WARM_ACCESS
381
    else:
382
        evm.accessed_addresses.add(address)
383
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
384
385
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
386
387
    # OPERATION
388
    evm.memory += b"\x00" * extend_memory.expand_by
389
    tx_state = evm.message.tx_env.state
391
    account = get_account(tx_state, address)
392
    code = get_code(tx_state, account.code_hash)
390
    code = get_code(tx_state, get_account(tx_state, address).code_hash)
391
392
    value = buffer_read(code, code_start_index, size)
393
    memory_write(evm.memory, memory_start_index, value)
394
395
    # PROGRAM COUNTER
396
    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:
400
    <snip>
409
    # STACK
410
    pass
411
412
    # GAS
413
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
414
415
    # OPERATION
416
    push(evm.stack, U256(len(evm.return_data)))
417
418
    # PROGRAM COUNTER
419
    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:
423
    <snip>
432
    # STACK
433
    memory_start_index = pop(evm.stack)
434
    return_data_start_position = pop(evm.stack)
435
    size = pop(evm.stack)
436
437
    # GAS
438
    words = ceil32(Uint(size)) // Uint(32)
439
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
440
    extend_memory = calculate_gas_extend_memory(
441
        evm.memory, [(memory_start_index, size)]
442
    )
443
    charge_gas(
444
        evm,
445
        GasCosts.OPCODE_RETURNDATACOPY_BASE
446
        + copy_gas_cost
447
        + extend_memory.cost,
448
    )
449
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
450
        raise OutOfBoundsRead
451
452
    evm.memory += b"\x00" * extend_memory.expand_by
453
    value = evm.return_data[
454
        return_data_start_position : return_data_start_position + size
455
    ]
456
    memory_write(evm.memory, memory_start_index, value)
457
458
    # PROGRAM COUNTER
459
    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:
463
    <snip>
472
    # STACK
473
    address = to_address_masked(pop(evm.stack))
474
475
    # GAS
476
    if address in evm.accessed_addresses:
477
        access_gas_cost = GasCosts.WARM_ACCESS
478
    else:
479
        evm.accessed_addresses.add(address)
480
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
481
482
    charge_gas(evm, access_gas_cost)
483
484
    # OPERATION
485
    account = get_account(evm.message.tx_env.state, address)
486
487
    if account == EMPTY_ACCOUNT:
488
        codehash = U256(0)
489
    else:
490
        codehash = U256.from_be_bytes(account.code_hash)
491
492
    push(evm.stack, codehash)
493
494
    # PROGRAM COUNTER
495
    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:
499
    <snip>
508
    # STACK
509
    pass
510
511
    # GAS
512
    charge_gas(evm, GasCosts.OPCODE_SELFBALANCE)
513
514
    # OPERATION
515
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
516
    balance = get_account(
517
        evm.message.tx_env.state, evm.message.current_target
518
    ).balance
519
520
    push(evm.stack, balance)
521
522
    # PROGRAM COUNTER
523
    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:
527
    <snip>
536
    # STACK
537
    pass
538
539
    # GAS
540
    charge_gas(evm, GasCosts.OPCODE_BASEFEE)
541
542
    # OPERATION
543
    push(evm.stack, U256(evm.message.block_env.base_fee_per_gas))
544
545
    # PROGRAM COUNTER
546
    evm.pc += Uint(1)