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:
73
    <snip>
82
    # These imports cause a circular import error
83
    # if they're not moved inside this method
84
    from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create
85
    from ...vm.runtime import get_valid_jump_destinations
86
87
    tx_state = evm.tx_env.state
88
89
    init_code = memory_read_bytes(
90
        evm.memory, memory_start_position, memory_size
91
    )
92
93
    evm.return_data = b""
94
95
    # PREFLIGHT
96
    # Abort without spawning the child: nothing has been charged or
97
    # withheld for it yet.
98
    sender_address = evm.current_target
99
    sender = get_account(tx_state, sender_address)
100
101
    if (
102
        sender.balance < endowment
103
        or sender.nonce == Uint(2**64 - 1)
104
        or evm.depth + Uint(1) > STACK_DEPTH_LIMIT
105
    ):
106
        push(evm.stack, U256(0))
107
        return
108
109
    # DESTINATION ACCESS
110
    # The account-creation charge is decided by existence alone,
111
    # independently of the collision outcome below.
112
    evm.accessed_addresses.add(contract_address)
113
114
    new_account_charged = not is_account_alive(tx_state, contract_address)
115
    if new_account_charged:
116
        charge_state_gas(evm, StateGasCosts.NEW_ACCOUNT)
117
118
    # CHILD GRANT
119
    # Withhold all but one 64th of the execution gas.
120
    create_message_gas = withhold_create_gas(evm.gas_meter)
121
122
    # On a collision the child's execution-gas grant is consumed and no
123
    # account is created; a storage-only collision target is
124
    # non-existent: charged above, refilled here.
125
    if not account_deployable(tx_state, contract_address):
126
        increment_nonce(tx_state, sender_address)
127
        if new_account_charged:
128
            credit_state_gas_refund(evm.gas_meter, StateGasCosts.NEW_ACCOUNT)
129
        push(evm.stack, U256(0))
130
        return
131
132
    # The whole state gas reservoir rides along (no 63/64 rule for
133
    # state gas) and is restored when the child returns.
134
    create_message_state_gas_reservoir = drain_state_gas_reservoir(
135
        evm.gas_meter
136
    )
137
138
    increment_nonce(tx_state, sender_address)
139
140
    # DISPATCH
141
142
    child_evm = Evm(
143
        # Context
144
        block_env=evm.block_env,
145
        tx_env=evm.tx_env,
146
        parent_evm=evm,
147
        depth=evm.depth + Uint(1),
148
        # Call Parameters
149
        caller=evm.current_target,
150
        current_target=contract_address,
151
        value=endowment,
152
        call_data=b"",
153
        should_transfer_value=True,
154
        is_static=False,
155
        disable_precompiles=False,
156
        # Code
157
        code_address=None,
158
        code=init_code,
159
        valid_jump_destinations=get_valid_jump_destinations(init_code),
160
        # Machine State
161
        gas_meter=GasMeter(
162
            gas_left=create_message_gas,
163
            state_gas_left=create_message_state_gas_reservoir,
164
            state_gas_baseline=create_message_state_gas_reservoir,
165
        ),
166
        pc=Uint(0),
167
        stack=[],
168
        memory=bytearray(),
169
        return_data=b"",
170
        # Accrued Effects
171
        logs=(),
172
        accounts_to_delete=set(),
173
        accessed_addresses=evm.accessed_addresses.copy(),
174
        accessed_storage_keys=evm.accessed_storage_keys.copy(),
175
        # Outcome
176
        running=True,
177
        output=b"",
178
        error=None,
179
    )
180
    child_evm = process_create(child_evm)
181
182
    # OUTCOME
183
    # The child settled its own gas; absorb it and resolve the
184
    # account-creation charge by the state's fate: it refills when a
185
    # charged creation failed.
186
    incorporate_child(evm, child_evm)
187
    if child_evm.error:
188
        if new_account_charged:
189
            credit_state_gas_refund(evm.gas_meter, StateGasCosts.NEW_ACCOUNT)
190
        evm.return_data = child_evm.output
191
        push(evm.stack, U256(0))
192
    else:
193
        evm.return_data = b""
194
        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:
198
    <snip>
207
    # This import causes a circular import error
208
    # if it's not moved inside this method
209
    from ...vm.interpreter import MAX_INIT_CODE_SIZE
