ethereum.forks.osaka.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:
43
    """
44
    Pushes the address of the current executing account to the stack.
45
46
    Parameters
47
    ----------
48
    evm :
49
        The current EVM frame.
50
51
    """
52
    # STACK
53
    pass
54
55
    # GAS
56
    charge_gas(evm, GAS_BASE)
57
58
    # OPERATION
59
    push(evm.stack, U256.from_be_bytes(evm.message.current_target))
60
61
    # PROGRAM COUNTER
62
    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:
66
    """
67
    Pushes the balance of the given account onto the stack.
68
69
    Parameters
70
    ----------
71
    evm :
72
        The current EVM frame.
73
74
    """
75
    # STACK
76
    address = to_address_masked(pop(evm.stack))
77
78
    # GAS
79
    if address in evm.accessed_addresses:
80
        charge_gas(evm, GAS_WARM_ACCESS)
81
    else:
82
        evm.accessed_addresses.add(address)
83
        charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS)
84
85
    # OPERATION
86
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
87
    balance = get_account(evm.message.block_env.state, address).balance
88
89
    push(evm.stack, balance)
90
91
    # PROGRAM COUNTER
92
    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:
96
    """
97
    Pushes the address of the original transaction sender to the stack.
98
    The origin address can only be an EOA.
99
100
    Parameters
101
    ----------
102
    evm :
103
        The current EVM frame.
104
105
    """
106
    # STACK
107
    pass
108
109
    # GAS
110
    charge_gas(evm, GAS_BASE)
111
112
    # OPERATION
113
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
114
115
    # PROGRAM COUNTER
116
    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:
120
    """
121
    Pushes the address of the caller onto the stack.
122
123
    Parameters
124
    ----------
125
    evm :
126
        The current EVM frame.
127
128
    """
129
    # STACK
130
    pass
131
132
    # GAS
133
    charge_gas(evm, GAS_BASE)
134
135
    # OPERATION
136
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
137
138
    # PROGRAM COUNTER
139
    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:
143
    """
144
    Push the value (in wei) sent with the call onto the stack.
145
146
    Parameters
147
    ----------
148
    evm :
149
        The current EVM frame.
150
151
    """
152
    # STACK
153
    pass
154
155
    # GAS
156
    charge_gas(evm, GAS_BASE)
157
158
    # OPERATION
159
    push(evm.stack, evm.message.value)
160
161
    # PROGRAM COUNTER
162
    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:
166
    """
167
    Push a word (32 bytes) of the input data belonging to the current
168
    environment onto the stack.
169
170
    Parameters
171
    ----------
172
    evm :
173
        The current EVM frame.
174
175
    """
176
    # STACK
177
    start_index = pop(evm.stack)
178
179
    # GAS
180
    charge_gas(evm, GAS_VERY_LOW)
181
182
    # OPERATION
183
    value = buffer_read(evm.message.data, start_index, U256(32))
184
185
    push(evm.stack, U256.from_be_bytes(value))
186
187
    # PROGRAM COUNTER
188
    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:
192
    """
193
    Push the size of input data in current environment onto the stack.
194
195
    Parameters
196
    ----------
197
    evm :
198
        The current EVM frame.
199
200
    """
201
    # STACK
202
    pass
203
204
    # GAS
205
    charge_gas(evm, GAS_BASE)
206
207
    # OPERATION
208
    push(evm.stack, U256(len(evm.message.data)))
209
210
    # PROGRAM COUNTER
211
    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:
215
    """
216
    Copy a portion of the input data in current environment to memory.
217
218
    This will also expand the memory, in case that the memory is insufficient
219
    to store the data.
220
221
    Parameters
222
    ----------
223
    evm :
224
        The current EVM frame.
225
226
    """
227
    # STACK
228
    memory_start_index = pop(evm.stack)
229
    data_start_index = pop(evm.stack)
230
    size = pop(evm.stack)
231
232
    # GAS
233
    words = ceil32(Uint(size)) // Uint(32)
234
    copy_gas_cost = GAS_COPY * words
