ethereum.forks.dao_fork.vm.instructions.environmentethereum.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:
31
    <snip>
40
    # STACK
41
    pass
42
43
    # GAS
44
    charge_gas(evm, GasCosts.OPCODE_ADDRESS)
45
46
    # OPERATION
47
    push(evm.stack, U256.from_be_bytes(evm.message.current_target))
48
49
    # PROGRAM COUNTER
50
    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:
54
    <snip>
63
    # STACK
64
    address = to_address_masked(pop(evm.stack))
65
66
    # GAS
67
    charge_gas(evm, GasCosts.OPCODE_BALANCE)
68
69
    # OPERATION
70
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
71
    tx_state = evm.message.tx_env.state
72
    balance = get_account(tx_state, address).balance
73
74
    push(evm.stack, balance)
75
76
    # PROGRAM COUNTER
77
    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:
81
    <snip>
91
    # STACK
92
    pass
93
94
    # GAS
95
    charge_gas(evm, GasCosts.OPCODE_ORIGIN)
96
97
    # OPERATION
98
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
99
100
    # PROGRAM COUNTER
101
    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:
105
    <snip>
114
    # STACK
115
    pass
116
117
    # GAS
118
    charge_gas(evm, GasCosts.OPCODE_CALLER)
119
120
    # OPERATION
121
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
122
123
    # PROGRAM COUNTER
124
    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:
128
    <snip>
137
    # STACK
138
    pass
139
140
    # GAS
141
    charge_gas(evm, GasCosts.OPCODE_CALLVALUE)
142
143
    # OPERATION
144
    push(evm.stack, evm.message.value)
145
146
    # PROGRAM COUNTER
147
    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:
151
    <snip>
161
    # STACK
162
    start_index = pop(evm.stack)
163
164
    # GAS
165
    charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD)
166
167
    # OPERATION
168
    value = buffer_read(evm.message.data, start_index, U256(32))
169
170
    push(evm.stack, U256.from_be_bytes(value))
171
172
    # PROGRAM COUNTER
173
    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:
177
    <snip>
186
    # STACK
187
    pass
188
189
    # GAS
190
    charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE)
191
192
    # OPERATION
193
    push(evm.stack, U256(len(evm.message.data)))
194
195
    # PROGRAM COUNTER
196
    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:
200
    <snip>
212
    # STACK
213
    memory_start_index = pop(evm.stack)
214
    data_start_index = pop(evm.stack)
215
    size = pop(evm.stack)
216
217
    # GAS
218
    words = ceil32(Uint(size)) // Uint(32)
219
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
220
    extend_memory = calculate_gas_extend_memory(
221
        evm.memory, [(memory_start_index, size)]
222
    )
223
    charge_gas(
224
        evm,
225
        GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost,
226
    )
227
228
    # OPERATION
229
    evm.memory += b"\x00" * extend_memory.expand_by
230
    value = buffer_read(evm.message.data, data_start_index, size)
231
    memory_write(evm.memory, memory_start_index, value)
232
233
    # PROGRAM COUNTER
234
    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:
238
    <snip>
247
    # STACK
248
    pass
249
250
    # GAS
251
    charge_gas(evm, GasCosts.OPCODE_CODESIZE)
252
253
    # OPERATION
254
    push(evm.stack, U256(len(evm.code)))
255
256
    # PROGRAM COUNTER
257
    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:
261
    <snip>
273
    # STACK
274
    memory_start_index = pop(evm.stack)
275
    code_start_index = pop(evm.stack)
276
    size = pop(evm.stack)
277
278
    # GAS
279
    words = ceil32(Uint(size)) // Uint(32)
280
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
281
    extend_memory = calculate_gas_extend_memory(
282
        evm.memory, [(memory_start_index, size)]
283
    )
284
    charge_gas(
285
        evm,
286
        GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost,
287
    )
288
289
    # OPERATION
290
    evm.memory += b"\x00" * extend_memory.expand_by
291
    value = buffer_read(evm.code, code_start_index, size)
292
    memory_write(evm.memory, memory_start_index, value)
293
294
    # PROGRAM COUNTER
295
    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:
299
    <snip>
308
    # STACK
309
    pass
310
311
    # GAS
312
    charge_gas(evm, GasCosts.OPCODE_GASPRICE)
313
314
    # OPERATION
315
    push(evm.stack, U256(evm.message.tx_env.gas_price))
316
317
    # PROGRAM COUNTER
318
    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:
322
    <snip>
331
    # STACK
332
    address = to_address_masked(pop(evm.stack))
333
334
    # GAS
335
    charge_gas(evm, GasCosts.OPCODE_EXTERNAL_BASE)
336
337
    # OPERATION
338
    tx_state = evm.message.tx_env.state
339
    account = get_account(tx_state, address)
340
    code = get_code(tx_state, account.code_hash)
341
342
    codesize = U256(len(code))
343
    push(evm.stack, codesize)
344
345
    # PROGRAM COUNTER
346
    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:
350
    <snip>
359
    # STACK
360
    address = to_address_masked(pop(evm.stack))
361
    memory_start_index = pop(evm.stack)
362
    code_start_index = pop(evm.stack)
363
    size = pop(evm.stack)
364
365
    # GAS
366
    words = ceil32(Uint(size)) // Uint(32)
367
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
368
    extend_memory = calculate_gas_extend_memory(
369
        evm.memory, [(memory_start_index, size)]
370
    )
371
    charge_gas(
372
        evm,
373
        GasCosts.OPCODE_EXTERNAL_BASE + copy_gas_cost + extend_memory.cost,
374
    )
375
376
    # OPERATION
377
    evm.memory += b"\x00" * extend_memory.expand_by
378
    tx_state = evm.message.tx_env.state
379
    account = get_account(tx_state, address)
380
    code = get_code(tx_state, account.code_hash)
381
382
    value = buffer_read(code, code_start_index, size)
383
    memory_write(evm.memory, memory_start_index, value)
384
385
    # PROGRAM COUNTER
386
    evm.pc += Uint(1)