3636
3737#[ cfg( feature = "try-runtime" ) ]
3838use frame_support:: ensure;
39+ use frame_support:: migration:: storage_key_iter;
3940
4041use {
4142 cumulus_primitives_core:: ParaId ,
4243 frame_support:: {
4344 pallet_prelude:: GetStorageVersion ,
4445 traits:: { OnRuntimeUpgrade , PalletInfoAccess , StorageVersion } ,
4546 weights:: Weight ,
47+ StoragePrefixedMap ,
4648 } ,
4749 pallet_configuration:: { weights:: WeightInfo as _, HostConfiguration } ,
50+ pallet_foreign_asset_creator:: AssetId ,
51+ pallet_foreign_asset_creator:: { AssetIdToForeignAsset , ForeignAssetToAssetId } ,
4852 pallet_migrations:: { GetMigrations , Migration } ,
4953 sp_core:: Get ,
5054 sp_std:: { collections:: btree_set:: BTreeSet , marker:: PhantomData , prelude:: * } ,
@@ -516,6 +520,9 @@ where
516520 Runtime : pallet_xcm:: Config ,
517521 <Runtime as pallet_balances:: Config >:: RuntimeHoldReason :
518522 From < pallet_pooled_staking:: HoldReason > ,
523+ Runtime : pallet_foreign_asset_creator:: Config ,
524+ <Runtime as pallet_foreign_asset_creator:: Config >:: ForeignAsset :
525+ TryFrom < staging_xcm:: v3:: MultiLocation > ,
519526{
520527 fn get_migrations ( ) -> Vec < Box < dyn Migration > > {
521528 // let migrate_invulnerables = MigrateInvulnerables::<Runtime>(Default::default());
@@ -540,6 +547,8 @@ where
540547 RegistrarParaManagerMigration :: < Runtime > ( Default :: default ( ) ) ;
541548
542549 let migrate_pallet_xcm_v4 = MigrateToLatestXcmVersion :: < Runtime > ( Default :: default ( ) ) ;
550+ let foreign_asset_creator_migration =
551+ ForeignAssetCreatorMigration :: < Runtime > ( Default :: default ( ) ) ;
543552
544553 vec ! [
545554 // Applied in runtime 200
@@ -564,6 +573,105 @@ where
564573 Box :: new( migrate_registrar_pending_verification) ,
565574 Box :: new( migrate_registrar_manager) ,
566575 Box :: new( migrate_pallet_xcm_v4) ,
576+ Box :: new( foreign_asset_creator_migration) ,
567577 ]
568578 }
569579}
580+
581+ pub struct ForeignAssetCreatorMigration < Runtime > ( PhantomData < Runtime > ) ;
582+
583+ impl < Runtime > Migration for ForeignAssetCreatorMigration < Runtime >
584+ where
585+ Runtime : pallet_foreign_asset_creator:: Config ,
586+ <Runtime as pallet_foreign_asset_creator:: Config >:: ForeignAsset :
587+ TryFrom < staging_xcm:: v3:: MultiLocation > ,
588+ {
589+ fn friendly_name ( & self ) -> & str {
590+ "TM_ForeignAssetCreatorMigration"
591+ }
592+
593+ fn migrate ( & self , _available_weight : Weight ) -> Weight {
594+ use frame_support:: pallet_prelude:: * ;
595+
596+ use staging_xcm:: v3:: MultiLocation as OldLocation ;
597+
598+ let pallet_prefix = AssetIdToForeignAsset :: < Runtime > :: pallet_prefix ( ) ;
599+ let asset_id_to_foreign_asset_storage_prefix =
600+ AssetIdToForeignAsset :: < Runtime > :: storage_prefix ( ) ;
601+ let foreign_asset_to_asset_id_prefix = ForeignAssetToAssetId :: < Runtime > :: storage_prefix ( ) ;
602+
603+ // Data required to migrate ForeignAsset values
604+ // Read all the data into memory.
605+ let asset_id_to_foreign_asset_data: Vec < _ > =
606+ storage_key_iter :: < AssetId < Runtime > , OldLocation , Blake2_128Concat > (
607+ pallet_prefix,
608+ asset_id_to_foreign_asset_storage_prefix,
609+ )
610+ . drain ( )
611+ . collect ( ) ;
612+
613+ // Data required to migrate ForeignAsset keys
614+ let foreign_asset_to_asset_id_data: Vec < _ > =
615+ storage_key_iter :: < OldLocation , AssetId < Runtime > , Blake2_128Concat > (
616+ pallet_prefix,
617+ foreign_asset_to_asset_id_prefix,
618+ )
619+ . drain ( )
620+ . collect ( ) ;
621+
622+ let foreign_asset_to_asset_id_count = foreign_asset_to_asset_id_data. len ( ) ;
623+
624+ let migrated_count = asset_id_to_foreign_asset_data
625+ . len ( )
626+ . saturating_add ( foreign_asset_to_asset_id_data. len ( ) ) ;
627+
628+ log:: info!( "Migrating {:?} elements" , migrated_count) ;
629+
630+ // Removing older entries with old location as key
631+ let mut removal_result = storage:: unhashed:: clear_prefix (
632+ & ForeignAssetToAssetId :: < Runtime > :: final_prefix ( ) ,
633+ None ,
634+ None ,
635+ ) ;
636+ while removal_result. maybe_cursor . is_some ( ) {
637+ removal_result = storage:: unhashed:: clear_prefix (
638+ & ForeignAssetToAssetId :: < Runtime > :: final_prefix ( ) ,
639+ None ,
640+ removal_result. maybe_cursor . as_deref ( ) ,
641+ ) ;
642+ }
643+
644+ // Write to the new storage with removed and added fields
645+ for ( asset_id, old_location) in asset_id_to_foreign_asset_data {
646+ if let Ok ( new_location) = Runtime :: ForeignAsset :: try_from ( old_location) {
647+ AssetIdToForeignAsset :: < Runtime > :: insert ( asset_id, new_location) ;
648+ } else {
649+ log:: warn!( "Location could not be converted safely to xcmV4" )
650+ }
651+ }
652+
653+ for ( old_location, asset_id) in foreign_asset_to_asset_id_data {
654+ if let Ok ( new_location) = Runtime :: ForeignAsset :: try_from ( old_location) {
655+ ForeignAssetToAssetId :: < Runtime > :: insert ( new_location, asset_id) ;
656+ } else {
657+ log:: warn!( "Location could not be converted safely to xcmV4" )
658+ }
659+ }
660+
661+ // One db read and one db write per element, plus the on-chain storage
662+ Runtime :: DbWeight :: get ( )
663+ . reads ( migrated_count as u64 )
664+ . saturating_add ( Runtime :: DbWeight :: get ( ) . writes ( migrated_count as u64 + 3u64 ) )
665+ . saturating_add ( Runtime :: DbWeight :: get ( ) . writes ( foreign_asset_to_asset_id_count as u64 ) )
666+ }
667+
668+ #[ cfg( feature = "try-runtime" ) ]
669+ fn pre_upgrade ( & self ) -> Result < Vec < u8 > , DispatchError > {
670+ Ok ( vec ! [ ] )
671+ }
672+
673+ #[ cfg( feature = "try-runtime" ) ]
674+ fn post_upgrade ( & self , _state : Vec < u8 > ) -> Result < ( ) , DispatchError > {
675+ Ok ( ( ) )
676+ }
677+ }
0 commit comments