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
    # This import causes a circular import error
83
    # if it's not moved inside this method
84
    from ...vm.interpreter import STACK_DEPTH_LIMIT, process_create_message
85
86
    tx_state = evm.message.tx_env.state
87
88
    call_data = memory_read_bytes(
89
        evm.memory, memory_start_position, memory_size
90
    )
91
92
    evm.return_data = b""
93
94
    # PREFLIGHT
95
    # Abort without spawning the child: nothing has been charged or
96
    # withheld for it yet.
97
    sender_address = evm.message.current_target
98
    sender = get_account(tx_state, sender_address)
99
100
    if (
101
        sender.balance < endowment
102
        or sender.nonce == Uint(2**64 - 1)
103
        or evm.message.depth + Uint(1) > STACK_DEPTH_LIMIT
104
    ):
105
        push(evm.stack, U256(0))
106
        return
107
108
    # DESTINATION ACCESS
109
    # The account-creation charge is decided by existence alone,
110
    # independently of the collision outcome below.
111
    evm.accessed_addresses.add(contract_address)
112
113
    new_account_charged = not is_account_alive(tx_state, contract_address)
114
    if new_account_charged:
115
        charge_state_gas(evm, StateGasCosts.NEW_ACCOUNT)
116
117
    # CHILD GRANT
118
    # Withhold all but one 64th of the regular gas.
119
    create_message_gas = withhold_create_gas(evm.gas_meter)
120
121
    # On a collision the child's regular grant is consumed and no
122
    # account is created; a storage-only collision target is
123
    # non-existent: charged above, refilled here.
124
    if not account_deployable(tx_state, contract_address):
125
        increment_nonce(tx_state, sender_address)
126
        if new_account_charged:
127
            credit_state_gas_refund(evm.gas_meter, StateGasCosts.NEW_ACCOUNT)
128
        push(evm.stack, U256(0))
129
        return
130
131
    # The whole state gas reservoir rides along (no 63/64 rule for
132
    # state gas) and is restored when the child returns.
133
    create_message_state_gas_reservoir = drain_state_gas_reservoir(
134
        evm.gas_meter
135
    )
136
137
    increment_nonce(tx_state, sender_address)
138
139
    # DISPATCH
140
141
    child_message = Message(
142
        block_env=evm.message.block_env,
143
        tx_env=evm.message.tx_env,
144
        caller=evm.message.current_target,
145
        target=Bytes0(),
146
        gas=create_message_gas,
147
        state_gas_reservoir=create_message_state_gas_reservoir,
148
        value=endowment,
149
        data=b"",
150
        code=call_data,
151
        current_target=contract_address,
152
        depth=evm.message.depth + Uint(1),
153
        code_address=None,
154
        should_transfer_value=True,
155
        is_static=False,
156
        accessed_addresses=evm.accessed_addresses.copy(),
157
        accessed_storage_keys=evm.accessed_storage_keys.copy(),
158
        disable_precompiles=False,
159
        parent_evm=evm,
160
    )
161
    child_evm = process_create_message(child_message)
162
163
    # OUTCOME
164
    # The child settled its own gas; absorb it and resolve the
165
    # account-creation charge by the state's fate: it refills when a
166
    # charged creation failed.
167
    incorporate_child(evm, child_evm)
168
    if child_evm.error:
169
        if new_account_charged:
170
            credit_state_gas_refund(evm.gas_meter, StateGasCosts.NEW_ACCOUNT)
171
        evm.return_data = child_evm.output
172
        push(evm.stack, U256(0))
173
    else:
174
        evm.return_data = b""
175
        push(evm.stack, U256.from_be_bytes(child_evm.message.current_target))

create

Creates a new account with associated code.

Parameters

evm : The current EVM frame.

def create(evm: Evm) -> None:
179
    <snip>
188
    # This import causes a circular import error
189
    # if it's not moved inside this method
190
    from ...vm.interpreter import MAX_INIT_CODE_SIZE
191
192
    if evm.message.is_static:
193
        raise WriteInStaticContext
194
195
    # STACK
196
    endowment = pop(evm.stack)
197
    memory_start_position = pop(evm.stack)
198
    memory_size = pop(evm.stack)
