ethereum.forks.istanbul.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
    charge_gas(evm, GasCosts.OPCODE_BALANCE)
66
67
    # OPERATION
68
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
69
    tx_state = evm.message.tx_env.state
70
    balance = get_account(tx_state, address).balance
71
72
    push(evm.stack, balance)
73
74
    # PROGRAM COUNTER
75
    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:
79
    <snip>
89
    # STACK
90
    pass
91
92
    # GAS
93
    charge_gas(evm, GasCosts.OPCODE_ORIGIN)
94
95
    # OPERATION
96
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
97
98
    # PROGRAM COUNTER
99
    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:
103
    <snip>
112
    # STACK
113
    pass
114
115
    # GAS
116
    charge_gas(evm, GasCosts.OPCODE_CALLER)
117
118
    # OPERATION
119
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
120
121
    # PROGRAM COUNTER
122
    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:
126
    <snip>
135
    # STACK
136
    pass
137
138
    # GAS
139
    charge_gas(evm, GasCosts.OPCODE_CALLVALUE)
140
141
    # OPERATION
142
    push(evm.stack, evm.message.value)
143
144
    # PROGRAM COUNTER
145
    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:
149
    <snip>
159
    # STACK
160
    start_index = pop(evm.stack)
161
162
    # GAS
163
    charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD)
164
165
    # OPERATION
166
    value = buffer_read(evm.message.data, start_index, U256(32))
167
168
    push(evm.stack, U256.from_be_bytes(value))
169
170
    # PROGRAM COUNTER
171
    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:
175
    <snip>
184
    # STACK
185
    pass
186
187
    # GAS
188
    charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE)
189
190
    # OPERATION
191
    push(evm.stack, U256(len(evm.message.data)))
192
193
    # PROGRAM COUNTER
194
    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:
198
    <snip>
210
    # STACK
211
    memory_start_index = pop(evm.stack)
212
    data_start_index = pop(evm.stack)
213
    size = pop(evm.stack)
214
215
    # GAS
216
    words = ceil32(Uint(size)) // Uint(32)
217
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
218
    extend_memory = calculate_gas_extend_memory(
219
        evm.memory, [(memory_start_index, size)]
220
    )
221
    charge_gas(
222
        evm,
223
        GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost,
224
    )
225
226
    # OPERATION
227
    evm.memory += b"\x00" * extend_memory.expand_by
228
    value = buffer_read(evm.message.data, data_start_index, size)
229
    memory_write(evm.memory, memory_start_index, value)
230
231
    # PROGRAM COUNTER
232
    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:
236
    <snip>
245
    # STACK
246
    pass
247
248
    # GAS
249
    charge_gas(evm, GasCosts.OPCODE_CODESIZE)
250
251
    # OPERATION
252
    push(evm.stack, U256(len(evm.code)))
253
254
    # PROGRAM COUNTER
255
    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:
259
    <snip>
271
    # STACK
272
    memory_start_index = pop(evm.stack)
273
    code_start_index = pop(evm.stack)
274
    size = pop(evm.stack)
275
276
    # GAS
277
    words = ceil32(Uint(size)) // Uint(32)
278
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
279
    extend_memory = calculate_gas_extend_memory(
280
        evm.memory, [(memory_start_index, size)]
281
    )
282
    charge_gas(
283
        evm,
284
        GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost,
285
    )
286
287
    # OPERATION
288
    evm.memory += b"\x00" * extend_memory.expand_by
289
    value = buffer_read(evm.code, code_start_index, size)
290
    memory_write(evm.memory, memory_start_index, value)
291
292
    # PROGRAM COUNTER
293
    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:
297
    <snip>
306
    # STACK
307
    pass
308
309
    # GAS
310
    charge_gas(evm, GasCosts.OPCODE_GASPRICE)
311
312
    # OPERATION
313
    push(evm.stack, U256(evm.message.tx_env.gas_price))
314
315
    # PROGRAM COUNTER
316
    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:
320
    <snip>
329
    # STACK
330
    address = to_address_masked(pop(evm.stack))
331
332
    # GAS
333
    charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE)
334
335
    # OPERATION
336
    tx_state = evm.message.tx_env.state
337
    account = get_account(tx_state, address)
338
    code = get_code(tx_state, account.code_hash)
339
340
    codesize = U256(len(code))
341
    push(evm.stack, codesize)
342
343
    # PROGRAM COUNTER
344
    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:
348
    <snip>
357
    # STACK
358
    address = to_address_masked(pop(evm.stack))
359
    memory_start_index = pop(evm.stack)
360
    code_start_index = pop(evm.stack)
361
    size = pop(evm.stack)
362
363
    # GAS
364
    words = ceil32(Uint(size)) // Uint(32)
365
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
366
    extend_memory = calculate_gas_extend_memory(
367
        evm.memory, [(memory_start_index, size)]
368
    )
369
    charge_gas(
370
        evm,
371
        GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost,
372
    )
373
374
    # OPERATION
375
    evm.memory += b"\x00" * extend_memory.expand_by
376
    tx_state = evm.message.tx_env.state
377
    account = get_account(tx_state, address)
378
    code = get_code(tx_state, account.code_hash)
379
380
    value = buffer_read(code, code_start_index, size)
381
    memory_write(evm.memory, memory_start_index, value)
382
383
    # PROGRAM COUNTER
384
    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:
388
    <snip>
397
    # STACK
398
    pass
399
400
    # GAS
401
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
402
403
    # OPERATION
404
    push(evm.stack, U256(len(evm.return_data)))
405
406
    # PROGRAM COUNTER
407
    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:
411
    <snip>
420
    # STACK
421
    memory_start_index = pop(evm.stack)
422
    return_data_start_position = pop(evm.stack)
423
    size = pop(evm.stack)
424
425
    # GAS
426
    words = ceil32(Uint(size)) // Uint(32)
427
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
428
    extend_memory = calculate_gas_extend_memory(
429
        evm.memory, [(memory_start_index, size)]
430
    )
431
    charge_gas(
432
        evm,
433
        GasCosts.OPCODE_RETURNDATACOPY_BASE
434
        + copy_gas_cost
435
        + extend_memory.cost,
436
    )
437
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
438
        raise OutOfBoundsRead
439
440
    evm.memory += b"\x00" * extend_memory.expand_by
441
    value = evm.return_data[
442
        return_data_start_position : return_data_start_position + size
443
    ]
444
    memory_write(evm.memory, memory_start_index, value)
445
446
    # PROGRAM COUNTER
447
    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:
451
    <snip>
460
    # STACK
461
    address = to_address_masked(pop(evm.stack))
462
463
    # GAS
464
    charge_gas(evm, GasCosts.OPCODE_EXTCODEHASH)
465
466
    # OPERATION
467
    account = get_account(evm.message.tx_env.state, address)
468
469
    if account == EMPTY_ACCOUNT:
470
        codehash = U256(0)
471
    else:
472
        codehash = U256.from_be_bytes(account.code_hash)
473
474
    push(evm.stack, codehash)
475
476
    # PROGRAM COUNTER
477
    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:
481
    <snip>
490
    # STACK
491
    pass
492
493
    # GAS
494
    charge_gas(evm, GasCosts.OPCODE_SELFBALANCE)
495
496
    # OPERATION
497
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
498
    balance = get_account(
499
        evm.message.tx_env.state, evm.message.current_target
500
    ).balance
501
502
    push(evm.stack, balance)
503
504
    # PROGRAM COUNTER
505
    evm.pc += Uint(1)