ethereum.forks.bpo5.vm.instructions.systemethereum.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

Core logic used by the CREATE* family of opcodes.

def generic_create(evm: Evm, ​​endowment: U256, ​​contract_address: Address, ​​memory_start_position: U256, ​​memory_size: U256) -> None:
74
    <snip>
77
    # This import causes a circular import error
78
    # if it's not moved inside this method
79
    from ...vm.interpreter import (
80
        MAX_INIT_CODE_SIZE,
81
        STACK_DEPTH_LIMIT,
82
        process_create_message,
83
    )
84
85
    # Check max init code size early before memory read
86
    if memory_size > U256(MAX_INIT_CODE_SIZE):
87
        raise OutOfGasError
88
89
    # Charge state gas for account creation (pay-before-execute).
90
    # Refunded to the reservoir on any failure path below.
91
    charge_state_gas(evm, StateGasCosts.NEW_ACCOUNT)
92
93
    tx_state = evm.message.tx_env.state
94
95
    call_data = memory_read_bytes(
96
        evm.memory, memory_start_position, memory_size
97
    )
78
    if len(call_data) > MAX_INIT_CODE_SIZE:
79
        raise OutOfGasError
98
99
    create_message_gas = max_message_call_gas(Uint(evm.gas_left))
100
    evm.gas_left -= create_message_gas
83
    if evm.message.is_static:
84
        raise WriteInStaticContext
101
102
    # Move full reservoir to child (no 63/64 rule for state gas). Parent's
103
    # `state_gas_left` is zeroed and restored when the child returns.
104
    create_message_state_gas_reservoir = evm.state_gas_left
105
    evm.state_gas_left = Uint(0)
106
107
    evm.return_data = b""
108
109
    sender_address = evm.message.current_target
88
    sender = get_account(evm.message.tx_env.state, sender_address)
110
    sender = get_account(tx_state, sender_address)
111
112
    if (
113
        sender.balance < endowment
114
        or sender.nonce == Uint(2**64 - 1)
115
        or evm.message.depth + Uint(1) > STACK_DEPTH_LIMIT
116
    ):
117
        evm.gas_left += create_message_gas
118
        evm.state_gas_left += create_message_state_gas_reservoir
119
        credit_state_gas_refund(evm, StateGasCosts.NEW_ACCOUNT)
120
        push(evm.stack, U256(0))
121
        return
122
123
    evm.accessed_addresses.add(contract_address)
124
125
    if account_has_code_or_nonce(
102
        evm.message.tx_env.state, contract_address
103
    ) or account_has_storage(evm.message.tx_env.state, contract_address):
104
        increment_nonce(evm.message.tx_env.state, evm.message.current_target)
126
        tx_state, contract_address
127
    ) or account_has_storage(tx_state, contract_address):
128
        increment_nonce(tx_state, evm.message.current_target)
129
        evm.regular_gas_used += create_message_gas
130
        evm.state_gas_left += create_message_state_gas_reservoir
131
        # Address collision — no account created, refund state gas.
132
        credit_state_gas_refund(evm, StateGasCosts.NEW_ACCOUNT)
133
        push(evm.stack, U256(0))
134
        return
135
108
    increment_nonce(evm.message.tx_env.state, evm.message.current_target)
136
    increment_nonce(tx_state, evm.message.current_target)
137
138
    child_message = Message(
139
        block_env=evm.message.block_env,
140
        tx_env=evm.message.tx_env,
141
        caller=evm.message.current_target,
142
        target=Bytes0(),
143
        gas=create_message_gas,
144
        state_gas_reservoir=create_message_state_gas_reservoir,
145
        value=endowment,
146
        data=b"",
147
        code=call_data,
148
        current_target=contract_address,
149
        depth=evm.message.depth + Uint(1),
150
        code_address=None,
151
        should_transfer_value=True,
152
        is_static=False,
153
        accessed_addresses=evm.accessed_addresses.copy(),
154
        accessed_storage_keys=evm.accessed_storage_keys.copy(),
155
        disable_precompiles=False,
156
        parent_evm=evm,
157
    )
