ethereum.forks.bpo1.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:
42
    """
43
    Pushes the address of the current executing account to the stack.
44
45
    Parameters
46
    ----------
47
    evm :
48
        The current EVM frame.
49
50
    """
51
    # STACK
52
    pass
53
54
    # GAS
55
    charge_gas(evm, GAS_BASE)
56
57
    # OPERATION
58
    push(evm.stack, U256.from_be_bytes(evm.message.current_target))
59
60
    # PROGRAM COUNTER
61
    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:
65
    """
66
    Pushes the balance of the given account onto the stack.
67
68
    Parameters
69
    ----------
70
    evm :
71
        The current EVM frame.
72
73
    """
74
    # STACK
75
    address = to_address_masked(pop(evm.stack))
76
77
    # GAS
78
    if address in evm.accessed_addresses:
79
        charge_gas(evm, GAS_WARM_ACCESS)
80
    else:
81
        evm.accessed_addresses.add(address)
82
        charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS)
83
84
    # OPERATION
85
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
86
    balance = get_account(evm.message.block_env.state, address).balance
87
88
    push(evm.stack, balance)
89
90
    # PROGRAM COUNTER
91
    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:
95
    """
96
    Pushes the address of the original transaction sender to the stack.
97
    The origin address can only be an EOA.
98
99
    Parameters
100
    ----------
101
    evm :
102
        The current EVM frame.
103
104
    """
105
    # STACK
106
    pass
107
108
    # GAS
109
    charge_gas(evm, GAS_BASE)
110
111
    # OPERATION
112
    push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin))
113
114
    # PROGRAM COUNTER
115
    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:
119
    """
120
    Pushes the address of the caller onto the stack.
121
122
    Parameters
123
    ----------
124
    evm :
125
        The current EVM frame.
126
127
    """
128
    # STACK
129
    pass
130
131
    # GAS
132
    charge_gas(evm, GAS_BASE)
133
134
    # OPERATION
135
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
136
137
    # PROGRAM COUNTER
138
    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:
142
    """
143
    Push the value (in wei) sent with the call onto the stack.
144
145
    Parameters
146
    ----------
147
    evm :
148
        The current EVM frame.
149
150
    """
151
    # STACK
152
    pass
153
154
    # GAS
155
    charge_gas(evm, GAS_BASE)
156
157
    # OPERATION
158
    push(evm.stack, evm.message.value)
159
160
    # PROGRAM COUNTER
161
    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:
165
    """
166
    Push a word (32 bytes) of the input data belonging to the current
167
    environment onto the stack.
168
169
    Parameters
170
    ----------
171
    evm :
172
        The current EVM frame.
173
174
    """
175
    # STACK
176
    start_index = pop(evm.stack)
177
178
    # GAS
179
    charge_gas(evm, GAS_VERY_LOW)
180
181
    # OPERATION
182
    value = buffer_read(evm.message.data, start_index, U256(32))
183
184
    push(evm.stack, U256.from_be_bytes(value))
185
186
    # PROGRAM COUNTER
187
    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:
191
    """
192
    Push the size of input data in current environment onto the stack.
193
194
    Parameters
195
    ----------
196
    evm :
197
        The current EVM frame.
198
199
    """
200
    # STACK
201
    pass
202
203
    # GAS
204
    charge_gas(evm, GAS_BASE)
205
206
    # OPERATION
207
    push(evm.stack, U256(len(evm.message.data)))
208
209
    # PROGRAM COUNTER
210
    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:
214
    """
215
    Copy a portion of the input data in current environment to memory.
216
217
    This will also expand the memory, in case that the memory is insufficient
218
    to store the data.
219
220
    Parameters
221
    ----------
222
    evm :
223
        The current EVM frame.
224
225
    """
226
    # STACK
227
    memory_start_index = pop(evm.stack)
228
    data_start_index = pop(evm.stack)
229
    size = pop(evm.stack)
230
231
    # GAS
232
    words = ceil32(Uint(size)) // Uint(32)
233
    copy_gas_cost = GAS_COPY * words
234
    extend_memory = calculate_gas_extend_memory(
235
        evm.memory, [(memory_start_index, size)]
236
    )
237
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
238
239
    # OPERATION
240
    evm.memory += b"\x00" * extend_memory.expand_by
