ethereum.forks.amsterdam.vm.instructions.system

Ethereum Virtual Machine (EVM) System Instructions.

.. contents:: Table of Contents :backlinks: none :local:

Introduction

Implementations of the EVM system related instructions.

generic_create

Run the child-frame lifecycle for the CREATE* family of opcodes.

The opcode has already priced the operation itself; this function runs the lifecycle: preflight checks that abort without spawning, the destination access with its account-creation charge and collision check, the child's gas grant, the child frame itself, and the resolution of its outcome back into the creating frame.

def generic_create(​evm: Evm, ​​endowment: U256, ​​contract_address: Address, ​​memory_start_position: U256, ​​memory_size: U256​) -> None:
66
    <snip>
75
    # These imports cause a circular import error
76
    # if they're not moved inside this method
77
    from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create
78
    from ...vm.runtime import get_valid_jump_destinations
79
80
    tx_state = evm.tx_env.state
81
82
    init_code = memory_read_bytes(
83
        evm.memory, memory_start_position, memory_size
84
    )
85
86
    evm.return_data = b""
87
88
    # PREFLIGHT
89
    # Abort without spawning the child: nothing has been charged or
90
    # withheld for it yet.
91
    sender_address = evm.current_target
92
    sender = get_account(tx_state, sender_address)
93
94
    if (
95
        sender.balance < endowment
96
        or sender.nonce == Uint(2**64 - 1)
97
        or evm.depth + Uint(1) > STACK_DEPTH_LIMIT
98
    ):
99
        push(evm.stack, U256(0))
100
        return
101
102
    # DESTINATION ACCESS
103
    # The account-creation charge is decided by existence alone,
104
    # independently of the collision outcome below.
105
    evm.accessed_addresses.add(contract_address)
106
107
    new_account_charged = not is_account_alive(tx_state, contract_address)
108
    if new_account_charged:
109
        charge_state_gas(evm, StateGasCosts.NEW_ACCOUNT)
110
111
    # CHILD GRANT
112
    # Withhold all but one 64th of the execution gas.
113
    create_message_gas = withhold_create_gas(evm.gas_meter)
114
115
    # On a collision the child's execution-gas grant is consumed and no
116
    # account is created. A collision target has code or a nonce, so
117
    # the account-creation charge above was never taken.
118
    if not account_deployable(tx_state, contract_address):
119
        increment_nonce(tx_state, sender_address)
120
        push(evm.stack, U256(0))
121
        return
122
123
    # The whole state gas reservoir rides along (no 63/64 rule for
124
    # state gas) and is restored when the child returns.
125
    create_message_state_gas_reservoir = drain_state_gas_reservoir(
126
        evm.gas_meter
127
    )
128
129
    increment_nonce(tx_state, sender_address)
130
131
    # DISPATCH
132
133
    child_evm = Evm(
134
        # Context
135
        block_env=evm.block_env,
136
        tx_env=evm.tx_env,
137
        parent_evm=evm,
138
        depth=evm.depth + Uint(1),
139
        # Call Parameters
140
        caller=evm.current_target,
141
        current_target=contract_address,
142
        value=endowment,
143
        call_data=b"",
144
        should_transfer_value=True,
145
        is_static=False,
146
        disable_precompiles=False,
147
        # Code
148
        code_address=None,
149
        code=init_code,
150
        valid_jump_destinations=get_valid_jump_destinations(init_code),
151
        # Machine State
152
        gas_meter=GasMeter(
153
            gas_left=create_message_gas,
154
            state_gas_left=create_message_state_gas_reservoir,
155
            state_gas_baseline=create_message_state_gas_reservoir,
156
        ),
157
        pc=Uint(0),
158
        stack=[],
159
        memory=bytearray(),
160
        return_data=b"",
161
        # Accrued Effects
162
        logs=(),
163
        accounts_to_delete=set(),
164
        accessed_addresses=evm.accessed_addresses.copy(),
165
        accessed_storage_keys=evm.accessed_storage_keys.copy(),
166
        # Outcome
167
        running=True,
168
        output=b"",
169
        error=None,
170
    )