235
    extend_memory = calculate_gas_extend_memory(
236
        evm.memory, [(memory_start_index, size)]
237
    )
238
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
239
240
    # OPERATION
241
    evm.memory += b"\x00" * extend_memory.expand_by
242
    value = buffer_read(evm.message.data, data_start_index, size)
243
    memory_write(evm.memory, memory_start_index, value)
244
245
    # PROGRAM COUNTER
246
    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:
250
    """
251
    Push the size of code running in current environment onto the stack.
252
253
    Parameters
254
    ----------
255
    evm :
256
        The current EVM frame.
257
258
    """
259
    # STACK
260
    pass
261
262
    # GAS
263
    charge_gas(evm, GAS_BASE)
264
265
    # OPERATION
266
    push(evm.stack, U256(len(evm.code)))
267
268
    # PROGRAM COUNTER
269
    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:
273
    """
274
    Copy a portion of the code in current environment to memory.
275
276
    This will also expand the memory, in case that the memory is insufficient
277
    to store the data.
278
279
    Parameters
280
    ----------
281
    evm :
282
        The current EVM frame.
283
284
    """
285
    # STACK
286
    memory_start_index = pop(evm.stack)
287
    code_start_index = pop(evm.stack)
288
    size = pop(evm.stack)
289
290
    # GAS
291
    words = ceil32(Uint(size)) // Uint(32)
292
    copy_gas_cost = GAS_COPY * words
293
    extend_memory = calculate_gas_extend_memory(
294
        evm.memory, [(memory_start_index, size)]
295
    )
296
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
297
298
    # OPERATION
299
    evm.memory += b"\x00" * extend_memory.expand_by
300
    value = buffer_read(evm.code, code_start_index, size)
301
    memory_write(evm.memory, memory_start_index, value)
302
303
    # PROGRAM COUNTER
304
    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:
308
    """
309
    Push the gas price used in current environment onto the stack.
310
311
    Parameters
312
    ----------
313
    evm :
314
        The current EVM frame.
315
316
    """
317
    # STACK
318
    pass
319
320
    # GAS
321
    charge_gas(evm, GAS_BASE)
322
323
    # OPERATION
324
    push(evm.stack, U256(evm.message.tx_env.gas_price))
325
326
    # PROGRAM COUNTER
327
    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:
331
    """
332
    Push the code size of a given account onto the stack.
333
334
    Parameters
335
    ----------
336
    evm :
337
        The current EVM frame.
338
339
    """
340
    # STACK
341
    address = to_address_masked(pop(evm.stack))
342
343
    # GAS
344
    if address in evm.accessed_addresses:
345
        access_gas_cost = GAS_WARM_ACCESS
346
    else:
347
        evm.accessed_addresses.add(address)
348
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
349
350
    charge_gas(evm, access_gas_cost)
351
352
    # OPERATION
353
    code = get_account(evm.message.block_env.state, address).code
354
355
    codesize = U256(len(code))
356
    push(evm.stack, codesize)
357
358
    # PROGRAM COUNTER
359
    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:
363
    """
364
    Copy a portion of an account's code to memory.
365
366
    Parameters
367
    ----------
368
    evm :
369
        The current EVM frame.
370
371
    """
372
    # STACK
373
    address = to_address_masked(pop(evm.stack))
374
    memory_start_index = pop(evm.stack)
375
    code_start_index = pop(evm.stack)
376
    size = pop(evm.stack)
377
378
    # GAS
379
    words = ceil32(Uint(size)) // Uint(32)
380
    copy_gas_cost = GAS_COPY * words
381
    extend_memory = calculate_gas_extend_memory(
382
        evm.memory, [(memory_start_index, size)]
383
    )
384
385
    if address in evm.accessed_addresses:
386
        access_gas_cost = GAS_WARM_ACCESS
387
    else:
388
        evm.accessed_addresses.add(address)
389
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
390
391
    charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost)
392
393
    # OPERATION
394
    evm.memory += b"\x00" * extend_memory.expand_by