199
200
    # GAS
201
    extend_memory = calculate_gas_extend_memory(
202
        evm.memory, [(memory_start_position, memory_size)]
203
    )
204
    init_code_gas = init_code_cost(Uint(memory_size))
205
    charge_gas(
206
        evm,
207
        GasCosts.CREATE_ACCESS + extend_memory.cost + init_code_gas,
208
    )
209
210
    if memory_size > U256(MAX_INIT_CODE_SIZE):
211
        raise OutOfGasError
212
213
    # OPERATION
214
    evm.memory += b"\x00" * extend_memory.expand_by
215
    contract_address = compute_contract_address(
216
        evm.message.current_target,
217
        get_account(
218
            evm.message.tx_env.state, evm.message.current_target
219
        ).nonce,
220
    )
221
222
    generic_create(
223
        evm,
224
        endowment,
225
        contract_address,
226
        memory_start_position,
227
        memory_size,
228
    )
229
230
    # PROGRAM COUNTER
231
    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:
235
    <snip>
247
    # This import causes a circular import error
248
    # if it's not moved inside this method
249
    from ...vm.interpreter import MAX_INIT_CODE_SIZE
250
251
    if evm.message.is_static:
252
        raise WriteInStaticContext
253
254
    # STACK
255
    endowment = pop(evm.stack)
256
    memory_start_position = pop(evm.stack)
257
    memory_size = pop(evm.stack)
258
    salt = pop(evm.stack).to_be_bytes32()
259
260
    # GAS
261
    extend_memory = calculate_gas_extend_memory(
262
        evm.memory, [(memory_start_position, memory_size)]
263
    )
264
    call_data_words = ceil32(Uint(memory_size)) // Uint(32)
265
    init_code_gas = init_code_cost(Uint(memory_size))
266
    charge_gas(
267
        evm,
268
        GasCosts.CREATE_ACCESS
269
        + GasCosts.OPCODE_KECCAK256_PER_WORD * call_data_words
270
        + extend_memory.cost
271
        + init_code_gas,
272
    )
273
274
    if memory_size > U256(MAX_INIT_CODE_SIZE):
275
        raise OutOfGasError
276
277
    # OPERATION
278
    evm.memory += b"\x00" * extend_memory.expand_by
279
    contract_address = compute_create2_contract_address(
280
        evm.message.current_target,
281
        salt,
282
        memory_read_bytes(evm.memory, memory_start_position, memory_size),
283
    )
284
285
    generic_create(
286
        evm,
287
        endowment,
288
        contract_address,
289
        memory_start_position,
290
        memory_size,
291
    )
292
293
    # PROGRAM COUNTER
294
    evm.pc += Uint(1)

return_

Halts execution returning output data.

Parameters

evm : The current EVM frame.

def return_(evm: Evm) -> None:
298
    <snip>
307
    # STACK
308
    memory_start_position = pop(evm.stack)
309
    memory_size = pop(evm.stack)
310
311
    # GAS
312
    extend_memory = calculate_gas_extend_memory(
313
        evm.memory, [(memory_start_position, memory_size)]
314
    )
315
316
    charge_gas(evm, GasCosts.ZERO + extend_memory.cost)
317
318
    # OPERATION
319
    evm.memory += b"\x00" * extend_memory.expand_by
320
    evm.output = memory_read_bytes(
321
        evm.memory, memory_start_position, memory_size
322
    )
323
324
    evm.running = False
325
326
    # PROGRAM COUNTER
327
    pass

GenericCall

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

330
@final
331
@dataclass
class GenericCall:

gas

337
    gas: Uint

state_gas_reservoir

338
    state_gas_reservoir: Uint

value

339
    value: U256

caller

340
    caller: Address

to

341
    to: Address

code_address

342
    code_address: Address

should_transfer_value

343
    should_transfer_value: bool

is_staticcall

344
    is_staticcall: bool

memory_input_start_position

345
    memory_input_start_position: U256

memory_input_size

346
    memory_input_size: U256

memory_output_start_position

347
    memory_output_start_position: U256

memory_output_size

348
    memory_output_size: U256

code

349
    code: Bytes

disable_precompiles

350
    disable_precompiles: bool

new_account_charged

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

