ethereum.forks.constantinople.vm.instructions.environmentethereum.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:
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)
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
    charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE)
338
339
    # OPERATION
340
    tx_state = evm.message.tx_env.state
341
    account = get_account(tx_state, address)
342
    code = get_code(tx_state, account.code_hash)
343
344
    codesize = U256(len(code))
345
    push(evm.stack, codesize)
346
347
    # PROGRAM COUNTER
348
    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:
352
    <snip>
361
    # STACK
362
    address = to_address_masked(pop(evm.stack))
363
    memory_start_index = pop(evm.stack)
364
    code_start_index = pop(evm.stack)
365
    size = pop(evm.stack)
366
367
    # GAS
368
    words = ceil32(Uint(size)) // Uint(32)
369
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
370
    extend_memory = calculate_gas_extend_memory(
371
        evm.memory, [(memory_start_index, size)]
372
    )
373
    charge_gas(
374
        evm,
375
        GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost,
376
    )
377
378
    # OPERATION
379
    evm.memory += b"\x00" * extend_memory.expand_by
380
    tx_state = evm.message.tx_env.state
381
    account = get_account(tx_state, address)
382
    code = get_code(tx_state, account.code_hash)
383
384
    value = buffer_read(code, code_start_index, size)
385
    memory_write(evm.memory, memory_start_index, value)
386
387
    # PROGRAM COUNTER
388
    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:
392
    <snip>
401
    # STACK
402
    pass
403
404
    # GAS
405
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
406
407
    # OPERATION
408
    push(evm.stack, U256(len(evm.return_data)))
409
410
    # PROGRAM COUNTER
411
    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:
415
    <snip>
424
    # STACK
425
    memory_start_index = pop(evm.stack)
426
    return_data_start_position = pop(evm.stack)
427
    size = pop(evm.stack)
428
429
    # GAS
430
    words = ceil32(Uint(size)) // Uint(32)
431
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
432
    extend_memory = calculate_gas_extend_memory(
433
        evm.memory, [(memory_start_index, size)]
434
    )
435
    charge_gas(
436
        evm,
437
        GasCosts.OPCODE_RETURNDATACOPY_BASE
438
        + copy_gas_cost
439
        + extend_memory.cost,
440
    )
441
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
442
        raise OutOfBoundsRead
443
444
    evm.memory += b"\x00" * extend_memory.expand_by
445
    value = evm.return_data[
446
        return_data_start_position : return_data_start_position + size
447
    ]
448
    memory_write(evm.memory, memory_start_index, value)
449
450
    # PROGRAM COUNTER
451
    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:
455
    <snip>
464
    # STACK
465
    address = to_address_masked(pop(evm.stack))
466
467
    # GAS
468
    charge_gas(evm, GasCosts.OPCODE_EXTCODEHASH)
469
470
    # OPERATION
471
    account = get_account(evm.message.tx_env.state, address)
472
473
    if account == EMPTY_ACCOUNT:
474
        codehash = U256(0)
475
    else:
476
        codehash = U256.from_be_bytes(account.code_hash)
477
478
    push(evm.stack, codehash)
479
480
    # PROGRAM COUNTER
481
    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:
485
    <snip>
494
    # STACK
495
    pass
496
497
    # GAS
498
    charge_gas(evm, GasCosts.FAST_STEP)
499
500
    # OPERATION
501
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
502
    balance = get_account(
503
        evm.message.tx_env.state, evm.message.current_target
504
    ).balance
505
506
    push(evm.stack, balance)
507
508
    # PROGRAM COUNTER
509
    evm.pc += Uint(1)