395
    code = get_account(evm.message.block_env.state, address).code
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, GAS_BASE)
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 code to memory.

Parameters

evm : The current EVM frame.

def returndatacopy(evm: Evm) -> None:
428
    """
429
    Copies data from the return data buffer code 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 = GAS_RETURN_DATA_COPY * words
445
    extend_memory = calculate_gas_extend_memory(
446
        evm.memory, [(memory_start_index, size)]
447
    )
448
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
449
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
450
        raise OutOfBoundsRead
451
452
    evm.memory += b"\x00" * extend_memory.expand_by
453
    value = evm.return_data[
454
        return_data_start_position : return_data_start_position + size
455
    ]
456
    memory_write(evm.memory, memory_start_index, value)
457
458
    # PROGRAM COUNTER
459
    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:
463
    """
464
    Returns the keccak256 hash of a contract’s bytecode.
465
466
    Parameters
467
    ----------
468
    evm :
469
        The current EVM frame.
470
471
    """
472
    # STACK
473
    address = to_address_masked(pop(evm.stack))
474
475
    # GAS
476
    if address in evm.accessed_addresses:
477
        access_gas_cost = GAS_WARM_ACCESS
478
    else:
479
        evm.accessed_addresses.add(address)
480
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
481
482
    charge_gas(evm, access_gas_cost)
483
484
    # OPERATION
485
    account = get_account(evm.message.block_env.state, address)
486
487
    if account == EMPTY_ACCOUNT:
488
        codehash = U256(0)
489
    else:
490
        code = account.code
491
        codehash = U256.from_be_bytes(keccak256(code))
492
493
    push(evm.stack, codehash)
494
495
    # PROGRAM COUNTER
496
    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:
500
    """
501
    Pushes the balance of the current address to the stack.
502
503
    Parameters
504
    ----------
505
    evm :
506
        The current EVM frame.
507
508
    """
509
    # STACK
510
    pass
511
512
    # GAS
513
    charge_gas(evm, GAS_FAST_STEP)
514
515
    # OPERATION
516
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
517
    balance = get_account(
518
        evm.message.block_env.state, evm.message.current_target
519
    ).balance
520
521
    push(evm.stack, balance)
522
523
    # PROGRAM COUNTER
524
    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:
528
    """
529
    Pushes the base fee of the current block on to the stack.
530
531
    Parameters
532
    ----------
533
    evm :
534
        The current EVM frame.
535
536
    """
537
    # STACK
538
    pass
539
540
    # GAS
541
    charge_gas(evm, GAS_BASE)
542
543
    # OPERATION
544
    push(evm.stack, U256(evm.message.block_env.base_fee_per_gas))
545
546
    # PROGRAM COUNTER
547
    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:
551
    """
552
    Pushes the versioned hash at a particular index on to the stack.
553
554
    Parameters
555
    ----------
556
    evm :
557
        The current EVM frame.
558
559
    """
560
    # STACK
561
    index = pop(evm.stack)
562
563
    # GAS
564
    charge_gas(evm, GAS_BLOBHASH_OPCODE)
565
566
    # OPERATION
567
    if int(index) < len(evm.message.tx_env.blob_versioned_hashes):
568
        blob_hash = evm.message.tx_env.blob_versioned_hashes[index]
569
    else:
570
        blob_hash = Bytes32(b"\x00" * 32)
571
    push(evm.stack, U256.from_be_bytes(blob_hash))
572
573
    # PROGRAM COUNTER
574
    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:
578
    """
579
    Pushes the blob base fee on to the stack.
580
581
    Parameters
582
    ----------
583
    evm :
584
        The current EVM frame.
585
586
    """
587
    # STACK
588
    pass
589
590
    # GAS
591
    charge_gas(evm, GAS_BASE)
592
593
    # OPERATION
594
    blob_base_fee = calculate_blob_gas_price(
595
        evm.message.block_env.excess_blob_gas
596
    )
597
    push(evm.stack, U256(blob_base_fee))
598
599
    # PROGRAM COUNTER
600
    evm.pc += Uint(1)