1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090 |
- //! # Proposals codex module
- //! Proposals `codex` module for the Joystream platform. Version 2.
- //! Component of the proposals system. It contains preset proposal types.
- //!
- //! ## Overview
- //!
- //! The proposals codex module serves as a facade and entry point of the proposals system. It uses
- //! proposals `engine` module to maintain a lifecycle of the proposal and to execute proposals.
- //! During the proposal creation, `codex` also create a discussion thread using the `discussion`
- //! proposals module. `Codex` uses predefined parameters (eg.:`voting_period`) for each proposal and
- //! encodes extrinsic calls from dependency modules in order to create proposals inside the `engine`
- //! module. For each proposal, [its crucial details](./enum.ProposalDetails.html) are saved to the
- //! `ProposalDetailsByProposalId` map.
- //!
- //! ### Supported extrinsics (proposal types)
- //! - [create_text_proposal](./struct.Module.html#method.create_text_proposal)
- //! - [create_runtime_upgrade_proposal](./struct.Module.html#method.create_runtime_upgrade_proposal)
- //! - [create_set_election_parameters_proposal](./struct.Module.html#method.create_set_election_parameters_proposal)
- //! - [create_set_content_working_group_mint_capacity_proposal](./struct.Module.html#method.create_set_content_working_group_mint_capacity_proposal)
- //! - [create_spending_proposal](./struct.Module.html#method.create_spending_proposal)
- //! - [create_set_lead_proposal](./struct.Module.html#method.create_set_lead_proposal)
- //! - [create_evict_storage_provider_proposal](./struct.Module.html#method.create_evict_storage_provider_proposal)
- //! - [create_set_validator_count_proposal](./struct.Module.html#method.create_set_validator_count_proposal)
- //! - [create_set_storage_role_parameters_proposal](./struct.Module.html#method.create_set_storage_role_parameters_proposal)
- //!
- //! ### Proposal implementations of this module
- //! - execute_text_proposal - prints the proposal to the log
- //! - execute_runtime_upgrade_proposal - sets the runtime code
- //!
- //! ### Dependencies:
- //! - [proposals engine](../substrate_proposals_engine_module/index.html)
- //! - [proposals discussion](../substrate_proposals_discussion_module/index.html)
- //! - [membership](../substrate_membership_module/index.html)
- //! - [governance](../substrate_governance_module/index.html)
- //! - [content_working_group](../substrate_content_working_group_module/index.html)
- //!
- //! ### Notes
- //! The module uses [ProposalEncoder](./trait.ProposalEncoder.html) to encode the proposal using
- //! its details. Encoded byte vector is passed to the _proposals engine_ as serialized executable code.
- // Clippy linter warning. TODO: remove after the Constaninople release
- #![allow(clippy::type_complexity)]
- // disable it because of possible frontend API break
- // Clippy linter warning. TODO: refactor "this function has too many argument"
- #![allow(clippy::too_many_arguments)] // disable it because of possible API break
- // Ensure we're `no_std` when compiling for Wasm.
- #![cfg_attr(not(feature = "std"), no_std)]
- // Do not delete! Cannot be uncommented by default, because of Parity decl_module! issue.
- // #![warn(missing_docs)]
- mod proposal_types;
- #[cfg(test)]
- mod tests;
- use common::origin_validator::ActorOriginValidator;
- use governance::election_params::ElectionParameters;
- use proposal_engine::ProposalParameters;
- use roles::actors::RoleParameters;
- use rstd::clone::Clone;
- use rstd::prelude::*;
- use rstd::str::from_utf8;
- use rstd::vec::Vec;
- use sr_primitives::traits::Zero;
- use srml_support::dispatch::DispatchResult;
- use srml_support::traits::{Currency, Get};
- use srml_support::{decl_error, decl_module, decl_storage, ensure, print};
- use system::{ensure_root, RawOrigin};
- pub use crate::proposal_types::ProposalsConfigParameters;
- pub use proposal_types::{ProposalDetails, ProposalDetailsOf, ProposalEncoder};
- // 'Set working group mint capacity' proposal limit
- const CONTENT_WORKING_GROUP_MINT_CAPACITY_MAX_VALUE: u32 = 1_000_000;
- // Max allowed value for 'spending' proposal
- const MAX_SPENDING_PROPOSAL_VALUE: u32 = 2_000_000_u32;
- // Max validator count for the 'set validator count' proposal
- const MAX_VALIDATOR_COUNT: u32 = 100;
- // min_actors min value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_MIN_ACTORS_MAX_VALUE: u32 = 2;
- // max_actors min value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_MAX_ACTORS_MIN_VALUE: u32 = 2;
- // max_actors max value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_MAX_ACTORS_MAX_VALUE: u32 = 100;
- // reward_period min value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_REWARD_PERIOD_MIN_VALUE: u32 = 600;
- // reward_period max value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_REWARD_PERIOD_MAX_VALUE: u32 = 3600;
- // bonding_period min value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_BONDING_PERIOD_MIN_VALUE: u32 = 600;
- // bonding_period max value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_BONDING_PERIOD_MAX_VALUE: u32 = 28800;
- // unbonding_period min value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_UNBONDING_PERIOD_MIN_VALUE: u32 = 600;
- // unbonding_period max value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_UNBONDING_PERIOD_MAX_VALUE: u32 = 28800;
- // min_service_period min value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_MIN_SERVICE_PERIOD_MIN_VALUE: u32 = 600;
- // min_service_period max value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_MIN_SERVICE_PERIOD_MAX_VALUE: u32 = 28800;
- // startup_grace_period min value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_STARTUP_GRACE_PERIOD_MIN_VALUE: u32 = 600;
- // startup_grace_period max value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_STARTUP_GRACE_PERIOD_MAX_VALUE: u32 = 28800;
- // min_stake min value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_MIN_STAKE_MIN_VALUE: u32 = 0;
- // min_stake max value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_MIN_STAKE_MAX_VALUE: u32 = 10_000_000;
- // entry_request_fee min value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_ENTRY_REQUEST_FEE_MIN_VALUE: u32 = 0;
- // entry_request_fee max value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_ENTRY_REQUEST_FEE_MAX_VALUE: u32 = 100_000;
- // reward min value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_REWARD_MIN_VALUE: u32 = 0;
- // reward max value for the 'set storage role parameters' proposal
- const ROLE_PARAMETERS_REWARD_MAX_VALUE: u32 = 1000;
- // council_size min value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_COUNCIL_SIZE_MIN_VALUE: u32 = 4;
- // council_size max value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_COUNCIL_SIZE_MAX_VALUE: u32 = 20;
- // candidacy_limit min value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_CANDIDACY_LIMIT_MIN_VALUE: u32 = 25;
- // candidacy_limit max value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_CANDIDACY_LIMIT_MAX_VALUE: u32 = 100;
- // min_voting_stake min value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_MIN_STAKE_MIN_VALUE: u32 = 1;
- // min_voting_stake max value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_MIN_STAKE_MAX_VALUE: u32 = 100_000_u32;
- // new_term_duration min value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_NEW_TERM_DURATION_MIN_VALUE: u32 = 14400;
- // new_term_duration max value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_NEW_TERM_DURATION_MAX_VALUE: u32 = 432_000;
- // revealing_period min value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_REVEALING_PERIOD_MIN_VALUE: u32 = 14400;
- // revealing_period max value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_REVEALING_PERIOD_MAX_VALUE: u32 = 28800;
- // voting_period min value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_VOTING_PERIOD_MIN_VALUE: u32 = 14400;
- // voting_period max value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_VOTING_PERIOD_MAX_VALUE: u32 = 28800;
- // announcing_period min value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_ANNOUNCING_PERIOD_MIN_VALUE: u32 = 14400;
- // announcing_period max value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_ANNOUNCING_PERIOD_MAX_VALUE: u32 = 43200;
- // min_council_stake min value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_MIN_COUNCIL_STAKE_MIN_VALUE: u32 = 1;
- // min_council_stake max value for the 'set election parameters' proposal
- const ELECTION_PARAMETERS_MIN_COUNCIL_STAKE_MAX_VALUE: u32 = 100_000_u32;
- /// 'Proposals codex' substrate module Trait
- pub trait Trait:
- system::Trait
- + proposal_engine::Trait
- + proposal_discussion::Trait
- + membership::members::Trait
- + governance::election::Trait
- + content_working_group::Trait
- + roles::actors::Trait
- + staking::Trait
- {
- /// Defines max allowed text proposal length.
- type TextProposalMaxLength: Get<u32>;
- /// Defines max wasm code length of the runtime upgrade proposal.
- type RuntimeUpgradeWasmProposalMaxLength: Get<u32>;
- /// Validates member id and origin combination
- type MembershipOriginValidator: ActorOriginValidator<
- Self::Origin,
- MemberId<Self>,
- Self::AccountId,
- >;
- /// Encodes the proposal usint its details
- type ProposalEncoder: ProposalEncoder<Self>;
- }
- /// Balance alias for `stake` module
- pub type BalanceOf<T> =
- <<T as stake::Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
- /// Currency alias for `stake` module
- pub type CurrencyOf<T> = <T as stake::Trait>::Currency;
- /// Balance alias for GovernanceCurrency from `common` module. TODO: replace with BalanceOf
- pub type BalanceOfGovernanceCurrency<T> =
- <<T as common::currency::GovernanceCurrency>::Currency as Currency<
- <T as system::Trait>::AccountId,
- >>::Balance;
- /// Balance alias for token mint balance from `token mint` module. TODO: replace with BalanceOf
- pub type BalanceOfMint<T> =
- <<T as mint::Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
- /// Negative imbalance alias for staking
- pub type NegativeImbalance<T> =
- <<T as stake::Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::NegativeImbalance;
- type MemberId<T> = <T as membership::members::Trait>::MemberId;
- decl_error! {
- /// Codex module predefined errors
- pub enum Error {
- /// The size of the provided text for text proposal exceeded the limit
- TextProposalSizeExceeded,
- /// Provided text for text proposal is empty
- TextProposalIsEmpty,
- /// The size of the provided WASM code for the runtime upgrade proposal exceeded the limit
- RuntimeProposalSizeExceeded,
- /// Provided WASM code for the runtime upgrade proposal is empty
- RuntimeProposalIsEmpty,
- /// Invalid balance value for the spending proposal
- InvalidSpendingProposalBalance,
- /// Invalid validator count for the 'set validator count' proposal
- InvalidValidatorCount,
- /// Require root origin in extrinsics
- RequireRootOrigin,
- /// Invalid storage role parameter - min_actors
- InvalidStorageRoleParameterMinActors,
- /// Invalid storage role parameter - max_actors
- InvalidStorageRoleParameterMaxActors,
- /// Invalid storage role parameter - reward_period
- InvalidStorageRoleParameterRewardPeriod,
- /// Invalid storage role parameter - bonding_period
- InvalidStorageRoleParameterBondingPeriod,
- /// Invalid storage role parameter - unbonding_period
- InvalidStorageRoleParameterUnbondingPeriod,
- /// Invalid storage role parameter - min_service_period
- InvalidStorageRoleParameterMinServicePeriod,
- /// Invalid storage role parameter - startup_grace_period
- InvalidStorageRoleParameterStartupGracePeriod,
- /// Invalid council election parameter - council_size
- InvalidCouncilElectionParameterCouncilSize,
- /// Invalid council election parameter - candidacy-limit
- InvalidCouncilElectionParameterCandidacyLimit,
- /// Invalid council election parameter - min-voting_stake
- InvalidCouncilElectionParameterMinVotingStake,
- /// Invalid council election parameter - new_term_duration
- InvalidCouncilElectionParameterNewTermDuration,
- /// Invalid council election parameter - min_council_stake
- InvalidCouncilElectionParameterMinCouncilStake,
- /// Invalid council election parameter - revealing_period
- InvalidCouncilElectionParameterRevealingPeriod,
- /// Invalid council election parameter - voting_period
- InvalidCouncilElectionParameterVotingPeriod,
- /// Invalid council election parameter - announcing_period
- InvalidCouncilElectionParameterAnnouncingPeriod,
- /// Invalid council election parameter - min_stake
- InvalidStorageRoleParameterMinStake,
- /// Invalid council election parameter - reward
- InvalidStorageRoleParameterReward,
- /// Invalid council election parameter - entry_request_fee
- InvalidStorageRoleParameterEntryRequestFee,
- /// Invalid working group mint capacity parameter
- InvalidStorageWorkingGroupMintCapacity,
- /// Invalid 'set lead proposal' parameter - proposed lead cannot be a councilor
- InvalidSetLeadParameterCannotBeCouncilor
- }
- }
- impl From<system::Error> for Error {
- fn from(error: system::Error) -> Self {
- match error {
- system::Error::Other(msg) => Error::Other(msg),
- system::Error::RequireRootOrigin => Error::RequireRootOrigin,
- _ => Error::Other(error.into()),
- }
- }
- }
- impl From<proposal_engine::Error> for Error {
- fn from(error: proposal_engine::Error) -> Self {
- match error {
- proposal_engine::Error::Other(msg) => Error::Other(msg),
- proposal_engine::Error::RequireRootOrigin => Error::RequireRootOrigin,
- _ => Error::Other(error.into()),
- }
- }
- }
- impl From<proposal_discussion::Error> for Error {
- fn from(error: proposal_discussion::Error) -> Self {
- match error {
- proposal_discussion::Error::Other(msg) => Error::Other(msg),
- proposal_discussion::Error::RequireRootOrigin => Error::RequireRootOrigin,
- _ => Error::Other(error.into()),
- }
- }
- }
- // Storage for the proposals codex module
- decl_storage! {
- pub trait Store for Module<T: Trait> as ProposalCodex{
- /// Map proposal id to its discussion thread id
- pub ThreadIdByProposalId get(fn thread_id_by_proposal_id):
- map T::ProposalId => T::ThreadId;
- /// Map proposal id to proposal details
- pub ProposalDetailsByProposalId get(fn proposal_details_by_proposal_id):
- map T::ProposalId => ProposalDetails<
- BalanceOfMint<T>,
- BalanceOfGovernanceCurrency<T>,
- T::BlockNumber,
- T::AccountId,
- T::MemberId
- >;
- /// Voting period for the 'set validator count' proposal
- pub SetValidatorCountProposalVotingPeriod get(set_validator_count_proposal_voting_period)
- config(): T::BlockNumber;
- /// Grace period for the 'set validator count' proposal
- pub SetValidatorCountProposalGracePeriod get(set_validator_count_proposal_grace_period)
- config(): T::BlockNumber;
- /// Voting period for the 'runtime upgrade' proposal
- pub RuntimeUpgradeProposalVotingPeriod get(runtime_upgrade_proposal_voting_period)
- config(): T::BlockNumber;
- /// Grace period for the 'runtime upgrade' proposal
- pub RuntimeUpgradeProposalGracePeriod get(runtime_upgrade_proposal_grace_period)
- config(): T::BlockNumber;
- /// Voting period for the 'set election parameters' proposal
- pub SetElectionParametersProposalVotingPeriod get(set_election_parameters_proposal_voting_period)
- config(): T::BlockNumber;
- /// Grace period for the 'set election parameters' proposal
- pub SetElectionParametersProposalGracePeriod get(set_election_parameters_proposal_grace_period)
- config(): T::BlockNumber;
- /// Voting period for the 'text' proposal
- pub TextProposalVotingPeriod get(text_proposal_voting_period) config(): T::BlockNumber;
- /// Grace period for the 'text' proposal
- pub TextProposalGracePeriod get(text_proposal_grace_period) config(): T::BlockNumber;
- /// Voting period for the 'set content working group mint capacity' proposal
- pub SetContentWorkingGroupMintCapacityProposalVotingPeriod get(set_content_working_group_mint_capacity_proposal_voting_period)
- config(): T::BlockNumber;
- /// Grace period for the 'set content working group mint capacity' proposal
- pub SetContentWorkingGroupMintCapacityProposalGracePeriod get(set_content_working_group_mint_capacity_proposal_grace_period)
- config(): T::BlockNumber;
- /// Voting period for the 'set lead' proposal
- pub SetLeadProposalVotingPeriod get(set_lead_proposal_voting_period)
- config(): T::BlockNumber;
- /// Grace period for the 'set lead' proposal
- pub SetLeadProposalGracePeriod get(set_lead_proposal_grace_period)
- config(): T::BlockNumber;
- /// Voting period for the 'spending' proposal
- pub SpendingProposalVotingPeriod get(spending_proposal_voting_period) config(): T::BlockNumber;
- /// Grace period for the 'spending' proposal
- pub SpendingProposalGracePeriod get(spending_proposal_grace_period) config(): T::BlockNumber;
- /// Voting period for the 'evict storage provider' proposal
- pub EvictStorageProviderProposalVotingPeriod get(evict_storage_provider_proposal_voting_period)
- config(): T::BlockNumber;
- /// Grace period for the 'evict storage provider' proposal
- pub EvictStorageProviderProposalGracePeriod get(evict_storage_provider_proposal_grace_period)
- config(): T::BlockNumber;
- /// Voting period for the 'set storage role parameters' proposal
- pub SetStorageRoleParametersProposalVotingPeriod get(set_storage_role_parameters_proposal_voting_period)
- config(): T::BlockNumber;
- /// Grace period for the 'set storage role parameters' proposal
- pub SetStorageRoleParametersProposalGracePeriod get(set_storage_role_parameters_proposal_grace_period)
- config(): T::BlockNumber;
- }
- }
- decl_module! {
- /// Proposal codex substrate module Call
- pub struct Module<T: Trait> for enum Call where origin: T::Origin {
- /// Predefined errors
- type Error = Error;
- /// Exports max allowed text proposal length const.
- const TextProposalMaxLength: u32 = T::TextProposalMaxLength::get();
- /// Exports max wasm code length of the runtime upgrade proposal const.
- const RuntimeUpgradeWasmProposalMaxLength: u32 = T::RuntimeUpgradeWasmProposalMaxLength::get();
- /// Create 'Text (signal)' proposal type.
- pub fn create_text_proposal(
- origin,
- member_id: MemberId<T>,
- title: Vec<u8>,
- description: Vec<u8>,
- stake_balance: Option<BalanceOf<T>>,
- text: Vec<u8>,
- ) {
- ensure!(!text.is_empty(), Error::TextProposalIsEmpty);
- ensure!(text.len() as u32 <= T::TextProposalMaxLength::get(),
- Error::TextProposalSizeExceeded);
- let proposal_parameters = proposal_types::parameters::text_proposal::<T>();
- let proposal_details = ProposalDetails::<BalanceOfMint<T>, BalanceOfGovernanceCurrency<T>, T::BlockNumber, T::AccountId, MemberId<T>>::Text(text);
- let proposal_code = T::ProposalEncoder::encode_proposal(proposal_details.clone());
- Self::create_proposal(
- origin,
- member_id,
- title,
- description,
- stake_balance,
- proposal_code,
- proposal_parameters,
- proposal_details,
- )?;
- }
- /// Create 'Runtime upgrade' proposal type. Runtime upgrade can be initiated only by
- /// members from the hardcoded list `RuntimeUpgradeProposalAllowedProposers`
- pub fn create_runtime_upgrade_proposal(
- origin,
- member_id: MemberId<T>,
- title: Vec<u8>,
- description: Vec<u8>,
- stake_balance: Option<BalanceOf<T>>,
- wasm: Vec<u8>,
- ) {
- ensure!(!wasm.is_empty(), Error::RuntimeProposalIsEmpty);
- ensure!(wasm.len() as u32 <= T::RuntimeUpgradeWasmProposalMaxLength::get(),
- Error::RuntimeProposalSizeExceeded);
- let proposal_parameters = proposal_types::parameters::runtime_upgrade_proposal::<T>();
- let proposal_details = ProposalDetails::RuntimeUpgrade(wasm);
- let proposal_code = T::ProposalEncoder::encode_proposal(proposal_details.clone());
- Self::create_proposal(
- origin,
- member_id,
- title,
- description,
- stake_balance,
- proposal_code,
- proposal_parameters,
- proposal_details,
- )?;
- }
- /// Create 'Set election parameters' proposal type. This proposal uses `set_election_parameters()`
- /// extrinsic from the `governance::election module`.
- pub fn create_set_election_parameters_proposal(
- origin,
- member_id: MemberId<T>,
- title: Vec<u8>,
- description: Vec<u8>,
- stake_balance: Option<BalanceOf<T>>,
- election_parameters: ElectionParameters<BalanceOfGovernanceCurrency<T>, T::BlockNumber>,
- ) {
- election_parameters.ensure_valid()?;
- Self::ensure_council_election_parameters_valid(&election_parameters)?;
- let proposal_details = ProposalDetails::SetElectionParameters(election_parameters);
- let proposal_code = T::ProposalEncoder::encode_proposal(proposal_details.clone());
- let proposal_parameters =
- proposal_types::parameters::set_election_parameters_proposal::<T>();
- Self::create_proposal(
- origin,
- member_id,
- title,
- description,
- stake_balance,
- proposal_code,
- proposal_parameters,
- proposal_details,
- )?;
- }
- /// Create 'Set content working group mint capacity' proposal type.
- /// This proposal uses `set_mint_capacity()` extrinsic from the `content-working-group` module.
- pub fn create_set_content_working_group_mint_capacity_proposal(
- origin,
- member_id: MemberId<T>,
- title: Vec<u8>,
- description: Vec<u8>,
- stake_balance: Option<BalanceOf<T>>,
- mint_balance: BalanceOfMint<T>,
- ) {
- ensure!(
- mint_balance <= <BalanceOfMint<T>>::from(CONTENT_WORKING_GROUP_MINT_CAPACITY_MAX_VALUE),
- Error::InvalidStorageWorkingGroupMintCapacity
- );
- let proposal_parameters =
- proposal_types::parameters::set_content_working_group_mint_capacity_proposal::<T>();
- let proposal_details = ProposalDetails::SetContentWorkingGroupMintCapacity(mint_balance);
- let proposal_code = T::ProposalEncoder::encode_proposal(proposal_details.clone());
- Self::create_proposal(
- origin,
- member_id,
- title,
- description,
- stake_balance,
- proposal_code,
- proposal_parameters,
- proposal_details,
- )?;
- }
- /// Create 'Spending' proposal type.
- /// This proposal uses `spend_from_council_mint()` extrinsic from the `governance::council` module.
- pub fn create_spending_proposal(
- origin,
- member_id: MemberId<T>,
- title: Vec<u8>,
- description: Vec<u8>,
- stake_balance: Option<BalanceOf<T>>,
- balance: BalanceOfMint<T>,
- destination: T::AccountId,
- ) {
- ensure!(balance != BalanceOfMint::<T>::zero(), Error::InvalidSpendingProposalBalance);
- ensure!(
- balance <= <BalanceOfMint<T>>::from(MAX_SPENDING_PROPOSAL_VALUE),
- Error::InvalidSpendingProposalBalance
- );
- let proposal_parameters =
- proposal_types::parameters::spending_proposal::<T>();
- let proposal_details = ProposalDetails::Spending(balance, destination);
- let proposal_code = T::ProposalEncoder::encode_proposal(proposal_details.clone());
- Self::create_proposal(
- origin,
- member_id,
- title,
- description,
- stake_balance,
- proposal_code,
- proposal_parameters,
- proposal_details,
- )?;
- }
- /// Create 'Set lead' proposal type.
- /// This proposal uses `replace_lead()` extrinsic from the `content_working_group` module.
- pub fn create_set_lead_proposal(
- origin,
- member_id: MemberId<T>,
- title: Vec<u8>,
- description: Vec<u8>,
- stake_balance: Option<BalanceOf<T>>,
- new_lead: Option<(T::MemberId, T::AccountId)>
- ) {
- if let Some(lead) = new_lead.clone() {
- let account_id = lead.1;
- ensure!(
- !<governance::council::Module<T>>::is_councilor(&account_id),
- Error::InvalidSetLeadParameterCannotBeCouncilor
- );
- }
- let proposal_parameters =
- proposal_types::parameters::set_lead_proposal::<T>();
- let proposal_details = ProposalDetails::SetLead(new_lead);
- let proposal_code = T::ProposalEncoder::encode_proposal(proposal_details.clone());
- Self::create_proposal(
- origin,
- member_id,
- title,
- description,
- stake_balance,
- proposal_code,
- proposal_parameters,
- proposal_details,
- )?;
- }
- /// Create 'Evict storage provider' proposal type.
- /// This proposal uses `remove_actor()` extrinsic from the `roles::actors` module.
- pub fn create_evict_storage_provider_proposal(
- origin,
- member_id: MemberId<T>,
- title: Vec<u8>,
- description: Vec<u8>,
- stake_balance: Option<BalanceOf<T>>,
- actor_account: T::AccountId,
- ) {
- let proposal_parameters =
- proposal_types::parameters::evict_storage_provider_proposal::<T>();
- let proposal_details = ProposalDetails::EvictStorageProvider(actor_account);
- let proposal_code = T::ProposalEncoder::encode_proposal(proposal_details.clone());
- Self::create_proposal(
- origin,
- member_id,
- title,
- description,
- stake_balance,
- proposal_code,
- proposal_parameters,
- proposal_details,
- )?;
- }
- /// Create 'Evict storage provider' proposal type.
- /// This proposal uses `set_validator_count()` extrinsic from the Substrate `staking` module.
- pub fn create_set_validator_count_proposal(
- origin,
- member_id: MemberId<T>,
- title: Vec<u8>,
- description: Vec<u8>,
- stake_balance: Option<BalanceOf<T>>,
- new_validator_count: u32,
- ) {
- ensure!(
- new_validator_count >= <staking::Module<T>>::minimum_validator_count(),
- Error::InvalidValidatorCount
- );
- ensure!(
- new_validator_count <= MAX_VALIDATOR_COUNT,
- Error::InvalidValidatorCount
- );
- let proposal_parameters =
- proposal_types::parameters::set_validator_count_proposal::<T>();
- let proposal_details = ProposalDetails::SetValidatorCount(new_validator_count);
- let proposal_code = T::ProposalEncoder::encode_proposal(proposal_details.clone());
- Self::create_proposal(
- origin,
- member_id,
- title,
- description,
- stake_balance,
- proposal_code,
- proposal_parameters,
- proposal_details,
- )?;
- }
- /// Create 'Set storage roles parameters' proposal type.
- /// This proposal uses `set_role_parameters()` extrinsic from the Substrate `roles::actors` module.
- pub fn create_set_storage_role_parameters_proposal(
- origin,
- member_id: MemberId<T>,
- title: Vec<u8>,
- description: Vec<u8>,
- stake_balance: Option<BalanceOf<T>>,
- role_parameters: RoleParameters<BalanceOfGovernanceCurrency<T>, T::BlockNumber>
- ) {
- Self::ensure_storage_role_parameters_valid(&role_parameters)?;
- let proposal_parameters =
- proposal_types::parameters::set_storage_role_parameters_proposal::<T>();
- let proposal_details = ProposalDetails::SetStorageRoleParameters(role_parameters);
- let proposal_code = T::ProposalEncoder::encode_proposal(proposal_details.clone());
- Self::create_proposal(
- origin,
- member_id,
- title,
- description,
- stake_balance,
- proposal_code,
- proposal_parameters,
- proposal_details,
- )?;
- }
- // *************** Extrinsic to execute
- /// Text proposal extrinsic. Should be used as callable object to pass to the `engine` module.
- pub fn execute_text_proposal(
- origin,
- text: Vec<u8>,
- ) {
- ensure_root(origin)?;
- print("Text proposal: ");
- let text_string_result = from_utf8(text.as_slice());
- if let Ok(text_string) = text_string_result{
- print(text_string);
- }
- }
- /// Runtime upgrade proposal extrinsic.
- /// Should be used as callable object to pass to the `engine` module.
- pub fn execute_runtime_upgrade_proposal(
- origin,
- wasm: Vec<u8>,
- ) {
- let (cloned_origin1, cloned_origin2) = Self::double_origin(origin);
- ensure_root(cloned_origin1)?;
- print("Runtime upgrade proposal execution started.");
- <system::Module<T>>::set_code(cloned_origin2, wasm)?;
- print("Runtime upgrade proposal execution finished.");
- }
- }
- }
- impl<T: Trait> Module<T> {
- // Multiplies the T::Origin.
- // In our current substrate version system::Origin doesn't support clone(),
- // but it will be supported in latest up-to-date substrate version.
- // TODO: delete when T::Origin will support the clone()
- fn double_origin(origin: T::Origin) -> (T::Origin, T::Origin) {
- let coerced_origin = origin.into().ok().unwrap_or(RawOrigin::None);
- let (cloned_origin1, cloned_origin2) = match coerced_origin {
- RawOrigin::None => (RawOrigin::None, RawOrigin::None),
- RawOrigin::Root => (RawOrigin::Root, RawOrigin::Root),
- RawOrigin::Signed(account_id) => (
- RawOrigin::Signed(account_id.clone()),
- RawOrigin::Signed(account_id),
- ),
- };
- (cloned_origin1.into(), cloned_origin2.into())
- }
- // Generic template proposal builder
- fn create_proposal(
- origin: T::Origin,
- member_id: MemberId<T>,
- title: Vec<u8>,
- description: Vec<u8>,
- stake_balance: Option<BalanceOf<T>>,
- proposal_code: Vec<u8>,
- proposal_parameters: ProposalParameters<T::BlockNumber, BalanceOf<T>>,
- proposal_details: ProposalDetails<
- BalanceOfMint<T>,
- BalanceOfGovernanceCurrency<T>,
- T::BlockNumber,
- T::AccountId,
- T::MemberId,
- >,
- ) -> DispatchResult<Error> {
- let account_id = T::MembershipOriginValidator::ensure_actor_origin(origin, member_id)?;
- <proposal_engine::Module<T>>::ensure_create_proposal_parameters_are_valid(
- &proposal_parameters,
- &title,
- &description,
- stake_balance,
- )?;
- <proposal_discussion::Module<T>>::ensure_can_create_thread(member_id, &title)?;
- let discussion_thread_id =
- <proposal_discussion::Module<T>>::create_thread(member_id, title.clone())?;
- let proposal_id = <proposal_engine::Module<T>>::create_proposal(
- account_id,
- member_id,
- proposal_parameters,
- title,
- description,
- stake_balance,
- proposal_code,
- )?;
- <ThreadIdByProposalId<T>>::insert(proposal_id, discussion_thread_id);
- <ProposalDetailsByProposalId<T>>::insert(proposal_id, proposal_details);
- Ok(())
- }
- // validates storage role parameters for the 'Set storage role parameters' proposal
- fn ensure_storage_role_parameters_valid(
- role_parameters: &RoleParameters<BalanceOfGovernanceCurrency<T>, T::BlockNumber>,
- ) -> Result<(), Error> {
- ensure!(
- role_parameters.min_actors < ROLE_PARAMETERS_MIN_ACTORS_MAX_VALUE,
- Error::InvalidStorageRoleParameterMinActors
- );
- ensure!(
- role_parameters.max_actors >= ROLE_PARAMETERS_MAX_ACTORS_MIN_VALUE,
- Error::InvalidStorageRoleParameterMaxActors
- );
- ensure!(
- role_parameters.max_actors < ROLE_PARAMETERS_MAX_ACTORS_MAX_VALUE,
- Error::InvalidStorageRoleParameterMaxActors
- );
- ensure!(
- role_parameters.reward_period
- >= T::BlockNumber::from(ROLE_PARAMETERS_REWARD_PERIOD_MIN_VALUE),
- Error::InvalidStorageRoleParameterRewardPeriod
- );
- ensure!(
- role_parameters.reward_period
- <= T::BlockNumber::from(ROLE_PARAMETERS_REWARD_PERIOD_MAX_VALUE),
- Error::InvalidStorageRoleParameterRewardPeriod
- );
- ensure!(
- role_parameters.bonding_period
- >= T::BlockNumber::from(ROLE_PARAMETERS_BONDING_PERIOD_MIN_VALUE),
- Error::InvalidStorageRoleParameterBondingPeriod
- );
- ensure!(
- role_parameters.bonding_period
- <= T::BlockNumber::from(ROLE_PARAMETERS_BONDING_PERIOD_MAX_VALUE),
- Error::InvalidStorageRoleParameterBondingPeriod
- );
- ensure!(
- role_parameters.unbonding_period
- >= T::BlockNumber::from(ROLE_PARAMETERS_UNBONDING_PERIOD_MIN_VALUE),
- Error::InvalidStorageRoleParameterUnbondingPeriod
- );
- ensure!(
- role_parameters.unbonding_period
- <= T::BlockNumber::from(ROLE_PARAMETERS_UNBONDING_PERIOD_MAX_VALUE),
- Error::InvalidStorageRoleParameterUnbondingPeriod
- );
- ensure!(
- role_parameters.min_service_period
- >= T::BlockNumber::from(ROLE_PARAMETERS_MIN_SERVICE_PERIOD_MIN_VALUE),
- Error::InvalidStorageRoleParameterMinServicePeriod
- );
- ensure!(
- role_parameters.min_service_period
- <= T::BlockNumber::from(ROLE_PARAMETERS_MIN_SERVICE_PERIOD_MAX_VALUE),
- Error::InvalidStorageRoleParameterMinServicePeriod
- );
- ensure!(
- role_parameters.startup_grace_period
- >= T::BlockNumber::from(ROLE_PARAMETERS_STARTUP_GRACE_PERIOD_MIN_VALUE),
- Error::InvalidStorageRoleParameterStartupGracePeriod
- );
- ensure!(
- role_parameters.startup_grace_period
- <= T::BlockNumber::from(ROLE_PARAMETERS_STARTUP_GRACE_PERIOD_MAX_VALUE),
- Error::InvalidStorageRoleParameterStartupGracePeriod
- );
- ensure!(
- role_parameters.min_stake
- > <BalanceOfGovernanceCurrency<T>>::from(ROLE_PARAMETERS_MIN_STAKE_MIN_VALUE),
- Error::InvalidStorageRoleParameterMinStake
- );
- ensure!(
- role_parameters.min_stake
- <= <BalanceOfGovernanceCurrency<T>>::from(ROLE_PARAMETERS_MIN_STAKE_MAX_VALUE),
- Error::InvalidStorageRoleParameterMinStake
- );
- ensure!(
- role_parameters.entry_request_fee
- > <BalanceOfGovernanceCurrency<T>>::from(
- ROLE_PARAMETERS_ENTRY_REQUEST_FEE_MIN_VALUE
- ),
- Error::InvalidStorageRoleParameterEntryRequestFee
- );
- ensure!(
- role_parameters.entry_request_fee
- <= <BalanceOfGovernanceCurrency<T>>::from(
- ROLE_PARAMETERS_ENTRY_REQUEST_FEE_MAX_VALUE
- ),
- Error::InvalidStorageRoleParameterEntryRequestFee
- );
- ensure!(
- role_parameters.reward
- > <BalanceOfGovernanceCurrency<T>>::from(ROLE_PARAMETERS_REWARD_MIN_VALUE),
- Error::InvalidStorageRoleParameterReward
- );
- ensure!(
- role_parameters.reward
- < <BalanceOfGovernanceCurrency<T>>::from(ROLE_PARAMETERS_REWARD_MAX_VALUE),
- Error::InvalidStorageRoleParameterReward
- );
- Ok(())
- }
- /*
- entry_request_fee [tJOY] >0 <1% NA
- * Not enforced by runtime. Should not be displayed in the UI, or at least grayed out.
- ** Should not be displayed in the UI, or at least grayed out.
- */
- // validates council election parameters for the 'Set election parameters' proposal
- pub(crate) fn ensure_council_election_parameters_valid(
- election_parameters: &ElectionParameters<BalanceOfGovernanceCurrency<T>, T::BlockNumber>,
- ) -> Result<(), Error> {
- ensure!(
- election_parameters.council_size >= ELECTION_PARAMETERS_COUNCIL_SIZE_MIN_VALUE,
- Error::InvalidCouncilElectionParameterCouncilSize
- );
- ensure!(
- election_parameters.council_size <= ELECTION_PARAMETERS_COUNCIL_SIZE_MAX_VALUE,
- Error::InvalidCouncilElectionParameterCouncilSize
- );
- ensure!(
- election_parameters.candidacy_limit >= ELECTION_PARAMETERS_CANDIDACY_LIMIT_MIN_VALUE,
- Error::InvalidCouncilElectionParameterCandidacyLimit
- );
- ensure!(
- election_parameters.candidacy_limit <= ELECTION_PARAMETERS_CANDIDACY_LIMIT_MAX_VALUE,
- Error::InvalidCouncilElectionParameterCandidacyLimit
- );
- ensure!(
- election_parameters.min_voting_stake
- >= <BalanceOfGovernanceCurrency<T>>::from(ELECTION_PARAMETERS_MIN_STAKE_MIN_VALUE),
- Error::InvalidCouncilElectionParameterMinVotingStake
- );
- ensure!(
- election_parameters.min_voting_stake
- <= <BalanceOfGovernanceCurrency<T>>::from(ELECTION_PARAMETERS_MIN_STAKE_MAX_VALUE),
- Error::InvalidCouncilElectionParameterMinVotingStake
- );
- ensure!(
- election_parameters.new_term_duration
- >= T::BlockNumber::from(ELECTION_PARAMETERS_NEW_TERM_DURATION_MIN_VALUE),
- Error::InvalidCouncilElectionParameterNewTermDuration
- );
- ensure!(
- election_parameters.new_term_duration
- <= T::BlockNumber::from(ELECTION_PARAMETERS_NEW_TERM_DURATION_MAX_VALUE),
- Error::InvalidCouncilElectionParameterNewTermDuration
- );
- ensure!(
- election_parameters.revealing_period
- >= T::BlockNumber::from(ELECTION_PARAMETERS_REVEALING_PERIOD_MIN_VALUE),
- Error::InvalidCouncilElectionParameterRevealingPeriod
- );
- ensure!(
- election_parameters.revealing_period
- <= T::BlockNumber::from(ELECTION_PARAMETERS_REVEALING_PERIOD_MAX_VALUE),
- Error::InvalidCouncilElectionParameterRevealingPeriod
- );
- ensure!(
- election_parameters.voting_period
- >= T::BlockNumber::from(ELECTION_PARAMETERS_VOTING_PERIOD_MIN_VALUE),
- Error::InvalidCouncilElectionParameterVotingPeriod
- );
- ensure!(
- election_parameters.voting_period
- <= T::BlockNumber::from(ELECTION_PARAMETERS_VOTING_PERIOD_MAX_VALUE),
- Error::InvalidCouncilElectionParameterVotingPeriod
- );
- ensure!(
- election_parameters.announcing_period
- >= T::BlockNumber::from(ELECTION_PARAMETERS_ANNOUNCING_PERIOD_MIN_VALUE),
- Error::InvalidCouncilElectionParameterAnnouncingPeriod
- );
- ensure!(
- election_parameters.announcing_period
- <= T::BlockNumber::from(ELECTION_PARAMETERS_ANNOUNCING_PERIOD_MAX_VALUE),
- Error::InvalidCouncilElectionParameterAnnouncingPeriod
- );
- ensure!(
- election_parameters.min_council_stake
- >= <BalanceOfGovernanceCurrency<T>>::from(
- ELECTION_PARAMETERS_MIN_COUNCIL_STAKE_MIN_VALUE
- ),
- Error::InvalidCouncilElectionParameterMinCouncilStake
- );
- ensure!(
- election_parameters.min_council_stake
- <= <BalanceOfGovernanceCurrency<T>>::from(
- ELECTION_PARAMETERS_MIN_COUNCIL_STAKE_MAX_VALUE
- ),
- Error::InvalidCouncilElectionParameterMinCouncilStake
- );
- Ok(())
- }
- /// Sets default config values for the proposals.
- /// Should be called on the migration to the new runtime version.
- pub fn set_default_config_values() {
- let p = ProposalsConfigParameters::default();
- <SetValidatorCountProposalVotingPeriod<T>>::put(T::BlockNumber::from(
- p.set_validator_count_proposal_voting_period,
- ));
- <SetValidatorCountProposalGracePeriod<T>>::put(T::BlockNumber::from(
- p.set_validator_count_proposal_grace_period,
- ));
- <RuntimeUpgradeProposalVotingPeriod<T>>::put(T::BlockNumber::from(
- p.runtime_upgrade_proposal_voting_period,
- ));
- <RuntimeUpgradeProposalGracePeriod<T>>::put(T::BlockNumber::from(
- p.runtime_upgrade_proposal_grace_period,
- ));
- <TextProposalVotingPeriod<T>>::put(T::BlockNumber::from(p.text_proposal_voting_period));
- <TextProposalGracePeriod<T>>::put(T::BlockNumber::from(p.text_proposal_grace_period));
- <SetElectionParametersProposalVotingPeriod<T>>::put(T::BlockNumber::from(
- p.set_election_parameters_proposal_voting_period,
- ));
- <SetElectionParametersProposalGracePeriod<T>>::put(T::BlockNumber::from(
- p.set_election_parameters_proposal_grace_period,
- ));
- <SetContentWorkingGroupMintCapacityProposalVotingPeriod<T>>::put(T::BlockNumber::from(
- p.set_content_working_group_mint_capacity_proposal_voting_period,
- ));
- <SetContentWorkingGroupMintCapacityProposalGracePeriod<T>>::put(T::BlockNumber::from(
- p.set_content_working_group_mint_capacity_proposal_grace_period,
- ));
- <SetLeadProposalVotingPeriod<T>>::put(T::BlockNumber::from(
- p.set_lead_proposal_voting_period,
- ));
- <SetLeadProposalGracePeriod<T>>::put(T::BlockNumber::from(
- p.set_lead_proposal_grace_period,
- ));
- <SpendingProposalVotingPeriod<T>>::put(T::BlockNumber::from(
- p.spending_proposal_voting_period,
- ));
- <SpendingProposalGracePeriod<T>>::put(T::BlockNumber::from(
- p.spending_proposal_grace_period,
- ));
- <EvictStorageProviderProposalVotingPeriod<T>>::put(T::BlockNumber::from(
- p.evict_storage_provider_proposal_voting_period,
- ));
- <EvictStorageProviderProposalGracePeriod<T>>::put(T::BlockNumber::from(
- p.evict_storage_provider_proposal_grace_period,
- ));
- <SetStorageRoleParametersProposalVotingPeriod<T>>::put(T::BlockNumber::from(
- p.set_storage_role_parameters_proposal_voting_period,
- ));
- <SetStorageRoleParametersProposalGracePeriod<T>>::put(T::BlockNumber::from(
- p.set_storage_role_parameters_proposal_grace_period,
- ));
- }
- }
|