From e2733e393355c68e954149cab1e7bb3f0e6d635c Mon Sep 17 00:00:00 2001 From: Francisco Valentim Castilho Date: Thu, 31 Oct 2024 13:28:15 -0300 Subject: [PATCH] Feat: Basic governance config for InvArch --- invarch/Cargo.lock | 7 + invarch/Cargo.toml | 7 + invarch/runtime/Cargo.toml | 22 ++ invarch/runtime/src/balances.rs | 17 +- invarch/runtime/src/governance/councils.rs | 30 +++ invarch/runtime/src/governance/mod.rs | 86 +++++++ invarch/runtime/src/governance/origins.rs | 112 +++++++++ invarch/runtime/src/governance/tracks.rs | 275 +++++++++++++++++++++ invarch/runtime/src/lib.rs | 67 ++++- 9 files changed, 608 insertions(+), 15 deletions(-) create mode 100644 invarch/runtime/src/governance/councils.rs create mode 100644 invarch/runtime/src/governance/mod.rs create mode 100644 invarch/runtime/src/governance/origins.rs create mode 100644 invarch/runtime/src/governance/tracks.rs diff --git a/invarch/Cargo.lock b/invarch/Cargo.lock index 32b2b8ba..bde34816 100644 --- a/invarch/Cargo.lock +++ b/invarch/Cargo.lock @@ -4910,12 +4910,17 @@ dependencies = [ "pallet-balances", "pallet-checked-inflation", "pallet-collator-selection", + "pallet-collective", "pallet-contracts", + "pallet-conviction-voting", "pallet-dao-manager", "pallet-dao-staking", "pallet-identity", "pallet-insecure-randomness-collective-flip", "pallet-message-queue", + "pallet-preimage", + "pallet-referenda", + "pallet-scheduler", "pallet-session", "pallet-sudo", "pallet-timestamp", @@ -4924,6 +4929,7 @@ dependencies = [ "pallet-treasury", "pallet-tx-pause", "pallet-utility", + "pallet-whitelist", "pallet-xcm", "parity-scale-codec", "polkadot-parachain-primitives 14.0.0", @@ -4931,6 +4937,7 @@ dependencies = [ "scale-info", "smallvec", "sp-api 34.0.0", + "sp-arithmetic 26.0.0", "sp-block-builder 34.0.0", "sp-consensus-aura 0.40.0", "sp-core 34.0.0", diff --git a/invarch/Cargo.toml b/invarch/Cargo.toml index 8c0c8ebb..7e7ac8aa 100644 --- a/invarch/Cargo.toml +++ b/invarch/Cargo.toml @@ -59,10 +59,15 @@ frame-try-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", br pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } pallet-authorship = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } +pallet-collective = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } pallet-contracts = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } +pallet-conviction-voting = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } pallet-identity = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } pallet-message-queue = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } +pallet-preimage = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } +pallet-referenda = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } +pallet-scheduler = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } pallet-session = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } @@ -72,7 +77,9 @@ pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/parityt pallet-treasury = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } pallet-tx-pause = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } pallet-utility = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } +pallet-whitelist = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } sp-api = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } +sp-arithmetic = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407", default-features = false } sp-blockchain = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407" } sp-consensus = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "stable2407" } diff --git a/invarch/runtime/Cargo.toml b/invarch/runtime/Cargo.toml index d0128076..2cca67bf 100644 --- a/invarch/runtime/Cargo.toml +++ b/invarch/runtime/Cargo.toml @@ -40,10 +40,15 @@ frame-try-runtime = { workspace = true, optional = true } pallet-aura = { workspace = true } pallet-authorship = { workspace = true } pallet-balances = { workspace = true } +pallet-collective = { workspace = true } pallet-contracts = { workspace = true } +pallet-conviction-voting = { workspace = true } pallet-identity = { workspace = true } pallet-insecure-randomness-collective-flip = { workspace = true } pallet-message-queue = { workspace = true } +pallet-preimage = { workspace = true } +pallet-referenda = { workspace = true } +pallet-scheduler = { workspace = true } pallet-session = { workspace = true } pallet-sudo = { workspace = true } pallet-timestamp = { workspace = true } @@ -52,7 +57,9 @@ pallet-transaction-payment-rpc-runtime-api = { workspace = true } pallet-treasury = { workspace = true } pallet-tx-pause = { workspace = true } pallet-utility = { workspace = true } +pallet-whitelist = { workspace = true } sp-api = { workspace = true } +sp-arithmetic = { workspace = true } sp-block-builder = { workspace = true } sp-consensus-aura = { workspace = true } sp-core = { workspace = true } @@ -137,11 +144,16 @@ std = [ "pallet-balances/std", "pallet-checked-inflation/std", "pallet-collator-selection/std", + "pallet-collective/std", "pallet-contracts/std", + "pallet-conviction-voting/std", "pallet-dao-manager/std", "pallet-dao-staking/std", "pallet-identity/std", "pallet-insecure-randomness-collective-flip/std", + "pallet-preimage/std", + "pallet-referenda/std", + "pallet-scheduler/std", "pallet-session/std", "pallet-sudo/std", "pallet-timestamp/std", @@ -150,12 +162,14 @@ std = [ "pallet-treasury/std", "pallet-tx-pause/std", "pallet-utility/std", + "pallet-whitelist/std", "pallet-xcm/std", "parachain-info/std", "polkadot-parachain/std", "polkadot-runtime-common/std", "scale-info/std", "sp-api/std", + "sp-arithmetic/std", "sp-block-builder/std", "sp-consensus-aura/std", "sp-core/std", @@ -181,9 +195,13 @@ runtime-benchmarks = [ "pallet-balances/runtime-benchmarks", "pallet-checked-inflation/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", + "pallet-collective/runtime-benchmarks", + "pallet-conviction-voting/runtime-benchmarks", "pallet-dao-manager/runtime-benchmarks", "pallet-dao-staking/runtime-benchmarks", + "pallet-referenda/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-whitelist/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", @@ -202,10 +220,14 @@ try-runtime = [ "pallet-authorship/try-runtime", "pallet-balances/try-runtime", "pallet-collator-selection/try-runtime", + "pallet-referenda/try-runtime", "pallet-session/try-runtime", "pallet-sudo/try-runtime", "pallet-timestamp/try-runtime", "pallet-transaction-payment/try-runtime", "pallet-xcm/try-runtime", "parachain-info/try-runtime", + "pallet-collective/try-runtime", + "pallet-conviction-voting/try-runtime", + "pallet-whitelist/try-runtime", ] diff --git a/invarch/runtime/src/balances.rs b/invarch/runtime/src/balances.rs index bffa19b0..80427195 100644 --- a/invarch/runtime/src/balances.rs +++ b/invarch/runtime/src/balances.rs @@ -1,7 +1,7 @@ use crate::{ - AccountId, Balance, Balances, BlockNumber, ExtrinsicBaseWeight, Runtime, RuntimeEvent, - RuntimeFreezeReason, RuntimeHoldReason, System, Treasury, DAYS, EXISTENTIAL_DEPOSIT, MICROUNIT, - MILLIUNIT, UNIT, + AccountId, Balance, Balances, BlockNumber, CouncilRejectOrigin, ExtrinsicBaseWeight, Runtime, + RuntimeEvent, RuntimeFreezeReason, RuntimeHoldReason, System, Treasury, TreasurySpender, DAYS, + EXISTENTIAL_DEPOSIT, MICROUNIT, MILLIUNIT, UNIT, }; use frame_support::{ pallet_prelude::ConstU32, @@ -16,7 +16,7 @@ use frame_support::{ }, PalletId, }; -use frame_system::{EnsureRoot, EnsureSignedBy}; +use frame_system::EnsureSignedBy; use polkadot_runtime_common::SlowAdjustingFeeUpdate; use sp_runtime::{ traits::{AccountIdConversion, IdentityLookup}, @@ -159,22 +159,17 @@ impl pallet_treasury::Config for Runtime { type BeneficiaryLookup = IdentityLookup; type PalletId = TreasuryPalletId; type Currency = Balances; - // type ApproveOrigin = EnsureRoot; - type RejectOrigin = EnsureRoot; + type RejectOrigin = CouncilRejectOrigin; type RuntimeEvent = RuntimeEvent; - // type OnSlash = (); type Paymaster = PayFromAccount; type PayoutPeriod = PayoutSpendPeriod; - // type ProposalBond = ProposalBond; - // type ProposalBondMinimum = ProposalBondMinimum; type SpendPeriod = SpendPeriod; type Burn = (); type BurnDestination = (); type SpendFunds = (); type WeightInfo = pallet_treasury::weights::SubstrateWeight; type MaxApprovals = MaxApprovals; - // type ProposalBondMaximum = (); - type SpendOrigin = frame_support::traits::NeverEnsureOrigin; + type SpendOrigin = TreasurySpender; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); } diff --git a/invarch/runtime/src/governance/councils.rs b/invarch/runtime/src/governance/councils.rs new file mode 100644 index 00000000..e4b07c36 --- /dev/null +++ b/invarch/runtime/src/governance/councils.rs @@ -0,0 +1,30 @@ +//! Councils for Governance + +use super::*; + +pub type TinkerCouncil = pallet_collective::Instance1; + +parameter_types! { + pub MaxProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block; + pub MaxMotionDuration: u32 = 3 * DAYS ; + pub MaxProposals: u32 = 20; + pub MaxMembers: u32 = 5; + +} + +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + /// The maximum amount of time (in blocks) council members to vote on motions. + /// Motions may end in fewer blocks if enough votes are cast to determine the result. + type MotionDuration = MaxMotionDuration; + /// The maximum number of proposals that can be open in council at once. + type MaxProposals = MaxProposals; + /// The maximum number of council members. + type MaxMembers = MaxMembers; + type DefaultVote = pallet_collective::MoreThanMajorityThenPrimeDefaultVote; + type WeightInfo = pallet_collective::weights::SubstrateWeight; + type SetMembersOrigin = EitherOf; + type MaxProposalWeight = MaxProposalWeight; +} diff --git a/invarch/runtime/src/governance/mod.rs b/invarch/runtime/src/governance/mod.rs new file mode 100644 index 00000000..2b636364 --- /dev/null +++ b/invarch/runtime/src/governance/mod.rs @@ -0,0 +1,86 @@ +use self::councils::TinkerCouncil; + +use super::*; +// use crate::xcm_config::CollectivesLocation; +use frame_support::{parameter_types, traits::EitherOf}; + +use frame_system::EnsureRootWithSuccess; + +mod origins; +pub use origins::{ + pallet_custom_origins, CouncilAdmin, GeneralManagement, ReferendumCanceller, ReferendumKiller, + Spender, WhitelistedCaller, +}; +mod tracks; +pub use tracks::TracksInfo; + +mod councils; + +parameter_types! { + pub const VoteLockingPeriod: BlockNumber = 7 * DAYS; +} + +impl pallet_conviction_voting::Config for Runtime { + type WeightInfo = pallet_conviction_voting::weights::SubstrateWeight; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type VoteLockingPeriod = VoteLockingPeriod; + type MaxVotes = ConstU32<512>; + type MaxTurnout = + frame_support::traits::tokens::currency::ActiveIssuanceOf; + type Polls = Referenda; +} + +parameter_types! { + pub const AlarmInterval: BlockNumber = 1; + pub const SubmissionDeposit: Balance = UNIT; + pub const UndecidingTimeout: BlockNumber = 14 * DAYS; +} + +parameter_types! { + pub const MaxBalance: Balance = Balance::max_value(); +} + +pub type AllCouncil = pallet_collective::EnsureProportionAtLeast; +pub type CouncilMoreThanApprove = + pallet_collective::EnsureProportionMoreThan; +pub type ConcilHalf = pallet_collective::EnsureProportionAtLeast; +pub type CouncilThreeFifths = + pallet_collective::EnsureProportionAtLeast; + +pub type TreasurySpender = EitherOf, Spender>; +pub type RootOrGeneralManagement = EitherOf, GeneralManagement>; +pub type CouncilApproveOrigin = EitherOf, CouncilThreeFifths>; +pub type CouncilRejectOrigin = EitherOf, ConcilHalf>; + +impl pallet_custom_origins::Config for Runtime {} + +impl pallet_whitelist::Config for Runtime { + type WeightInfo = pallet_whitelist::weights::SubstrateWeight; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type WhitelistOrigin = CouncilApproveOrigin; + type DispatchWhitelistedOrigin = EitherOf, WhitelistedCaller>; + type Preimages = Preimage; +} + +impl pallet_referenda::Config for Runtime { + type WeightInfo = pallet_referenda::weights::SubstrateWeight; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type Scheduler = Scheduler; + type Currency = Balances; + type SubmitOrigin = frame_system::EnsureSigned; + type CancelOrigin = + EitherOf, ReferendumCanceller>, CouncilMoreThanApprove>; + type KillOrigin = EitherOf, ReferendumKiller>, AllCouncil>; + type Slash = Treasury; + type Votes = pallet_conviction_voting::VotesOf; + type Tally = pallet_conviction_voting::TallyOf; + type SubmissionDeposit = SubmissionDeposit; + type MaxQueued = ConstU32<100>; + type UndecidingTimeout = UndecidingTimeout; + type AlarmInterval = AlarmInterval; + type Tracks = TracksInfo; + type Preimages = Preimage; +} diff --git a/invarch/runtime/src/governance/origins.rs b/invarch/runtime/src/governance/origins.rs new file mode 100644 index 00000000..54ba53c5 --- /dev/null +++ b/invarch/runtime/src/governance/origins.rs @@ -0,0 +1,112 @@ +//! Custom origins for governance interventions. + +pub use pallet_custom_origins::*; + +#[frame_support::pallet] +pub mod pallet_custom_origins { + use crate::{Balance, GRAND}; + use frame_support::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug)] + #[pallet::origin] + pub enum Origin { + /// Origin for managing the composition of the council. + CouncilAdmin, + /// Origin able to cancel a referenda. + ReferendumCanceller, + /// Origin able to kill referenda. + ReferendumKiller, + /// Origin able to dispatch a whitelisted call. + WhitelistedCaller, + /// Origin for general management that does not require a runtime upgrade. + GeneralManagement, + /// Origin able to spend around $??? from the treasury at once. + SmallSpender, + /// Origin able to spend up to $??? from the treasury at once. + BigSpender, + } + + macro_rules! decl_unit_ensures { + ( $name:ident: $success_type:ty = $success:expr ) => { + pub struct $name; + impl> + From> + EnsureOrigin for $name + { + type Success = $success_type; + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + Origin::$name => Ok($success), + r => Err(O::from(r)), + }) + } + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin() -> Result { + Ok(O::from(Origin::$name)) + } + } + }; + ( $name:ident ) => { decl_unit_ensures! { $name : () = () } }; + ( $name:ident: $success_type:ty = $success:expr, $( $rest:tt )* ) => { + decl_unit_ensures! { $name: $success_type = $success } + decl_unit_ensures! { $( $rest )* } + }; + ( $name:ident, $( $rest:tt )* ) => { + decl_unit_ensures! { $name } + decl_unit_ensures! { $( $rest )* } + }; + () => {} + } + decl_unit_ensures!( + CouncilAdmin, + ReferendumCanceller, + ReferendumKiller, + WhitelistedCaller, + GeneralManagement, + ); + + macro_rules! decl_ensure { + ( + $vis:vis type $name:ident: EnsureOrigin { + $( $item:ident = $success:expr, )* + } + ) => { + $vis struct $name; + impl> + From> + EnsureOrigin for $name + { + type Success = $success_type; + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + $( + Origin::$item => Ok($success), + )* + r => Err(O::from(r)), + }) + } + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin() -> Result { + // By convention the more privileged origins go later, so for greatest chance + // of success, we want the last one. + let _result: Result = Err(()); + $( + let _result: Result = Ok(O::from(Origin::$item)); + )* + _result + } + } + } + } + + decl_ensure! { + pub type Spender: EnsureOrigin { + SmallSpender = 10 * GRAND, + BigSpender = 1_000 * GRAND, + } + } +} diff --git a/invarch/runtime/src/governance/tracks.rs b/invarch/runtime/src/governance/tracks.rs new file mode 100644 index 00000000..dfcf7c41 --- /dev/null +++ b/invarch/runtime/src/governance/tracks.rs @@ -0,0 +1,275 @@ +//! Track configurations for governance. + +use super::*; + +const fn percent(x: i32) -> sp_arithmetic::FixedI64 { + sp_arithmetic::FixedI64::from_rational(x as u128, 100) +} +use pallet_referenda::Curve; +const APP_ROOT: Curve = Curve::make_reciprocal(4, 28, percent(80), percent(50), percent(100)); +const SUP_ROOT: Curve = Curve::make_linear(28, 28, percent(0), percent(50)); +const APP_COUNCIL_ADMIN: Curve = Curve::make_linear(17, 28, percent(50), percent(100)); +const SUP_COUNCIL_ADMIN: Curve = + Curve::make_reciprocal(12, 28, percent(1), percent(0), percent(50)); +const APP_GENERAL_MANAGEMENT: Curve = + Curve::make_reciprocal(4, 28, percent(80), percent(50), percent(100)); +const SUP_GENERAL_MANAGEMENT: Curve = + Curve::make_reciprocal(7, 28, percent(10), percent(0), percent(50)); +const APP_REFERENDUM_CANCELLER: Curve = Curve::make_linear(17, 28, percent(50), percent(100)); +const SUP_REFERENDUM_CANCELLER: Curve = + Curve::make_reciprocal(12, 28, percent(1), percent(0), percent(50)); +const APP_REFERENDUM_KILLER: Curve = Curve::make_linear(17, 28, percent(50), percent(100)); +const SUP_REFERENDUM_KILLER: Curve = + Curve::make_reciprocal(12, 28, percent(1), percent(0), percent(50)); +const APP_SMALL_SPENDER: Curve = Curve::make_linear(17, 28, percent(50), percent(100)); +const SUP_SMALL_SPENDER: Curve = + Curve::make_reciprocal(12, 28, percent(1), percent(0), percent(50)); +const APP_BIG_SPENDER: Curve = Curve::make_linear(28, 28, percent(50), percent(100)); +const SUP_BIG_SPENDER: Curve = Curve::make_reciprocal(20, 28, percent(1), percent(0), percent(50)); +const APP_WHITELISTED_CALLER: Curve = + Curve::make_reciprocal(16, 28 * 24, percent(96), percent(50), percent(100)); +const SUP_WHITELISTED_CALLER: Curve = + Curve::make_reciprocal(1, 28, percent(20), percent(5), percent(50)); +const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 8] = [ + ( + 0, + pallet_referenda::TrackInfo { + name: "root", + max_deciding: 1, + decision_deposit: 100 * GRAND, + #[cfg(not(feature = "on-chain-release-build"))] + prepare_period: 4 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + prepare_period: 2 * HOURS, + #[cfg(not(feature = "on-chain-release-build"))] + decision_period: 10 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + decision_period: 28 * DAYS, + #[cfg(not(feature = "on-chain-release-build"))] + confirm_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + confirm_period: 7 * DAYS, + #[cfg(not(feature = "on-chain-release-build"))] + min_enactment_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + min_enactment_period: 24 * HOURS, + min_approval: APP_ROOT, + min_support: SUP_ROOT, + }, + ), + ( + 1, + pallet_referenda::TrackInfo { + name: "whitelisted_caller", + max_deciding: 100, + decision_deposit: 10 * GRAND, + #[cfg(not(feature = "on-chain-release-build"))] + prepare_period: 2 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + prepare_period: 30 * MINUTES, + #[cfg(not(feature = "on-chain-release-build"))] + decision_period: 10 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + decision_period: 28 * DAYS, + #[cfg(not(feature = "on-chain-release-build"))] + confirm_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + confirm_period: 10 * MINUTES, + #[cfg(not(feature = "on-chain-release-build"))] + min_enactment_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + min_enactment_period: 10 * MINUTES, + min_approval: APP_WHITELISTED_CALLER, + min_support: SUP_WHITELISTED_CALLER, + }, + ), + ( + 2, + pallet_referenda::TrackInfo { + name: "general_management", + max_deciding: 10, + decision_deposit: 10 * GRAND, + #[cfg(not(feature = "on-chain-release-build"))] + prepare_period: 4 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + prepare_period: 2 * HOURS, + #[cfg(not(feature = "on-chain-release-build"))] + decision_period: 10 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + decision_period: 28 * DAYS, + #[cfg(not(feature = "on-chain-release-build"))] + confirm_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + confirm_period: 24 * HOURS, + #[cfg(not(feature = "on-chain-release-build"))] + min_enactment_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + min_enactment_period: 10 * MINUTES, + min_approval: APP_GENERAL_MANAGEMENT, + min_support: SUP_GENERAL_MANAGEMENT, + }, + ), + ( + 13, + pallet_referenda::TrackInfo { + name: "council_admin", + max_deciding: 10, + decision_deposit: 10 * GRAND, + #[cfg(not(feature = "on-chain-release-build"))] + prepare_period: 4 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + prepare_period: 2 * HOURS, + #[cfg(not(feature = "on-chain-release-build"))] + decision_period: 10 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + decision_period: 28 * DAYS, + #[cfg(not(feature = "on-chain-release-build"))] + confirm_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + confirm_period: 3 * HOURS, + #[cfg(not(feature = "on-chain-release-build"))] + min_enactment_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + min_enactment_period: 10 * MINUTES, + min_approval: APP_COUNCIL_ADMIN, + min_support: SUP_COUNCIL_ADMIN, + }, + ), + ( + 20, + pallet_referenda::TrackInfo { + name: "referendum_canceller", + max_deciding: 1_000, + decision_deposit: 10 * GRAND, + #[cfg(not(feature = "on-chain-release-build"))] + prepare_period: 4 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + prepare_period: 2 * HOURS, + #[cfg(not(feature = "on-chain-release-build"))] + decision_period: 10 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + decision_period: 7 * DAYS, + #[cfg(not(feature = "on-chain-release-build"))] + confirm_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + confirm_period: 3 * HOURS, + #[cfg(not(feature = "on-chain-release-build"))] + min_enactment_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + min_enactment_period: 10 * MINUTES, + min_approval: APP_REFERENDUM_CANCELLER, + min_support: SUP_REFERENDUM_CANCELLER, + }, + ), + ( + 21, + pallet_referenda::TrackInfo { + name: "referendum_killer", + max_deciding: 1_000, + decision_deposit: 50 * GRAND, + #[cfg(not(feature = "on-chain-release-build"))] + prepare_period: 4 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + prepare_period: 2 * HOURS, + #[cfg(not(feature = "on-chain-release-build"))] + decision_period: 10 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + decision_period: 28 * DAYS, + #[cfg(not(feature = "on-chain-release-build"))] + confirm_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + confirm_period: 3 * HOURS, + #[cfg(not(feature = "on-chain-release-build"))] + min_enactment_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + min_enactment_period: 10 * MINUTES, + min_approval: APP_REFERENDUM_KILLER, + min_support: SUP_REFERENDUM_KILLER, + }, + ), + ( + 32, + pallet_referenda::TrackInfo { + name: "small_spender", + max_deciding: 50, + decision_deposit: 100 * UNIT, + #[cfg(not(feature = "on-chain-release-build"))] + prepare_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + prepare_period: 4 * HOURS, + #[cfg(not(feature = "on-chain-release-build"))] + decision_period: 10 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + decision_period: 28 * DAYS, + #[cfg(not(feature = "on-chain-release-build"))] + confirm_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + confirm_period: 2 * DAYS, + #[cfg(not(feature = "on-chain-release-build"))] + min_enactment_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + min_enactment_period: 24 * HOURS, + min_approval: APP_SMALL_SPENDER, + min_support: SUP_SMALL_SPENDER, + }, + ), + ( + 34, + pallet_referenda::TrackInfo { + name: "big_spender", + max_deciding: 50, + decision_deposit: 400 * UNIT, + #[cfg(not(feature = "on-chain-release-build"))] + prepare_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + prepare_period: 4 * HOURS, + #[cfg(not(feature = "on-chain-release-build"))] + decision_period: 10 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + decision_period: 28 * DAYS, + #[cfg(not(feature = "on-chain-release-build"))] + confirm_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + confirm_period: 7 * DAYS, + #[cfg(not(feature = "on-chain-release-build"))] + min_enactment_period: 5 * MINUTES, + #[cfg(feature = "on-chain-release-build")] + min_enactment_period: 24 * HOURS, + min_approval: APP_BIG_SPENDER, + min_support: SUP_BIG_SPENDER, + }, + ), +]; + +pub struct TracksInfo; +impl pallet_referenda::TracksInfo for TracksInfo { + type Id = u16; + type RuntimeOrigin = ::PalletsOrigin; + fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { + &TRACKS_DATA[..] + } + fn track_for(id: &Self::RuntimeOrigin) -> Result { + if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { + match system_origin { + frame_system::RawOrigin::Root => Ok(0), + _ => Err(()), + } + } else if let Ok(custom_origin) = origins::Origin::try_from(id.clone()) { + match custom_origin { + origins::Origin::WhitelistedCaller => Ok(1), + origins::Origin::GeneralManagement => Ok(2), + // General admin + origins::Origin::CouncilAdmin => Ok(13), + // Referendum admins + origins::Origin::ReferendumCanceller => Ok(20), + origins::Origin::ReferendumKiller => Ok(21), + // Limited treasury spenders + origins::Origin::SmallSpender => Ok(32), + origins::Origin::BigSpender => Ok(34), + } + } else { + Err(()) + } + } +} +pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber); diff --git a/invarch/runtime/src/lib.rs b/invarch/runtime/src/lib.rs index 029bb206..63611454 100644 --- a/invarch/runtime/src/lib.rs +++ b/invarch/runtime/src/lib.rs @@ -11,7 +11,10 @@ use frame_support::{ derive_impl, dispatch::DispatchClass, parameter_types, - traits::{ConstU32, ConstU64, Contains, Everything, InsideBoth, Nothing}, + traits::{ + fungible::HoldConsideration, ConstU32, ConstU64, Contains, EqualPrivilegeOnly, Everything, + InsideBoth, LinearStoragePrice, Nothing, + }, weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, PalletId, }; @@ -19,6 +22,12 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, EnsureSigned, }; +mod governance; +pub use governance::{ + pallet_custom_origins, CouncilAdmin, CouncilApproveOrigin, CouncilRejectOrigin, + GeneralManagement, ReferendumCanceller, ReferendumKiller, RootOrGeneralManagement, + TreasurySpender, WhitelistedCaller, +}; use pallet_identity::legacy::IdentityInfo; use polkadot_runtime_common::BlockHashCount; use sp_api::impl_runtime_apis; @@ -192,6 +201,7 @@ pub const HOURS: BlockNumber = MINUTES * 60; pub const DAYS: BlockNumber = HOURS * 24; // Unit = the base number of indivisible units for balances +pub const GRAND: Balance = UNIT * 1_000; pub const UNIT: Balance = 1_000_000_000_000; pub const MILLIUNIT: Balance = 1_000_000_000; pub const MICROUNIT: Balance = 1_000_000; @@ -386,7 +396,7 @@ parameter_types! { } // We allow root only to execute privileged collator selection operations. -pub type CollatorSelectionUpdateOrigin = EnsureRoot; +pub type CollatorSelectionUpdateOrigin = RootOrGeneralManagement; impl pallet_collator_selection::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -432,7 +442,7 @@ impl pallet_identity::Config for Runtime { type BasicDeposit = BasicDeposit; type ByteDeposit = ByteDeposit; type Currency = Balances; - type ForceOrigin = EnsureRoot; + type ForceOrigin = RootOrGeneralManagement; type IdentityInformation = IdentityInfo; type MaxRegistrars = MaxRegistrars; type MaxSubAccounts = MaxSubAccounts; @@ -440,7 +450,7 @@ impl pallet_identity::Config for Runtime { type MaxUsernameLength = (); type OffchainSignature = Signature; type PendingUsernameExpiration = (); - type RegistrarOrigin = EnsureRoot; + type RegistrarOrigin = RootOrGeneralManagement; type RuntimeEvent = RuntimeEvent; type SigningPublicKey = ::Signer; type Slashed = Treasury; @@ -528,6 +538,46 @@ impl pallet_contracts::Config for Runtime { type ApiVersion = (); } +parameter_types! { + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * + RuntimeBlockWeights::get().max_block; + // Retry a scheduled item every 25 blocks (5 minute) until the preimage exists. + pub const NoPreimagePostponement: Option = Some(5 * MINUTES); + pub const MaxScheduledPerBlock: u32 = 50u32; +} + +impl pallet_scheduler::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureRoot; + type MaxScheduledPerBlock = MaxScheduledPerBlock; + type WeightInfo = pallet_scheduler::weights::SubstrateWeight; + type OriginPrivilegeCmp = EqualPrivilegeOnly; + type Preimages = Preimage; +} + +parameter_types! { + pub const PreimageBaseDeposit: Balance = deposit(2, 64); + pub const PreimageByteDeposit: Balance = deposit(0, 1); + pub const PreimageHoldReason: RuntimeHoldReason = RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage); +} + +impl pallet_preimage::Config for Runtime { + type WeightInfo = pallet_preimage::weights::SubstrateWeight; + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type Consideration = HoldConsideration< + AccountId, + Balances, + PreimageHoldReason, + LinearStoragePrice, + >; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime_modified!( pub enum Runtime @@ -541,6 +591,8 @@ construct_runtime_modified!( Utility: pallet_utility = 5, TxPause: pallet_tx_pause = 6, RandomnessCollectiveFlip: pallet_insecure_randomness_collective_flip = 7, + Scheduler: pallet_scheduler = 8, + Preimage: pallet_preimage = 9, // Monetary stuff. Balances: pallet_balances = 10, @@ -578,6 +630,13 @@ construct_runtime_modified!( INV4: pallet_dao_manager = 71, CoreAssets: orml_tokens = 72, // Asset used for DAO Management + // Governance + Council: pallet_collective:: = 80, + Referenda: pallet_referenda = 81, + ConvictionVoting: pallet_conviction_voting = 82, + Origins: governance::pallet_custom_origins = 83, + Whitelist: pallet_whitelist = 84, + } );