352
    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:
360
    <snip>
368
    from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message
369
370
    evm.return_data = b""
371
372
    # PREFLIGHT
373
    # Abort without spawning the child: both grants return untouched
374
    # and any account-creation charge refills.
375
    if (
376
        evm.message.depth + Uint(1) > STACK_DEPTH_LIMIT
377
        or params.insufficient_balance
378
    ):
379
        restore_child_gas(
380
            evm.gas_meter, params.gas, params.state_gas_reservoir
381
        )
382
        if params.new_account_charged:
383
            credit_state_gas_refund(evm.gas_meter, StateGasCosts.NEW_ACCOUNT)
384
        push(evm.stack, U256(0))
385
        return
386
387
    # DISPATCH
388
    call_data = memory_read_bytes(
389
        evm.memory,
390
        params.memory_input_start_position,
391
        params.memory_input_size,
392
    )
393
394
    child_message = Message(
395
        block_env=evm.message.block_env,
396
        tx_env=evm.message.tx_env,
397
        caller=params.caller,
398
        target=params.to,
399
        gas=params.gas,
400
        state_gas_reservoir=params.state_gas_reservoir,
401
        value=params.value,
402
        data=call_data,
403
        code=params.code,
404
        current_target=params.to,
405
        depth=evm.message.depth + Uint(1),
406
        code_address=params.code_address,
407
        should_transfer_value=params.should_transfer_value,
408
        is_static=params.is_staticcall or evm.message.is_static,
409
        accessed_addresses=evm.accessed_addresses.copy(),
410
        accessed_storage_keys=evm.accessed_storage_keys.copy(),
411
        disable_precompiles=params.disable_precompiles,
412
        parent_evm=evm,
413
    )
414
415
    child_evm = process_message(child_message)
416
417
    # OUTCOME
418
    # The child settled its own gas; absorb it and resolve the
419
    # account-creation charge by the state's fate.
420
    incorporate_child(evm, child_evm)
421
    evm.return_data = child_evm.output
422
    if child_evm.error:
423
        if params.new_account_charged:
424
            credit_state_gas_refund(evm.gas_meter, StateGasCosts.NEW_ACCOUNT)
425
        push(evm.stack, U256(0))
426
    else:
427
        push(evm.stack, CALL_SUCCESS)
428
429
    actual_output_size = min(
430
        params.memory_output_size, U256(len(child_evm.output))
431
    )
432
    memory_write(
433
        evm.memory,
434
        params.memory_output_start_position,
435
        child_evm.output[:actual_output_size],
436
    )

call

Message-call into an account.

Parameters

evm : The current EVM frame.

def call(evm: Evm) -> None:
440
    <snip>
449
    # STACK
450
    gas = Uint(pop(evm.stack))
451
    to = to_address_masked(pop(evm.stack))
452
    value = pop(evm.stack)
453
    memory_input_start_position = pop(evm.stack)
454
    memory_input_size = pop(evm.stack)
455
    memory_output_start_position = pop(evm.stack)
456
    memory_output_size = pop(evm.stack)
457
458
    if evm.message.is_static and value != U256(0):
459
        raise WriteInStaticContext
460
461
    # GAS (STATE-INDEPENDENT)
462
    # Price what is computable without touching state, and check it is
463
    # affordable before any state access is performed.
464
    extend_memory = calculate_gas_extend_memory(
465
        evm.memory,
466
        [
467
            (memory_input_start_position, memory_input_size),
468
            (memory_output_start_position, memory_output_size),
469
        ],
470
    )
471
472
    is_cold_access = to not in evm.accessed_addresses
473
    if is_cold_access:
474
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
475
    else:
476
        access_gas_cost = GasCosts.WARM_ACCESS
477
478
    transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE
479
480
    check_gas(
481
        evm,
482
        access_gas_cost + transfer_gas_cost + extend_memory.cost,
483
    )
484
485
    # STATE ACCESS (STATE-DEPENDENT GAS)
486
    # Perform the accesses and complete the state-dependent pricing --
487
    # a delegation adds its access cost -- then charge the regular
488
    # gas.
489
    tx_state = evm.message.tx_env.state
490
    if is_cold_access:
491
        evm.accessed_addresses.add(to)
