ethereum.forks.spurious_dragon.vm.instructions.environmentethereum.forks.byzantium.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:
32
    <snip>
41
    # STACK
42
    pass
43
44
    # GAS
45
    charge_gas(evm, GasCosts.OPCODE_ADDRESS)
46
47
    # OPERATION
48
    push(evm.stack, U256.from_be_bytes(evm.message.current_target))
49
50
    # PROGRAM COUNTER
51
    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:
55
    <snip>
64
    # STACK
65
    address = to_address_masked(pop(evm.stack))
66
67
    # GAS
68
    charge_gas(evm, GasCosts.OPCODE_BALANCE)
69
70
    # OPERATION
71
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
72
    tx_state = evm.message.tx_env.state
73
    balance = get_account(tx_state, address).balance
74
75
    push(evm.stack, balance)
76
77
    # PROGRAM COUNTER
78
    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:
82
    <snip>
92
    # STACK
93
    pass
94
95
    # GAS
96
    charge_gas(evm, GasCosts.OPCODE_ORIGIN)
97
98
    # OPERATION
99
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
100
101
    # PROGRAM COUNTER
102
    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:
106
    <snip>
115
    # STACK
116
    pass
117
118
    # GAS
119
    charge_gas(evm, GasCosts.OPCODE_CALLER)
120
121
    # OPERATION
122
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
123
124
    # PROGRAM COUNTER
125
    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:
129
    <snip>
138
    # STACK
139
    pass
140
141
    # GAS
142
    charge_gas(evm, GasCosts.OPCODE_CALLVALUE)
143
144
    # OPERATION
145
    push(evm.stack, evm.message.value)
146
147
    # PROGRAM COUNTER
148
    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:
152
    <snip>
162
    # STACK
163
    start_index = pop(evm.stack)
164
165
    # GAS
166
    charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD)
167
168
    # OPERATION
169
    value = buffer_read(evm.message.data, start_index, U256(32))
170
171
    push(evm.stack, U256.from_be_bytes(value))
172
173
    # PROGRAM COUNTER
174
    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:
178
    <snip>
187
    # STACK
188
    pass
189
190
    # GAS
191
    charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE)
192
193
    # OPERATION
194
    push(evm.stack, U256(len(evm.message.data)))
195
196
    # PROGRAM COUNTER
197
    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:
201
    <snip>
213
    # STACK
214
    memory_start_index = pop(evm.stack)
215
    data_start_index = pop(evm.stack)
216
    size = pop(evm.stack)
217
218
    # GAS
219
    words = ceil32(Uint(size)) // Uint(32)
220
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
221
    extend_memory = calculate_gas_extend_memory(
222
        evm.memory, [(memory_start_index, size)]
223
    )
224
    charge_gas(
225
        evm,
226
        GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost,
227
    )
228
229
    # OPERATION
230
    evm.memory += b"\x00" * extend_memory.expand_by
231
    value = buffer_read(evm.message.data, data_start_index, size)
232
    memory_write(evm.memory, memory_start_index, value)
233
234
    # PROGRAM COUNTER
235
    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:
239
    <snip>
248
    # STACK
249
    pass
250
251
    # GAS
252
    charge_gas(evm, GasCosts.OPCODE_CODESIZE)
253
254
    # OPERATION
255
    push(evm.stack, U256(len(evm.code)))
256
257
    # PROGRAM COUNTER
258
    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:
262
    <snip>
274
    # STACK
275
    memory_start_index = pop(evm.stack)
276
    code_start_index = pop(evm.stack)
277
    size = pop(evm.stack)
278
279
    # GAS
280
    words = ceil32(Uint(size)) // Uint(32)
281
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
282
    extend_memory = calculate_gas_extend_memory(
283
        evm.memory, [(memory_start_index, size)]
284
    )
285
    charge_gas(
286
        evm,
287
        GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost,
288
    )
289
290
    # OPERATION
291
    evm.memory += b"\x00" * extend_memory.expand_by
292
    value = buffer_read(evm.code, code_start_index, size)
293
    memory_write(evm.memory, memory_start_index, value)
294
295
    # PROGRAM COUNTER
296
    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:
300
    <snip>
309
    # STACK
310
    pass
311
312
    # GAS
313
    charge_gas(evm, GasCosts.OPCODE_GASPRICE)
314
315
    # OPERATION
316
    push(evm.stack, U256(evm.message.tx_env.gas_price))
317
318
    # PROGRAM COUNTER
319
    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:
323
    <snip>
332
    # STACK
333
    address = to_address_masked(pop(evm.stack))
334
335
    # GAS
336
    charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE)
337
338
    # OPERATION
339
    tx_state = evm.message.tx_env.state
340
    account = get_account(tx_state, address)
341
    code = get_code(tx_state, account.code_hash)
342
343
    codesize = U256(len(code))
344
    push(evm.stack, codesize)
345
346
    # PROGRAM COUNTER
347
    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:
351
    <snip>
360
    # STACK
361
    address = to_address_masked(pop(evm.stack))
362
    memory_start_index = pop(evm.stack)
363
    code_start_index = pop(evm.stack)
364
    size = pop(evm.stack)
365
366
    # GAS
367
    words = ceil32(Uint(size)) // Uint(32)
368
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
369
    extend_memory = calculate_gas_extend_memory(
370
        evm.memory, [(memory_start_index, size)]
371
    )
372
    charge_gas(
373
        evm,
374
        GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost,
375
    )
376
377
    # OPERATION
378
    evm.memory += b"\x00" * extend_memory.expand_by
379
    tx_state = evm.message.tx_env.state
380
    account = get_account(tx_state, address)
381
    code = get_code(tx_state, account.code_hash)
382
383
    value = buffer_read(code, code_start_index, size)
384
    memory_write(evm.memory, memory_start_index, value)
385
386
    # PROGRAM COUNTER
387
    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:
391
    <snip>
400
    # STACK
401
    pass
402
403
    # GAS
404
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
405
406
    # OPERATION
407
    push(evm.stack, U256(len(evm.return_data)))
408
409
    # PROGRAM COUNTER
410
    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:
414
    <snip>
423
    # STACK
424
    memory_start_index = pop(evm.stack)
425
    return_data_start_position = pop(evm.stack)
426
    size = pop(evm.stack)
427
428
    # GAS
429
    words = ceil32(Uint(size)) // Uint(32)
430
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
431
    extend_memory = calculate_gas_extend_memory(
432
        evm.memory, [(memory_start_index, size)]
433
    )
434
    charge_gas(
435
        evm,
436
        GasCosts.OPCODE_RETURNDATACOPY_BASE
437
        + copy_gas_cost
438
        + extend_memory.cost,
439
    )
440
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
441
        raise OutOfBoundsRead
442
443
    evm.memory += b"\x00" * extend_memory.expand_by
444
    value = evm.return_data[
445
        return_data_start_position : return_data_start_position + size
446
    ]
447
    memory_write(evm.memory, memory_start_index, value)
448
449
    # PROGRAM COUNTER
450
    evm.pc += Uint(1)