ethereum.forks.muir_glacier.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
    """
34
    Pushes the address of the current executing account to the stack.
35
36
    Parameters
37
    ----------
38
    evm :
39
        The current EVM frame.
40
41
    """
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
    """
57
    Pushes the balance of the given account onto the stack.
58
59
    Parameters
60
    ----------
61
    evm :
62
        The current EVM frame.
63
64
    """
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
    """
84
    Pushes the address of the original transaction sender to the stack.
85
    The origin address can only be an EOA.
86
87
    Parameters
88
    ----------
89
    evm :
90
        The current EVM frame.
91
92
    """
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
    """
108
    Pushes the address of the caller onto the stack.
109
110
    Parameters
111
    ----------
112
    evm :
113
        The current EVM frame.
114
115
    """
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
    """
131
    Push the value (in wei) sent with the call onto the stack.
132
133
    Parameters
134
    ----------
135
    evm :
136
        The current EVM frame.
137
138
    """
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
    """
154
    Push a word (32 bytes) of the input data belonging to the current
155
    environment onto the stack.
156
157
    Parameters
158
    ----------
159
    evm :
160
        The current EVM frame.
161
162
    """
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
    """
180
    Push the size of input data in current environment onto the stack.
181
182
    Parameters
183
    ----------
184
    evm :
185
        The current EVM frame.
186
187
    """
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
    """
203
    Copy a portion of the input data in current environment to memory.
204
205
    This will also expand the memory, in case that the memory is insufficient
206
    to store the data.
207
208
    Parameters
209
    ----------
210
    evm :
211
        The current EVM frame.
212
213
    """
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
    """
241
    Push the size of code running in current environment onto the stack.
242
243
    Parameters
244
    ----------
245
    evm :
246
        The current EVM frame.
247
248
    """
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
    """
264
    Copy a portion of the code in current environment to memory.
265
266
    This will also expand the memory, in case that the memory is insufficient
267
    to store the data.
268
269
    Parameters
270
    ----------
271
    evm :
272
        The current EVM frame.
273
274
    """
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
    """
302
    Push the gas price used in current environment onto the stack.
303
304
    Parameters
305
    ----------
306
    evm :
307
        The current EVM frame.
308
309
    """
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
    """
325
    Push the code size of a given account onto the stack.
326
327
    Parameters
328
    ----------
329
    evm :
330
        The current EVM frame.
331
332
    """
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
    """
353
    Copy a portion of an account's code to memory.
354
355
    Parameters
356
    ----------
357
    evm :
358
        The current EVM frame.
359
360
    """
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
    """
393
    Pushes the size of the return data buffer onto the stack.
394
395
    Parameters
396
    ----------
397
    evm :
398
        The current EVM frame.
399
400
    """
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
    """
416
    Copies data from the return data buffer to memory.
417
418
    Parameters
419
    ----------
420
    evm :
421
        The current EVM frame.
422
423
    """
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
    """
456
    Returns the keccak256 hash of a contract’s bytecode.
457
458
    Parameters
459
    ----------
460
    evm :
461
        The current EVM frame.
462
463
    """
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
    """
486
    Pushes the balance of the current address to the stack.
487
488
    Parameters
489
    ----------
490
    evm :
491
        The current EVM frame.
492
493
    """
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)