171
    child_evm = process_create(child_evm)
172
173
    # OUTCOME
174
    # The child settled its own gas; absorb it and resolve the
175
    # account-creation charge by the state's fate: it refills when a
176
    # charged creation failed.
177
    incorporate_child(evm, child_evm)
178
    if child_evm.error:
179
        if new_account_charged:
180
            credit_state_gas_refund(evm.gas_meter, StateGasCosts.NEW_ACCOUNT)
181
        evm.return_data = child_evm.output
182
        push(evm.stack, U256(0))
183
    else:
184
        evm.return_data = b""
185
        push(evm.stack, U256.from_be_bytes(child_evm.current_target))

create

Creates a new account with associated code.

Parameters

evm : The current EVM frame.

def create(​evm: Evm​) -> None:
189
    <snip>
198
    # This import causes a circular import error
199
    # if it's not moved inside this method
200
    from ...vm.interpreter import MAX_INIT_CODE_SIZE
201
202
    if evm.is_static:
203
        raise WriteInStaticContext
204
205
    # STACK
206
    endowment = pop(evm.stack)
207
    memory_start_position = pop(evm.stack)
208
    memory_size = pop(evm.stack)
209
210
    # GAS
211
    extend_memory = calculate_gas_extend_memory(
212
        evm.memory, [(memory_start_position, memory_size)]
213
    )
214
    init_code_gas = init_code_cost(Uint(memory_size))
215
216
    charge_gas(
217
        evm,
218
        GasCosts.CREATE_ACCESS + extend_memory.cost + init_code_gas,
219
    )
220
221
    if memory_size > U256(MAX_INIT_CODE_SIZE):
222
        raise OutOfGasError
223
224
    # OPERATION
225
    evm.memory += b"\x00" * extend_memory.expand_by
226
    contract_address = compute_contract_address(
227
        evm.current_target,
228
        get_account(evm.tx_env.state, evm.current_target).nonce,
229
    )
230
231
    generic_create(
232
        evm,
233
        endowment,
234
        contract_address,
235
        memory_start_position,
236
        memory_size,
237
    )
238
239
    # PROGRAM COUNTER
240
    evm.pc += Uint(1)

create2

Creates a new account with associated code.

It's similar to the CREATE opcode except that the address of the new account depends on the init_code instead of the nonce of sender.

Parameters

evm : The current EVM frame.

def create2(​evm: Evm​) -> None:
244
    <snip>
256
    # This import causes a circular import error
257
    # if it's not moved inside this method
258
    from ...vm.interpreter import MAX_INIT_CODE_SIZE
259
260
    if evm.is_static:
261
        raise WriteInStaticContext
262
263
    # STACK
264
    endowment = pop(evm.stack)
265
    memory_start_position = pop(evm.stack)
266
    memory_size = pop(evm.stack)
267
    salt = pop(evm.stack).to_be_bytes32()
268
269
    # GAS
270
    extend_memory = calculate_gas_extend_memory(
271
        evm.memory, [(memory_start_position, memory_size)]
272
    )
273
    call_data_words = ceil32(Uint(memory_size)) // Uint(32)
274
    init_code_gas = init_code_cost(Uint(memory_size))
275
    charge_gas(
276
        evm,
277
        ExecutionGas(
278
            GasCosts.CREATE_ACCESS
279
            + GasCosts.OPCODE_KECCAK256_PER_WORD * call_data_words
280
            + extend_memory.cost
281
            + init_code_gas
282
        ),
283
    )
284
285
    if memory_size > U256(MAX_INIT_CODE_SIZE):
286
        raise OutOfGasError
287
288
    # OPERATION
289
    evm.memory += b"\x00" * extend_memory.expand_by
290
    contract_address = compute_create2_contract_address(
291
        evm.current_target,
292
        salt,
293
        memory_read_bytes(evm.memory, memory_start_position, memory_size),
294
    )
295
296
    generic_create(
297
        evm,
298
        endowment,
299
        contract_address,
300
        memory_start_position,
301
        memory_size,
302
    )