210
211
    if evm.is_static:
212
        raise WriteInStaticContext
213
214
    # STACK
215
    endowment = pop(evm.stack)
216
    memory_start_position = pop(evm.stack)
217
    memory_size = pop(evm.stack)
218
219
    # GAS
220
    extend_memory = calculate_gas_extend_memory(
221
        evm.memory, [(memory_start_position, memory_size)]
222
    )
223
    init_code_gas = init_code_cost(Uint(memory_size))
224
    charge_gas(
225
        evm,
226
        GasCosts.CREATE_ACCESS + extend_memory.cost + init_code_gas,
227
    )
228
229
    if memory_size > U256(MAX_INIT_CODE_SIZE):
230
        raise OutOfGasError
231
232
    # OPERATION
233
    evm.memory += b"\x00" * extend_memory.expand_by
234
    contract_address = compute_contract_address(
235
        evm.current_target,
236
        get_account(evm.tx_env.state, evm.current_target).nonce,
237
    )
238
239
    generic_create(
240
        evm,
241
        endowment,
242
        contract_address,
243
        memory_start_position,
244
        memory_size,
245
    )
246
247
    # PROGRAM COUNTER
248
    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:
252
    <snip>
264
    # This import causes a circular import error
265
    # if it's not moved inside this method
266
    from ...vm.interpreter import MAX_INIT_CODE_SIZE
267
268
    if evm.is_static:
269
        raise WriteInStaticContext
270
271
    # STACK
272
    endowment = pop(evm.stack)
273
    memory_start_position = pop(evm.stack)
274
    memory_size = pop(evm.stack)
275
    salt = pop(evm.stack).to_be_bytes32()
276
277
    # GAS
278
    extend_memory = calculate_gas_extend_memory(
279
        evm.memory, [(memory_start_position, memory_size)]
280
    )
281
    call_data_words = ceil32(Uint(memory_size)) // Uint(32)
282
    init_code_gas = init_code_cost(Uint(memory_size))
283
    charge_gas(
284
        evm,
285
        ExecutionGas(
286
            GasCosts.CREATE_ACCESS
287
            + GasCosts.OPCODE_KECCAK256_PER_WORD * call_data_words
288
            + extend_memory.cost
289
            + init_code_gas
290
        ),
291
    )
292
293
    if memory_size > U256(MAX_INIT_CODE_SIZE):
294
        raise OutOfGasError
295
296
    # OPERATION
297
    evm.memory += b"\x00" * extend_memory.expand_by
298
    contract_address = compute_create2_contract_address(
299
        evm.current_target,
300
        salt,
301
        memory_read_bytes(evm.memory, memory_start_position, memory_size),
302
    )
303
304
    generic_create(
305
        evm,
306
        endowment,
307
        contract_address,
308
        memory_start_position,
309
        memory_size,
310
    )
311
312
    # PROGRAM COUNTER
313
    evm.pc += Uint(1)

return_

Halts execution returning output data.

Parameters

evm : The current EVM frame.

def return_(evm: Evm) -> None:
317
    <snip>
326
    # STACK
327
    memory_start_position = pop(evm.stack)
328
    memory_size = pop(evm.stack)
329
330
    # GAS
331
    extend_memory = calculate_gas_extend_memory(
332
        evm.memory, [(memory_start_position, memory_size)]
333
    )
334
335
    charge_gas(evm, GasCosts.ZERO + extend_memory.cost)
336
337
    # OPERATION
338
    evm.memory += b"\x00" * extend_memory.expand_by
339
    evm.output = memory_read_bytes(
340
        evm.memory, memory_start_position, memory_size
341
    )
342
343
    evm.running = False
344
345
    # PROGRAM COUNTER
346
    pass

GenericCall

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

349
@final
350
@dataclass
class GenericCall:

gas

356
    gas: ExecutionGas

state_gas_reservoir

357
    state_gas_reservoir: StateGas

value

358
    value: U256

caller

359
    caller: Address

to

360
    to: Address

code_address

361
    code_address: Address

should_transfer_value

362
    should_transfer_value: bool

is_staticcall

363
    is_staticcall: bool

memory_input_start_position

364
    memory_input_start_position: U256

memory_input_size

365
    memory_input_size: U256

memory_output_start_position

366
    memory_output_start_position: U256

