@@ -104,6 +104,7 @@ use crate::special_contracts::{
104104 V1_BOUND_CAIRO1_CONTRACT_SIERRA ,
105105} ;
106106use crate :: test_manager:: {
107+ block_context_for_flow_tests,
107108 TestManager ,
108109 TestParameters ,
109110 FUNDED_ACCOUNT_ADDRESS ,
@@ -2851,3 +2852,111 @@ async fn test_empty_multi_block() {
28512852 ) ;
28522853 test_output. expect_hint_coverage ( "test_empty_multi_block" ) ;
28532854}
2855+
2856+ /// Validates the migration flow for both declaring contract with casm hash v2, and migrating a
2857+ /// contract that was already declared with casm hash v1. This test covers:
2858+ /// 1. Declaring a contract with casm hash v2 and using it in the same block where it was declared.
2859+ /// 2. Using a contract that was previously declared with casm hash v1 (a migration should be
2860+ /// triggered in this case).
2861+ /// 3. Using the migrated contract in a block after the migration.
2862+ #[ rstest]
2863+ #[ tokio:: test]
2864+ async fn test_compiled_class_hash_migration ( ) {
2865+ let ( mut test_manager, _) =
2866+ TestManager :: < DictStateReader > :: new_with_default_initial_state ( [ ] ) . await ;
2867+ let use_kzg_da = true ;
2868+
2869+ // Declare two contracts, with V1 and V2 hashes.
2870+ let test_contract = FeatureContract :: TestContract ( CairoVersion :: Cairo1 ( RunnableCairo1 :: Casm ) ) ;
2871+ let empty_contract = FeatureContract :: Empty ( CairoVersion :: Cairo1 ( RunnableCairo1 :: Casm ) ) ;
2872+ let test_contract_sierra = test_contract. get_sierra ( ) ;
2873+ let empty_contract_sierra = empty_contract. get_sierra ( ) ;
2874+ let test_class_hash = test_contract_sierra. calculate_class_hash ( ) ;
2875+ let empty_class_hash = empty_contract_sierra. calculate_class_hash ( ) ;
2876+ let compiled_test_class_hash_v1 = test_contract. get_compiled_class_hash ( & HashVersion :: V1 ) ;
2877+ let compiled_empty_class_hash_v2 = empty_contract. get_compiled_class_hash ( & HashVersion :: V2 ) ;
2878+ let declare_tx_args_v1 = declare_tx_args ! {
2879+ sender_address: * FUNDED_ACCOUNT_ADDRESS ,
2880+ class_hash: test_class_hash,
2881+ compiled_class_hash: compiled_test_class_hash_v1,
2882+ resource_bounds: * NON_TRIVIAL_RESOURCE_BOUNDS ,
2883+ nonce: test_manager. next_nonce( * FUNDED_ACCOUNT_ADDRESS ) ,
2884+ } ;
2885+ let account_declare_tx_v1 = declare_tx ( declare_tx_args_v1) ;
2886+ let class_info = get_class_info_of_feature_contract ( test_contract) ;
2887+ let tx_v1 =
2888+ DeclareTransaction :: create ( account_declare_tx_v1, class_info, & CHAIN_ID_FOR_TESTS ) . unwrap ( ) ;
2889+ test_manager. add_cairo1_declare_tx ( tx_v1, & test_contract_sierra) ;
2890+
2891+ // Block context for the first block. Migration and v1-declare-blocking should be disabled.
2892+ let mut next_block_number = test_manager. initial_state . next_block_number ;
2893+ let mut block_context_0 = block_context_for_flow_tests ( next_block_number, use_kzg_da) ;
2894+ block_context_0. versioned_constants . enable_casm_hash_migration = false ;
2895+ block_context_0. versioned_constants . block_casm_hash_v1_declares = false ;
2896+ test_manager. move_to_next_block ( ) ;
2897+ next_block_number = BlockNumber ( next_block_number. 0 + 1 ) ;
2898+
2899+ // Declare the contract with V2 hash.
2900+ let declare_tx_args_v2 = declare_tx_args ! {
2901+ sender_address: * FUNDED_ACCOUNT_ADDRESS ,
2902+ class_hash: empty_class_hash,
2903+ compiled_class_hash: compiled_empty_class_hash_v2,
2904+ resource_bounds: * NON_TRIVIAL_RESOURCE_BOUNDS ,
2905+ nonce: test_manager. next_nonce( * FUNDED_ACCOUNT_ADDRESS ) ,
2906+ } ;
2907+ let account_declare_tx_v2 = declare_tx ( declare_tx_args_v2) ;
2908+ let class_info = get_class_info_of_feature_contract ( empty_contract) ;
2909+ let tx_v2 =
2910+ DeclareTransaction :: create ( account_declare_tx_v2, class_info, & CHAIN_ID_FOR_TESTS ) . unwrap ( ) ;
2911+ test_manager. add_cairo1_declare_tx ( tx_v2, & empty_contract_sierra) ;
2912+
2913+ // Move to the next block. After the V1 declare, enable migration and block V1 declares.
2914+ let block_context_1 = block_context_for_flow_tests ( next_block_number, use_kzg_da) ;
2915+ // These should be true be default.
2916+ assert ! ( block_context_1. versioned_constants. enable_casm_hash_migration) ;
2917+ assert ! ( block_context_1. versioned_constants. block_casm_hash_v1_declares) ;
2918+ test_manager. move_to_next_block ( ) ;
2919+ next_block_number = BlockNumber ( next_block_number. 0 + 1 ) ;
2920+
2921+ // Deploy the contract with V2 hash.
2922+ let ( deploy_tx_v2, _address_v2) = get_deploy_contract_tx_and_address_with_salt (
2923+ empty_class_hash,
2924+ calldata ! [ ] ,
2925+ test_manager. next_nonce ( * FUNDED_ACCOUNT_ADDRESS ) ,
2926+ * NON_TRIVIAL_RESOURCE_BOUNDS ,
2927+ ContractAddressSalt ( Felt :: ZERO ) ,
2928+ ) ;
2929+ test_manager. add_invoke_tx ( deploy_tx_v2, None ) ;
2930+
2931+ // Deploy the V1 contract.
2932+ let ( deploy_tx_v1, address_v1) = get_deploy_contract_tx_and_address_with_salt (
2933+ test_class_hash,
2934+ calldata ! [ Felt :: ONE , Felt :: TWO ] ,
2935+ test_manager. next_nonce ( * FUNDED_ACCOUNT_ADDRESS ) ,
2936+ * NON_TRIVIAL_RESOURCE_BOUNDS ,
2937+ ContractAddressSalt ( Felt :: ZERO ) ,
2938+ ) ;
2939+ test_manager. add_invoke_tx ( deploy_tx_v1, None ) ;
2940+
2941+ // Invoke some function on the V1 contract.
2942+ let calldata = create_calldata ( address_v1, "return_result" , & [ Felt :: from ( 3 ) ] ) ;
2943+ test_manager. add_funded_account_invoke ( invoke_tx_args ! { calldata } ) ;
2944+
2945+ // Create custom block contexts for the two blocks.
2946+ assert_eq ! ( test_manager. n_blocks( ) , 3 ) ;
2947+ let block_context_2 = block_context_for_flow_tests ( next_block_number, use_kzg_da) ;
2948+ // These should be true be default.
2949+ assert ! ( block_context_2. versioned_constants. enable_casm_hash_migration) ;
2950+ assert ! ( block_context_2. versioned_constants. block_casm_hash_v1_declares) ;
2951+ let block_contexts = vec ! [ block_context_0, block_context_1, block_context_2] ;
2952+
2953+ // Run the test and verify the storage changes.
2954+ let test_output = test_manager
2955+ . execute_test_with_block_contexts (
2956+ block_contexts,
2957+ & TestParameters { use_kzg_da, ..Default :: default ( ) } ,
2958+ )
2959+ . await ;
2960+ test_output. perform_default_validations ( ) ;
2961+ test_output. expect_hint_coverage ( "test_compiled_class_hash_migration" ) ;
2962+ }
0 commit comments