303
304
    # PROGRAM COUNTER
305
    evm.pc += Uint(1)

return_

Halts execution returning output data.

Parameters

evm : The current EVM frame.

def return_(​evm: Evm​) -> None:
309
    <snip>
318
    # STACK
319
    memory_start_position = pop(evm.stack)
320
    memory_size = pop(evm.stack)
321
322
    # GAS
323
    extend_memory = calculate_gas_extend_memory(
324
        evm.memory, [(memory_start_position, memory_size)]
325
    )
326
327
    charge_gas(evm, GasCosts.ZERO + extend_memory.cost)
328
329
    # OPERATION
330
    evm.memory += b"\x00" * extend_memory.expand_by
331
    evm.output = memory_read_bytes(
332
        evm.memory, memory_start_position, memory_size
333
    )
334
335
    evm.running = False
336
337
    # PROGRAM COUNTER
338
    pass

GenericCall

Parameters for the core logic of the CALL* family of opcodes.

341
@final
342
@dataclass
class GenericCall:

gas

348
    gas: ExecutionGas

state_gas_reservoir

349
    state_gas_reservoir: StateGas

value

350
    value: U256

caller

351
    caller: Address

to

352
    to: Address

code_address

353
    code_address: Address

should_transfer_value

354
    should_transfer_value: bool

is_staticcall

355
    is_staticcall: bool

memory_input_start_position

356
    memory_input_start_position: U256

memory_input_size

357
    memory_input_size: U256

memory_output_start_position

358
    memory_output_start_position: U256

memory_output_size

359
    memory_output_size: U256

code

360
    code: Bytes

disable_precompiles

361
    disable_precompiles: bool

new_account_charged

362
    new_account_charged: bool = False

insufficient_balance

True when the calling account cannot cover value; the call then aborts in preflight without spawning the child frame.

363
    insufficient_balance: bool = False

generic_call

Run the child-frame lifecycle for the CALL* family of opcodes.

The opcode has already priced the call and withheld the child's grant; this function only runs the lifecycle: preflight checks that abort without spawning, the child frame itself, and the resolution of its outcome back into the calling frame.

def generic_call(​evm: Evm, ​​params: GenericCall​) -> None:
371
    <snip>
379
    from ...vm.interpreter import STACK_DEPTH_LIMIT, process_call
380
    from ...vm.runtime import get_valid_jump_destinations
381
382
    evm.return_data = b""
383
384
    # PREFLIGHT
385
    # Abort without spawning the child: both grants return untouched
386
    # and any account-creation charge refills.
387
    if evm.depth + Uint(1) > STACK_DEPTH_LIMIT or params.insufficient_balance:
388
        restore_child_gas(
389
            evm.gas_meter, params.gas, params.state_gas_reservoir
390
        )
391
        if params.new_account_charged:
392
            credit_state_gas_refund(evm.gas_meter, StateGasCosts.NEW_ACCOUNT)
393
        push(evm.stack, U256(0))
394
        return
395
396
    # DISPATCH
397
    call_data = memory_read_bytes(
398
        evm.memory,
399
        params.memory_input_start_position,
400
        params.memory_input_size,
401
    )
402
403
    child_evm = Evm(
404
        # Context
405
        block_env=evm.block_env,
406
        tx_env=evm.tx_env,
407
        parent_evm=evm,
408
        depth=evm.depth + Uint(1),
409
        # Call Parameters
410
        caller=params.caller,
411
        current_target=params.to,
412
        value=params.value,
413
        call_data=call_data,
414
        should_transfer_value=params.should_transfer_value,
415
        is_static=params.is_staticcall or evm.is_static,
416
        disable_precompiles=params.disable_precompiles,
417
        # Code
418
        code_address=params.code_address,
419
        code=params.code,
420
        valid_jump_destinations=get_valid_jump_destinations(params.code),
421
        # Machine State
422
        gas_meter=GasMeter(
423
            gas_left=params.gas,
424
            state_gas_left=params.state_gas_reservoir,
425
            state_gas_baseline=params.state_gas_reservoir,
426
        ),
427
        pc=Uint(0),
428
        stack=[],
429
        memory=bytearray(),
430
        return_data=b"",
431
        # Accrued Effects
432
        logs=(),
433
        accounts_to_delete=set(),
434
        accessed_addresses=evm.accessed_addresses.copy(),
435
        accessed_storage_keys=evm.accessed_storage_keys.copy(),
436
        # Outcome
437
        running=True,
438
        output=b"",
439
        error=None,
440
    )