158
    child_evm = process_create_message(child_message)
159
160
    if child_evm.error:
161
        incorporate_child_on_error(evm, child_evm)
162
        # No account created, refund parent's CREATE state gas.
163
        credit_state_gas_refund(evm, StateGasCosts.NEW_ACCOUNT)
164
        evm.return_data = child_evm.output
165
        push(evm.stack, U256(0))
166
    else:
167
        incorporate_child_on_success(evm, child_evm)
168
        evm.return_data = b""
169
        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:
173
    <snip>
182
    if evm.message.is_static:
183
        raise WriteInStaticContext
184
185
    # STACK
186
    endowment = pop(evm.stack)
187
    memory_start_position = pop(evm.stack)
188
    memory_size = pop(evm.stack)
189
190
    # GAS
191
    extend_memory = calculate_gas_extend_memory(
192
        evm.memory, [(memory_start_position, memory_size)]
193
    )
194
    init_code_gas = init_code_cost(Uint(memory_size))
161
195
    charge_gas(
196
        evm,
164
        GasCosts.OPCODE_CREATE_BASE + extend_memory.cost + init_code_gas,
197
        GasCosts.REGULAR_GAS_CREATE + extend_memory.cost + init_code_gas,
198
    )
199
200
    # OPERATION
201
    evm.memory += b"\x00" * extend_memory.expand_by
202
    contract_address = compute_contract_address(
203
        evm.message.current_target,
204
        get_account(
205
            evm.message.tx_env.state, evm.message.current_target
206
        ).nonce,
207
    )
208
209
    generic_create(
210
        evm,
211
        endowment,
212
        contract_address,
213
        memory_start_position,
214
        memory_size,
215
    )
216
217
    # PROGRAM COUNTER
218
    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:
222
    <snip>
234
    if evm.message.is_static:
235
        raise WriteInStaticContext
236
237
    # STACK
238
    endowment = pop(evm.stack)
239
    memory_start_position = pop(evm.stack)
240
    memory_size = pop(evm.stack)
241
    salt = pop(evm.stack).to_be_bytes32()
242
243
    # GAS
244
    extend_memory = calculate_gas_extend_memory(
245
        evm.memory, [(memory_start_position, memory_size)]
246
    )
247
    call_data_words = ceil32(Uint(memory_size)) // Uint(32)
248
    init_code_gas = init_code_cost(Uint(memory_size))
249
    charge_gas(
250
        evm,
215
        GasCosts.OPCODE_CREATE_BASE
251
        GasCosts.REGULAR_GAS_CREATE
252
        + GasCosts.OPCODE_KECCAK256_PER_WORD * call_data_words
253
        + extend_memory.cost
254
        + init_code_gas,
255
    )
256
257
    # OPERATION
258
    evm.memory += b"\x00" * extend_memory.expand_by
259
    contract_address = compute_create2_contract_address(
260
        evm.message.current_target,
261
        salt,
262
        memory_read_bytes(evm.memory, memory_start_position, memory_size),
263
    )
264
265
    generic_create(
266
        evm,
267
        endowment,
268
        contract_address,
269
        memory_start_position,
270
        memory_size,
271
    )
272
273
    # PROGRAM COUNTER
274
    evm.pc += Uint(1)

return_

Halts execution returning output data.

Parameters

evm : The current EVM frame.

def return_(evm: Evm) -> None:
278
    <snip>
287
    # STACK
288
    memory_start_position = pop(evm.stack)
289
    memory_size = pop(evm.stack)
290
291
    # GAS
292
    extend_memory = calculate_gas_extend_memory(
293
        evm.memory, [(memory_start_position, memory_size)]
294
    )
295
296
    charge_gas(evm, GasCosts.ZERO + extend_memory.cost)
297
298
    # OPERATION
299
    evm.memory += b"\x00" * extend_memory.expand_by
300
    evm.output = memory_read_bytes(
301
        evm.memory, memory_start_position, memory_size
302
    )
303
304
    evm.running = False
305
306
    # PROGRAM COUNTER