492
493
    extra_gas = access_gas_cost + transfer_gas_cost
494
    (
495
        is_delegated,
496
        code_address,
497
        delegation_access_cost,
498
    ) = calculate_delegation_cost(evm, to)
499
500
    if is_delegated:
501
        # check enough gas for delegation access
502
        extra_gas += delegation_access_cost
503
        check_gas(evm, extra_gas + extend_memory.cost)
504
        if code_address not in evm.accessed_addresses:
505
            evm.accessed_addresses.add(code_address)
506
507
    code_hash = get_account(tx_state, code_address).code_hash
508
    code = get_code(tx_state, code_hash)
509
510
    charge_gas(evm, extra_gas + extend_memory.cost)
511
512
    # STATE GAS
513
    # A value transfer that will create the recipient is charged by
514
    # the frame whose opcode causes it; refilled in `generic_call`
515
    # whenever the creation fails or never happens.
516
    has_value = value != 0
517
    new_account_charged = has_value and not is_account_alive(tx_state, to)
518
    if new_account_charged:
519
        charge_state_gas(evm, StateGasCosts.NEW_ACCOUNT)
520
521
    # CHILD GRANT
522
    # Computed after every charge above, so any state-gas spill has
523
    # already thinned `gas_left`. The whole reservoir rides along (no
524
    # 63/64 rule for state gas).
525
    message_call_gas = calculate_message_call_gas(
526
        value,
527
        gas,
528
        Uint(evm.gas_meter.gas_left),
529
        memory_cost=Uint(0),
530
        extra_gas=Uint(0),
531
    )
532
    charge_gas(evm, message_call_gas.cost)
533
    call_state_gas_reservoir = drain_state_gas_reservoir(evm.gas_meter)
534
535
    # OPERATION
536
    evm.memory += b"\x00" * extend_memory.expand_by
537
538
    sender_balance = get_account(tx_state, evm.message.current_target).balance
539
540
    generic_call(
541
        evm,
542
        GenericCall(
543
            gas=message_call_gas.sub_call,
544
            state_gas_reservoir=call_state_gas_reservoir,
545
            value=value,
546
            caller=evm.message.current_target,
547
            to=to,
548
            code_address=code_address,
549
            should_transfer_value=True,
550
            is_staticcall=False,
551
            memory_input_start_position=memory_input_start_position,
552
            memory_input_size=memory_input_size,
553
            memory_output_start_position=memory_output_start_position,
554
            memory_output_size=memory_output_size,
555
            code=code,
556
            disable_precompiles=is_delegated,
557
            new_account_charged=new_account_charged,
558
            insufficient_balance=sender_balance < value,
559
        ),
560
    )
561
562
    # PROGRAM COUNTER
563
    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:
567
    <snip>
576
    # STACK
577
    gas = Uint(pop(evm.stack))
578
    code_address = to_address_masked(pop(evm.stack))
579
    value = pop(evm.stack)
580
    memory_input_start_position = pop(evm.stack)
581
    memory_input_size = pop(evm.stack)
582
    memory_output_start_position = pop(evm.stack)
583
    memory_output_size = pop(evm.stack)
584
585
    # GAS (STATE-INDEPENDENT)
586
    # Price what is computable without touching state, and check it is
587
    # affordable before any state access is performed.
588
    to = evm.message.current_target
589
590
    extend_memory = calculate_gas_extend_memory(
591
        evm.memory,
592
        [
593
            (memory_input_start_position, memory_input_size),
594
            (memory_output_start_position, memory_output_size),
595
        ],
596
    )
597
598
    is_cold_access = code_address not in evm.accessed_addresses
599
    if is_cold_access:
600
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
601
    else:
602
        access_gas_cost = GasCosts.WARM_ACCESS
603
604
    transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE
605
606
    check_gas(
607
        evm,
608
        access_gas_cost + extend_memory.cost + transfer_gas_cost,
609
    )
610
611
    # STATE ACCESS (STATE-DEPENDENT GAS)
612
    # Perform the accesses and complete the state-dependent pricing --
613
    # a delegation adds its access cost; the regular gas is charged
614
    # with the child grant.
615
    tx_state = evm.message.tx_env.state