memory_output_size

367
    memory_output_size: U256

code

368
    code: Bytes

disable_precompiles

369
    disable_precompiles: bool

new_account_charged

370
    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.

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

call

Message-call into an account.

Parameters

evm : The current EVM frame.

def call(evm: Evm) -> None:
475
    <snip>
484
    # STACK
485
    gas = ExecutionGas(Uint(pop(evm.stack)))
486
    to = to_address_masked(pop(evm.stack))
487
    value = pop(evm.stack)
488
    memory_input_start_position = pop(evm.stack)
489
    memory_input_size = pop(evm.stack)
490
    memory_output_start_position = pop(evm.stack)
491
    memory_output_size = pop(evm.stack)
492
493
    if evm.is_static and value != U256(0):
494
        raise WriteInStaticContext
495
496
    # GAS (STATE-INDEPENDENT)
497
    # Price what is computable without touching state, and check it is
498
    # affordable before any state access is performed.
499
    extend_memory = calculate_gas_extend_memory(
500
        evm.memory,
501
        [
502
            (memory_input_start_position, memory_input_size),
503
            (memory_output_start_position, memory_output_size),
504
        ],
505
    )
506
507
    is_cold_access = to not in evm.accessed_addresses
508
    if is_cold_access:
509
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
510
    else:
511
        access_gas_cost = GasCosts.WARM_ACCESS
512
513
    transfer_gas_cost = GasCosts.ZERO if value == 0 else GasCosts.CALL_VALUE
514
515
    check_gas(
516
        evm,
517
        access_gas_cost + transfer_gas_cost + extend_memory.cost,
518
    )
519
520
    # STATE ACCESS (STATE-DEPENDENT GAS)
521
    # Perform the accesses and complete the state-dependent pricing --
522
    # a delegation adds its access cost -- then charge the execution
523
    # gas.
524
    tx_state = evm.tx_env.state
525
    if is_cold_access:
526
        evm.accessed_addresses.add(to)
527
528
    extra_gas = access_gas_cost + transfer_gas_cost
529
    (
530
        is_delegated,
531
        code_address,
532
        delegation_access_cost,
533
    ) = calculate_delegation_cost(evm, to)
534
535
    if is_delegated:
536
        # check enough gas for delegation access
537
        extra_gas += delegation_access_cost
538
        check_gas(evm, extra_gas + extend_memory.cost)
539
        if code_address not in evm.accessed_addresses:
540
            evm.accessed_addresses.add(code_address)
541
542
    code_hash = get_account(tx_state, code_address).code_hash
543
    code = get_code(tx_state, code_hash)
544
545
    charge_gas(evm, extra_gas + extend_memory.cost)
546
547
    # STATE GAS
548
    # A value transfer that will create the recipient is charged by
549
    # the frame whose opcode causes it; refilled in `generic_call`
550
    # whenever the creation fails or never happens.
551
    has_value = value != 0
552
    new_account_charged = has_value and not is_account_alive(tx_state, to)
553
    if new_account_charged:
554
        charge_state_gas(evm, StateGasCosts.NEW_ACCOUNT)
555
556
    # CHILD GRANT
557
    # Computed after every charge above, so any state-gas spill has
558
    # already thinned `gas_left`. The whole reservoir rides along (no
559
    # 63/64 rule for state gas).
560
    message_call_gas = calculate_message_call_gas(
561
        value,
562
        gas,
563
        evm.gas_meter.gas_left,
564
        memory_cost=GasCosts.ZERO,
565
        extra_gas=GasCosts.ZERO,
566
    )
567
    charge_gas(evm, message_call_gas.cost)
568
    call_state_gas_reservoir = drain_state_gas_reservoir(evm.gas_meter)
569
570
    # OPERATION
571
    evm.memory += b"\x00" * extend_memory.expand_by
572
573
    sender_balance = get_account(tx_state, evm.current_target).balance
574
575
    generic_call(
576
        evm,
577
        GenericCall(
578
            gas=message_call_gas.sub_call,
579
            state_gas_reservoir=call_state_gas_reservoir,
580
            value=value,
581
            caller=evm.current_target,
582
            to=to,
583
            code_address=code_address,
584
            should_transfer_value=True,
585
            is_staticcall=False,
586
            memory_input_start_position=memory_input_start_position,
587
            memory_input_size=memory_input_size,
588
            memory_output_start_position=memory_output_start_position,
589
            memory_output_size=memory_output_size,
590
            code=code,
591
            disable_precompiles=is_delegated,
592
            new_account_charged=new_account_charged,
593
            insufficient_balance=sender_balance < value,
594
        ),
595
    )
