@@ -267,7 +267,7 @@ def process_create_message(message: Message) -> Evm:
267267 create_frame = create_child_frame (parent_frame )
268268
269269 increment_nonce (state , message .current_target , create_frame )
270- evm = process_message (message )
270+ evm = process_message (message , parent_state_frame = create_frame )
271271 if not evm .error :
272272 contract_code = evm .output
273273 contract_code_gas = Uint (len (contract_code )) * GAS_CODE_DEPOSIT
@@ -296,14 +296,23 @@ def process_create_message(message: Message) -> Evm:
296296 return evm
297297
298298
299- def process_message (message : Message ) -> Evm :
299+ def process_message (
300+ message : Message ,
301+ parent_state_frame : Optional [StateChanges ] = None ,
302+ ) -> Evm :
300303 """
301304 Move ether and execute the relevant code.
302305
303306 Parameters
304307 ----------
305308 message :
306309 Transaction specific items.
310+ parent_state_frame :
311+ Optional parent frame for state tracking. When provided (e.g., for
312+ CREATE's init code), state changes are tracked as a child of this
313+ frame instead of the default parent determined by the message.
314+ This ensures proper frame hierarchy for CREATE operations where
315+ init code changes must be children of the CREATE frame.
307316
308317 Returns
309318 -------
@@ -318,8 +327,15 @@ def process_message(message: Message) -> Evm:
318327
319328 begin_transaction (state , transient_storage )
320329
321- parent_frame = get_parent_frame (message )
322- state_changes = get_message_state_frame (message )
330+ if parent_state_frame is not None :
331+ # Use provided parent for CREATE's init code execution.
332+ # This ensures init code state changes are children of create_frame,
333+ # so they are properly converted to reads if code deposit fails.
334+ parent_changes = parent_state_frame
335+ state_changes = create_child_frame (parent_state_frame )
336+ else :
337+ parent_changes = get_parent_frame (message )
338+ state_changes = get_message_state_frame (message )
323339
324340 track_address (state_changes , message .current_target )
325341
@@ -335,11 +351,11 @@ def process_message(message: Message) -> Evm:
335351 evm = execute_code (message , state_changes )
336352 if evm .error :
337353 rollback_transaction (state , transient_storage )
338- if state_changes != parent_frame :
354+ if state_changes != parent_changes :
339355 merge_on_failure (evm .state_changes )
340356 else :
341357 commit_transaction (state , transient_storage )
342- if state_changes != parent_frame :
358+ if state_changes != parent_changes :
343359 merge_on_success (evm .state_changes )
344360 return evm
345361
0 commit comments