441
442
    child_evm = process_call(child_evm)
443
444
    # OUTCOME
445
    # The child settled its own gas; absorb it and resolve the
446
    # account-creation charge by the state's fate.
447
    incorporate_child(evm, child_evm)
448
    evm.return_data = child_evm.output
449
    if child_evm.error:
450
        if params.new_account_charged:
451
            credit_state_gas_refund(evm.gas_meter, StateGasCosts.NEW_ACCOUNT)
452
        push(evm.stack, U256(0))
453
    else:
454
        push(evm.stack, CALL_SUCCESS)
455
456
    actual_output_size = min(
457
        params.memory_output_size, U256(len(child_evm.output))
458
    )
459
    memory_write(
460
        evm.memory,
461
        params.memory_output_start_position,
462
        child_evm.output[:actual_output_size],
463
    )

call

Message-call into an account.

Parameters

evm : The current EVM frame.

def call(​evm: Evm​) -> None:
467
    <snip>
476
    # STACK
477
    gas = ExecutionGas(Uint(pop(evm.stack)))
478
    to = to_address_masked(pop(evm.stack))
479
    value = pop(evm.stack)
480
    memory_input_start_position = pop(evm.stack)
481
    memory_input_size = pop(evm.stack)
482
    memory_output_start_position = pop(evm.stack)
483
    memory_output_size = pop(evm.stack)
484
485
    if evm.is_static and value != U256(0):
486
        raise WriteInStaticContext
487
488
    # GAS (STATE-INDEPENDENT)
489
    # Price what is computable without touching state, and check it is
490
    # affordable before any state access is performed.
491
    extend_memory = calculate_gas_extend_memory(
492
        evm.memory,
493
        [
494
            (memory_input_start_position, memory_input_size),
495
            (memory_output_start_position, memory_output_size),
496
        ],
497
    )
498
499
    is_cold_access = to not in evm.accessed_addresses
500
    if is_cold_access:
501
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
502
    else:
503
        access_gas_cost = GasCosts.WARM_ACCESS
504
505
    transfer_gas_cost = GasCosts.ZERO if value == 0 else GasCosts.CALL_VALUE
506
507
    check_gas(
508
        evm,
509
        access_gas_cost + transfer_gas_cost + extend_memory.cost,
510
    )
511
512
    # STATE ACCESS (STATE-DEPENDENT GAS)
513
    # Perform the accesses and complete the state-dependent pricing --
514
    # a delegation adds its access cost -- then charge the execution
515
    # gas.
516
    tx_state = evm.tx_env.state
517
    if is_cold_access:
518
        evm.accessed_addresses.add(to)
519
520
    extra_gas = access_gas_cost + transfer_gas_cost
521
    (
522
        is_delegated,
523
        code_address,
524
        delegation_access_cost,
525
    ) = calculate_delegation_cost(evm, to)
526
527
    if is_delegated:
528
        # check enough gas for delegation access
529
        extra_gas += delegation_access_cost
530
        check_gas(evm, extra_gas + extend_memory.cost)
531
        if code_address not in evm.accessed_addresses:
532
            evm.accessed_addresses.add(code_address)
533
534
    code_hash = get_account(tx_state, code_address).code_hash
535
    code = get_code(tx_state, code_hash)
536
537
    charge_gas(evm, extra_gas + extend_memory.cost)
538
539
    # STATE GAS
540
    # A value transfer that will create the recipient is charged by
541
    # the frame whose opcode causes it; refilled in `generic_call`
542
    # whenever the creation fails or never happens.
543
    has_value = value != 0
544
    new_account_charged = has_value and not is_account_alive(tx_state, to)