596
597
    # PROGRAM COUNTER
598
    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:
602
    <snip>
611
    # STACK
612
    gas = ExecutionGas(Uint(pop(evm.stack)))
613
    code_address = to_address_masked(pop(evm.stack))
614
    value = pop(evm.stack)
615
    memory_input_start_position = pop(evm.stack)
616
    memory_input_size = pop(evm.stack)
617
    memory_output_start_position = pop(evm.stack)
618
    memory_output_size = pop(evm.stack)
619
620
    # GAS (STATE-INDEPENDENT)
621
    # Price what is computable without touching state, and check it is
622
    # affordable before any state access is performed.
623
    to = evm.current_target
624
625
    extend_memory = calculate_gas_extend_memory(
626
        evm.memory,
627
        [
628
            (memory_input_start_position, memory_input_size),
629
            (memory_output_start_position, memory_output_size),
630
        ],
631
    )
632
633
    is_cold_access = code_address not in evm.accessed_addresses
634
    if is_cold_access:
635
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
636
    else:
637
        access_gas_cost = GasCosts.WARM_ACCESS
638
639
    transfer_gas_cost = GasCosts.ZERO if value == 0 else GasCosts.CALL_VALUE
640
641
    check_gas(
642
        evm,
643
        access_gas_cost + extend_memory.cost + transfer_gas_cost,
644
    )
645
646
    # STATE ACCESS (STATE-DEPENDENT GAS)
647
    # Perform the accesses and complete the state-dependent pricing --
648
    # a delegation adds its access cost; the execution gas is charged
649
    # with the child grant.
650
    tx_state = evm.tx_env.state
651
    if is_cold_access:
652
        evm.accessed_addresses.add(code_address)
653
654
    extra_gas = access_gas_cost + transfer_gas_cost
655
    (
656
        is_delegated,
657
        code_address,
658
        delegation_access_cost,
659
    ) = calculate_delegation_cost(evm, code_address)
660
661
    if is_delegated:
662
        # check enough gas for delegation access
663
        extra_gas += delegation_access_cost
664
        check_gas(evm, extra_gas + extend_memory.cost)
665
        if code_address not in evm.accessed_addresses:
666
            evm.accessed_addresses.add(code_address)
667
668
    code_hash = get_account(tx_state, code_address).code_hash
669
    code = get_code(tx_state, code_hash)
670
671
    # CHILD GRANT
672
    # Charge the call's cost and withhold the child's execution gas
673
    # share in one step. The whole reservoir rides along (no 63/64
674
    # rule for state gas).
675
    message_call_gas = calculate_message_call_gas(
676
        value,
677
        gas,
678
        evm.gas_meter.gas_left,
679
        extend_memory.cost,
680
        extra_gas,
681
    )
682
    charge_gas(evm, message_call_gas.cost + extend_memory.cost)
683
    call_state_gas_reservoir = drain_state_gas_reservoir(evm.gas_meter)
684
685
    # OPERATION
686
    evm.memory += b"\x00" * extend_memory.expand_by
687
688
    sender_balance = get_account(tx_state, evm.current_target).balance
689
690
    generic_call(
691
        evm,
692
        GenericCall(
693
            gas=message_call_gas.sub_call,
694
            state_gas_reservoir=call_state_gas_reservoir,
695
            value=value,
696
            caller=evm.current_target,
697
            to=to,
698
            code_address=code_address,
699
            should_transfer_value=True,
700
            is_staticcall=False,
701
            memory_input_start_position=memory_input_start_position,
702
            memory_input_size=memory_input_size,
703
            memory_output_start_position=memory_output_start_position,
704
            memory_output_size=memory_output_size,
705
            code=code,
706
            disable_precompiles=is_delegated,
707
            insufficient_balance=sender_balance < value,
708
        ),
709
    )
710
711
    # PROGRAM COUNTER
712
    evm.pc += Uint(1)

selfdestruct

Halt execution and register account for later deletion.

Parameters

evm : The current EVM frame.

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