307
    pass

GenericCall

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

310
@final
311
@dataclass
class GenericCall:

gas

317
    gas: Uint

state_gas_reservoir

318
    state_gas_reservoir: Uint

value

319
    value: U256

caller

320
    caller: Address

to

321
    to: Address

code_address

322
    code_address: Address

should_transfer_value

323
    should_transfer_value: bool

is_staticcall

324
    is_staticcall: bool

memory_input_start_position

325
    memory_input_start_position: U256

memory_input_size

326
    memory_input_size: U256

memory_output_start_position

327
    memory_output_start_position: U256

memory_output_size

328
    memory_output_size: U256

code

329
    code: Bytes

disable_precompiles

330
    disable_precompiles: bool

generic_call

Perform the core logic of the CALL* family of opcodes.

def generic_call(evm: Evm, ​​params: GenericCall) -> None:
334
    <snip>
337
    from ...vm.interpreter import STACK_DEPTH_LIMIT, process_message
338
339
    evm.return_data = b""
340
341
    if evm.message.depth + Uint(1) > STACK_DEPTH_LIMIT:
342
        evm.gas_left += params.gas
343
        evm.state_gas_left += params.state_gas_reservoir
344
        push(evm.stack, U256(0))
345
        return
346
347
    call_data = memory_read_bytes(
348
        evm.memory,
349
        params.memory_input_start_position,
350
        params.memory_input_size,
351
    )
352
353
    child_message = Message(
354
        block_env=evm.message.block_env,
355
        tx_env=evm.message.tx_env,
356
        caller=params.caller,
357
        target=params.to,
358
        gas=params.gas,
359
        state_gas_reservoir=params.state_gas_reservoir,
360
        value=params.value,
361
        data=call_data,
362
        code=params.code,
363
        current_target=params.to,
364
        depth=evm.message.depth + Uint(1),
365
        code_address=params.code_address,
366
        should_transfer_value=params.should_transfer_value,
367
        is_static=params.is_staticcall or evm.message.is_static,
368
        accessed_addresses=evm.accessed_addresses.copy(),
369
        accessed_storage_keys=evm.accessed_storage_keys.copy(),
370
        disable_precompiles=params.disable_precompiles,
371
        parent_evm=evm,
372
    )
373
374
    child_evm = process_message(child_message)
375
376
    if child_evm.error:
377
        incorporate_child_on_error(evm, child_evm)
378
        evm.return_data = child_evm.output
379
        push(evm.stack, U256(0))
380
    else:
381
        incorporate_child_on_success(evm, child_evm)
382
        evm.return_data = child_evm.output
343
        push(evm.stack, U256(1))
383
        push(evm.stack, CALL_SUCCESS)
384
385
    actual_output_size = min(
386
        params.memory_output_size, U256(len(child_evm.output))
387
    )
388
    memory_write(
389
        evm.memory,
390
        params.memory_output_start_position,
391
        child_evm.output[:actual_output_size],
392
    )

call

Message-call into an account.

Parameters

evm : The current EVM frame.

def call(evm: Evm) -> None:
396
    <snip>
405
    # STACK
406
    gas = Uint(pop(evm.stack))
407
    to = to_address_masked(pop(evm.stack))
408
    value = pop(evm.stack)
409
    memory_input_start_position = pop(evm.stack)
410
    memory_input_size = pop(evm.stack)
411
    memory_output_start_position = pop(evm.stack)
412
    memory_output_size = pop(evm.stack)
413
414
    if evm.message.is_static and value != U256(0):
415
        raise WriteInStaticContext
416
417
    # GAS
418
    extend_memory = calculate_gas_extend_memory(
419
        evm.memory,
420
        [
421
            (memory_input_start_position, memory_input_size),
422
            (memory_output_start_position, memory_output_size),
423
        ],
424
    )
425
383
    if to in evm.accessed_addresses:
384
        access_gas_cost = GasCosts.WARM_ACCESS
426
    is_cold_access = to not in evm.accessed_addresses
427
    if is_cold_access:
428
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
429
    else:
386
        evm.accessed_addresses.add(to)
387
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
430
        access_gas_cost = GasCosts.WARM_ACCESS
431
389
    code_address = to
432
    transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE
433
434
    # check static gas before state access
435
    check_gas(
436
        evm,
437
        access_gas_cost + transfer_gas_cost + extend_memory.cost,
438
    )
439
440
    # STATE ACCESS
441
    tx_state = evm.message.tx_env.state
442
    if is_cold_access:
443
        evm.accessed_addresses.add(to)
444
445
    extra_gas = access_gas_cost + transfer_gas_cost
446
    (
391
        disable_precompiles,
447
        is_delegated,
448
        code_address,
393
        code,
394
        delegated_access_gas_cost,
395
    ) = access_delegation(evm, code_address)
396
    access_gas_cost += delegated_access_gas_cost
449
        delegation_access_cost,
450
    ) = calculate_delegation_cost(evm, to)
451
398
    create_gas_cost = GasCosts.NEW_ACCOUNT
399
    if value == 0 or is_account_alive(evm.message.tx_env.state, to):
400
        create_gas_cost = Uint(0)
401
    transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE
452
    if is_delegated:
453
        # check enough gas for delegation access
454
        extra_gas += delegation_access_cost
455
        check_gas(evm, extra_gas + extend_memory.cost)
456
        if code_address not in evm.accessed_addresses:
457
            evm.accessed_addresses.add(code_address)
458
459
    code_hash = get_account(tx_state, code_address).code_hash
460
    code = get_code(tx_state, code_hash)
461
462
    charge_gas(evm, extra_gas + extend_memory.cost)
463
    if value != 0 and not is_account_alive(tx_state, to):
464
        charge_state_gas(evm, StateGasCosts.NEW_ACCOUNT)
465
466
    message_call_gas = calculate_message_call_gas(
467
        value,
468
        gas,
469
        Uint(evm.gas_left),
406
        memory_cost=extend_memory.cost,
407
        extra_gas=access_gas_cost + create_gas_cost + transfer_gas_cost,
470
        memory_cost=Uint(0),
471
        extra_gas=Uint(0),
472
    )
409
    charge_gas(evm, message_call_gas.cost + extend_memory.cost)
410
    if evm.message.is_static and value != U256(0):
411
        raise WriteInStaticContext
412
    evm.memory += b"\x00" * extend_memory.expand_by
413
    sender_balance = get_account(
414
        evm.message.tx_env.state, evm.message.current_target
415
    ).balance
473
    charge_gas(evm, message_call_gas.cost)
474
    evm.regular_gas_used -= message_call_gas.sub_call
475
476
    # OPERATION
477
    evm.memory += b"\x00" * extend_memory.expand_by
478
479
    # Pass full reservoir to child (no 63/64 rule for state gas)
480
    call_state_gas_reservoir = evm.state_gas_left
481
    evm.state_gas_left = Uint(0)
482
483
    sender_balance = get_account(tx_state, evm.message.current_target).balance
484
    if sender_balance < value:
485
        push(evm.stack, U256(0))
486
        evm.return_data = b""
419
        evm.gas_left += message_call_gas.sub_call
487
        evm.gas_left += message_call_gas.sub_call
488
        evm.state_gas_left += call_state_gas_reservoir
489
    else:
490
        generic_call(
491
            evm,
492
            GenericCall(
493
                gas=message_call_gas.sub_call,
494
                state_gas_reservoir=call_state_gas_reservoir,
495
                value=value,
496
                caller=evm.message.current_target,
497
                to=to,
498
                code_address=code_address,
499
                should_transfer_value=True,
500
                is_staticcall=False,
501
                memory_input_start_position=memory_input_start_position,
502
                memory_input_size=memory_input_size,
503
                memory_output_start_position=memory_output_start_position,
504
                memory_output_size=memory_output_size,
505
                code=code,
436
                disable_precompiles=disable_precompiles,
506
                disable_precompiles=is_delegated,
507
            ),
508
        )
509
510
    # PROGRAM COUNTER
