use super::*;
use frame_support::{
pallet_prelude::*,
traits::{Get, UncheckedOnRuntimeUpgrade},
};
use sp_std::{marker::PhantomData, vec::Vec};
use xcm::{IntoVersion, VersionedLocation};
pub mod versioned {
use super::*;
pub type V2ToV3<T> = frame_support::migrations::VersionedMigration<
2,
3,
MigrationXcmV4<T>,
Pallet<T>,
<T as frame_system::Config>::DbWeight,
>;
}
pub struct MigrationXcmV3<T: Config>(PhantomData<T>);
impl<T: Config> UncheckedOnRuntimeUpgrade for MigrationXcmV3<T> {
fn on_runtime_upgrade() -> Weight {
let version = Pallet::<T>::on_chain_storage_version();
let mut consumed_weight = Weight::zero();
if version >= 2 {
return consumed_weight;
}
let id_to_location_entries: Vec<_> = AssetIdToLocation::<T>::iter().collect();
for (asset_id, legacy_location) in id_to_location_entries {
consumed_weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
if let Ok(new_location) = legacy_location.into_version(3) {
AssetIdToLocation::<T>::insert(asset_id, new_location);
} else {
log::warn!(
"Failed to convert AssetIdToLocation value for asset Id: {:?}",
asset_id
);
}
}
let location_to_id_entries: Vec<_> = AssetLocationToId::<T>::drain().collect();
for (legacy_location, asset_id) in location_to_id_entries {
consumed_weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2));
if let Ok(new_location) = legacy_location.into_version(3) {
AssetLocationToId::<T>::insert(new_location, asset_id);
} else {
log::warn!(
"Failed to convert AssetLocationToId value for asset Id: {:?}",
asset_id
);
}
}
let location_to_price_entries: Vec<_> = AssetLocationUnitsPerSecond::<T>::drain().collect();
for (legacy_location, price) in location_to_price_entries {
consumed_weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 2));
if let Ok(new_location) = legacy_location.into_version(3) {
AssetLocationUnitsPerSecond::<T>::insert(new_location, price);
} else {
log::warn!("Failed to convert AssetLocationUnitsPerSecond value!");
}
}
StorageVersion::new(2).put::<Pallet<T>>();
consumed_weight.saturating_accrue(T::DbWeight::get().reads(1));
consumed_weight
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
assert!(Pallet::<T>::on_chain_storage_version() < 2);
let id_to_location_entries: Vec<_> = AssetIdToLocation::<T>::iter().collect();
Ok(id_to_location_entries.encode())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
assert_eq!(Pallet::<T>::on_chain_storage_version(), 2);
let legacy_id_to_location_entries: Vec<(T::AssetId, VersionedLocation)> =
Decode::decode(&mut state.as_ref())
.map_err(|_| "Cannot decode data from pre_upgrade")?;
let new_id_to_location_entries: Vec<_> = AssetIdToLocation::<T>::iter().collect();
assert_eq!(
legacy_id_to_location_entries.len(),
new_id_to_location_entries.len()
);
for (ref id, ref _legacy_location) in legacy_id_to_location_entries {
let new_location = AssetIdToLocation::<T>::get(id);
assert!(new_location.is_some());
let new_location = new_location.expect("Assert above ensures it's `Some`.");
assert_eq!(AssetLocationToId::<T>::get(&new_location), Some(*id));
assert!(AssetLocationUnitsPerSecond::<T>::contains_key(
&new_location
));
}
Ok(())
}
}
pub struct MigrationXcmV4<T: Config>(PhantomData<T>);
impl<T: Config> UncheckedOnRuntimeUpgrade for MigrationXcmV4<T> {
#[allow(deprecated)]
fn on_runtime_upgrade() -> Weight {
let mut consumed_weight = Weight::zero();
AssetIdToLocation::<T>::translate::<xcm::VersionedMultiLocation, _>(
|asset_id, multi_location| {
consumed_weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
VersionedLocation::try_from(multi_location)
.map_err(|_| {
log::error!(
"Failed to convert AssetIdToLocation value for asset Id: {asset_id:?}",
);
})
.ok()
},
);
let location_to_id_entries: Vec<_> = AssetLocationToId::<T>::drain().collect();
for (multi_location, asset_id) in location_to_id_entries {
consumed_weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
if let Ok(new_location) = multi_location.into_version(4) {
AssetLocationToId::<T>::insert(new_location, asset_id);
} else {
log::error!("Failed to convert AssetLocationToId value for asset Id: {asset_id:?}",);
}
}
let location_to_price_entries: Vec<_> = AssetLocationUnitsPerSecond::<T>::drain().collect();
for (multi_location, price) in location_to_price_entries {
consumed_weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
if let Ok(new_location) = multi_location.into_version(4) {
AssetLocationUnitsPerSecond::<T>::insert(new_location, price);
} else {
log::error!("Failed to convert AssetLocationUnitsPerSecond value failed!");
}
}
StorageVersion::new(3).put::<Pallet<T>>();
consumed_weight.saturating_accrue(T::DbWeight::get().writes(1));
consumed_weight
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
assert!(Pallet::<T>::on_chain_storage_version() < 3);
let mut count = AssetIdToLocation::<T>::iter().collect::<Vec<_>>().len();
count += AssetLocationToId::<T>::iter().collect::<Vec<_>>().len();
count += AssetLocationUnitsPerSecond::<T>::iter()
.collect::<Vec<_>>()
.len();
Ok((count as u32).encode())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
assert_eq!(Pallet::<T>::on_chain_storage_version(), 3);
let old_count: u32 = Decode::decode(&mut state.as_ref())
.map_err(|_| "Cannot decode data from pre_upgrade")?;
let mut count = AssetIdToLocation::<T>::iter().collect::<Vec<_>>().len();
count += AssetLocationToId::<T>::iter().collect::<Vec<_>>().len();
count += AssetLocationUnitsPerSecond::<T>::iter()
.collect::<Vec<_>>()
.len();
assert_eq!(old_count, count as u32);
Ok(())
}
}