pallet_xc_asset_config/
migrations.rs

1// This file is part of Astar.
2
3// Copyright (C) Stake Technologies Pte.Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later
5
6// Astar is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// Astar is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with Astar. If not, see <http://www.gnu.org/licenses/>.
18
19use super::*;
20use frame_support::{
21    pallet_prelude::*,
22    traits::{Get, UncheckedOnRuntimeUpgrade},
23};
24use sp_std::{marker::PhantomData, vec::Vec};
25
26/// Exports for versioned migration `type`s for this pallet.
27pub mod versioned {
28    use super::*;
29
30    /// Migration storage V3 to V4 wrapped in a [`frame_support::migrations::VersionedMigration`], ensuring
31    /// the migration is only performed when on-chain version is 3.
32    pub type V3ToV4<T> = frame_support::migrations::VersionedMigration<
33        3,
34        4,
35        unchecked_migration::UncheckedMigrationXcmVersion<{ xcm::v5::VERSION }, T>,
36        Pallet<T>,
37        <T as frame_system::Config>::DbWeight,
38    >;
39
40    /// Migration storage V4 to V5 which removes `AssetHubMigrationStep`.
41    pub type V4ToV5<T> = frame_support::migrations::VersionedMigration<
42        4,
43        5,
44        unchecked_migration::UncheckedMigrationRemoveAssetHubStep<T>,
45        Pallet<T>,
46        <T as frame_system::Config>::DbWeight,
47    >;
48}
49
50mod unchecked_migration {
51    use super::*;
52    use xcm::IntoVersion;
53
54    /// Migration for XCM versioned locations, generic over XCM version.
55    pub struct UncheckedMigrationXcmVersion<const XCM_VERSION: u32, T: Config>(PhantomData<T>);
56    impl<const XCM_VERSION: u32, T: Config> UncheckedOnRuntimeUpgrade
57        for UncheckedMigrationXcmVersion<XCM_VERSION, T>
58    {
59        fn on_runtime_upgrade() -> Weight {
60            let mut consumed_weight = Weight::zero();
61
62            // 1st map
63            AssetIdToLocation::<T>::translate::<xcm::VersionedLocation, _>(
64                |asset_id, multi_location| {
65                    consumed_weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
66
67                    multi_location
68                        .into_version(XCM_VERSION)
69                        .map_err(|_| {
70                            log::error!(
71                            "Failed to convert AssetIdToLocation value for asset Id: {asset_id:?}",
72                        );
73                        })
74                        .ok()
75                },
76            );
77
78            // 2nd map
79            let location_to_id_entries: Vec<_> = AssetLocationToId::<T>::drain().collect();
80            for (multi_location, asset_id) in location_to_id_entries {
81                consumed_weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
82
83                if let Ok(new_location) = multi_location.into_version(XCM_VERSION) {
84                    AssetLocationToId::<T>::insert(new_location, asset_id);
85                } else {
86                    log::error!(
87                        "Failed to convert AssetLocationToId value for asset Id: {asset_id:?}",
88                    );
89                }
90            }
91
92            // 3rd map
93            let location_to_price_entries: Vec<_> =
94                AssetLocationUnitsPerSecond::<T>::drain().collect();
95            for (multi_location, price) in location_to_price_entries {
96                consumed_weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
97
98                if let Ok(new_location) = multi_location.into_version(XCM_VERSION) {
99                    AssetLocationUnitsPerSecond::<T>::insert(new_location, price);
100                } else {
101                    log::error!("Failed to convert AssetLocationUnitsPerSecond value failed!");
102                }
103            }
104
105            consumed_weight
106        }
107
108        #[cfg(feature = "try-runtime")]
109        fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
110            let mut count = AssetIdToLocation::<T>::iter().collect::<Vec<_>>().len();
111            count += AssetLocationToId::<T>::iter().collect::<Vec<_>>().len();
112            count += AssetLocationUnitsPerSecond::<T>::iter()
113                .collect::<Vec<_>>()
114                .len();
115
116            Ok((count as u32).encode())
117        }
118
119        #[cfg(feature = "try-runtime")]
120        fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
121            let old_count: u32 = Decode::decode(&mut state.as_ref())
122                .map_err(|_| "Cannot decode data from pre_upgrade")?;
123
124            let mut count = AssetIdToLocation::<T>::iter().collect::<Vec<_>>().len();
125            count += AssetLocationToId::<T>::iter().collect::<Vec<_>>().len();
126            count += AssetLocationUnitsPerSecond::<T>::iter()
127                .collect::<Vec<_>>()
128                .len();
129
130            assert_eq!(old_count, count as u32);
131            Ok(())
132        }
133    }
134
135    /// Migration that clears the old `AssetHubMigrationStep` storage key.
136    pub struct UncheckedMigrationRemoveAssetHubStep<T: Config>(PhantomData<T>);
137    impl<T: Config> UncheckedOnRuntimeUpgrade for UncheckedMigrationRemoveAssetHubStep<T> {
138        fn on_runtime_upgrade() -> Weight {
139            use sp_core::hexdisplay::HexDisplay;
140
141            let key = frame_support::storage::storage_prefix(
142                <Pallet<T>>::name().as_bytes(),
143                b"AssetHubMigrationStep",
144            );
145            frame_support::storage::unhashed::kill(&key);
146
147            log::info!(
148                "Deleted AssetHubMigrationStep key: 0x{}",
149                HexDisplay::from(&key)
150            );
151
152            T::DbWeight::get().writes(1)
153        }
154
155        #[cfg(feature = "try-runtime")]
156        fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::DispatchError> {
157            let key = frame_support::storage::storage_prefix(
158                <Pallet<T>>::name().as_bytes(),
159                b"AssetHubMigrationStep",
160            );
161
162            Ok(key.to_vec())
163        }
164
165        #[cfg(feature = "try-runtime")]
166        fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::DispatchError> {
167            use sp_io::storage::exists;
168
169            let key = state;
170
171            // Ensure the value was deleted.
172            assert!(
173                !exists(&key),
174                "AssetHubMigrationStep should be removed after migration"
175            );
176
177            Ok(())
178        }
179    }
180}