511
    evm.pc += Uint(1)

callcode

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

Parameters

evm : The current EVM frame.

def callcode(evm: Evm) -> None:
515
    <snip>
524
    # STACK
525
    gas = Uint(pop(evm.stack))
526
    code_address = to_address_masked(pop(evm.stack))
527
    value = pop(evm.stack)
528
    memory_input_start_position = pop(evm.stack)
529
    memory_input_size = pop(evm.stack)
530
    memory_output_start_position = pop(evm.stack)
531
    memory_output_size = pop(evm.stack)
532
533
    # GAS
534
    to = evm.message.current_target
535
536
    extend_memory = calculate_gas_extend_memory(
537
        evm.memory,
538
        [
539
            (memory_input_start_position, memory_input_size),
540
            (memory_output_start_position, memory_output_size),
541
        ],
542
    )
543
474
    if code_address in evm.accessed_addresses:
475
        access_gas_cost = GasCosts.WARM_ACCESS
544
    is_cold_access = code_address not in evm.accessed_addresses
545
    if is_cold_access:
546
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
547
    else:
477
        evm.accessed_addresses.add(code_address)
478
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
479
480
    (
481
        disable_precompiles,
482
        code_address,
483
        code,
484
        delegated_access_gas_cost,
485
    ) = access_delegation(evm, code_address)
486
    access_gas_cost += delegated_access_gas_cost
548
        access_gas_cost = GasCosts.WARM_ACCESS
549
550
    transfer_gas_cost = Uint(0) if value == 0 else GasCosts.CALL_VALUE
551
552
    # check static gas before state access
553
    check_gas(
554
        evm,
555
        access_gas_cost + extend_memory.cost + transfer_gas_cost,
556
    )
557
558
    # STATE ACCESS
559
    tx_state = evm.message.tx_env.state
560
    if is_cold_access:
561
        evm.accessed_addresses.add(code_address)
562
563
    extra_gas = access_gas_cost + transfer_gas_cost
564
    (
565
        is_delegated,
566
        code_address,
567
        delegation_access_cost,
568
    ) = calculate_delegation_cost(evm, code_address)
569
570
    if is_delegated:
571
        # check enough gas for delegation access
572
        extra_gas += delegation_access_cost
573
        check_gas(evm, extra_gas + extend_memory.cost)
574
        if code_address not in evm.accessed_addresses:
575
            evm.accessed_addresses.add(code_address)
576
577
    code_hash = get_account(tx_state, code_address).code_hash
578
    code = get_code(tx_state, code_hash)
579
580
    message_call_gas = calculate_message_call_gas(
581
        value,
582
        gas,
583
        Uint(evm.gas_left),
584
        extend_memory.cost,
494
        access_gas_cost + transfer_gas_cost,
585
        extra_gas,
586
    )
587
    charge_gas(evm, message_call_gas.cost + extend_memory.cost)
588
    evm.regular_gas_used -= message_call_gas.sub_call
589
590
    # OPERATION
591
    evm.memory += b"\x00" * extend_memory.expand_by
500
    sender_balance = get_account(
501
        evm.message.tx_env.state, evm.message.current_target
502
    ).balance
592
593
    # Pass full reservoir to child (no 63/64 rule for state gas)
594
    call_state_gas_reservoir = evm.state_gas_left
595
    evm.state_gas_left = Uint(0)
596
597
    sender_balance = get_account(tx_state, evm.message.current_target).balance
598
599
    if sender_balance < value:
600
        push(evm.stack, U256(0))
601
        evm.return_data = b""
506
        evm.gas_left += message_call_gas.sub_call
602
        evm.gas_left += message_call_gas.sub_call
603
        evm.state_gas_left += call_state_gas_reservoir
604
    else:
605
        generic_call(
606
            evm,
607
            GenericCall(
608
                gas=message_call_gas.sub_call,
609
                state_gas_reservoir=call_state_gas_reservoir,
610
                value=value,
611
                caller=evm.message.current_target,
612
                to=to,
613
                code_address=code_address,
614
                should_transfer_value=True,
615
                is_staticcall=False,
616
                memory_input_start_position=memory_input_start_position,
617
                memory_input_size=memory_input_size,
618
                memory_output_start_position=memory_output_start_position,
619
                memory_output_size=memory_output_size,
620
                code=code,
523
                disable_precompiles=disable_precompiles,
621
                disable_precompiles=is_delegated,
622
            ),
623
        )
624
625
    # PROGRAM COUNTER
626
    evm.pc += Uint(1)

selfdestruct

Halt execution and register account for later deletion.

Parameters

evm : The current EVM frame.

def selfdestruct(evm: Evm) -> None:
630
    <snip>
639
    if evm.message.is_static:
640
        raise WriteInStaticContext
641
642
    # STACK
643
    beneficiary = to_address_masked(pop(evm.stack))
644
645
    # GAS
646
    gas_cost = GasCosts.OPCODE_SELFDESTRUCT_BASE
546
    if beneficiary not in evm.accessed_addresses:
547
        evm.accessed_addresses.add(beneficiary)
548
        gas_cost += GasCosts.COLD_ACCOUNT_ACCESS
647
648
    is_cold_access = beneficiary not in evm.accessed_addresses
649
    if is_cold_access:
650
        gas_cost += GasCosts.COLD_ACCOUNT_ACCESS
651
652
    # check access gas cost before state access
653
    check_gas(evm, gas_cost)
654
655
    # STATE ACCESS
656
    tx_state = evm.message.tx_env.state
657
    if is_cold_access:
658
        evm.accessed_addresses.add(beneficiary)
659
660
    state_gas = Uint(0)
661
    if (
551
        not is_account_alive(evm.message.tx_env.state, beneficiary)
552
        and get_account(
553
            evm.message.tx_env.state, evm.message.current_target
554
        ).balance
555
        != 0
662
        not is_account_alive(tx_state, beneficiary)
663
        and get_account(tx_state, evm.message.current_target).balance != 0
664
    ):
557
        gas_cost += GasCosts.OPCODE_SELFDESTRUCT_NEW_ACCOUNT
665
        state_gas = StateGasCosts.NEW_ACCOUNT
666
559
    charge_gas(evm, gas_cost)
560
    if evm.message.is_static:
561
        raise WriteInStaticContext
667
    # Charge regular gas before state gas so that a regular-gas OOG
668
    # does not consume state gas that would inflate the parent's
669
    # reservoir on frame failure.
670
    charge_gas(evm, gas_cost)
671
    charge_state_gas(evm, state_gas)
672
673
    originator = evm.message.current_target
564
    originator_balance = get_account(
565
        evm.message.tx_env.state, originator
566
    ).balance
674
    originator_balance = get_account(tx_state, originator).balance
675
568
    move_ether(
569
        evm.message.tx_env.state,
570
        originator,
571
        beneficiary,
572
        originator_balance,
573
    )
676
    # Transfer balance
677
    move_ether(tx_state, originator, beneficiary, originator_balance)
678
575
    # register account for deletion only if it was created
576
    # in the same transaction
577
    if originator in evm.message.tx_env.state.created_accounts:
578
        # If beneficiary is the same as originator, then
579
        # the ether is burnt.
580
        set_account_balance(evm.message.tx_env.state, originator, U256(0))
679
    # Emit transfer or burn log
680
    if originator in tx_state.created_accounts and beneficiary == originator:
681
        emit_burn_log(evm, originator, originator_balance)
682
    elif beneficiary != originator:
683
        emit_transfer_log(evm, originator, beneficiary, originator_balance)
684
685
    # Register account for deletion iff created in same transaction
686
    if originator in tx_state.created_accounts:
687
        # If beneficiary and originator are the same then the ether is burnt.
688
        set_account_balance(tx_state, originator, U256(0))
689
        evm.accounts_to_delete.add(originator)
690
691
    # HALT the execution
692
    evm.running = False
693
694
    # PROGRAM COUNTER
695
    pass

delegatecall

Message-call into an account.

Parameters