616
    if is_cold_access:
617
        evm.accessed_addresses.add(code_address)
618
619
    extra_gas = access_gas_cost + transfer_gas_cost
620
    (
621
        is_delegated,
622
        code_address,
623
        delegation_access_cost,
624
    ) = calculate_delegation_cost(evm, code_address)
625
626
    if is_delegated:
627
        # check enough gas for delegation access
628
        extra_gas += delegation_access_cost
629
        check_gas(evm, extra_gas + extend_memory.cost)
630
        if code_address not in evm.accessed_addresses:
631
            evm.accessed_addresses.add(code_address)
632
633
    code_hash = get_account(tx_state, code_address).code_hash
634
    code = get_code(tx_state, code_hash)
635
636
    # CHILD GRANT
637
    # Charge the call's cost and withhold the child's regular gas
638
    # share in one step. The whole reservoir rides along (no 63/64
639
    # rule for state gas).
640
    message_call_gas = calculate_message_call_gas(
641
        value,
642
        gas,
643
        Uint(evm.gas_meter.gas_left),
644
        extend_memory.cost,
645
        extra_gas,
646
    )
647
    charge_gas(evm, message_call_gas.cost + extend_memory.cost)
648
    call_state_gas_reservoir = drain_state_gas_reservoir(evm.gas_meter)
649
650
    # OPERATION
651
    evm.memory += b"\x00" * extend_memory.expand_by
652
653
    sender_balance = get_account(tx_state, evm.message.current_target).balance
654
655
    generic_call(
656
        evm,
657
        GenericCall(
658
            gas=message_call_gas.sub_call,
659
            state_gas_reservoir=call_state_gas_reservoir,
660
            value=value,
661
            caller=evm.message.current_target,
662
            to=to,
663
            code_address=code_address,
664
            should_transfer_value=True,
665
            is_staticcall=False,
666
            memory_input_start_position=memory_input_start_position,
667
            memory_input_size=memory_input_size,
668
            memory_output_start_position=memory_output_start_position,
669
            memory_output_size=memory_output_size,
670
            code=code,
671
            disable_precompiles=is_delegated,
672
            insufficient_balance=sender_balance < value,
673
        ),
674
    )
675
676
    # PROGRAM COUNTER
677
    evm.pc += Uint(1)

selfdestruct

Halt execution and register account for later deletion.

Parameters

evm : The current EVM frame.

def selfdestruct(evm: Evm) -> None:
681
    <snip>
690
    if evm.message.is_static:
691
        raise WriteInStaticContext
692
693
    # STACK
694
    beneficiary = to_address_masked(pop(evm.stack))
695
696
    # GAS (STATE-INDEPENDENT)
697
    # Price what is computable without touching state, and check it is
698
    # affordable before any state access is performed.
699
    gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE
700
701
    is_cold_access = beneficiary not in evm.accessed_addresses
702
    if is_cold_access:
703
        gas_cost += GasCosts.COLD_ACCOUNT_ACCESS
704
705
    check_gas(evm, gas_cost)
706
707
    # STATE ACCESS (STATE-DEPENDENT GAS)
708
    # Perform the access; the pricing completes with the state gas
709
    # below.
710
    tx_state = evm.message.tx_env.state
711
    if is_cold_access:
712
        evm.accessed_addresses.add(beneficiary)
713
714
    # STATE GAS
715
    # A sweep that will create the beneficiary pays the account write
716
    # and the creation, charged by the frame whose opcode causes it;
717
    # it refills only through the frame's own rollback.
718
    state_gas = StateGas(Uint(0))
719
    account_write_gas = Uint(0)
720
    if (
721
        not is_account_alive(tx_state, beneficiary)
722
        and get_account(tx_state, evm.message.current_target).balance != 0
723
    ):
724
        state_gas = StateGasCosts.NEW_ACCOUNT
725
        account_write_gas = GasCosts.ACCOUNT_WRITE
726
727
    # Charge regular gas before state gas so that a regular-gas OOG
728
    # does not consume state gas that would inflate the parent's
729
    # reservoir on frame failure.
730
    charge_gas(evm, gas_cost + account_write_gas)
731
    charge_state_gas(evm, state_gas)
