3434 to_address_masked ,
3535)
3636from ...vm .eoa_delegation import (
37- apply_delegation_tracking ,
38- check_delegation ,
37+ calculate_delegation_cost ,
38+ read_delegation_target ,
3939)
4040from .. import (
4141 Evm ,
@@ -397,13 +397,30 @@ def call(evm: Evm) -> None:
397397 if is_cold_access :
398398 evm .accessed_addresses .add (to )
399399
400+ # check gas for base access before reading `to` account
401+ base_gas_cost = extend_memory .cost + access_gas_cost
402+ check_gas (evm , base_gas_cost )
403+
404+ # read `to` account and assess delegation cost
400405 (
401406 is_delegated ,
402407 original_address ,
403- final_address ,
404- code ,
408+ delegated_address ,
405409 delegation_gas_cost ,
406- ) = check_delegation (evm , to )
410+ ) = calculate_delegation_cost (evm , to )
411+
412+ # check gas again for delegation target access before reading it
413+ if is_delegated and delegation_gas_cost > Uint (0 ):
414+ check_gas (evm , base_gas_cost + delegation_gas_cost )
415+
416+ if is_delegated :
417+ assert delegated_address is not None
418+ code = read_delegation_target (evm , delegated_address )
419+ final_address = delegated_address
420+ else :
421+ code = get_account (evm .message .block_env .state , to ).code
422+ final_address = to
423+
407424 access_gas_cost += delegation_gas_cost
408425
409426 code_address = final_address
@@ -421,12 +438,6 @@ def call(evm: Evm) -> None:
421438 access_gas_cost + create_gas_cost + transfer_gas_cost ,
422439 )
423440
424- check_gas (evm , message_call_gas .cost + extend_memory .cost )
425-
426- track_address (evm .state_changes , to )
427- if is_delegated :
428- apply_delegation_tracking (evm , original_address , final_address )
429-
430441 charge_gas (evm , message_call_gas .cost + extend_memory .cost )
431442 if evm .message .is_static and value != U256 (0 ):
432443 raise WriteInStaticContext
@@ -497,13 +508,30 @@ def callcode(evm: Evm) -> None:
497508 if is_cold_access :
498509 evm .accessed_addresses .add (code_address )
499510
511+ # check gas for base access before reading `code_address` account
512+ base_gas_cost = extend_memory .cost + access_gas_cost
513+ check_gas (evm , base_gas_cost )
514+
515+ # read code_address account and assess delegation cost
500516 (
501517 is_delegated ,
502518 original_address ,
503- final_address ,
504- code ,
519+ delegated_address ,
505520 delegation_gas_cost ,
506- ) = check_delegation (evm , code_address )
521+ ) = calculate_delegation_cost (evm , code_address )
522+
523+ # check gas again for delegation target access before reading it
524+ if is_delegated and delegation_gas_cost > Uint (0 ):
525+ check_gas (evm , base_gas_cost + delegation_gas_cost )
526+
527+ if is_delegated :
528+ assert delegated_address is not None
529+ code = read_delegation_target (evm , delegated_address )
530+ final_address = delegated_address
531+ else :
532+ code = get_account (evm .message .block_env .state , code_address ).code
533+ final_address = code_address
534+
507535 access_gas_cost += delegation_gas_cost
508536
509537 code_address = final_address
@@ -518,12 +546,6 @@ def callcode(evm: Evm) -> None:
518546 access_gas_cost + transfer_gas_cost ,
519547 )
520548
521- check_gas (evm , message_call_gas .cost + extend_memory .cost )
522-
523- track_address (evm .state_changes , original_address )
524- if is_delegated :
525- apply_delegation_tracking (evm , original_address , final_address )
526-
527549 charge_gas (evm , message_call_gas .cost + extend_memory .cost )
528550
529551 # OPERATION
@@ -665,16 +687,35 @@ def delegatecall(evm: Evm) -> None:
665687 access_gas_cost = (
666688 GAS_COLD_ACCOUNT_ACCESS if is_cold_access else GAS_WARM_ACCESS
667689 )
690+
691+ # check gas for base access before reading `code_address` account
692+ base_gas_cost = extend_memory .cost + access_gas_cost
693+ check_gas (evm , base_gas_cost )
694+
668695 if is_cold_access :
669696 evm .accessed_addresses .add (code_address )
670697
698+ # read `code_address` account and assess delegation cost
671699 (
672700 is_delegated ,
673701 original_address ,
674- final_address ,
675- code ,
702+ delegated_address ,
676703 delegation_gas_cost ,
677- ) = check_delegation (evm , code_address )
704+ ) = calculate_delegation_cost (evm , code_address )
705+
706+ # check gas again for delegation target access before reading it
707+ if is_delegated and delegation_gas_cost > Uint (0 ):
708+ check_gas (evm , base_gas_cost + delegation_gas_cost )
709+
710+ # Now safe to read delegation target since we verified gas
711+ if is_delegated :
712+ assert delegated_address is not None
713+ code = read_delegation_target (evm , delegated_address )
714+ final_address = delegated_address
715+ else :
716+ code = get_account (evm .message .block_env .state , code_address ).code
717+ final_address = code_address
718+
678719 access_gas_cost += delegation_gas_cost
679720
680721 code_address = final_address
@@ -684,12 +725,6 @@ def delegatecall(evm: Evm) -> None:
684725 U256 (0 ), gas , Uint (evm .gas_left ), extend_memory .cost , access_gas_cost
685726 )
686727
687- check_gas (evm , message_call_gas .cost + extend_memory .cost )
688-
689- track_address (evm .state_changes , original_address )
690- if is_delegated :
691- apply_delegation_tracking (evm , original_address , final_address )
692-
693728 charge_gas (evm , message_call_gas .cost + extend_memory .cost )
694729
695730 # OPERATION
@@ -749,13 +784,31 @@ def staticcall(evm: Evm) -> None:
749784 if is_cold_access :
750785 evm .accessed_addresses .add (to )
751786
787+ # check gas for base access before reading `to` account
788+ base_gas_cost = extend_memory .cost + access_gas_cost
789+ check_gas (evm , base_gas_cost )
790+
791+ # read `to` account and assess delegation cost
752792 (
753793 is_delegated ,
754794 original_address ,
755- final_address ,
756- code ,
795+ delegated_address ,
757796 delegation_gas_cost ,
758- ) = check_delegation (evm , to )
797+ ) = calculate_delegation_cost (evm , to )
798+
799+ # check gas again for delegation target access before reading it
800+ if is_delegated and delegation_gas_cost > Uint (0 ):
801+ check_gas (evm , base_gas_cost + delegation_gas_cost )
802+
803+ # Now safe to read delegation target since we verified gas
804+ if is_delegated :
805+ assert delegated_address is not None
806+ code = read_delegation_target (evm , delegated_address )
807+ final_address = delegated_address
808+ else :
809+ code = get_account (evm .message .block_env .state , to ).code
810+ final_address = to
811+
759812 access_gas_cost += delegation_gas_cost
760813
761814 code_address = final_address
@@ -769,12 +822,6 @@ def staticcall(evm: Evm) -> None:
769822 access_gas_cost ,
770823 )
771824
772- check_gas (evm , message_call_gas .cost + extend_memory .cost )
773-
774- track_address (evm .state_changes , to )
775- if is_delegated :
776- apply_delegation_tracking (evm , original_address , final_address )
777-
778825 charge_gas (evm , message_call_gas .cost + extend_memory .cost )
779826
780827 # OPERATION
0 commit comments