ethereum.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:
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)
349
350
    codesize = U256(len(code))
351
    push(evm.stack, codesize)
352
353
    # PROGRAM COUNTER
354
    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:
358
    <snip>
367
    # STACK
368
    address = to_address_masked(pop(evm.stack))
369
    memory_start_index = pop(evm.stack)
370
    code_start_index = pop(evm.stack)
371
    size = pop(evm.stack)
372
373
    # GAS
374
    words = ceil32(Uint(size)) // Uint(32)
375
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
376
    extend_memory = calculate_gas_extend_memory(
377
        evm.memory, [(memory_start_index, size)]
378
    )
379
380
    if address in evm.accessed_addresses:
381
        access_gas_cost = GasCosts.WARM_ACCESS
382
    else:
383
        evm.accessed_addresses.add(address)
384
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
385
386
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
387
388
    # OPERATION
389
    evm.memory += b"\x00" * extend_memory.expand_by
390
    tx_state = evm.message.tx_env.state
391
    account = get_account(tx_state, address)
392
    code = get_code(tx_state, account.code_hash)
393
394
    value = buffer_read(code, code_start_index, size)
395
    memory_write(evm.memory, memory_start_index, value)
396
397
    # PROGRAM COUNTER
398
    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:
402
    <snip>
411
    # STACK
412
    pass
413
414
    # GAS
415
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
416
417
    # OPERATION
418
    push(evm.stack, U256(len(evm.return_data)))
419
420
    # PROGRAM COUNTER
421
    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:
425
    <snip>
434
    # STACK
435
    memory_start_index = pop(evm.stack)
436
    return_data_start_position = pop(evm.stack)
437
    size = pop(evm.stack)
438
439
    # GAS
440
    words = ceil32(Uint(size)) // Uint(32)
441
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
442
    extend_memory = calculate_gas_extend_memory(
443
        evm.memory, [(memory_start_index, size)]
444
    )
445
    charge_gas(
446
        evm,
447
        GasCosts.OPCODE_RETURNDATACOPY_BASE
448
        + copy_gas_cost
449
        + extend_memory.cost,
450
    )
451
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
452
        raise OutOfBoundsRead
453
454
    evm.memory += b"\x00" * extend_memory.expand_by
455
    value = evm.return_data[
456
        return_data_start_position : return_data_start_position + size
457
    ]
458
    memory_write(evm.memory, memory_start_index, value)
459
460
    # PROGRAM COUNTER
461
    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:
465
    <snip>
474
    # STACK
475
    address = to_address_masked(pop(evm.stack))
476
477
    # GAS
478
    if address in evm.accessed_addresses:
479
        access_gas_cost = GasCosts.WARM_ACCESS
480
    else:
481
        evm.accessed_addresses.add(address)
482
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
483
484
    charge_gas(evm, access_gas_cost)
485
486
    # OPERATION
487
    account = get_account(evm.message.tx_env.state, address)
488
489
    if account == EMPTY_ACCOUNT:
490
        codehash = U256(0)
491
    else:
492
        codehash = U256.from_be_bytes(account.code_hash)
493
494
    push(evm.stack, codehash)
495
496
    # PROGRAM COUNTER
497
    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:
501
    <snip>
510
    # STACK
511
    pass
512
513
    # GAS
514
    charge_gas(evm, GasCosts.OPCODE_SELFBALANCE)
515
516
    # OPERATION
517
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
518
    balance = get_account(
519
        evm.message.tx_env.state, evm.message.current_target
520
    ).balance
521
522
    push(evm.stack, balance)
523
524
    # PROGRAM COUNTER
525
    evm.pc += Uint(1)