ethereum.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:
28
    <snip>
37
    # STACK
38
    pass
39
40
    # GAS
41
    charge_gas(evm, GasCosts.OPCODE_ADDRESS)
42
43
    # OPERATION
44
    push(evm.stack, U256.from_be_bytes(evm.message.current_target))
45
46
    # PROGRAM COUNTER
47
    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:
51
    <snip>
60
    # STACK
61
    address = to_address_masked(pop(evm.stack))
62
63
    # GAS
64
    charge_gas(evm, GasCosts.OPCODE_BALANCE)
65
66
    # OPERATION
67
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
68
    tx_state = evm.message.tx_env.state
69
    balance = get_account(tx_state, address).balance
70
71
    push(evm.stack, balance)
72
73
    # PROGRAM COUNTER
74
    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:
78
    <snip>
88
    # STACK
89
    pass
90
91
    # GAS
92
    charge_gas(evm, GasCosts.OPCODE_ORIGIN)
93
94
    # OPERATION
95
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
96
97
    # PROGRAM COUNTER
98
    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:
102
    <snip>
111
    # STACK
112
    pass
113
114
    # GAS
115
    charge_gas(evm, GasCosts.OPCODE_CALLER)
116
117
    # OPERATION
118
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
119
120
    # PROGRAM COUNTER
121
    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:
125
    <snip>
134
    # STACK
135
    pass
136
137
    # GAS
138
    charge_gas(evm, GasCosts.OPCODE_CALLVALUE)
139
140
    # OPERATION
141
    push(evm.stack, evm.message.value)
142
143
    # PROGRAM COUNTER
144
    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:
148
    <snip>
158
    # STACK
159
    start_index = pop(evm.stack)
160
161
    # GAS
162
    charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD)
163
164
    # OPERATION
165
    value = buffer_read(evm.message.data, start_index, U256(32))
166
167
    push(evm.stack, U256.from_be_bytes(value))
168
169
    # PROGRAM COUNTER
170
    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:
174
    <snip>
183
    # STACK
184
    pass
185
186
    # GAS
187
    charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE)
188
189
    # OPERATION
190
    push(evm.stack, U256(len(evm.message.data)))
191
192
    # PROGRAM COUNTER
193
    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:
197
    <snip>
209
    # STACK
210
    memory_start_index = pop(evm.stack)
211
    data_start_index = pop(evm.stack)
212
    size = pop(evm.stack)
213
214
    # GAS
215
    words = ceil32(Uint(size)) // Uint(32)
216
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
217
    extend_memory = calculate_gas_extend_memory(
218
        evm.memory, [(memory_start_index, size)]
219
    )
220
    charge_gas(
221
        evm,
222
        GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost,
223
    )
224
225
    # OPERATION
226
    evm.memory += b"\x00" * extend_memory.expand_by
227
    value = buffer_read(evm.message.data, data_start_index, size)
228
    memory_write(evm.memory, memory_start_index, value)
229
230
    # PROGRAM COUNTER
231
    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:
235
    <snip>
244
    # STACK
245
    pass
246
247
    # GAS
248
    charge_gas(evm, GasCosts.OPCODE_CODESIZE)
249
250
    # OPERATION
251
    push(evm.stack, U256(len(evm.code)))
252
253
    # PROGRAM COUNTER
254
    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:
258
    <snip>
270
    # STACK
271
    memory_start_index = pop(evm.stack)
272
    code_start_index = pop(evm.stack)
273
    size = pop(evm.stack)
274
275
    # GAS
276
    words = ceil32(Uint(size)) // Uint(32)
277
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
278
    extend_memory = calculate_gas_extend_memory(
279
        evm.memory, [(memory_start_index, size)]
280
    )
281
    charge_gas(
282
        evm,
283
        GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost,
284
    )
285
286
    # OPERATION
287
    evm.memory += b"\x00" * extend_memory.expand_by
288
    value = buffer_read(evm.code, code_start_index, size)
289
    memory_write(evm.memory, memory_start_index, value)
290
291
    # PROGRAM COUNTER
292
    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:
296
    <snip>
305
    # STACK
306
    pass
307
308
    # GAS
309
    charge_gas(evm, GasCosts.OPCODE_GASPRICE)
310
311
    # OPERATION
312
    push(evm.stack, U256(evm.message.tx_env.gas_price))
313
314
    # PROGRAM COUNTER
315
    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:
319
    <snip>
328
    # STACK
329
    address = to_address_masked(pop(evm.stack))
330
331
    # GAS
332
    charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE)
333
334
    # OPERATION
335
    tx_state = evm.message.tx_env.state
336
    account = get_account(tx_state, address)
337
    code = get_code(tx_state, account.code_hash)
338
339
    codesize = U256(len(code))
340
    push(evm.stack, codesize)
341
342
    # PROGRAM COUNTER
343
    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:
347
    <snip>
356
    # STACK
357
    address = to_address_masked(pop(evm.stack))
358
    memory_start_index = pop(evm.stack)
359
    code_start_index = pop(evm.stack)
360
    size = pop(evm.stack)
361
362
    # GAS
363
    words = ceil32(Uint(size)) // Uint(32)
364
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
365
    extend_memory = calculate_gas_extend_memory(
366
        evm.memory, [(memory_start_index, size)]
367
    )
368
    charge_gas(
369
        evm,
370
        GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost,
371
    )
372
373
    # OPERATION
374
    evm.memory += b"\x00" * extend_memory.expand_by
375
    tx_state = evm.message.tx_env.state
376
    account = get_account(tx_state, address)
377
    code = get_code(tx_state, account.code_hash)
378
379
    value = buffer_read(code, code_start_index, size)
380
    memory_write(evm.memory, memory_start_index, value)
381
382
    # PROGRAM COUNTER
383
    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:
387
    <snip>
396
    # STACK
397
    pass
398
399
    # GAS
400
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
401
402
    # OPERATION
403
    push(evm.stack, U256(len(evm.return_data)))
404
405
    # PROGRAM COUNTER
406
    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:
410
    <snip>
419
    # STACK
420
    memory_start_index = pop(evm.stack)
421
    return_data_start_position = pop(evm.stack)
422
    size = pop(evm.stack)
423
424
    # GAS
425
    words = ceil32(Uint(size)) // Uint(32)
426
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
427
    extend_memory = calculate_gas_extend_memory(
428
        evm.memory, [(memory_start_index, size)]
429
    )
430
    charge_gas(
431
        evm,
432
        GasCosts.OPCODE_RETURNDATACOPY_BASE
433
        + copy_gas_cost
434
        + extend_memory.cost,
435
    )
436
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
437
        raise OutOfBoundsRead
438
439
    evm.memory += b"\x00" * extend_memory.expand_by
440
    value = evm.return_data[
441
        return_data_start_position : return_data_start_position + size
442
    ]
443
    memory_write(evm.memory, memory_start_index, value)
444
445
    # PROGRAM COUNTER
446
    evm.pc += Uint(1)