git.delta.rocks / unique-network / refs/commits / 0d52e2cbc000

difftreelog

Merge pull request #1068 from UniqueNetwork/chore/migrate-foreign-asset-to-v4

Yaroslav Bolyukin2024-06-06parents: #f78f490 #9a73a32.patch.diff
in: master
migrate foreign asset to v4 + fix foreign flags

3 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -7279,6 +7279,7 @@
 name = "pallet-foreign-assets"
 version = "0.1.0"
 dependencies = [
+ "derivative",
  "frame-benchmarking",
  "frame-support",
  "frame-system",
modifiedpallets/foreign-assets/Cargo.tomldiffbeforeafterboth
--- a/pallets/foreign-assets/Cargo.toml
+++ b/pallets/foreign-assets/Cargo.toml
@@ -21,6 +21,7 @@
 staging-xcm = { workspace = true }
 staging-xcm-executor = { workspace = true }
 up-data-structs = { workspace = true }
+derivative = { workspace = true }
 
 [features]
 default = ["std"]
modifiedpallets/foreign-assets/src/lib.rsdiffbeforeafterboth
2525
26use core::ops::Deref;26use core::ops::Deref;
2727
28use derivative::Derivative;
28use frame_support::{dispatch::DispatchResult, pallet_prelude::*, traits::EnsureOrigin, PalletId};29use frame_support::{
30 dispatch::DispatchResult, pallet_prelude::*, storage_alias, traits::EnsureOrigin, PalletId,
31};
29use frame_system::pallet_prelude::*;32use frame_system::pallet_prelude::*;
30use pallet_common::{33use pallet_common::{
38 AssetsInHolding,41 AssetsInHolding,
39};42};
40use up_data_structs::{43use up_data_structs::{
41 budget::ZeroBudget, CollectionId, CollectionMode, CollectionName, CollectionTokenPrefix,44 budget::ZeroBudget, CollectionFlags, CollectionId, CollectionMode, CollectionName,
42 CreateCollectionData, CreateFungibleData, CreateItemData, TokenId,45 CollectionTokenPrefix, CreateCollectionData, CreateFungibleData, CreateItemData, TokenId,
43};46};
4447
50pub use module::*;53pub use module::*;
51pub use weights::WeightInfo;54pub use weights::WeightInfo;
55
56/// Status of storage migration from an old XCM version to a new one.
57#[derive(Clone, Copy, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
58pub enum MigrationStatus {
59 V3ToV4(MigrationStatusV3ToV4),
60}
61
62/// Status of storage migration from XCMv3 to XCMv4.
63#[derive(Clone, Copy, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]
64pub enum MigrationStatusV3ToV4 {
65 /// The migration is completed.
66 Done,
67
68 /// An asset is skipped during the migration
69 /// due to its inconsistent state.
70 SkippedInconsistentAssetData(staging_xcm::v3::AssetId),
71
72 /// An asset instance is skipped during the migration
73 /// due to its inconsistent state.
74 SkippedInconsistentAssetInstanceData {
75 asset_id: staging_xcm::v3::AssetId,
76 asset_instance: staging_xcm::v3::AssetInstance,
77 },
78
79 /// An asset is skipped during the migration
80 /// because it couldn't be converted to the new XCM version.
81 SkippedNotConvertibleAssetId(staging_xcm::v3::AssetId),
82
83 /// An asset instance is skipped during the migration
84 /// because it couldn't be converted to the new XCM version.
85 SkippedNotConvertibleAssetInstance {
86 asset_id: staging_xcm::v3::AssetId,
87 asset_instance: staging_xcm::v3::AssetInstance,
88 },
89}
5290
53#[frame_support::pallet]91#[frame_support::pallet]
54pub mod module {92pub mod module {
93 use frame_support::traits::BuildGenesisConfig;
55 use pallet_common::CollectionIssuer;94 use pallet_common::CollectionIssuer;
56 use up_data_structs::CollectionDescription;95 use up_data_structs::CollectionDescription;
5796
93 }132 }
94133
95 #[pallet::event]134 #[pallet::event]
96 #[pallet::generate_deposit(fn deposit_event)]135 #[pallet::generate_deposit(pub(crate) fn deposit_event)]
97 pub enum Event<T: Config> {136 pub enum Event<T: Config> {
98 /// The foreign asset registered.137 /// The foreign asset registered.
99 ForeignAssetRegistered {138 ForeignAssetRegistered {
100 collection_id: CollectionId,139 collection_id: CollectionId,
101 asset_id: Box<VersionedAssetId>,140 asset_id: Box<VersionedAssetId>,
102 },141 },
142
143 /// The migration status.
144 MigrationStatus(MigrationStatus),
103 }145 }
104146
105 /// The corresponding collections of foreign assets.147 /// The corresponding collections of foreign assets.
106 #[pallet::storage]148 #[pallet::storage]
107 #[pallet::getter(fn foreign_asset_to_collection)]149 #[pallet::getter(fn foreign_asset_to_collection)]
108 pub type ForeignAssetToCollection<T: Config> =150 pub type ForeignAssetToCollection<T: Config> =
109 StorageMap<_, Twox64Concat, staging_xcm::v4::AssetId, CollectionId, OptionQuery>;151 StorageMap<_, Blake2_128Concat, staging_xcm::v4::AssetId, CollectionId, OptionQuery>;
110152
111 /// The corresponding foreign assets of collections.153 /// The corresponding foreign assets of collections.
112 #[pallet::storage]154 #[pallet::storage]
113 #[pallet::getter(fn collection_to_foreign_asset)]155 #[pallet::getter(fn collection_to_foreign_asset)]
114 pub type CollectionToForeignAsset<T: Config> =156 pub type CollectionToForeignAsset<T: Config> =
115 StorageMap<_, Twox64Concat, CollectionId, staging_xcm::v4::AssetId, OptionQuery>;157 StorageMap<_, Blake2_128Concat, CollectionId, staging_xcm::v4::AssetId, OptionQuery>;
116158
117 /// The correponding NFT token id of reserve NFTs159 /// The correponding NFT token id of reserve NFTs
118 #[pallet::storage]160 #[pallet::storage]
119 #[pallet::getter(fn foreign_reserve_asset_instance_to_token_id)]161 #[pallet::getter(fn foreign_reserve_asset_instance_to_token_id)]
120 pub type ForeignReserveAssetInstanceToTokenId<T: Config> = StorageDoubleMap<162 pub type ForeignReserveAssetInstanceToTokenId<T: Config> = StorageDoubleMap<
121 Hasher1 = Twox64Concat,163 Hasher1 = Blake2_128Concat,
122 Key1 = CollectionId,164 Key1 = CollectionId,
123 Hasher2 = Blake2_128Concat,165 Hasher2 = Blake2_128Concat,
124 // Key2 = staging_xcm::v3::AssetInstance,
125 Key2 = staging_xcm::v4::AssetInstance,166 Key2 = staging_xcm::v4::AssetInstance,
126 Value = TokenId,167 Value = TokenId,
127 QueryKind = OptionQuery,168 QueryKind = OptionQuery,
131 #[pallet::storage]172 #[pallet::storage]
132 #[pallet::getter(fn token_id_to_foreign_reserve_asset_instance)]173 #[pallet::getter(fn token_id_to_foreign_reserve_asset_instance)]
133 pub type TokenIdToForeignReserveAssetInstance<T: Config> = StorageDoubleMap<174 pub type TokenIdToForeignReserveAssetInstance<T: Config> = StorageDoubleMap<
134 Hasher1 = Twox64Concat,175 Hasher1 = Blake2_128Concat,
135 Key1 = CollectionId,176 Key1 = CollectionId,
136 Hasher2 = Blake2_128Concat,177 Hasher2 = Blake2_128Concat,
137 Key2 = TokenId,178 Key2 = TokenId,
138 // Value = staging_xcm::v3::AssetInstance,
139 Value = staging_xcm::v4::AssetInstance,179 Value = staging_xcm::v4::AssetInstance,
140 QueryKind = OptionQuery,180 QueryKind = OptionQuery,
141 >;181 >;
182
183 const STORAGE_VERSION: StorageVersion = StorageVersion::new(staging_xcm::v4::VERSION as u16);
142184
143 #[pallet::pallet]185 #[pallet::pallet]
186 #[pallet::storage_version(STORAGE_VERSION)]
144 pub struct Pallet<T>(_);187 pub struct Pallet<T>(_);
145188
146 #[pallet::call]189 #[pallet::call]
183 token_prefix,226 token_prefix,
184 description,227 description,
185 mode: mode.into(),228 mode: mode.into(),
229 flags: CollectionFlags {
230 foreign: true,
231 ..Default::default()
232 },
186 ..Default::default()233 ..Default::default()
187 },234 },
188 )?;235 )?;
199 }246 }
200 }247 }
248
249 #[pallet::genesis_config]
250 #[derive(Derivative)]
251 #[derivative(Default(bound = ""))]
252 pub struct GenesisConfig<T: Config>(PhantomData<T>);
253
254 #[pallet::genesis_build]
255 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
256 fn build(&self) {
257 <Pallet<T>>::in_code_storage_version().put::<Pallet<T>>();
258 }
259 }
260
261 #[pallet::hooks]
262 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
263 fn on_runtime_upgrade() -> Weight {
264 if Self::on_chain_storage_version() < staging_xcm::v4::VERSION as u16 {
265 let put_version_weight = T::DbWeight::get().writes(1);
266 let fix_foreign_flag_weight = Self::fix_foreign_flag();
267 let weight_v3_to_v4 = Self::migrate_v3_to_v4();
268
269 Self::in_code_storage_version().put::<Self>();
270
271 put_version_weight
272 .saturating_add(fix_foreign_flag_weight)
273 .saturating_add(weight_v3_to_v4)
274 } else {
275 Weight::zero()
276 }
277 }
278 }
201}279}
280
281mod v3_storage {
282 use super::*;
283
284 #[storage_alias]
285 pub type ForeignAssetToCollection<T: Config> =
286 StorageMap<Pallet<T>, Twox64Concat, staging_xcm::v3::AssetId, CollectionId, OptionQuery>;
287
288 #[storage_alias]
289 pub type CollectionToForeignAsset<T: Config> =
290 StorageMap<Pallet<T>, Twox64Concat, CollectionId, staging_xcm::v3::AssetId, OptionQuery>;
291
292 #[storage_alias]
293 pub type ForeignReserveAssetInstanceToTokenId<T: Config> = StorageDoubleMap<
294 Pallet<T>,
295 Twox64Concat,
296 CollectionId,
297 Blake2_128Concat,
298 staging_xcm::v3::AssetInstance,
299 TokenId,
300 OptionQuery,
301 >;
302
303 #[storage_alias]
304 pub type TokenIdToForeignReserveAssetInstance<T: Config> = StorageDoubleMap<
305 Pallet<T>,
306 Twox64Concat,
307 CollectionId,
308 Blake2_128Concat,
309 TokenId,
310 staging_xcm::v3::AssetInstance,
311 OptionQuery,
312 >;
313}
202314
203impl<T: Config> Pallet<T> {315impl<T: Config> Pallet<T> {
316 fn fix_foreign_flag() -> Weight {
317 let mut weight = Weight::zero();
318
319 for (_, collection_id) in v3_storage::ForeignAssetToCollection::<T>::iter() {
320 pallet_common::CollectionById::<T>::mutate(collection_id, |collection| {
321 if let Some(collection) = collection {
322 collection.flags.foreign = true;
323 }
324 });
325
326 weight = weight.saturating_add(T::DbWeight::get().reads_writes(2, 1));
327 }
328
329 weight
330 }
331
332 fn migrate_v3_to_v4() -> Weight {
333 let event_weight = T::DbWeight::get().writes(1);
334 let collection_migration_weight = Self::migrate_collections();
335
336 Self::deposit_event(Event::<T>::MigrationStatus(MigrationStatus::V3ToV4(
337 MigrationStatusV3ToV4::Done,
338 )));
339
340 collection_migration_weight.saturating_add(event_weight)
341 }
342
343 fn migrate_collections() -> Weight {
344 use MigrationStatus::*;
345 use MigrationStatusV3ToV4::*;
346
347 let mut weight = Weight::zero();
348
349 for (fwd_asset_id, collection_id) in v3_storage::ForeignAssetToCollection::<T>::drain() {
350 let bwd_asset_id = v3_storage::CollectionToForeignAsset::<T>::take(collection_id);
351 weight = weight.saturating_add(T::DbWeight::get().reads(2));
352
353 let Some(bwd_asset_id) = bwd_asset_id else {
354 Self::deposit_event(Event::<T>::MigrationStatus(V3ToV4(
355 SkippedInconsistentAssetData(fwd_asset_id),
356 )));
357
358 weight = weight.saturating_add(T::DbWeight::get().writes(1));
359 continue;
360 };
361
362 if fwd_asset_id != bwd_asset_id {
363 Self::deposit_event(Event::<T>::MigrationStatus(V3ToV4(
364 SkippedInconsistentAssetData(fwd_asset_id),
365 )));
366
367 weight = weight.saturating_add(T::DbWeight::get().writes(1));
368 continue;
369 }
370
371 let Ok(asset_id) = staging_xcm::v4::AssetId::try_from(fwd_asset_id) else {
372 Self::deposit_event(Event::<T>::MigrationStatus(V3ToV4(
373 SkippedNotConvertibleAssetId(fwd_asset_id),
374 )));
375
376 weight = weight.saturating_add(T::DbWeight::get().writes(1));
377 continue;
378 };
379
380 <ForeignAssetToCollection<T>>::insert(&asset_id, collection_id);
381 <CollectionToForeignAsset<T>>::insert(collection_id, asset_id);
382 weight = weight.saturating_add(T::DbWeight::get().writes(2));
383
384 let migrate_tokens_weight = Self::migrate_tokens(&fwd_asset_id, collection_id);
385 weight = weight.saturating_add(migrate_tokens_weight);
386 }
387
388 weight
389 }
390
391 fn migrate_tokens(asset_id: &staging_xcm::v3::AssetId, collection_id: CollectionId) -> Weight {
392 use MigrationStatus::*;
393 use MigrationStatusV3ToV4::*;
394
395 let mut weight = Weight::zero();
396
397 for (fwd_asset_instance, token_id) in
398 v3_storage::ForeignReserveAssetInstanceToTokenId::<T>::drain_prefix(collection_id)
399 {
400 let bwd_asset_instance = v3_storage::TokenIdToForeignReserveAssetInstance::<T>::take(
401 collection_id,
402 token_id,
403 );
404 weight = weight.saturating_add(T::DbWeight::get().reads(2));
405
406 let Some(bwd_asset_instance) = bwd_asset_instance else {
407 Self::deposit_event(Event::<T>::MigrationStatus(V3ToV4(
408 SkippedInconsistentAssetInstanceData {
409 asset_id: *asset_id,
410 asset_instance: fwd_asset_instance,
411 },
412 )));
413
414 weight = weight.saturating_add(T::DbWeight::get().writes(1));
415 continue;
416 };
417
418 if fwd_asset_instance != bwd_asset_instance {
419 Self::deposit_event(Event::<T>::MigrationStatus(V3ToV4(
420 SkippedInconsistentAssetInstanceData {
421 asset_id: *asset_id,
422 asset_instance: fwd_asset_instance,
423 },
424 )));
425
426 weight = weight.saturating_add(T::DbWeight::get().writes(1));
427 continue;
428 }
429
430 let Ok(asset_instance) = staging_xcm::v4::AssetInstance::try_from(fwd_asset_instance)
431 else {
432 Self::deposit_event(Event::<T>::MigrationStatus(V3ToV4(
433 SkippedNotConvertibleAssetInstance {
434 asset_id: *asset_id,
435 asset_instance: fwd_asset_instance,
436 },
437 )));
438
439 weight = weight.saturating_add(T::DbWeight::get().writes(1));
440 continue;
441 };
442
443 <ForeignReserveAssetInstanceToTokenId<T>>::insert(
444 collection_id,
445 &asset_instance,
446 token_id,
447 );
448 <TokenIdToForeignReserveAssetInstance<T>>::insert(
449 collection_id,
450 token_id,
451 asset_instance,
452 );
453 weight = weight.saturating_add(T::DbWeight::get().writes(2));
454 }
455
456 weight
457 }
458
204 fn pallet_account() -> T::CrossAccountId {459 fn pallet_account() -> T::CrossAccountId {
205 let owner: T::AccountId = T::PalletId::get().into_account_truncating();460 let owner: T::AccountId = T::PalletId::get().into_account_truncating();