ethereum.forks.tangerine_whistle.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:
27
    <snip>
36
    # STACK
37
    pass
38
39
    # GAS
40
    charge_gas(evm, GasCosts.OPCODE_ADDRESS)
41
42
    # OPERATION
43
    push(evm.stack, U256.from_be_bytes(evm.message.current_target))
44
45
    # PROGRAM COUNTER
46
    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:
50
    <snip>
59
    # STACK
60
    address = to_address_masked(pop(evm.stack))
61
62
    # GAS
63
    charge_gas(evm, GasCosts.OPCODE_BALANCE)
64
65
    # OPERATION
66
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
67
    tx_state = evm.message.tx_env.state
68
    balance = get_account(tx_state, address).balance
69
70
    push(evm.stack, balance)
71
72
    # PROGRAM COUNTER
73
    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:
77
    <snip>
87
    # STACK
88
    pass
89
90
    # GAS
91
    charge_gas(evm, GasCosts.OPCODE_ORIGIN)
92
93
    # OPERATION
94
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
95
96
    # PROGRAM COUNTER
97
    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:
101
    <snip>
110
    # STACK
111
    pass
112
113
    # GAS
114
    charge_gas(evm, GasCosts.OPCODE_CALLER)
115
116
    # OPERATION
117
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
118
119
    # PROGRAM COUNTER
120
    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:
124
    <snip>
133
    # STACK
134
    pass
135
136
    # GAS
137
    charge_gas(evm, GasCosts.OPCODE_CALLVALUE)
138
139
    # OPERATION
140
    push(evm.stack, evm.message.value)
141
142
    # PROGRAM COUNTER
143
    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:
147
    <snip>
157
    # STACK
158
    start_index = pop(evm.stack)
159
160
    # GAS
161
    charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD)
162
163
    # OPERATION
164
    value = buffer_read(evm.message.data, start_index, U256(32))
165
166
    push(evm.stack, U256.from_be_bytes(value))
167
168
    # PROGRAM COUNTER
169
    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:
173
    <snip>
182
    # STACK
183
    pass
184
185
    # GAS
186
    charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE)
187
188
    # OPERATION
189
    push(evm.stack, U256(len(evm.message.data)))
190
191
    # PROGRAM COUNTER
192
    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:
196
    <snip>
208
    # STACK
209
    memory_start_index = pop(evm.stack)
210
    data_start_index = pop(evm.stack)
211
    size = pop(evm.stack)
212
213
    # GAS
214
    words = ceil32(Uint(size)) // Uint(32)
215
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
216
    extend_memory = calculate_gas_extend_memory(
217
        evm.memory, [(memory_start_index, size)]
218
    )
219
    charge_gas(
220
        evm,
221
        GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost,
222
    )
223
224
    # OPERATION
225
    evm.memory += b"\x00" * extend_memory.expand_by
226
    value = buffer_read(evm.message.data, data_start_index, size)
227
    memory_write(evm.memory, memory_start_index, value)
228
229
    # PROGRAM COUNTER
230
    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:
234
    <snip>
243
    # STACK
244
    pass
245
246
    # GAS
247
    charge_gas(evm, GasCosts.OPCODE_CODESIZE)
248
249
    # OPERATION
250
    push(evm.stack, U256(len(evm.code)))
251
252
    # PROGRAM COUNTER
253
    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:
257
    <snip>
269
    # STACK
270
    memory_start_index = pop(evm.stack)
271
    code_start_index = pop(evm.stack)
272
    size = pop(evm.stack)
273
274
    # GAS
275
    words = ceil32(Uint(size)) // Uint(32)
276
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
277
    extend_memory = calculate_gas_extend_memory(
278
        evm.memory, [(memory_start_index, size)]
279
    )
280
    charge_gas(
281
        evm,
282
        GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost,
283
    )
284
285
    # OPERATION
286
    evm.memory += b"\x00" * extend_memory.expand_by
287
    value = buffer_read(evm.code, code_start_index, size)
288
    memory_write(evm.memory, memory_start_index, value)
289
290
    # PROGRAM COUNTER
291
    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:
295
    <snip>
304
    # STACK
305
    pass
306
307
    # GAS
308
    charge_gas(evm, GasCosts.OPCODE_GASPRICE)
309
310
    # OPERATION
311
    push(evm.stack, U256(evm.message.tx_env.gas_price))
312
313
    # PROGRAM COUNTER
314
    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:
318
    <snip>
327
    # STACK
328
    address = to_address_masked(pop(evm.stack))
329
330
    # GAS
331
    charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE)
332
333
    # OPERATION
334
    tx_state = evm.message.tx_env.state
335
    account = get_account(tx_state, address)
336
    code = get_code(tx_state, account.code_hash)
337
338
    codesize = U256(len(code))
339
    push(evm.stack, codesize)
340
341
    # PROGRAM COUNTER
342
    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:
346
    <snip>
355
    # STACK
356
    address = to_address_masked(pop(evm.stack))
357
    memory_start_index = pop(evm.stack)
358
    code_start_index = pop(evm.stack)
359
    size = pop(evm.stack)
360
361
    # GAS
362
    words = ceil32(Uint(size)) // Uint(32)
363
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
364
    extend_memory = calculate_gas_extend_memory(
365
        evm.memory, [(memory_start_index, size)]
366
    )
367
    charge_gas(
368
        evm,
369
        GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost,
370
    )
371
372
    # OPERATION
373
    evm.memory += b"\x00" * extend_memory.expand_by
374
    tx_state = evm.message.tx_env.state
375
    account = get_account(tx_state, address)
376
    code = get_code(tx_state, account.code_hash)
377
378
    value = buffer_read(code, code_start_index, size)
379
    memory_write(evm.memory, memory_start_index, value)
380
381
    # PROGRAM COUNTER
382
    evm.pc += Uint(1)