ethereum.forks.london.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
    account = get_account(tx_state, address)
352
    code = get_code(tx_state, account.code_hash)
353
354
    codesize = U256(len(code))
355
    push(evm.stack, codesize)
356
357
    # PROGRAM COUNTER
358
    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:
362
    """
363
    Copy a portion of an account's code to memory.
364
365
    Parameters
366
    ----------
367
    evm :
368
        The current EVM frame.
369
370
    """
371
    # STACK
372
    address = to_address_masked(pop(evm.stack))
373
    memory_start_index = pop(evm.stack)
374
    code_start_index = pop(evm.stack)
375
    size = pop(evm.stack)
376
377
    # GAS
378
    words = ceil32(Uint(size)) // Uint(32)
379
    copy_gas_cost = GasCosts.OPCODE_COPY_PER_WORD * words
380
    extend_memory = calculate_gas_extend_memory(
381
        evm.memory, [(memory_start_index, size)]
382
    )
383
384
    if address in evm.accessed_addresses:
385
        access_gas_cost = GasCosts.WARM_ACCESS
386
    else:
387
        evm.accessed_addresses.add(address)
388
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
389
390
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
391
392
    # OPERATION
393
    evm.memory += b"\x00" * extend_memory.expand_by
394
    tx_state = evm.message.tx_env.state
395
    account = get_account(tx_state, address)
396
    code = get_code(tx_state, account.code_hash)
397
398
    value = buffer_read(code, code_start_index, size)
399
    memory_write(evm.memory, memory_start_index, value)
400
401
    # PROGRAM COUNTER
402
    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:
406
    """
407
    Pushes the size of the return data buffer onto the stack.
408
409
    Parameters
410
    ----------
411
    evm :
412
        The current EVM frame.
413
414
    """
415
    # STACK
416
    pass
417
418
    # GAS
419
    charge_gas(evm, GasCosts.OPCODE_RETURNDATASIZE)
420
421
    # OPERATION
422
    push(evm.stack, U256(len(evm.return_data)))
423
424
    # PROGRAM COUNTER
425
    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:
429
    """
430
    Copies data from the return data buffer to memory.
431
432
    Parameters
433
    ----------
434
    evm :
435
        The current EVM frame.
436
437
    """
438
    # STACK
439
    memory_start_index = pop(evm.stack)
440
    return_data_start_position = pop(evm.stack)
441
    size = pop(evm.stack)
442
443
    # GAS
444
    words = ceil32(Uint(size)) // Uint(32)
445
    copy_gas_cost = GasCosts.OPCODE_RETURNDATACOPY_PER_WORD * words
446
    extend_memory = calculate_gas_extend_memory(
447
        evm.memory, [(memory_start_index, size)]
448
    )
449
    charge_gas(
450
        evm,
451
        GasCosts.OPCODE_RETURNDATACOPY_BASE
452
        + copy_gas_cost
453
        + extend_memory.cost,
454
    )
455
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
456
        raise OutOfBoundsRead
457
458
    evm.memory += b"\x00" * extend_memory.expand_by
459
    value = evm.return_data[
460
        return_data_start_position : return_data_start_position + size
461
    ]
462
    memory_write(evm.memory, memory_start_index, value)
463
464
    # PROGRAM COUNTER
465
    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:
469
    """
470
    Returns the keccak256 hash of a contract’s bytecode.
471
472
    Parameters
473
    ----------
474
    evm :
475
        The current EVM frame.
476
477
    """
478
    # STACK
479
    address = to_address_masked(pop(evm.stack))
480
481
    # GAS
482
    if address in evm.accessed_addresses:
483
        access_gas_cost = GasCosts.WARM_ACCESS
484
    else:
485
        evm.accessed_addresses.add(address)
486
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
487
488
    charge_gas(evm, access_gas_cost)
489
490
    # OPERATION
491
    account = get_account(evm.message.tx_env.state, address)
492
493
    if account == EMPTY_ACCOUNT:
494
        codehash = U256(0)
495
    else:
496
        codehash = U256.from_be_bytes(account.code_hash)
497
498
    push(evm.stack, codehash)
499
500
    # PROGRAM COUNTER
501
    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:
505
    """
506
    Pushes the balance of the current address to the stack.
507
508
    Parameters
509
    ----------
510
    evm :
511
        The current EVM frame.
512
513
    """
514
    # STACK
515
    pass
516
517
    # GAS
518
    charge_gas(evm, GasCosts.FAST_STEP)
519
520
    # OPERATION
521
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
522
    balance = get_account(
523
        evm.message.tx_env.state, evm.message.current_target
524
    ).balance
525
526
    push(evm.stack, balance)
527
528
    # PROGRAM COUNTER
529
    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:
533
    """
534
    Pushes the base fee of the current block on to the stack.
535
536
    Parameters
537
    ----------
538
    evm :
539
        The current EVM frame.
540
541
    """
542
    # STACK
543
    pass
544
545
    # GAS
546
    charge_gas(evm, GasCosts.OPCODE_BASEFEE)
547
548
    # OPERATION
549
    push(evm.stack, U256(evm.message.block_env.base_fee_per_gas))
550
551
    # PROGRAM COUNTER
552
    evm.pc += Uint(1)