732
733
    # OPERATION
734
    originator = evm.message.current_target
735
    originator_balance = get_account(tx_state, originator).balance
736
737
    # Transfer balance
738
    move_ether(tx_state, originator, beneficiary, originator_balance)
739
740
    # Emit transfer log
741
    if beneficiary != originator:
742
        emit_transfer_log(evm, originator, beneficiary, originator_balance)
743
744
    # Register account for deletion iff created in same transaction
745
    if originator in tx_state.created_accounts:
746
        evm.accounts_to_delete.add(originator)
747
748
    # HALT the execution
749
    evm.running = False
750
751
    # PROGRAM COUNTER
752
    pass

delegatecall

Message-call into an account.

Parameters

evm : The current EVM frame.

def delegatecall(evm: Evm) -> None:
756
    <snip>
765
    # STACK
766
    gas = Uint(pop(evm.stack))
767
    code_address = to_address_masked(pop(evm.stack))
768
    memory_input_start_position = pop(evm.stack)
769
    memory_input_size = pop(evm.stack)
770
    memory_output_start_position = pop(evm.stack)
771
    memory_output_size = pop(evm.stack)
772
773
    # GAS (STATE-INDEPENDENT)
774
    # Price what is computable without touching state, and check it is
775
    # affordable before any state access is performed.
776
    extend_memory = calculate_gas_extend_memory(
777
        evm.memory,
778
        [
779
            (memory_input_start_position, memory_input_size),
780
            (memory_output_start_position, memory_output_size),
781
        ],
782
    )
783
784
    is_cold_access = code_address not in evm.accessed_addresses
785
    if is_cold_access:
786
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
787
    else:
788
        access_gas_cost = GasCosts.WARM_ACCESS
789
790
    check_gas(evm, access_gas_cost + extend_memory.cost)
791
792
    # STATE ACCESS (STATE-DEPENDENT GAS)
793
    # Perform the accesses and complete the state-dependent pricing --
794
    # a delegation adds its access cost; the regular gas is charged
795
    # with the child grant.
796
    if is_cold_access:
797
        evm.accessed_addresses.add(code_address)
798
799
    extra_gas = access_gas_cost
800
    (
801
        is_delegated,
802
        code_address,
803
        delegation_access_cost,
804
    ) = calculate_delegation_cost(evm, code_address)
805
806
    if is_delegated:
807
        # check enough gas for delegation access
808
        extra_gas += delegation_access_cost
809
        check_gas(evm, extra_gas + extend_memory.cost)
810
        if code_address not in evm.accessed_addresses:
811
            evm.accessed_addresses.add(code_address)
812
813
    tx_state = evm.message.tx_env.state
814
    code_hash = get_account(tx_state, code_address).code_hash
815
    code = get_code(tx_state, code_hash)
816
817
    # CHILD GRANT
818
    # Charge the call's cost and withhold the child's regular gas
819
    # share in one step. The whole reservoir rides along (no 63/64
820
    # rule for state gas).
821
    message_call_gas = calculate_message_call_gas(
822
        U256(0),
823
        gas,
824
        Uint(evm.gas_meter.gas_left),
825
        extend_memory.cost,
826
        extra_gas,
827
    )
828
    charge_gas(evm, message_call_gas.cost + extend_memory.cost)
829
    call_state_gas_reservoir = drain_state_gas_reservoir(evm.gas_meter)
830
831
    # OPERATION
832
    evm.memory += b"\x00" * extend_memory.expand_by
833
834
    generic_call(
835
        evm,
836
        GenericCall(
837
            gas=message_call_gas.sub_call,
838
            state_gas_reservoir=call_state_gas_reservoir,
839
            value=evm.message.value,
840
            caller=evm.message.caller,
841
            to=evm.message.current_target,
842
            code_address=code_address,
843
            should_transfer_value=False,
844
            is_staticcall=False,
845
            memory_input_start_position=memory_input_start_position,
846
            memory_input_size=memory_input_size,
847
            memory_output_start_position=memory_output_start_position,
848
            memory_output_size=memory_output_size,
849
            code=code,
850
            disable_precompiles=is_delegated,
851
        ),
852
    )
853
854
    # PROGRAM COUNTER
