1
// Copyright 2019-2022 PureStake Inc.
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Moonbeam is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
use frame_support::{traits::OnRuntimeUpgrade, weights::Weight};
18

            
19
use crate::*;
20

            
21
#[derive(
22
	Clone,
23
	PartialEq,
24
	Eq,
25
	parity_scale_codec::Decode,
26
	parity_scale_codec::Encode,
27
	sp_runtime::RuntimeDebug,
28
)]
29
/// Reserve information { account, percent_of_inflation }
30
pub struct OldParachainBondConfig<AccountId> {
31
	/// Account which receives funds intended for parachain bond
32
	pub account: AccountId,
33
	/// Percent of inflation set aside for parachain bond account
34
	pub percent: sp_runtime::Percent,
35
}
36

            
37
pub struct MigrateParachainBondConfig<T>(sp_std::marker::PhantomData<T>);
38
impl<T: Config> OnRuntimeUpgrade for MigrateParachainBondConfig<T> {
39
	fn on_runtime_upgrade() -> Weight {
40
		let (account, percent) = if let Some(config) =
41
			frame_support::storage::migration::get_storage_value::<
42
				OldParachainBondConfig<T::AccountId>,
43
			>(b"ParachainStaking", b"ParachainBondInfo", &[])
44
		{
45
			(config.account, config.percent)
46
		} else {
47
			return Weight::default();
48
		};
49

            
50
		let pbr = InflationDistributionAccount { account, percent };
51
		let treasury = InflationDistributionAccount::<T::AccountId>::default();
52
		let configs: InflationDistributionConfig<T::AccountId> = [pbr, treasury].into();
53

            
54
		//***** Start mutate storage *****//
55

            
56
		InflationDistributionInfo::<T>::put(configs);
57

            
58
		// Remove storage value ParachainStaking::ParachainBondInfo
59
		frame_support::storage::unhashed::kill(&frame_support::storage::storage_prefix(
60
			b"ParachainStaking",
61
			b"ParachainBondInfo",
62
		));
63

            
64
		Weight::default()
65
	}
66

            
67
	#[cfg(feature = "try-runtime")]
68
	fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::DispatchError> {
69
		use frame_support::ensure;
70
		use parity_scale_codec::Encode;
71

            
72
		let state = frame_support::storage::migration::get_storage_value::<
73
			OldParachainBondConfig<T::AccountId>,
74
		>(b"ParachainStaking", b"ParachainBondInfo", &[]);
75

            
76
		ensure!(state.is_some(), "State not found");
77

            
78
		Ok(state.unwrap().encode())
79
	}
80

            
81
	#[cfg(feature = "try-runtime")]
82
	fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::DispatchError> {
83
		use frame_support::ensure;
84

            
85
		let old_state: OldParachainBondConfig<T::AccountId> =
86
			parity_scale_codec::Decode::decode(&mut &state[..])
87
				.map_err(|_| sp_runtime::DispatchError::Other("Failed to decode old state"))?;
88

            
89
		let new_state = InflationDistributionInfo::<T>::get();
90

            
91
		let pbr = InflationDistributionAccount {
92
			account: old_state.account,
93
			percent: old_state.percent,
94
		};
95
		let treasury = InflationDistributionAccount::<T::AccountId>::default();
96
		let expected_new_state: InflationDistributionConfig<T::AccountId> = [pbr, treasury].into();
97

            
98
		ensure!(new_state == expected_new_state, "State migration failed");
99

            
100
		Ok(())
101
	}
102
}