545
    if new_account_charged:
546
        charge_state_gas(evm, StateGasCosts.NEW_ACCOUNT)
547
548
    # CHILD GRANT
549
    # Computed after every charge above, so any state-gas spill has
550
    # already thinned `gas_left`. The whole reservoir rides along (no
551
    # 63/64 rule for state gas).
552
    message_call_gas = calculate_message_call_gas(
553
        value,
554
        gas,
555
        evm.gas_meter.gas_left,
556
        memory_cost=GasCosts.ZERO,
557
        extra_gas=GasCosts.ZERO,
558
    )
559
    charge_gas(evm, message_call_gas.cost)
560
    call_state_gas_reservoir = drain_state_gas_reservoir(evm.gas_meter)
561
562
    # OPERATION
563
    evm.memory += b"\x00" * extend_memory.expand_by
564
    sender_balance = get_account(tx_state, evm.current_target).balance
565
566
    generic_call(
567
        evm,
568
        GenericCall(
569
            gas=message_call_gas.sub_call,
570
            state_gas_reservoir=call_state_gas_reservoir,
571
            value=value,
572
            caller=evm.current_target,
573
            to=to,
574
            code_address=code_address,
575
            should_transfer_value=True,
576
            is_staticcall=False,
577
            memory_input_start_position=memory_input_start_position,
578
            memory_input_size=memory_input_size,
579
            memory_output_start_position=memory_output_start_position,
580
            memory_output_size=memory_output_size,
581
            code=code,
582
            disable_precompiles=is_delegated,
583
            new_account_charged=new_account_charged,
584
            insufficient_balance=sender_balance < value,
585
        ),
586
    )
587
588
    # PROGRAM COUNTER
589
    evm.pc += Uint(1)

callcode

Message-call into this account with alternative account's code.

Parameters

evm : The current EVM frame.

def callcode(​evm: Evm​) -> None:
593
    <snip>
602
    # STACK
603
    gas = ExecutionGas(Uint(pop(evm.stack)))
604
    code_address = to_address_masked(pop(evm.stack))
605
    value = pop(evm.stack)
606
    memory_input_start_position = pop(evm.stack)
607
    memory_input_size = pop(evm.stack)
608
    memory_output_start_position = pop(evm.stack)
609
    memory_output_size = pop(evm.stack)
610
611
    # GAS (STATE-INDEPENDENT)
612
    # Price what is computable without touching state, and check it is
613
    # affordable before any state access is performed.
614
    to = evm.current_target
615
616
    extend_memory = calculate_gas_extend_memory(
617
        evm.memory,
618
        [
619
            (memory_input_start_position, memory_input_size),
620
            (memory_output_start_position, memory_output_size),
621
        ],
622
    )
623
624
    is_cold_access = code_address not in evm.accessed_addresses
625
    if is_cold_access:
626
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
627
    else:
628
        access_gas_cost = GasCosts.WARM_ACCESS
629
630
    transfer_gas_cost = GasCosts.ZERO if value == 0 else GasCosts.CALL_VALUE
631
632
    check_gas(
633
        evm,
634
        access_gas_cost + extend_memory.cost + transfer_gas_cost,
635
    )
636
637
    # STATE ACCESS (STATE-DEPENDENT GAS)
638
    # Perform the accesses and complete the state-dependent pricing --
639
    # a delegation adds its access cost; the execution gas is charged
640
    # with the child grant.
641
    tx_state = evm.tx_env.state
642
    if is_cold_access:
643
        evm.accessed_addresses.add(code_address)
644
645
    extra_gas = access_gas_cost + transfer_gas_cost
646
    (
647
        is_delegated,
648
        code_address,
649
        delegation_access_cost,
650
    ) = calculate_delegation_cost(evm, code_address)
651
652
    if is_delegated:
653
        # check enough gas for delegation access
654
        extra_gas += delegation_access_cost
655
        check_gas(evm, extra_gas + extend_memory.cost)
656
        if code_address not in evm.accessed_addresses:
657
            evm.accessed_addresses.add(code_address)
