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

blob_hash

Pushes the versioned hash at a particular index on to the stack.

Parameters

evm : The current EVM frame.

def blob_hash(evm: Evm) -> None:
555
    """
556
    Pushes the versioned hash at a particular index on to the stack.
557
558
    Parameters
559
    ----------
560
    evm :
561
        The current EVM frame.
562
563
    """
564
    # STACK
565
    index = pop(evm.stack)
566
567
    # GAS
568
    charge_gas(evm, GasCosts.OPCODE_BLOBHASH)
569
570
    # OPERATION
571
    if int(index) < len(evm.message.tx_env.blob_versioned_hashes):
572
        blob_hash = evm.message.tx_env.blob_versioned_hashes[index]
573
    else:
574
        blob_hash = Bytes32(b"\x00" * 32)
575
    push(evm.stack, U256.from_be_bytes(blob_hash))
576
577
    # PROGRAM COUNTER
578
    evm.pc += Uint(1)

blob_base_fee

Pushes the blob base fee on to the stack.

Parameters

evm : The current EVM frame.

def blob_base_fee(evm: Evm) -> None:
582
    """
583
    Pushes the blob base fee on to the stack.
584
585
    Parameters
586
    ----------
587
    evm :
588
        The current EVM frame.
589
590
    """
591
    # STACK
592
    pass
593
594
    # GAS
595
    charge_gas(evm, GasCosts.OPCODE_BLOBBASEFEE)
596
597
    # OPERATION
598
    blob_base_fee = calculate_blob_gas_price(
599
        evm.message.block_env.excess_blob_gas
600
    )
601
    push(evm.stack, U256(blob_base_fee))
602
603
    # PROGRAM COUNTER
604
    evm.pc += Uint(1)