241
    value = buffer_read(evm.message.data, data_start_index, size)
242
    memory_write(evm.memory, memory_start_index, value)
243
244
    # PROGRAM COUNTER
245
    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:
249
    """
250
    Push the size of code running in current environment onto the stack.
251
252
    Parameters
253
    ----------
254
    evm :
255
        The current EVM frame.
256
257
    """
258
    # STACK
259
    pass
260
261
    # GAS
262
    charge_gas(evm, GAS_BASE)
263
264
    # OPERATION
265
    push(evm.stack, U256(len(evm.code)))
266
267
    # PROGRAM COUNTER
268
    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:
272
    """
273
    Copy a portion of the code in current environment to memory.
274
275
    This will also expand the memory, in case that the memory is insufficient
276
    to store the data.
277
278
    Parameters
279
    ----------
280
    evm :
281
        The current EVM frame.
282
283
    """
284
    # STACK
285
    memory_start_index = pop(evm.stack)
286
    code_start_index = pop(evm.stack)
287
    size = pop(evm.stack)
288
289
    # GAS
290
    words = ceil32(Uint(size)) // Uint(32)
291
    copy_gas_cost = GAS_COPY * words
292
    extend_memory = calculate_gas_extend_memory(
293
        evm.memory, [(memory_start_index, size)]
294
    )
295
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
296
297
    # OPERATION
298
    evm.memory += b"\x00" * extend_memory.expand_by
299
    value = buffer_read(evm.code, code_start_index, size)
300
    memory_write(evm.memory, memory_start_index, value)
301
302
    # PROGRAM COUNTER
303
    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:
307
    """
308
    Push the gas price used in current environment onto the stack.
309
310
    Parameters
311
    ----------
312
    evm :
313
        The current EVM frame.
314
315
    """
316
    # STACK
317
    pass
318
319
    # GAS
320
    charge_gas(evm, GAS_BASE)
321
322
    # OPERATION
323
    push(evm.stack, U256(evm.message.tx_env.gas_price))
324
325
    # PROGRAM COUNTER
326
    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:
330
    """
331
    Push the code size of a given account onto the stack.
332
333
    Parameters
334
    ----------
335
    evm :
336
        The current EVM frame.
337
338
    """
339
    # STACK
340
    address = to_address_masked(pop(evm.stack))
341
342
    # GAS
343
    if address in evm.accessed_addresses:
344
        access_gas_cost = GAS_WARM_ACCESS
345
    else:
346
        evm.accessed_addresses.add(address)
347
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
348
349
    charge_gas(evm, access_gas_cost)
350
351
    # OPERATION
352
    state = evm.message.block_env.state
353
    code = get_code(state, get_account(state, address).code_hash)
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
    state = evm.message.block_env.state
396
    code = get_code(state, get_account(state, address).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, GAS_BASE)
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 = GAS_RETURN_DATA_COPY * words
446
    extend_memory = calculate_gas_extend_memory(
447
        evm.memory, [(memory_start_index, size)]
448
    )
449
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
450
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
451
        raise OutOfBoundsRead
452
453
    evm.memory += b"\x00" * extend_memory.expand_by
454
    value = evm.return_data[
455
        return_data_start_position : return_data_start_position + size
456
    ]
457
    memory_write(evm.memory, memory_start_index, value)
458
459
    # PROGRAM COUNTER
460
    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:
464
    """
465
    Returns the keccak256 hash of a contract’s bytecode.
466
467
    Parameters
468
    ----------
469
    evm :
470
        The current EVM frame.
471
472
    """
473
    # STACK
474
    address = to_address_masked(pop(evm.stack))
475
476
    # GAS
477
    if address in evm.accessed_addresses:
478
        access_gas_cost = GAS_WARM_ACCESS
479
    else:
480
        evm.accessed_addresses.add(address)
481
        access_gas_cost = GAS_COLD_ACCOUNT_ACCESS
482
483
    charge_gas(evm, access_gas_cost)
484
485
    # OPERATION
486
    account = get_account(evm.message.block_env.state, address)
487
488
    if account == EMPTY_ACCOUNT:
489
        codehash = U256(0)
490
    else:
491
        codehash = U256.from_be_bytes(account.code_hash)
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)