pallet_governance/
migrations.rs

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}