ethereum.forks.paris.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
    if address in evm.accessed_addresses:
70
        charge_gas(evm, GasCosts.WARM_ACCESS)
71
    else:
72
        evm.accessed_addresses.add(address)
73
        charge_gas(evm, GasCosts.COLD_ACCOUNT_ACCESS)
74
75
    # OPERATION
76
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
77
    balance = get_account(evm.message.block_env.state, address).balance
78
79
    push(evm.stack, balance)
80
81
    # PROGRAM COUNTER
82
    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:
86
    """
87
    Pushes the address of the original transaction sender to the stack.
88
    The origin address can only be an EOA.
89
90
    Parameters
91
    ----------
92
    evm :
93
        The current EVM frame.
94
95
    """
96
    # STACK
97
    pass
98
99
    # GAS
100
    charge_gas(evm, GasCosts.OPCODE_ORIGIN)
101
102
    # OPERATION
103
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
104
105
    # PROGRAM COUNTER
106
    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:
110
    """
111
    Pushes the address of the caller onto the stack.
112
113
    Parameters
114
    ----------
115
    evm :
116
        The current EVM frame.
117
118
    """
119
    # STACK
120
    pass
121
122
    # GAS
123
    charge_gas(evm, GasCosts.OPCODE_CALLER)
124
125
    # OPERATION
126
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
127
128
    # PROGRAM COUNTER
129
    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:
133
    """
134
    Push the value (in wei) sent with the call onto the stack.
135
136
    Parameters
137
    ----------
138
    evm :
139
        The current EVM frame.
140
141
    """
142
    # STACK
143
    pass
144
145
    # GAS
146
    charge_gas(evm, GasCosts.OPCODE_CALLVALUE)
147
148
    # OPERATION
149
    push(evm.stack, evm.message.value)
150
151
    # PROGRAM COUNTER
152
    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:
156
    """
157
    Push a word (32 bytes) of the input data belonging to the current
158
    environment onto the stack.
159
160
    Parameters
161
    ----------
162
    evm :
163
        The current EVM frame.
164
165
    """
166
    # STACK
167
    start_index = pop(evm.stack)
168
169
    # GAS
170
    charge_gas(evm, GasCosts.OPCODE_CALLDATALOAD)
171
172
    # OPERATION
173
    value = buffer_read(evm.message.data, start_index, U256(32))
174
175
    push(evm.stack, U256.from_be_bytes(value))
176
177
    # PROGRAM COUNTER
178
    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:
182
    """
183
    Push the size of input data in current environment onto the stack.
184
185
    Parameters
186
    ----------
187
    evm :
188
        The current EVM frame.
189
190
    """
191
    # STACK
192
    pass
193
194
    # GAS
195
    charge_gas(evm, GasCosts.OPCODE_CALLDATASIZE)
196
197
    # OPERATION
198
    push(evm.stack, U256(len(evm.message.data)))
199
200
    # PROGRAM COUNTER
201
    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:
205
    """
206
    Copy a portion of the input data in current environment to memory.
207
208
    This will also expand the memory, in case that the memory is insufficient
209
    to store the data.
210
211
    Parameters
212
    ----------
213
    evm :
214
        The current EVM frame.
215
216
    """
217
    # STACK
218
    memory_start_index = pop(evm.stack)
219
    data_start_index = pop(evm.stack)
220
    size = pop(evm.stack)
221
222
    # GAS
223
    words = ceil32(Uint(size)) // Uint(32)
224
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
225
    extend_memory = calculate_gas_extend_memory(
226
        evm.memory, [(memory_start_index, size)]
227
    )
228
    charge_gas(
229
        evm,
230
        GasCosts.OPCODE_CALLDATACOPY_BASE + copy_gas_cost + extend_memory.cost,
231
    )
232
233
    # OPERATION
234
    evm.memory += b"\x00" * extend_memory.expand_by
235
    value = buffer_read(evm.message.data, data_start_index, size)
