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