evm : The current EVM frame.

def delegatecall(evm: Evm) -> None:
699
    <snip>
708
    # STACK
709
    gas = Uint(pop(evm.stack))
710
    code_address = to_address_masked(pop(evm.stack))
711
    memory_input_start_position = pop(evm.stack)
712
    memory_input_size = pop(evm.stack)
713
    memory_output_start_position = pop(evm.stack)
714
    memory_output_size = pop(evm.stack)
715
716
    # GAS
717
    extend_memory = calculate_gas_extend_memory(
718
        evm.memory,
719
        [
720
            (memory_input_start_position, memory_input_size),
721
            (memory_output_start_position, memory_output_size),
722
        ],
723
    )
724
617
    if code_address in evm.accessed_addresses:
618
        access_gas_cost = GasCosts.WARM_ACCESS
725
    is_cold_access = code_address not in evm.accessed_addresses
726
    if is_cold_access:
727
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
728
    else:
620
        evm.accessed_addresses.add(code_address)
621
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
729
        access_gas_cost = GasCosts.WARM_ACCESS
730
731
    # check static gas before state access
732
    check_gas(evm, access_gas_cost + extend_memory.cost)
733
734
    # STATE ACCESS
735
    if is_cold_access:
736
        evm.accessed_addresses.add(code_address)
737
738
    extra_gas = access_gas_cost
739
    (
624
        disable_precompiles,
740
        is_delegated,
741
        code_address,
626
        code,
627
        delegated_access_gas_cost,
628
    ) = access_delegation(evm, code_address)
629
    access_gas_cost += delegated_access_gas_cost
742
        delegation_access_cost,
743
    ) = calculate_delegation_cost(evm, code_address)
744
745
    if is_delegated:
746
        # check enough gas for delegation access
747
        extra_gas += delegation_access_cost
748
        check_gas(evm, extra_gas + extend_memory.cost)
749
        if code_address not in evm.accessed_addresses:
750
            evm.accessed_addresses.add(code_address)
751
752
    tx_state = evm.message.tx_env.state
753
    code_hash = get_account(tx_state, code_address).code_hash
754
    code = get_code(tx_state, code_hash)
755
756
    message_call_gas = calculate_message_call_gas(
632
        U256(0), gas, Uint(evm.gas_left), extend_memory.cost, access_gas_cost
757
        U256(0),
758
        gas,
759
        Uint(evm.gas_left),
760
        extend_memory.cost,
761
        extra_gas,
762
    )
763
    charge_gas(evm, message_call_gas.cost + extend_memory.cost)
764
    evm.regular_gas_used -= message_call_gas.sub_call
765
766
    # OPERATION
767
    evm.memory += b"\x00" * extend_memory.expand_by
768
769
    # Pass full reservoir to child (no 63/64 rule for state gas)
770
    call_state_gas_reservoir = evm.state_gas_left
771
    evm.state_gas_left = Uint(0)
772
773
    generic_call(
774
        evm,
775
        GenericCall(
776
            gas=message_call_gas.sub_call,
777
            state_gas_reservoir=call_state_gas_reservoir,
778
            value=evm.message.value,
779
            caller=evm.message.caller,
780
            to=evm.message.current_target,
781
            code_address=code_address,
782
            should_transfer_value=False,
783
            is_staticcall=False,
784
            memory_input_start_position=memory_input_start_position,
785
            memory_input_size=memory_input_size,
786
            memory_output_start_position=memory_output_start_position,
787
            memory_output_size=memory_output_size,
788
            code=code,
653
            disable_precompiles=disable_precompiles,
789
            disable_precompiles=is_delegated,
790
        ),
791
    )
792
793
    # PROGRAM COUNTER
794
    evm.pc += Uint(1)

staticcall

Message-call into an account.

Parameters

evm : The current EVM frame.

def staticcall(evm: Evm) -> None:
798
    <snip>
807
    # STACK
808
    gas = Uint(pop(evm.stack))
809
    to = to_address_masked(pop(evm.stack))
810
    memory_input_start_position = pop(evm.stack)