236
    memory_write(evm.memory, memory_start_index, value)
237
238
    # PROGRAM COUNTER
239
    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:
243
    """
244
    Push the size of code running in current environment onto the stack.
245
246
    Parameters
247
    ----------
248
    evm :
249
        The current EVM frame.
250
251
    """
252
    # STACK
253
    pass
254
255
    # GAS
256
    charge_gas(evm, GasCosts.OPCODE_CODESIZE)
257
258
    # OPERATION
259
    push(evm.stack, U256(len(evm.code)))
260
261
    # PROGRAM COUNTER
262
    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:
266
    """
267
    Copy a portion of the code in current environment to memory.
268
269
    This will also expand the memory, in case that the memory is insufficient
270
    to store the data.
271
272
    Parameters
273
    ----------
274
    evm :
275
        The current EVM frame.
276
277
    """
278
    # STACK
279
    memory_start_index = pop(evm.stack)
280
    code_start_index = pop(evm.stack)
281
    size = pop(evm.stack)
282
283
    # GAS
284
    words = ceil32(Uint(size)) // Uint(32)
285
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
286
    extend_memory = calculate_gas_extend_memory(
287
        evm.memory, [(memory_start_index, size)]
288
    )
289
    charge_gas(
290
        evm,
291
        GasCosts.OPCODE_CODECOPY_BASE + copy_gas_cost + extend_memory.cost,
292
    )
293
294
    # OPERATION
295
    evm.memory += b"\x00" * extend_memory.expand_by
296
    value = buffer_read(evm.code, code_start_index, size)
297
    memory_write(evm.memory, memory_start_index, value)
298
299
    # PROGRAM COUNTER
300
    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:
304
    """
305
    Push the gas price used in current environment onto the stack.
306
307
    Parameters
308
    ----------
309
    evm :
310
        The current EVM frame.
311
312
    """
313
    # STACK
314
    pass
315
316
    # GAS
317
    charge_gas(evm, GasCosts.OPCODE_GASPRICE)
318
319
    # OPERATION
320
    push(evm.stack, U256(evm.message.tx_env.gas_price))
321
322
    # PROGRAM COUNTER
323
    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:
327
    """
328
    Push the code size of a given account onto the stack.
329
330
    Parameters
331
    ----------
332
    evm :
333
        The current EVM frame.
334
335
    """
336
    # STACK
337
    address = to_address_masked(pop(evm.stack))
338
339
    # GAS
340
    if address in evm.accessed_addresses:
341
        access_gas_cost = GasCosts.WARM_ACCESS
342
    else:
343
        evm.accessed_addresses.add(address)
344
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
345
346
    charge_gas(evm, access_gas_cost)
347
348
    # OPERATION
349
    state = evm.message.block_env.state
350
    code = get_code(state, get_account(state, address).code_hash)
351
352
    codesize = U256(len(code))
353
    push(evm.stack, codesize)
354
355
    # PROGRAM COUNTER
356
    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:
360
    """
361
    Copy a portion of an account's code to memory.
362
363
    Parameters
364
    ----------
365
    evm :
366
        The current EVM frame.
367
368
    """
369
    # STACK
370
    address = to_address_masked(pop(evm.stack))
371
    memory_start_index = pop(evm.stack)
372
    code_start_index = pop(evm.stack)
373
    size = pop(evm.stack)
374
375
    # GAS
376
    words = ceil32(Uint(size)) // Uint(32)
377
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
378
    extend_memory = calculate_gas_extend_memory(
379
        evm.memory, [(memory_start_index, size)]
380
    )
381
382
    if address in evm.accessed_addresses:
383
        access_gas_cost = GasCosts.WARM_ACCESS
384
    else:
385
        evm.accessed_addresses.add(address)
386
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
387
388
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
389
390
    # OPERATION
391
    evm.memory += b"\x00" * extend_memory.expand_by