658
659
    code_hash = get_account(tx_state, code_address).code_hash
660
    code = get_code(tx_state, code_hash)
661
662
    # CHILD GRANT
663
    # Charge the call's cost and withhold the child's execution gas
664
    # share in one step. The whole reservoir rides along (no 63/64
665
    # rule for state gas).
666
    message_call_gas = calculate_message_call_gas(
667
        value,
668
        gas,
669
        evm.gas_meter.gas_left,
670
        extend_memory.cost,
671
        extra_gas,
672
    )
673
    charge_gas(evm, message_call_gas.cost + extend_memory.cost)
674
    call_state_gas_reservoir = drain_state_gas_reservoir(evm.gas_meter)
675
676
    # OPERATION
677
    evm.memory += b"\x00" * extend_memory.expand_by
678
    sender_balance = get_account(tx_state, evm.current_target).balance
679
680
    generic_call(
681
        evm,
682
        GenericCall(
683
            gas=message_call_gas.sub_call,
684
            state_gas_reservoir=call_state_gas_reservoir,
685
            value=value,
686
            caller=evm.current_target,
687
            to=to,
688
            code_address=code_address,
689
            should_transfer_value=True,
690
            is_staticcall=False,
691
            memory_input_start_position=memory_input_start_position,
692
            memory_input_size=memory_input_size,
693
            memory_output_start_position=memory_output_start_position,
694
            memory_output_size=memory_output_size,
695
            code=code,
696
            disable_precompiles=is_delegated,
697
            insufficient_balance=sender_balance < value,
698
        ),
699
    )
700
701
    # PROGRAM COUNTER
702
    evm.pc += Uint(1)

selfdestruct

Halt execution and register account for later deletion.

Parameters

evm : The current EVM frame.

def selfdestruct(​evm: Evm​) -> None:
706
    <snip>
715
    if evm.is_static:
716
        raise WriteInStaticContext
717
718
    # STACK
719
    beneficiary = to_address_masked(pop(evm.stack))
720
721
    # GAS (STATE-INDEPENDENT)
722
    # Price what is computable without touching state, and check it is
723
    # affordable before any state access is performed.
724
    gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE
725
726
    is_cold_access = beneficiary not in evm.accessed_addresses
727
    if is_cold_access:
728
        gas_cost += GasCosts.COLD_ACCOUNT_ACCESS
729
730
    check_gas(evm, gas_cost)
731
732
    # STATE ACCESS (STATE-DEPENDENT GAS)
733
    # Perform the access; the pricing completes with the state gas
734
    # below.
735
    tx_state = evm.tx_env.state
736
    if is_cold_access:
737
        evm.accessed_addresses.add(beneficiary)
738
739
    # STATE GAS
740
    # A sweep that will create the beneficiary pays the account write
741
    # and the creation, charged by the frame whose opcode causes it;
742
    # it refills only through the frame's own rollback.
743
    state_gas = StateGas(Uint(0))
744
    account_write_gas = GasCosts.ZERO
745
    if (
746
        not is_account_alive(tx_state, beneficiary)
747
        and get_account(tx_state, evm.current_target).balance != 0
748
    ):
749
        state_gas = StateGasCosts.NEW_ACCOUNT
750
        account_write_gas = GasCosts.ACCOUNT_WRITE
751
752
    # Charge execution gas before state gas so that an execution-gas
753
    # OOG does not consume state gas that would inflate the parent's
754
    # reservoir on frame failure.
755
    charge_gas(evm, gas_cost + account_write_gas)
756
    charge_state_gas(evm, state_gas)
757
758
    # OPERATION
759
    originator = evm.current_target
760
    originator_balance = get_account(tx_state, originator).balance
761
762
    # Transfer balance
763
    move_ether(tx_state, originator, beneficiary, originator_balance)
764
765
    # Emit transfer log
766
    if beneficiary != originator:
767
        emit_transfer_log(evm, originator, beneficiary, originator_balance)
768
769
    # Register account for deletion iff created in same transaction
770
    if originator in tx_state.created_accounts:
