pallet_inflation/
migration.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::pallet_prelude::Weight;
21use frame_support::traits::UncheckedOnRuntimeUpgrade;
22
23#[cfg(feature = "try-runtime")]
24use sp_std::vec::Vec;
25
26#[cfg(feature = "try-runtime")]
27use sp_runtime::TryRuntimeError;
28
29/// Exports for versioned migration `type`s for this pallet.
30pub mod versioned_migrations {
31    use super::*;
32
33    /// Migration V1 to V2 wrapped in a [`frame_support::migrations::VersionedMigration`], ensuring
34    /// the migration is only performed when on-chain version is 1.
35    pub type V1ToV2<T, DecayRate, DecayFactor> = frame_support::migrations::VersionedMigration<
36        1,
37        2,
38        v2::VersionMigrateV1ToV2<T, DecayRate, DecayFactor>,
39        Pallet<T>,
40        <T as frame_system::Config>::DbWeight,
41    >;
42}
43
44mod v2 {
45    use super::*;
46    use crate::migration::v1::{
47        InflationConfiguration as InflationConfigurationV1,
48        InflationParameters as InflationParametersV1,
49    };
50
51    pub struct VersionMigrateV1ToV2<T, DecayRate, DecayFactor>(
52        PhantomData<(T, DecayRate, DecayFactor)>,
53    );
54
55    impl<T: Config, DecayRate: Get<Perquintill>, DecayFactor: Get<Perquintill>>
56        UncheckedOnRuntimeUpgrade for VersionMigrateV1ToV2<T, DecayRate, DecayFactor>
57    {
58        fn on_runtime_upgrade() -> Weight {
59            let decay_rate = DecayRate::get();
60            let decay_factor = DecayFactor::get();
61
62            // Add the _decay_rate_ to the inflation params
63            let result =
64                InflationParams::<T>::translate::<InflationParametersV1, _>(|maybe_old_params| {
65                    match maybe_old_params {
66                        Some(old_params) => Some(InflationParameters {
67                            max_inflation_rate: old_params.max_inflation_rate,
68                            treasury_part: old_params.treasury_part,
69                            collators_part: old_params.collators_part,
70                            dapps_part: old_params.dapps_part,
71                            base_stakers_part: old_params.base_stakers_part,
72                            adjustable_stakers_part: old_params.adjustable_stakers_part,
73                            bonus_part: old_params.bonus_part,
74                            ideal_staking_rate: old_params.ideal_staking_rate,
75                            decay_rate,
76                        }),
77                        _ => None,
78                    }
79                });
80
81            if result.is_err() {
82                log::error!("Failed to translate InflationParams from previous V1 type to current V2 type. Check InflationParametersV1 decoding.");
83                return T::DbWeight::get().reads_writes(1, 0);
84            }
85
86            // Add the _decay_rate_ and _decay_factor_ to the active config
87            let result = ActiveInflationConfig::<T>::translate::<InflationConfigurationV1, _>(
88                |maybe_old_config| match maybe_old_config {
89                    Some(old_config) => Some(InflationConfiguration {
90                        recalculation_era: old_config.recalculation_era,
91                        issuance_safety_cap: old_config.issuance_safety_cap,
92                        collator_reward_per_block: old_config.collator_reward_per_block,
93                        treasury_reward_per_block: old_config.treasury_reward_per_block,
94                        dapp_reward_pool_per_era: old_config.dapp_reward_pool_per_era,
95                        base_staker_reward_pool_per_era: old_config.base_staker_reward_pool_per_era,
96                        adjustable_staker_reward_pool_per_era: old_config
97                            .adjustable_staker_reward_pool_per_era,
98                        bonus_reward_pool_per_period: old_config.bonus_reward_pool_per_period,
99                        ideal_staking_rate: old_config.ideal_staking_rate,
100                        decay_rate,
101                        decay_factor,
102                    }),
103                    _ => None,
104                },
105            );
106
107            if result.is_err() {
108                log::error!("Failed to translate InflationConfiguration from previous V1 type to current V2 type. Check InflationConfigurationV1 decoding.");
109                return T::DbWeight::get().reads_writes(2, 1);
110            }
111
112            T::DbWeight::get().reads_writes(2, 2)
113        }
114
115        #[cfg(feature = "try-runtime")]
116        fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
117            let old_config = v1::ActiveInflationConfig::<T>::get().ok_or_else(|| {
118                TryRuntimeError::Other(
119                    "pallet-inflation::migration::v2: No old config found for ActiveInflationConfig",
120                )
121            })?;
122
123            let old_params = v1::InflationParams::<T>::get().ok_or_else(|| {
124                TryRuntimeError::Other(
125                    "pallet-inflation::migration::v2: No old params found for InflationParams",
126                )
127            })?;
128            Ok((old_config, old_params).encode())
129        }
130
131        #[cfg(feature = "try-runtime")]
132        fn post_upgrade(data: Vec<u8>) -> Result<(), TryRuntimeError> {
133            // Decode the old values
134            let (old_config, old_params): (InflationConfigurationV1, InflationParametersV1) =
135                Decode::decode(&mut &data[..]).map_err(|_| {
136                    TryRuntimeError::Other(
137                        "pallet-inflation::migration::v2: Failed to decode old values",
138                    )
139                })?;
140
141            // Get the new values
142            let new_config = ActiveInflationConfig::<T>::get();
143            let new_params = InflationParams::<T>::get();
144
145            // Verify that new params and new config are valid
146            assert!(new_params.is_valid());
147            new_config.sanity_check();
148
149            // Verify active config remain unchanged
150            assert_eq!(
151                old_config.recalculation_era, new_config.recalculation_era,
152                "pallet-inflation::migration::v2: Recalculation Era has changed"
153            );
154            assert_eq!(
155                old_config.issuance_safety_cap, new_config.issuance_safety_cap,
156                "pallet-inflation::migration::v2: Issuance Safety Cap has changed"
157            );
158            assert_eq!(
159                old_config.collator_reward_per_block, new_config.collator_reward_per_block,
160                "pallet-inflation::migration::v2: Collator Reward Per Block has changed"
161            );
162            assert_eq!(
163                old_config.treasury_reward_per_block, new_config.treasury_reward_per_block,
164                "pallet-inflation::migration::v2: Treasury Reward Per Block has changed"
165            );
166            assert_eq!(
167                old_config.dapp_reward_pool_per_era, new_config.dapp_reward_pool_per_era,
168                "pallet-inflation::migration::v2: Dapp Reward Per Era has changed"
169            );
170            assert_eq!(
171                old_config.base_staker_reward_pool_per_era,
172                new_config.base_staker_reward_pool_per_era,
173                "pallet-inflation::migration::v2: Staker Reward Pool Per Era has changed"
174            );
175            assert_eq!(
176                old_config.adjustable_staker_reward_pool_per_era, new_config.adjustable_staker_reward_pool_per_era,
177                "pallet-inflation::migration::v2: Adjustable Staker Reward Pool Per Era has changed"
178            );
179            assert_eq!(
180                old_config.bonus_reward_pool_per_period, new_config.bonus_reward_pool_per_period,
181                "pallet-inflation::migration::v2: Bonus Reward Pool Per Period has changed"
182            );
183            assert_eq!(
184                old_config.ideal_staking_rate, new_config.ideal_staking_rate,
185                "pallet-inflation::migration::v2: Ideal staking rate has changed in config"
186            );
187
188            // Verify parameters remain unchanged
189            assert_eq!(
190                old_params.max_inflation_rate, new_params.max_inflation_rate,
191                "pallet-inflation::migration::v2: Max inflation rate has changed"
192            );
193            assert_eq!(
194                old_params.treasury_part, new_params.treasury_part,
195                "pallet-inflation::migration::v2: Treasury part has changed"
196            );
197            assert_eq!(
198                old_params.collators_part, new_params.collators_part,
199                "pallet-inflation::migration::v2: Collator part has changed"
200            );
201            assert_eq!(
202                old_params.dapps_part, new_params.dapps_part,
203                "pallet-inflation::migration::v2: Dapps part has changed"
204            );
205            assert_eq!(
206                old_params.base_stakers_part, new_params.base_stakers_part,
207                "pallet-inflation::migration::v2: Base staker part has changed"
208            );
209            assert_eq!(
210                old_params.adjustable_stakers_part, new_params.adjustable_stakers_part,
211                "pallet-inflation::migration::v2: Adjustable staker part has changed"
212            );
213            assert_eq!(
214                old_params.bonus_part, new_params.bonus_part,
215                "pallet-inflation::migration::v2: Bonus staker part has changed"
216            );
217            assert_eq!(
218                old_params.ideal_staking_rate, new_params.ideal_staking_rate,
219                "pallet-inflation::migration::v2: Ideal staking rate has changed in params"
220            );
221
222            // Verify correct decay rate is initialized
223            let expected_decay_rate = DecayRate::get();
224            assert_eq!(
225                expected_decay_rate, new_params.decay_rate,
226                "pallet-inflation::migration::v2: No correct decay rate in params"
227            );
228            assert_eq!(
229                expected_decay_rate, new_config.decay_rate,
230                "pallet-inflation::migration::v2: No correct decay rate in config"
231            );
232
233            // Verify correct decay factor is initialized
234            let expected_decay_factor = DecayFactor::get();
235            assert_eq!(
236                expected_decay_factor, new_config.decay_factor,
237                "pallet-inflation::migration::v2: No correct decay factor in config"
238            );
239
240            // Verify storage version has been updated
241            ensure!(
242                Pallet::<T>::on_chain_storage_version() >= 2,
243                "pallet-inflation::migration::v2: Wrong storage version."
244            );
245
246            Ok(())
247        }
248    }
249}
250
251mod v1 {
252    use super::*;
253    use frame_support::storage_alias;
254
255    #[derive(Encode, Decode)]
256    pub struct InflationConfiguration {
257        #[codec(compact)]
258        pub recalculation_era: EraNumber,
259        #[codec(compact)]
260        pub issuance_safety_cap: Balance,
261        #[codec(compact)]
262        pub collator_reward_per_block: Balance,
263        #[codec(compact)]
264        pub treasury_reward_per_block: Balance,
265        #[codec(compact)]
266        pub dapp_reward_pool_per_era: Balance,
267        #[codec(compact)]
268        pub base_staker_reward_pool_per_era: Balance,
269        #[codec(compact)]
270        pub adjustable_staker_reward_pool_per_era: Balance,
271        #[codec(compact)]
272        pub bonus_reward_pool_per_period: Balance,
273        #[codec(compact)]
274        pub ideal_staking_rate: Perquintill,
275    }
276
277    #[derive(Encode, Decode)]
278    pub struct InflationParameters {
279        #[codec(compact)]
280        pub max_inflation_rate: Perquintill,
281        #[codec(compact)]
282        pub treasury_part: Perquintill,
283        #[codec(compact)]
284        pub collators_part: Perquintill,
285        #[codec(compact)]
286        pub dapps_part: Perquintill,
287        #[codec(compact)]
288        pub base_stakers_part: Perquintill,
289        #[codec(compact)]
290        pub adjustable_stakers_part: Perquintill,
291        #[codec(compact)]
292        pub bonus_part: Perquintill,
293        #[codec(compact)]
294        pub ideal_staking_rate: Perquintill,
295    }
296
297    /// v1 type for [`crate::ActiveInflationConfig`]
298    #[storage_alias]
299    pub type ActiveInflationConfig<T: Config> = StorageValue<Pallet<T>, InflationConfiguration>;
300
301    /// v1 type for [`crate::InflationParams`]
302    #[storage_alias]
303    pub type InflationParams<T: Config> = StorageValue<Pallet<T>, InflationParameters>;
304}