1use polkadot_sdk::frame_support::{
2 migrations::VersionedMigration, sp_runtime::traits::Get, traits::UncheckedOnRuntimeUpgrade,
3 weights::Weight,
4};
5
6use crate::{Config, Pallet};
7
8pub mod v5 {
9 use pallet_permission0_api::{CuratorPermissions, Permission0CuratorApi, PermissionDuration};
10 use polkadot_sdk::{
11 frame_system::RawOrigin,
12 sp_tracing::{info, warn},
13 };
14
15 use crate::proposal::{GlobalParamsData, ProposalData};
16
17 use super::*;
18
19 pub type Migration<T, W> = VersionedMigration<2, 5, MigrateToV3<T>, Pallet<T>, W>;
20 pub struct MigrateToV3<T>(core::marker::PhantomData<T>);
21
22 mod old_storage {
23 use codec::{Decode, Encode, MaxEncodedLen};
24 use polkadot_sdk::{
25 frame_support::{storage_alias, DebugNoBound, Identity},
26 polkadot_sdk_frame::prelude::BlockNumberFor,
27 sp_core::ConstU32,
28 sp_runtime::{BoundedVec, Percent},
29 };
30 use scale_info::TypeInfo;
31
32 use crate::{
33 proposal::{ProposalId, ProposalStatus},
34 AccountIdOf, BalanceOf,
35 };
36
37 #[derive(Clone, DebugNoBound, TypeInfo, Decode, Encode, MaxEncodedLen)]
38 #[scale_info(skip_type_params(T))]
39 pub struct Proposal<T: crate::Config> {
40 pub id: ProposalId,
41 pub proposer: AccountIdOf<T>,
42 pub expiration_block: BlockNumberFor<T>,
43 pub data: ProposalData<T>,
44 pub status: ProposalStatus<T>,
45 pub metadata: BoundedVec<u8, ConstU32<256>>,
46 pub proposal_cost: BalanceOf<T>,
47 pub creation_block: BlockNumberFor<T>,
48 }
49
50 #[derive(Clone, DebugNoBound, TypeInfo, Decode, Encode, MaxEncodedLen, PartialEq, Eq)]
51 #[scale_info(skip_type_params(T))]
52 pub enum ProposalData<T: crate::Config> {
53 GlobalParams(GlobalParamsData<T>),
54 GlobalCustom,
55 Emission {
56 recycling_percentage: Percent,
57 treasury_percentage: Percent,
58 incentives_ratio: Percent,
59 },
60 TransferDaoTreasury {
61 account: AccountIdOf<T>,
62 amount: BalanceOf<T>,
63 },
64 }
65
66 #[derive(Clone, DebugNoBound, TypeInfo, Decode, Encode, MaxEncodedLen, PartialEq, Eq)]
67 #[scale_info(skip_type_params(T))]
68 pub struct GlobalParamsData<T: crate::Config> {
69 pub min_name_length: u16,
70 pub max_name_length: u16,
71 pub max_allowed_agents: u16,
72 pub max_allowed_weights: u16,
73 pub min_stake_per_weight: BalanceOf<T>,
74 pub min_weight_control_fee: u8,
75 pub min_staking_fee: u8,
76 pub dividends_participation_weight: Percent,
77 pub proposal_cost: BalanceOf<T>,
78 }
79
80 #[storage_alias]
81 pub type Proposals<T: crate::Config> =
82 StorageMap<crate::Pallet<T>, Identity, ProposalId, Proposal<T>>;
83
84 #[storage_alias]
85 pub type Curators<T: crate::Config> =
86 StorageMap<crate::Pallet<T>, Identity, AccountIdOf<T>, ()>;
87 }
88
89 impl<T: Config> UncheckedOnRuntimeUpgrade for MigrateToV3<T> {
90 fn on_runtime_upgrade() -> Weight {
91 for (id, proposal) in old_storage::Proposals::iter() {
92 let new_data = match proposal.data {
93 old_storage::ProposalData::GlobalParams(old_storage::GlobalParamsData {
94 min_name_length,
95 max_name_length,
96 min_weight_control_fee,
97 min_staking_fee,
98 dividends_participation_weight,
99 proposal_cost,
100 ..
101 }) => ProposalData::GlobalParams(GlobalParamsData {
102 min_name_length,
103 max_name_length,
104 min_weight_control_fee,
105 min_staking_fee,
106 dividends_participation_weight,
107 namespace_pricing_config:
108 <T as pallet_torus0::Config>::DefaultNamespacePricingConfig::get(),
109 proposal_cost,
110 }),
111 old_storage::ProposalData::GlobalCustom => ProposalData::GlobalCustom,
112 old_storage::ProposalData::Emission {
113 recycling_percentage,
114 treasury_percentage,
115 incentives_ratio,
116 } => ProposalData::Emission {
117 recycling_percentage,
118 treasury_percentage,
119 incentives_ratio,
120 },
121 old_storage::ProposalData::TransferDaoTreasury { account, amount } => {
122 ProposalData::TransferDaoTreasury { account, amount }
123 }
124 };
125
126 let new_proposal = crate::proposal::Proposal {
127 id: proposal.id,
128 proposer: proposal.proposer,
129 expiration_block: proposal.expiration_block,
130 data: new_data,
131 status: proposal.status,
132 metadata: proposal.metadata,
133 proposal_cost: proposal.proposal_cost,
134 creation_block: proposal.creation_block,
135 };
136
137 crate::Proposals::<T>::set(id, Some(new_proposal));
138 }
139
140 for (curator, _) in old_storage::Curators::<T>::iter() {
141 let res = <<T as Config>::Permission0>::grant_curator_permission(
142 RawOrigin::Root.into(),
143 curator.clone(),
144 CuratorPermissions::all(),
145 None,
146 PermissionDuration::Indefinite,
147 pallet_permission0_api::RevocationTerms::RevocableByGrantor,
148 );
149
150 match res {
151 Ok(perm_id) => info!("migrated curator {curator:?} to permission0: {perm_id}"),
152 Err(err) => {
153 warn!("Could not migrate curator {curator:?} to permission0: {err:?}");
154 }
155 }
156 }
157
158 Weight::zero()
159 }
160 }
161}