771
        evm.accounts_to_delete.add(originator)
772
773
    # HALT the execution
774
    evm.running = False
775
776
    # PROGRAM COUNTER
777
    pass

delegatecall

Message-call into an account.

Parameters

evm : The current EVM frame.

def delegatecall(​evm: Evm​) -> None:
781
    <snip>
790
    # STACK
791
    gas = ExecutionGas(Uint(pop(evm.stack)))
792
    code_address = to_address_masked(pop(evm.stack))
793
    memory_input_start_position = pop(evm.stack)
794
    memory_input_size = pop(evm.stack)
795
    memory_output_start_position = pop(evm.stack)
796
    memory_output_size = pop(evm.stack)
797
798
    # GAS (STATE-INDEPENDENT)
799
    # Price what is computable without touching state, and check it is
800
    # affordable before any state access is performed.
801
    extend_memory = calculate_gas_extend_memory(
802
        evm.memory,
803
        [
804
            (memory_input_start_position, memory_input_size),
805
            (memory_output_start_position, memory_output_size),
806
        ],
807
    )
808
809
    is_cold_access = code_address not in evm.accessed_addresses
810
    if is_cold_access:
811
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
812
    else:
813
        access_gas_cost = GasCosts.WARM_ACCESS
814
815
    check_gas(evm, access_gas_cost + extend_memory.cost)
816
817
    # STATE ACCESS (STATE-DEPENDENT GAS)
818
    # Perform the accesses and complete the state-dependent pricing --
819
    # a delegation adds its access cost; the execution gas is charged
820
    # with the child grant.
821
    if is_cold_access:
822
        evm.accessed_addresses.add(code_address)
823
824
    extra_gas = access_gas_cost
825
    (
826
        is_delegated,
827
        code_address,
828
        delegation_access_cost,
829
    ) = calculate_delegation_cost(evm, code_address)
830
831
    if is_delegated:
832
        # check enough gas for delegation access
833
        extra_gas += delegation_access_cost
834
        check_gas(evm, extra_gas + extend_memory.cost)
835
        if code_address not in evm.accessed_addresses:
836
            evm.accessed_addresses.add(code_address)
837
838
    tx_state = evm.tx_env.state
839
    code_hash = get_account(tx_state, code_address).code_hash
840
    code = get_code(tx_state, code_hash)
841
842
    # CHILD GRANT
843
    # Charge the call's cost and withhold the child's execution gas
844
    # share in one step. The whole reservoir rides along (no 63/64
845
    # rule for state gas).
846
    message_call_gas = calculate_message_call_gas(
847
        U256(0),
848
        gas,
849
        evm.gas_meter.gas_left,
850
        extend_memory.cost,
851
        extra_gas,
852
    )
853
    charge_gas(evm, message_call_gas.cost + extend_memory.cost)
854
    call_state_gas_reservoir = drain_state_gas_reservoir(evm.gas_meter)
855
856
    # OPERATION
857
    evm.memory += b"\x00" * extend_memory.expand_by
858
    generic_call(
859
        evm,
860
        GenericCall(
861
            gas=message_call_gas.sub_call,
862
            state_gas_reservoir=call_state_gas_reservoir,
863
            value=evm.value,
864
            caller=evm.caller,
865
            to=evm.current_target,
866
            code_address=code_address,
867
            should_transfer_value=False,
868
            is_staticcall=False,
869
            memory_input_start_position=memory_input_start_position,
870
            memory_input_size=memory_input_size,
871
            memory_output_start_position=memory_output_start_position,
872
            memory_output_size=memory_output_size,
873
            code=code,
874
            disable_precompiles=is_delegated,
875
        ),
876
    )
877
878
    # PROGRAM COUNTER
879
    evm.pc += Uint(1)

staticcall

Message-call into an account.

Parameters

evm : The current EVM frame.

def staticcall(​evm: Evm​) -> None:
883
    <snip>
892
    # STACK
893
    gas = ExecutionGas(Uint(pop(evm.stack)))
894
    to = to_address_masked(pop(evm.stack))
895
    memory_input_start_position = pop(evm.stack)
