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
    balance = get_account(evm.message.block_env.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
    """
83
    Pushes the address of the original transaction sender to the stack.
84
    The origin address can only be an EOA.
85
86
    Parameters
87
    ----------
88
    evm :
89
        The current EVM frame.
90
91
    """
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
    """
107
    Pushes the address of the caller onto the stack.
108
109
    Parameters
110
    ----------
111
    evm :
112
        The current EVM frame.
113
114
    """
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
    """
130
    Push the value (in wei) sent with the call onto the stack.
131
132
    Parameters
133
    ----------
134
    evm :
135
        The current EVM frame.
136
137
    """
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
    """
153
    Push a word (32 bytes) of the input data belonging to the current
154
    environment onto the stack.
155
156
    Parameters
157
    ----------
158
    evm :
159
        The current EVM frame.
160
161
    """
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
    """
179
    Push the size of input data in current environment onto the stack.
180
181
    Parameters
182
    ----------
183
    evm :
184
        The current EVM frame.
185
186
    """
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
    """
202
    Copy a portion of the input data in current environment to memory.
203
204
    This will also expand the memory, in case that the memory is insufficient
205
    to store the data.
206
207
    Parameters
208
    ----------
209
    evm :
210
        The current EVM frame.
211
212
    """
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
    """
240
    Push the size of code running in current environment onto the stack.
241
242
    Parameters
243
    ----------
244
    evm :
245
        The current EVM frame.
246
247
    """
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
    """
263
    Copy a portion of the code in current environment to memory.
264
265
    This will also expand the memory, in case that the memory is insufficient
266
    to store the data.
267
268
    Parameters
269
    ----------
270
    evm :
271
        The current EVM frame.
272
273
    """
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
    """
301
    Push the gas price used in current environment onto the stack.
302
303
    Parameters
304
    ----------
305
    evm :
306
        The current EVM frame.
307
308
    """
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
    """
324
    Push the code size of a given account onto the stack.
325
326
    Parameters
327
    ----------
328
    evm :
329
        The current EVM frame.
330
331
    """
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
    account = get_account(evm.message.block_env.state, address)
340
    code = get_code(evm.message.block_env.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
    """
351
    Copy a portion of an account's code to memory.
352
353
    Parameters
354
    ----------
355
    evm :
356
        The current EVM frame.
357
358
    """
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
    account = get_account(evm.message.block_env.state, address)
379
    code = get_code(evm.message.block_env.state, account.code_hash)
380
381
    value = buffer_read(code, code_start_index, size)
382
    memory_write(evm.memory, memory_start_index, value)
383
384
    # PROGRAM COUNTER
385
    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:
389
    """
390
    Pushes the size of the return data buffer onto the stack.
391
392
    Parameters
393
    ----------
394
    evm :
395
        The current EVM frame.
396
397
    """
398
    # STACK
399
    pass
400
401
    # GAS
402
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
403
404
    # OPERATION
405
    push(evm.stack, U256(len(evm.return_data)))
406
407
    # PROGRAM COUNTER
408
    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:
412
    """
413
    Copies data from the return data buffer to memory.
414
415
    Parameters
416
    ----------
417
    evm :
418
        The current EVM frame.
419
420
    """
421
    # STACK
422
    memory_start_index = pop(evm.stack)
423
    return_data_start_position = pop(evm.stack)
424
    size = pop(evm.stack)
425
426
    # GAS
427
    words = ceil32(Uint(size)) // Uint(32)
428
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
429
    extend_memory = calculate_gas_extend_memory(
430
        evm.memory, [(memory_start_index, size)]
431
    )
432
    charge_gas(
433
        evm,
434
        GasCosts.OPCODE_RETURNDATACOPY_BASE
435
        + copy_gas_cost
436
        + extend_memory.cost,
437
    )
438
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
439
        raise OutOfBoundsRead
440
441
    evm.memory += b"\x00" * extend_memory.expand_by
442
    value = evm.return_data[
443
        return_data_start_position : return_data_start_position + size
444
    ]
445
    memory_write(evm.memory, memory_start_index, value)
446
447
    # PROGRAM COUNTER
448
    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:
452
    """
453
    Returns the keccak256 hash of a contract’s bytecode.
454
455
    Parameters
456
    ----------
457
    evm :
458
        The current EVM frame.
459
460
    """
461
    # STACK
462
    address = to_address_masked(pop(evm.stack))
463
464
    # GAS
465
    charge_gas(evm, GasCosts.OPCODE_EXTCODEHASH)
466
467
    # OPERATION
468
    account = get_account(evm.message.block_env.state, address)
469
470
    if account == EMPTY_ACCOUNT:
471
        codehash = U256(0)
472
    else:
473
        codehash = U256.from_be_bytes(account.code_hash)
474
475
    push(evm.stack, codehash)
476
477
    # PROGRAM COUNTER
478
    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:
482
    """
483
    Pushes the balance of the current address to the stack.
484
485
    Parameters
486
    ----------
487
    evm :
488
        The current EVM frame.
489
490
    """
491
    # STACK
492
    pass
493
494
    # GAS
495
    charge_gas(evm, GasCosts.FAST_STEP)
496
497
    # OPERATION
498
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
499
    balance = get_account(
500
        evm.message.block_env.state, evm.message.current_target
501
    ).balance
502
503
    push(evm.stack, balance)
504
505
    # PROGRAM COUNTER
506
    evm.pc += Uint(1)