855
    evm.pc += Uint(1)

staticcall

Message-call into an account.

Parameters

evm : The current EVM frame.

def staticcall(evm: Evm) -> None:
859
    <snip>
868
    # STACK
869
    gas = Uint(pop(evm.stack))
870
    to = to_address_masked(pop(evm.stack))
871
    memory_input_start_position = pop(evm.stack)
872
    memory_input_size = pop(evm.stack)
873
    memory_output_start_position = pop(evm.stack)
874
    memory_output_size = pop(evm.stack)
875
876
    # GAS (STATE-INDEPENDENT)
877
    # Price what is computable without touching state, and check it is
878
    # affordable before any state access is performed.
879
    extend_memory = calculate_gas_extend_memory(
880
        evm.memory,
881
        [
882
            (memory_input_start_position, memory_input_size),
883
            (memory_output_start_position, memory_output_size),
884
        ],
885
    )
886
887
    is_cold_access = to not in evm.accessed_addresses
888
    if is_cold_access:
889
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
890
    else:
891
        access_gas_cost = GasCosts.WARM_ACCESS
892
893
    check_gas(evm, access_gas_cost + extend_memory.cost)
894
895
    # STATE ACCESS (STATE-DEPENDENT GAS)
896
    # Perform the accesses and complete the state-dependent pricing --
897
    # a delegation adds its access cost; the regular gas is charged
898
    # with the child grant.
899
    if is_cold_access:
900
        evm.accessed_addresses.add(to)
901
902
    extra_gas = access_gas_cost
903
    (
904
        is_delegated,
905
        code_address,
906
        delegation_access_cost,
907
    ) = calculate_delegation_cost(evm, to)
908
909
    if is_delegated:
910
        # check enough gas for delegation access
911
        extra_gas += delegation_access_cost
912
        check_gas(evm, extra_gas + extend_memory.cost)
913
        if code_address not in evm.accessed_addresses:
914
            evm.accessed_addresses.add(code_address)
915
916
    tx_state = evm.message.tx_env.state
917
    code_hash = get_account(tx_state, code_address).code_hash
918
    code = get_code(tx_state, code_hash)
919
920
    # CHILD GRANT
921
    # Charge the call's cost and withhold the child's regular gas
922
    # share in one step. The whole reservoir rides along (no 63/64
923
    # rule for state gas).
924
    message_call_gas = calculate_message_call_gas(
925
        U256(0),
926
        gas,
927
        Uint(evm.gas_meter.gas_left),
928
        extend_memory.cost,
929
        extra_gas,
930
    )
931
    charge_gas(evm, message_call_gas.cost + extend_memory.cost)
932
    call_state_gas_reservoir = drain_state_gas_reservoir(evm.gas_meter)
933
934
    # OPERATION
935
    evm.memory += b"\x00" * extend_memory.expand_by
936
937
    generic_call(
938
        evm,
939
        GenericCall(
940
            gas=message_call_gas.sub_call,
941
            state_gas_reservoir=call_state_gas_reservoir,
942
            value=U256(0),
943
            caller=evm.message.current_target,
944
            to=to,
945
            code_address=code_address,
946
            should_transfer_value=True,
947
            is_staticcall=True,
948
            memory_input_start_position=memory_input_start_position,
949
            memory_input_size=memory_input_size,
950
            memory_output_start_position=memory_output_start_position,
951
            memory_output_size=memory_output_size,
952
            code=code,
953
            disable_precompiles=is_delegated,
954
        ),
955
    )
956
957
    # PROGRAM COUNTER
958
    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:
962
    <snip>
972
    # STACK
973
    memory_start_index = pop(evm.stack)
974
    size = pop(evm.stack)
975
976
    # GAS
977
    extend_memory = calculate_gas_extend_memory(
978
        evm.memory, [(memory_start_index, size)]
979
    )
980
981
    charge_gas(evm, extend_memory.cost)
982
983
    # OPERATION
984
    evm.memory += b"\x00" * extend_memory.expand_by
985
    output = memory_read_bytes(evm.memory, memory_start_index, size)
986
    evm.output = Bytes(output)
987
    raise Revert
988
989
    # PROGRAM COUNTER
990
    # no-op