896
    memory_input_size = pop(evm.stack)
897
    memory_output_start_position = pop(evm.stack)
898
    memory_output_size = pop(evm.stack)
899
900
    # GAS (STATE-INDEPENDENT)
901
    # Price what is computable without touching state, and check it is
902
    # affordable before any state access is performed.
903
    extend_memory = calculate_gas_extend_memory(
904
        evm.memory,
905
        [
906
            (memory_input_start_position, memory_input_size),
907
            (memory_output_start_position, memory_output_size),
908
        ],
909
    )
910
911
    is_cold_access = to not in evm.accessed_addresses
912
    if is_cold_access:
913
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
914
    else:
915
        access_gas_cost = GasCosts.WARM_ACCESS
916
917
    check_gas(evm, access_gas_cost + extend_memory.cost)
918
919
    # STATE ACCESS (STATE-DEPENDENT GAS)
920
    # Perform the accesses and complete the state-dependent pricing --
921
    # a delegation adds its access cost; the execution gas is charged
922
    # with the child grant.
923
    if is_cold_access:
924
        evm.accessed_addresses.add(to)
925
926
    extra_gas = access_gas_cost
927
    (
928
        is_delegated,
929
        code_address,
930
        delegation_access_cost,
931
    ) = calculate_delegation_cost(evm, to)
932
933
    if is_delegated:
934
        # check enough gas for delegation access
935
        extra_gas += delegation_access_cost
936
        check_gas(evm, extra_gas + extend_memory.cost)
937
        if code_address not in evm.accessed_addresses:
938
            evm.accessed_addresses.add(code_address)
939
940
    tx_state = evm.tx_env.state
941
    code_hash = get_account(tx_state, code_address).code_hash
942
    code = get_code(tx_state, code_hash)
943
944
    # CHILD GRANT
945
    # Charge the call's cost and withhold the child's execution gas
946
    # share in one step. The whole reservoir rides along (no 63/64
947
    # rule for state gas).
948
    message_call_gas = calculate_message_call_gas(
949
        U256(0),
950
        gas,
951
        evm.gas_meter.gas_left,
952
        extend_memory.cost,
953
        extra_gas,
954
    )
955
    charge_gas(evm, message_call_gas.cost + extend_memory.cost)
956
    call_state_gas_reservoir = drain_state_gas_reservoir(evm.gas_meter)
957
958
    # OPERATION
959
    evm.memory += b"\x00" * extend_memory.expand_by
960
    generic_call(
961
        evm,
962
        GenericCall(
963
            gas=message_call_gas.sub_call,
964
            state_gas_reservoir=call_state_gas_reservoir,
965
            value=U256(0),
966
            caller=evm.current_target,
967
            to=to,
968
            code_address=code_address,
969
            should_transfer_value=True,
970
            is_staticcall=True,
971
            memory_input_start_position=memory_input_start_position,
972
            memory_input_size=memory_input_size,
973
            memory_output_start_position=memory_output_start_position,
974
            memory_output_size=memory_output_size,
975
            code=code,
976
            disable_precompiles=is_delegated,
977
        ),
978
    )
979
980
    # PROGRAM COUNTER
981
    evm.pc += Uint(1)

revert

Stop execution and revert state changes, without consuming all provided gas and also has the ability to return a reason.

Parameters

evm : The current EVM frame.

def revert(​evm: Evm​) -> None:
985
    <snip>
995
    # STACK
996
    memory_start_index = pop(evm.stack)
997
    size = pop(evm.stack)
998
999
    # GAS
1000
    extend_memory = calculate_gas_extend_memory(
1001
        evm.memory, [(memory_start_index, size)]
1002
    )
1003
1004
    charge_gas(evm, extend_memory.cost)
1005
1006
    # OPERATION
1007
    evm.memory += b"\x00" * extend_memory.expand_by
1008
    output = memory_read_bytes(evm.memory, memory_start_index, size)
1009
    evm.output = Bytes(output)
1010
    raise Revert
1011
1012
    # PROGRAM COUNTER
1013
    # no-op