811
    memory_input_size = pop(evm.stack)
812
    memory_output_start_position = pop(evm.stack)
813
    memory_output_size = pop(evm.stack)
814
815
    # GAS
816
    extend_memory = calculate_gas_extend_memory(
817
        evm.memory,
818
        [
819
            (memory_input_start_position, memory_input_size),
820
            (memory_output_start_position, memory_output_size),
821
        ],
822
    )
823
688
    if to in evm.accessed_addresses:
689
        access_gas_cost = GasCosts.WARM_ACCESS
824
    is_cold_access = to not in evm.accessed_addresses
825
    if is_cold_access:
826
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
827
    else:
691
        evm.accessed_addresses.add(to)
692
        access_gas_cost = GasCosts.COLD_ACCOUNT_ACCESS
828
        access_gas_cost = GasCosts.WARM_ACCESS
829
694
    code_address = to
830
    # check static gas before state access
831
    check_gas(evm, access_gas_cost + extend_memory.cost)
832
833
    # STATE ACCESS
834
    if is_cold_access:
835
        evm.accessed_addresses.add(to)
836
837
    extra_gas = access_gas_cost
838
    (
696
        disable_precompiles,
839
        is_delegated,
840
        code_address,
698
        code,
699
        delegated_access_gas_cost,
700
    ) = access_delegation(evm, code_address)
701
    access_gas_cost += delegated_access_gas_cost
841
        delegation_access_cost,
842
    ) = calculate_delegation_cost(evm, to)
843
844
    if is_delegated:
845
        # check enough gas for delegation access
846
        extra_gas += delegation_access_cost
847
        check_gas(evm, extra_gas + extend_memory.cost)
848
        if code_address not in evm.accessed_addresses:
849
            evm.accessed_addresses.add(code_address)
850
851
    tx_state = evm.message.tx_env.state
852
    code_hash = get_account(tx_state, code_address).code_hash
853
    code = get_code(tx_state, code_hash)
854
855
    message_call_gas = calculate_message_call_gas(
856
        U256(0),
857
        gas,
858
        Uint(evm.gas_left),
859
        extend_memory.cost,
708
        access_gas_cost,
860
        extra_gas,
861
    )
862
    charge_gas(evm, message_call_gas.cost + extend_memory.cost)
863
    evm.regular_gas_used -= message_call_gas.sub_call
864
865
    # OPERATION
866
    evm.memory += b"\x00" * extend_memory.expand_by
867
868
    # Pass full reservoir to child (no 63/64 rule for state gas)
869
    call_state_gas_reservoir = evm.state_gas_left
870
    evm.state_gas_left = Uint(0)
871
872
    generic_call(
873
        evm,
874
        GenericCall(
875
            gas=message_call_gas.sub_call,
876
            state_gas_reservoir=call_state_gas_reservoir,
877
            value=U256(0),
878
            caller=evm.message.current_target,
879
            to=to,
880
            code_address=code_address,
881
            should_transfer_value=True,
882
            is_staticcall=True,
883
            memory_input_start_position=memory_input_start_position,
884
            memory_input_size=memory_input_size,
885
            memory_output_start_position=memory_output_start_position,
886
            memory_output_size=memory_output_size,
887
            code=code,
729
            disable_precompiles=disable_precompiles,
888
            disable_precompiles=is_delegated,
889
        ),
890
    )
891
892
    # PROGRAM COUNTER
893
    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:
897
    <snip>
907
    # STACK
908
    memory_start_index = pop(evm.stack)
909
    size = pop(evm.stack)
910
911
    # GAS
912
    extend_memory = calculate_gas_extend_memory(
913
        evm.memory, [(memory_start_index, size)]
914
    )
915
916
    charge_gas(evm, extend_memory.cost)
917
918
    # OPERATION
919
    evm.memory += b"\x00" * extend_memory.expand_by
920
    output = memory_read_bytes(evm.memory, memory_start_index, size)
921
    evm.output = Bytes(output)
922
    raise Revert
923
924
    # PROGRAM COUNTER
925
    # no-op