@@ -298,15 +298,10 @@ def generic_call(
298298 """
299299 Perform the core logic of the `CALL*` family of opcodes.
300300 """
301- from ...vm .interpreter import STACK_DEPTH_LIMIT , process_message
301+ from ...vm .interpreter import process_message
302302
303303 evm .return_data = b""
304304
305- if evm .message .depth + Uint (1 ) > STACK_DEPTH_LIMIT :
306- evm .gas_left += gas
307- push (evm .stack , U256 (0 ))
308- return
309-
310305 tx_state = evm .message .tx_env .state
311306 code_hash = get_account (tx_state , code_address ).code_hash
312307 code = get_code (tx_state , code_hash )
@@ -386,37 +381,45 @@ def call(evm: Evm) -> None:
386381 )
387382
388383 is_cold_access = to not in evm .accessed_addresses
389- if is_cold_access :
390- access_gas_cost = GasCosts .COLD_ACCOUNT_ACCESS
391- else :
392- access_gas_cost = GasCosts .WARM_ACCESS
393-
394384 transfer_gas_cost = Uint (0 ) if value == 0 else GasCosts .CALL_VALUE
395385
396- # check static gas before state access
397- check_gas (
398- evm ,
399- access_gas_cost + transfer_gas_cost + extend_memory .cost ,
400- )
386+ # Pre-state extra gas (warm-equivalent access cost only; cold surcharge
387+ # is deferred to post-state).
388+ extra_gas = GasCosts .WARM_ACCESS + transfer_gas_cost
389+ check_gas (evm , extra_gas + extend_memory .cost )
390+
391+ # Pre-state preconditions: stack depth and (if value > 0) sender balance.
392+ from ...vm .interpreter import STACK_DEPTH_LIMIT
401393
402- # STATE ACCESS
403394 tx_state = evm .message .tx_env .state
395+ sender_balance = get_account (tx_state , evm .message .current_target ).balance
396+ if evm .message .depth + Uint (1 ) > STACK_DEPTH_LIMIT or (
397+ value > U256 (0 ) and sender_balance < value
398+ ):
399+ charge_gas (evm , extra_gas + extend_memory .cost )
400+ evm .memory += b"\x00 " * extend_memory .expand_by
401+ push (evm .stack , U256 (0 ))
402+ evm .return_data = b""
403+ evm .pc += Uint (1 )
404+ return
405+
406+ # Post-state: cold surcharge paired with warming and BAL insertion.
404407 if is_cold_access :
408+ extra_gas += GasCosts .COLD_ACCOUNT_ACCESS - GasCosts .WARM_ACCESS
409+ check_gas (evm , extra_gas + extend_memory .cost )
405410 evm .accessed_addresses .add (to )
406411
407- create_gas_cost = GasCosts . NEW_ACCOUNT
408- if value == 0 or is_account_alive ( tx_state , to ):
409- create_gas_cost = Uint ( 0 )
412+ if value > U256 ( 0 ) and not is_account_alive ( tx_state , to ):
413+ extra_gas += GasCosts . NEW_ACCOUNT
414+ check_gas ( evm , extra_gas + extend_memory . cost )
410415
411- extra_gas = access_gas_cost + transfer_gas_cost + create_gas_cost
412416 (
413417 is_delegated ,
414418 code_address ,
415419 delegation_access_cost ,
416420 ) = calculate_delegation_cost (evm , to )
417421
418422 if is_delegated :
419- # check enough gas for delegation access
420423 extra_gas += delegation_access_cost
421424 check_gas (evm , extra_gas + extend_memory .cost )
422425 if code_address not in evm .accessed_addresses :
@@ -433,27 +436,21 @@ def call(evm: Evm) -> None:
433436
434437 # OPERATION
435438 evm .memory += b"\x00 " * extend_memory .expand_by
436- sender_balance = get_account (tx_state , evm .message .current_target ).balance
437- if sender_balance < value :
438- push (evm .stack , U256 (0 ))
439- evm .return_data = b""
440- evm .gas_left += message_call_gas .sub_call
441- else :
442- generic_call (
443- evm ,
444- message_call_gas .sub_call ,
445- value ,
446- evm .message .current_target ,
447- to ,
448- code_address ,
449- True ,
450- False ,
451- memory_input_start_position ,
452- memory_input_size ,
453- memory_output_start_position ,
454- memory_output_size ,
455- is_delegated ,
456- )
439+ generic_call (
440+ evm ,
441+ message_call_gas .sub_call ,
442+ value ,
443+ evm .message .current_target ,
444+ to ,
445+ code_address ,
446+ True ,
447+ False ,
448+ memory_input_start_position ,
449+ memory_input_size ,
450+ memory_output_start_position ,
451+ memory_output_size ,
452+ is_delegated ,
453+ )
457454
458455 # PROGRAM COUNTER
459456 evm .pc += Uint (1 )
@@ -490,33 +487,41 @@ def callcode(evm: Evm) -> None:
490487 )
491488
492489 is_cold_access = code_address not in evm .accessed_addresses
493- if is_cold_access :
494- access_gas_cost = GasCosts .COLD_ACCOUNT_ACCESS
495- else :
496- access_gas_cost = GasCosts .WARM_ACCESS
497-
498490 transfer_gas_cost = Uint (0 ) if value == 0 else GasCosts .CALL_VALUE
499491
500- # check static gas before state access
501- check_gas (
502- evm ,
503- access_gas_cost + extend_memory .cost + transfer_gas_cost ,
504- )
492+ # Pre-state extra gas (warm-equivalent access cost only; cold surcharge
493+ # is deferred to post-state).
494+ extra_gas = GasCosts .WARM_ACCESS + transfer_gas_cost
495+ check_gas (evm , extra_gas + extend_memory .cost )
496+
497+ # Pre-state preconditions: stack depth and (if value > 0) sender balance.
498+ from ...vm .interpreter import STACK_DEPTH_LIMIT
505499
506- # STATE ACCESS
507500 tx_state = evm .message .tx_env .state
501+ sender_balance = get_account (tx_state , evm .message .current_target ).balance
502+ if evm .message .depth + Uint (1 ) > STACK_DEPTH_LIMIT or (
503+ value > U256 (0 ) and sender_balance < value
504+ ):
505+ charge_gas (evm , extra_gas + extend_memory .cost )
506+ evm .memory += b"\x00 " * extend_memory .expand_by
507+ push (evm .stack , U256 (0 ))
508+ evm .return_data = b""
509+ evm .pc += Uint (1 )
510+ return
511+
512+ # Post-state: cold surcharge paired with warming and BAL insertion.
508513 if is_cold_access :
514+ extra_gas += GasCosts .COLD_ACCOUNT_ACCESS - GasCosts .WARM_ACCESS
515+ check_gas (evm , extra_gas + extend_memory .cost )
509516 evm .accessed_addresses .add (code_address )
510517
511- extra_gas = access_gas_cost + transfer_gas_cost
512518 (
513519 is_delegated ,
514520 code_address ,
515521 delegation_access_cost ,
516522 ) = calculate_delegation_cost (evm , code_address )
517523
518524 if is_delegated :
519- # check enough gas for delegation access
520525 extra_gas += delegation_access_cost
521526 check_gas (evm , extra_gas + extend_memory .cost )
522527 if code_address not in evm .accessed_addresses :
@@ -533,28 +538,21 @@ def callcode(evm: Evm) -> None:
533538
534539 # OPERATION
535540 evm .memory += b"\x00 " * extend_memory .expand_by
536- sender_balance = get_account (tx_state , evm .message .current_target ).balance
537-
538- if sender_balance < value :
539- push (evm .stack , U256 (0 ))
540- evm .return_data = b""
541- evm .gas_left += message_call_gas .sub_call
542- else :
543- generic_call (
544- evm ,
545- message_call_gas .sub_call ,
546- value ,
547- evm .message .current_target ,
548- to ,
549- code_address ,
550- True ,
551- False ,
552- memory_input_start_position ,
553- memory_input_size ,
554- memory_output_start_position ,
555- memory_output_size ,
556- is_delegated ,
557- )
541+ generic_call (
542+ evm ,
543+ message_call_gas .sub_call ,
544+ value ,
545+ evm .message .current_target ,
546+ to ,
547+ code_address ,
548+ True ,
549+ False ,
550+ memory_input_start_position ,
551+ memory_input_size ,
552+ memory_output_start_position ,
553+ memory_output_size ,
554+ is_delegated ,
555+ )
558556
559557 # PROGRAM COUNTER
560558 evm .pc += Uint (1 )
@@ -652,27 +650,36 @@ def delegatecall(evm: Evm) -> None:
652650 )
653651
654652 is_cold_access = code_address not in evm .accessed_addresses
655- if is_cold_access :
656- access_gas_cost = GasCosts .COLD_ACCOUNT_ACCESS
657- else :
658- access_gas_cost = GasCosts .WARM_ACCESS
659653
660- # check static gas before state access
661- check_gas (evm , access_gas_cost + extend_memory .cost )
654+ # Pre-state extra gas (warm-equivalent access cost only; cold surcharge
655+ # is deferred to post-state).
656+ extra_gas = GasCosts .WARM_ACCESS
657+ check_gas (evm , extra_gas + extend_memory .cost )
662658
663- # STATE ACCESS
659+ # Pre-state precondition: stack depth.
660+ from ...vm .interpreter import STACK_DEPTH_LIMIT
661+
662+ if evm .message .depth + Uint (1 ) > STACK_DEPTH_LIMIT :
663+ charge_gas (evm , extra_gas + extend_memory .cost )
664+ evm .memory += b"\x00 " * extend_memory .expand_by
665+ push (evm .stack , U256 (0 ))
666+ evm .return_data = b""
667+ evm .pc += Uint (1 )
668+ return
669+
670+ # Post-state: cold surcharge paired with warming and BAL insertion.
664671 if is_cold_access :
672+ extra_gas += GasCosts .COLD_ACCOUNT_ACCESS - GasCosts .WARM_ACCESS
673+ check_gas (evm , extra_gas + extend_memory .cost )
665674 evm .accessed_addresses .add (code_address )
666675
667- extra_gas = access_gas_cost
668676 (
669677 is_delegated ,
670678 code_address ,
671679 delegation_access_cost ,
672680 ) = calculate_delegation_cost (evm , code_address )
673681
674682 if is_delegated :
675- # check enough gas for delegation access
676683 extra_gas += delegation_access_cost
677684 check_gas (evm , extra_gas + extend_memory .cost )
678685 if code_address not in evm .accessed_addresses :
@@ -737,27 +744,36 @@ def staticcall(evm: Evm) -> None:
737744 )
738745
739746 is_cold_access = to not in evm .accessed_addresses
740- if is_cold_access :
741- access_gas_cost = GasCosts .COLD_ACCOUNT_ACCESS
742- else :
743- access_gas_cost = GasCosts .WARM_ACCESS
744747
745- # check static gas before state access
746- check_gas (evm , access_gas_cost + extend_memory .cost )
748+ # Pre-state extra gas (warm-equivalent access cost only; cold surcharge
749+ # is deferred to post-state).
750+ extra_gas = GasCosts .WARM_ACCESS
751+ check_gas (evm , extra_gas + extend_memory .cost )
747752
748- # STATE ACCESS
753+ # Pre-state precondition: stack depth.
754+ from ...vm .interpreter import STACK_DEPTH_LIMIT
755+
756+ if evm .message .depth + Uint (1 ) > STACK_DEPTH_LIMIT :
757+ charge_gas (evm , extra_gas + extend_memory .cost )
758+ evm .memory += b"\x00 " * extend_memory .expand_by
759+ push (evm .stack , U256 (0 ))
760+ evm .return_data = b""
761+ evm .pc += Uint (1 )
762+ return
763+
764+ # Post-state: cold surcharge paired with warming and BAL insertion.
749765 if is_cold_access :
766+ extra_gas += GasCosts .COLD_ACCOUNT_ACCESS - GasCosts .WARM_ACCESS
767+ check_gas (evm , extra_gas + extend_memory .cost )
750768 evm .accessed_addresses .add (to )
751769
752- extra_gas = access_gas_cost
753770 (
754771 is_delegated ,
755772 code_address ,
756773 delegation_access_cost ,
757774 ) = calculate_delegation_cost (evm , to )
758775
759776 if is_delegated :
760- # check enough gas for delegation access
761777 extra_gas += delegation_access_cost
762778 check_gas (evm , extra_gas + extend_memory .cost )
763779 if code_address not in evm .accessed_addresses :
0 commit comments