ethereum.forks.muir_glacier.vm.instructions.environmentethereum.forks.berlin.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
    charge_gas(evm, GasCosts.OPCODE_BALANCE)
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
336
    # GAS
337
    charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE)
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)
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
    )
373
    charge_gas(
374
        evm,
375
        GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost,
376
    )
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
390
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
391
392
    # OPERATION
393
    evm.memory += b"\x00" * extend_memory.expand_by
394
    tx_state = evm.message.tx_env.state
395
    account = get_account(tx_state, address)
396
    code = get_code(tx_state, account.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
467
    # GAS
468
    charge_gas(evm, GasCosts.OPCODE_EXTCODEHASH)
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)