392
    state = evm.message.block_env.state
393
    code = get_code(state, get_account(state, address).code_hash)
394
395
    value = buffer_read(code, code_start_index, size)
396
    memory_write(evm.memory, memory_start_index, value)
397
398
    # PROGRAM COUNTER
399
    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:
403
    """
404
    Pushes the size of the return data buffer onto the stack.
405
406
    Parameters
407
    ----------
408
    evm :
409
        The current EVM frame.
410
411
    """
412
    # STACK
413
    pass
414
415
    # GAS
416
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
417
418
    # OPERATION
419
    push(evm.stack, U256(len(evm.return_data)))
420
421
    # PROGRAM COUNTER
422
    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:
426
    """
427
    Copies data from the return data buffer to memory.
428
429
    Parameters
430
    ----------
431
    evm :
432
        The current EVM frame.
433
434
    """
435
    # STACK
436
    memory_start_index = pop(evm.stack)
437
    return_data_start_position = pop(evm.stack)
438
    size = pop(evm.stack)
439
440
    # GAS
441
    words = ceil32(Uint(size)) // Uint(32)
442
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
443
    extend_memory = calculate_gas_extend_memory(
444
        evm.memory, [(memory_start_index, size)]
445
    )
446
    charge_gas(
447
        evm,
448
        GasCosts.OPCODE_RETURNDATACOPY_BASE
449
        + copy_gas_cost
450
        + extend_memory.cost,
451
    )
452
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
453
        raise OutOfBoundsRead
454
455
    evm.memory += b"\x00" * extend_memory.expand_by
456
    value = evm.return_data[
457
        return_data_start_position : return_data_start_position + size
458
    ]
459
    memory_write(evm.memory, memory_start_index, value)
460
461
    # PROGRAM COUNTER
462
    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:
466
    """
467
    Returns the keccak256 hash of a contract’s bytecode.
468
469
    Parameters
470
    ----------
471
    evm :
472
        The current EVM frame.
473
474
    """
475
    # STACK
476
    address = to_address_masked(pop(evm.stack))
477
478
    # GAS
479
    if address in evm.accessed_addresses:
480
        access_gas_cost = GasCosts.WARM_ACCESS
481
    else:
482
        evm.accessed_addresses.add(address)
483
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
484
485
    charge_gas(evm, access_gas_cost)
486
487
    # OPERATION
488
    account = get_account(evm.message.block_env.state, address)
489
490
    if account == EMPTY_ACCOUNT:
491
        codehash = U256(0)
492
    else:
493
        codehash = U256.from_be_bytes(account.code_hash)
494
495
    push(evm.stack, codehash)
496
497
    # PROGRAM COUNTER
498
    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:
502
    """
503
    Pushes the balance of the current address to the stack.
504
505
    Parameters
506
    ----------
507
    evm :
508
        The current EVM frame.
509
510
    """
511
    # STACK
512
    pass
513
514
    # GAS
515
    charge_gas(evm, GasCosts.FAST_STEP)
516
517
    # OPERATION
518
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
519
    balance = get_account(
520
        evm.message.block_env.state, evm.message.current_target
521
    ).balance
522
523
    push(evm.stack, balance)
524
525
    # PROGRAM COUNTER
526
    evm.pc += Uint(1)

base_fee

Pushes the base fee of the current block on to the stack.

Parameters

evm : The current EVM frame.

def base_fee(evm: Evm) -> None:
530
    """
531
    Pushes the base fee of the current block on to the stack.
532
533
    Parameters
534
    ----------
535
    evm :
536
        The current EVM frame.
537
538
    """
539
    # STACK
540
    pass
541
542
    # GAS
543
    charge_gas(evm, GasCosts.OPCODE_BASEFEE)
544
545
    # OPERATION
546
    push(evm.stack, U256(evm.message.block_env.base_fee_per_gas))
547
548
    # PROGRAM COUNTER
549
    evm.pc += Uint(1)