delegatecall

Message-call into an account.

Parameters

evm : The current EVM frame.

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

staticcall

Message-call into an account.

Parameters

evm : The current EVM frame.

def staticcall(evm: Evm) -> None:
894
    <snip>
903
    # STACK
904
    gas = ExecutionGas(Uint(pop(evm.stack)))
905
    to = to_address_masked(pop(evm.stack))
906
    memory_input_start_position = pop(evm.stack)
907
    memory_input_size = pop(evm.stack)
908
    memory_output_start_position = pop(evm.stack)
909
    memory_output_size = pop(evm.stack)
910
911
    # GAS (STATE-INDEPENDENT)
912
    # Price what is computable without touching state, and check it is
913
    # affordable before any state access is performed.
914
    extend_memory = calculate_gas_extend_memory(
915
        evm.memory,
916
        [
917
            (memory_input_start_position, memory_input_size),
918
            (memory_output_start_position, memory_output_size),
919
        ],
920
    )
921
922
    is_cold_access = to not in evm.accessed_addresses
923
    if is_cold_access:
924
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
925
    else:
926
        access_gas_cost = GasCosts.WARM_ACCESS
927
928
    check_gas(evm, access_gas_cost + extend_memory.cost)
929
930
    # STATE ACCESS (STATE-DEPENDENT GAS)
931
    # Perform the accesses and complete the state-dependent pricing --
932
    # a delegation adds its access cost; the execution gas is charged
933
    # with the child grant.
934
    if is_cold_access:
935
        evm.accessed_addresses.add(to)
936
937
    extra_gas = access_gas_cost
938
    (
939
        is_delegated,
940
        code_address,
941
        delegation_access_cost,
942
    ) = calculate_delegation_cost(evm, to)
943
944
    if is_delegated:
945
        # check enough gas for delegation access
946
        extra_gas += delegation_access_cost
947
        check_gas(evm, extra_gas + extend_memory.cost)
948
        if code_address not in evm.accessed_addresses:
949
            evm.accessed_addresses.add(code_address)
950
951
    tx_state = evm.tx_env.state
952
    code_hash = get_account(tx_state, code_address).code_hash
953
    code = get_code(tx_state, code_hash)
954
955
    # CHILD GRANT
956
    # Charge the call's cost and withhold the child's execution gas
957
    # share in one step. The whole reservoir rides along (no 63/64
958
    # rule for state gas).
959
    message_call_gas = calculate_message_call_gas(
960
        U256(0),
961
        gas,
962
        evm.gas_meter.gas_left,
963
        extend_memory.cost,
964
        extra_gas,
965
    )
966
    charge_gas(evm, message_call_gas.cost + extend_memory.cost)
967
    call_state_gas_reservoir = drain_state_gas_reservoir(evm.gas_meter)
968
969
    # OPERATION
970
    evm.memory += b"\x00" * extend_memory.expand_by
971
972
    generic_call(
973
        evm,
974
        GenericCall(
975
            gas=message_call_gas.sub_call,
976
            state_gas_reservoir=call_state_gas_reservoir,
977
            value=U256(0),
978
            caller=evm.current_target,
979
            to=to,
980
            code_address=code_address,
981
            should_transfer_value=True,
982
            is_staticcall=True,
983
            memory_input_start_position=memory_input_start_position,
984
            memory_input_size=memory_input_size,
985
            memory_output_start_position=memory_output_start_position,
986
            memory_output_size=memory_output_size,
987
            code=code,
988
            disable_precompiles=is_delegated,
989
        ),
990
    )
991
992
    # PROGRAM COUNTER
993
    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:
997
    <snip>
1007
    # STACK
1008
    memory_start_index = pop(evm.stack)
1009
    size = pop(evm.stack)
1010
1011
    # GAS
1012
    extend_memory = calculate_gas_extend_memory(
1013
        evm.memory, [(memory_start_index, size)]
1014
    )
1015
1016
    charge_gas(evm, extend_memory.cost)
1017
1018
    # OPERATION
1019
    evm.memory += b"\x00" * extend_memory.expand_by
1020
    output = memory_read_bytes(evm.memory, memory_start_index, size)
1021
    evm.output = Bytes(output)
1022
    raise Revert
1023
1024
    # PROGRAM COUNTER
1025
    # no-op