diff --git a/Cargo.lock b/Cargo.lock
index cdf5207a796..06467f55336 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5015,6 +5015,7 @@ dependencies = [
"pallet-balances",
"pallet-base-fee",
"pallet-collective",
+ "pallet-conviction-voting",
"pallet-crowdloan-rewards",
"pallet-democracy",
"pallet-ethereum",
@@ -5047,10 +5048,12 @@ dependencies = [
"pallet-migrations",
"pallet-moonbeam-orbiters",
"pallet-parachain-staking",
+ "pallet-preimage",
"pallet-proxy",
"pallet-proxy-genesis-companion",
"pallet-randomness",
"pallet-randomness-collective-flip",
+ "pallet-referenda",
"pallet-scheduler",
"pallet-society",
"pallet-sudo",
@@ -5059,6 +5062,7 @@ dependencies = [
"pallet-transaction-payment-rpc-runtime-api",
"pallet-treasury",
"pallet-utility",
+ "pallet-whitelist",
"pallet-xcm",
"pallet-xcm-transactor",
"parachain-info",
@@ -5075,6 +5079,7 @@ dependencies = [
"sha3 0.9.1",
"smallvec",
"sp-api",
+ "sp-arithmetic",
"sp-block-builder",
"sp-core",
"sp-debug-derive",
@@ -6722,6 +6727,23 @@ dependencies = [
"sp-std",
]
+[[package]]
+name = "pallet-conviction-voting"
+version = "4.0.0-dev"
+source = "git+https://github.com/purestake/substrate?branch=moonbeam-polkadot-v0.9.26#c674000cb498e8d885987bde1a4490939b5fe3db"
+dependencies = [
+ "assert_matches",
+ "frame-benchmarking",
+ "frame-support",
+ "frame-system",
+ "parity-scale-codec",
+ "scale-info",
+ "serde",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+]
+
[[package]]
name = "pallet-crowdloan-rewards"
version = "0.6.0"
@@ -7748,6 +7770,24 @@ dependencies = [
"sp-std",
]
+[[package]]
+name = "pallet-referenda"
+version = "4.0.0-dev"
+source = "git+https://github.com/purestake/substrate?branch=moonbeam-polkadot-v0.9.26#c674000cb498e8d885987bde1a4490939b5fe3db"
+dependencies = [
+ "assert_matches",
+ "frame-benchmarking",
+ "frame-support",
+ "frame-system",
+ "parity-scale-codec",
+ "scale-info",
+ "serde",
+ "sp-arithmetic",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+]
+
[[package]]
name = "pallet-scheduler"
version = "4.0.0-dev"
@@ -7977,6 +8017,20 @@ dependencies = [
"sp-std",
]
+[[package]]
+name = "pallet-whitelist"
+version = "4.0.0-dev"
+source = "git+https://github.com/purestake/substrate?branch=moonbeam-polkadot-v0.9.26#c674000cb498e8d885987bde1a4490939b5fe3db"
+dependencies = [
+ "frame-support",
+ "frame-system",
+ "parity-scale-codec",
+ "scale-info",
+ "sp-api",
+ "sp-runtime",
+ "sp-std",
+]
+
[[package]]
name = "pallet-xcm"
version = "0.9.26"
diff --git a/runtime/moonbase/Cargo.toml b/runtime/moonbase/Cargo.toml
index b4d1b0ab340..61f4e409dd4 100644
--- a/runtime/moonbase/Cargo.toml
+++ b/runtime/moonbase/Cargo.toml
@@ -70,10 +70,13 @@ frame-system-rpc-runtime-api = { git = "https://github.com/purestake/substrate",
pallet-assets = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
pallet-balances = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
pallet-collective = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
+pallet-conviction-voting = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
pallet-democracy = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
pallet-identity = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
+pallet-preimage = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
pallet-proxy = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
pallet-randomness-collective-flip = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
+pallet-referenda = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
pallet-scheduler = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
pallet-society = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
pallet-sudo = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
@@ -82,9 +85,11 @@ pallet-transaction-payment = { git = "https://github.com/purestake/substrate", b
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
pallet-treasury = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
pallet-utility = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
+pallet-whitelist = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
parity-scale-codec = { version = "3.0.0", default-features = false, features = [ "derive", "max-encoded-len" ] }
scale-info = { version = "2.0", default-features = false, features = [ "derive" ] }
sp-api = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
+sp-arithmetic = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
sp-block-builder = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
sp-core = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
sp-debug-derive = { git = "https://github.com/purestake/substrate", branch = "moonbeam-polkadot-v0.9.26", default-features = false }
@@ -190,6 +195,7 @@ std = [
"pallet-balances/std",
"pallet-base-fee/std",
"pallet-collective/std",
+ "pallet-conviction-voting/std",
"pallet-crowdloan-rewards/std",
"pallet-democracy/std",
"pallet-ethereum-chain-id/std",
@@ -213,10 +219,12 @@ std = [
"pallet-migrations/std",
"pallet-moonbeam-orbiters/std",
"pallet-parachain-staking/std",
+ "pallet-preimage/std",
"pallet-proxy-genesis-companion/std",
"pallet-proxy/std",
"pallet-randomness-collective-flip/std",
"pallet-randomness/std",
+ "pallet-referenda/std",
"pallet-scheduler/std",
"pallet-society/std",
"pallet-sudo/std",
@@ -225,6 +233,7 @@ std = [
"pallet-transaction-payment/std",
"pallet-treasury/std",
"pallet-utility/std",
+ "pallet-whitelist/std",
"pallet-xcm-transactor/std",
"pallet-xcm/std",
"parachain-info/std",
@@ -234,6 +243,7 @@ std = [
"serde",
"session-keys-primitives/std",
"sp-api/std",
+ "sp-arithmetic/std",
"sp-block-builder/std",
"sp-core/std",
"sp-inherents/std",
@@ -277,12 +287,14 @@ runtime-benchmarks = [
"pallet-author-slot-filter/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-collective/runtime-benchmarks",
+ "pallet-conviction-voting/runtime-benchmarks",
"pallet-crowdloan-rewards/runtime-benchmarks",
"pallet-ethereum-xcm/runtime-benchmarks",
"pallet-ethereum/runtime-benchmarks",
"pallet-moonbeam-orbiters/runtime-benchmarks",
"pallet-parachain-staking/runtime-benchmarks",
"pallet-randomness/runtime-benchmarks",
+ "pallet-referenda/runtime-benchmarks",
"pallet-society/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-xcm-transactor/runtime-benchmarks",
@@ -301,11 +313,13 @@ try-runtime = [
"pallet-author-slot-filter/try-runtime",
"pallet-balances/try-runtime",
"pallet-collective/try-runtime",
+ "pallet-conviction-voting/try-runtime",
"pallet-maintenance-mode/try-runtime",
#"pallet-crowdloan-rewards/try-runtime",
"pallet-maintenance-mode/try-runtime",
"pallet-migrations/try-runtime",
"pallet-parachain-staking/try-runtime",
+ "pallet-referenda/try-runtime",
"pallet-scheduler/try-runtime",
"pallet-society/try-runtime",
"pallet-timestamp/try-runtime",
diff --git a/runtime/moonbase/src/governance/mod.rs b/runtime/moonbase/src/governance/mod.rs
new file mode 100644
index 00000000000..64e4fc52914
--- /dev/null
+++ b/runtime/moonbase/src/governance/mod.rs
@@ -0,0 +1,88 @@
+// Copyright 2019-2022 PureStake Inc.
+// This file is part of Moonbeam.
+
+// Moonbeam is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Moonbeam is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Moonbeam. If not, see .
+
+//! New governance configurations for the Moonbase runtime.
+
+use super::*;
+use crate::currency::*;
+use frame_support::traits::EitherOf;
+use frame_system::EnsureRootWithSuccess;
+
+mod origins;
+pub use origins::{
+ pallet_custom_origins, GeneralAdmin, ReferendumCanceller, ReferendumKiller, Spender,
+ WhitelistedCaller,
+};
+mod tracks;
+pub use tracks::TracksInfo;
+
+parameter_types! {
+ pub const VoteLockingPeriod: BlockNumber = 7 * DAYS;
+}
+
+impl pallet_conviction_voting::Config for Runtime {
+ type WeightInfo = pallet_conviction_voting::weights::SubstrateWeight;
+ type Event = Event;
+ type Currency = Balances;
+ type VoteLockingPeriod = VoteLockingPeriod;
+ type MaxVotes = ConstU32<512>;
+ type MaxTurnout = frame_support::traits::TotalIssuanceOf;
+ type Polls = Referenda;
+}
+
+parameter_types! {
+ pub const AlarmInterval: BlockNumber = 1;
+ pub const SubmissionDeposit: Balance = 100 * UNIT;
+ pub const UndecidingTimeout: BlockNumber = 28 * DAYS;
+}
+
+parameter_types! {
+ pub const MaxBalance: Balance = Balance::max_value();
+}
+pub type TreasurySpender = EitherOf, Spender>;
+
+impl origins::pallet_custom_origins::Config for Runtime {}
+
+// purpose of this pallet is to queue calls to be dispatched as root for later
+impl pallet_whitelist::Config for Runtime {
+ type WeightInfo = pallet_whitelist::weights::SubstrateWeight;
+ type Event = Event;
+ type Call = Call;
+ // polkadot: EitherOf>, Fellows>;
+ type WhitelistOrigin =
+ EnsureRootWithSuccess, TODO: COLLECTIVE>;
+ type DispatchWhitelistedOrigin = EitherOf, WhitelistedCaller>;
+ type PreimageProvider = Preimage;
+}
+
+impl pallet_referenda::Config for Runtime {
+ type WeightInfo = pallet_referenda::weights::SubstrateWeight;
+ type Call = Call;
+ type Event = Event;
+ type Scheduler = Scheduler;
+ type Currency = Balances;
+ type SubmitOrigin = frame_system::EnsureSigned;
+ type CancelOrigin = ReferendumCanceller;
+ type KillOrigin = ReferendumKiller;
+ 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;
+}
diff --git a/runtime/moonbase/src/governance/old.rs b/runtime/moonbase/src/governance/old.rs
new file mode 100644
index 00000000000..867d58fa8d9
--- /dev/null
+++ b/runtime/moonbase/src/governance/old.rs
@@ -0,0 +1 @@
+//! old governance configurations
\ No newline at end of file
diff --git a/runtime/moonbase/src/governance/origins.rs b/runtime/moonbase/src/governance/origins.rs
new file mode 100644
index 00000000000..8353de5713e
--- /dev/null
+++ b/runtime/moonbase/src/governance/origins.rs
@@ -0,0 +1,136 @@
+// Copyright 2019-2022 PureStake Inc.
+// This file is part of Moonbeam.
+
+// Moonbeam is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Moonbeam is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+//! Custom origins for governance interventions.
+
+pub use pallet_custom_origins::*;
+
+#[frame_support::pallet]
+pub mod pallet_custom_origins {
+ use crate::{
+ currency::{KILOUNIT, UNIT},
+ Balance,
+ };
+ 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 spending (any amount of) funds.
+ Treasurer,
+ /// Origin for managing the registrar.
+ GeneralAdmin,
+ /// Origin able to cancel referenda.
+ ReferendumCanceller,
+ /// Origin able to kill referenda.
+ ReferendumKiller,
+ /// Origin able to spend up to 1 KSM from the treasury at once.
+ SmallTipper,
+ /// Origin able to spend up to 5 KSM from the treasury at once.
+ BigTipper,
+ /// Origin able to spend up to 50 KSM from the treasury at once.
+ SmallSpender,
+ /// Origin able to spend up to 500 KSM from the treasury at once.
+ MediumSpender,
+ /// Origin able to spend up to 5,000 KSM from the treasury at once.
+ BigSpender,
+ /// Origin able to dispatch a whitelisted call.
+ WhitelistedCaller,
+ }
+
+ 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!(
+ GeneralAdmin,
+ ReferendumCanceller,
+ ReferendumKiller,
+ WhitelistedCaller,
+ );
+
+ 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 {
+ SmallTipper = 250 * 100 * UNIT,
+ BigTipper = 1 * KILOUNIT,
+ SmallSpender = 10 * KILOUNIT,
+ MediumSpender = 100 * KILOUNIT,
+ BigSpender = 1_000 * KILOUNIT,
+ }
+ }
+}
diff --git a/runtime/moonbase/src/governance/tracks.rs b/runtime/moonbase/src/governance/tracks.rs
new file mode 100644
index 00000000000..cd54b786f1e
--- /dev/null
+++ b/runtime/moonbase/src/governance/tracks.rs
@@ -0,0 +1,250 @@
+// Copyright 2022 Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Polkadot is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Polkadot. If not, see .
+
+//! Track configurations for governance.
+
+use super::*;
+use crate::currency::{KILOUNIT, UNIT};
+
+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_TREASURER: Curve = Curve::make_reciprocal(4, 28, percent(80), percent(50), percent(100));
+const SUP_TREASURER: Curve = Curve::make_linear(28, 28, percent(0), percent(50));
+const APP_GENERAL_ADMIN: Curve =
+ Curve::make_reciprocal(4, 28, percent(80), percent(50), percent(100));
+const SUP_GENERAL_ADMIN: 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_TIPPER: Curve = Curve::make_linear(10, 28, percent(50), percent(100));
+const SUP_SMALL_TIPPER: Curve = Curve::make_reciprocal(1, 28, percent(4), percent(0), percent(50));
+const APP_BIG_TIPPER: Curve = Curve::make_linear(10, 28, percent(50), percent(100));
+const SUP_BIG_TIPPER: Curve = Curve::make_reciprocal(8, 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_MEDIUM_SPENDER: Curve = Curve::make_linear(23, 28, percent(50), percent(100));
+const SUP_MEDIUM_SPENDER: Curve =
+ Curve::make_reciprocal(16, 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(10), percent(50));
+
+const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 11] = [
+ (
+ 0,
+ pallet_referenda::TrackInfo {
+ name: "root",
+ max_deciding: 1,
+ decision_deposit: 1_000 * KILOUNIT,
+ prepare_period: 3 * HOURS,
+ decision_period: 28 * DAYS,
+ confirm_period: 3 * HOURS,
+ min_enactment_period: 3 * HOURS,
+ min_approval: APP_ROOT,
+ min_support: SUP_ROOT,
+ },
+ ),
+ // Fastrack
+ (
+ 1,
+ pallet_referenda::TrackInfo {
+ name: "whitelisted_caller",
+ max_deciding: 10,
+ decision_deposit: 10_000 * KILOUNIT,
+ prepare_period: 3 * HOURS,
+ decision_period: 28 * DAYS,
+ // TODO: review
+ confirm_period: 10 * MINUTES,
+ // TODO: review
+ min_enactment_period: 30 * MINUTES,
+ min_approval: APP_WHITELISTED_CALLER,
+ min_support: SUP_WHITELISTED_CALLER,
+ },
+ ),
+ (
+ 10,
+ pallet_referenda::TrackInfo {
+ name: "treasurer",
+ max_deciding: 10,
+ decision_deposit: 5 * KILOUNIT,
+ prepare_period: 4,
+ decision_period: 28 * DAYS,
+ confirm_period: 3 * HOURS,
+ min_enactment_period: 2 * DAYS,
+ min_approval: APP_TREASURER,
+ min_support: SUP_TREASURER,
+ },
+ ),
+ (
+ 11,
+ pallet_referenda::TrackInfo {
+ name: "general_admin",
+ max_deciding: 10,
+ decision_deposit: 5 * KILOUNIT,
+ prepare_period: 4,
+ decision_period: 28 * DAYS,
+ confirm_period: 3 * HOURS,
+ min_enactment_period: 2 * DAYS,
+ min_approval: APP_GENERAL_ADMIN,
+ min_support: SUP_GENERAL_ADMIN,
+ },
+ ),
+ (
+ 12,
+ pallet_referenda::TrackInfo {
+ name: "referendum_canceller",
+ max_deciding: 1_000,
+ decision_deposit: 50 * KILOUNIT,
+ prepare_period: 4,
+ decision_period: 28 * DAYS,
+ confirm_period: 3 * HOURS,
+ min_enactment_period: 10 * MINUTES,
+ min_approval: APP_REFERENDUM_CANCELLER,
+ min_support: SUP_REFERENDUM_CANCELLER,
+ },
+ ),
+ (
+ 13,
+ pallet_referenda::TrackInfo {
+ name: "referendum_killer",
+ max_deciding: 1_000,
+ decision_deposit: 50 * KILOUNIT,
+ prepare_period: 4,
+ decision_period: 28 * DAYS,
+ confirm_period: 3 * HOURS,
+ min_enactment_period: 10 * MINUTES,
+ min_approval: APP_REFERENDUM_KILLER,
+ min_support: SUP_REFERENDUM_KILLER,
+ },
+ ),
+ (
+ 14,
+ pallet_referenda::TrackInfo {
+ name: "small_tipper",
+ max_deciding: 200,
+ decision_deposit: 5 * 100 * UNIT,
+ prepare_period: 4,
+ decision_period: 28 * DAYS,
+ confirm_period: 3 * HOURS,
+ min_enactment_period: 28 * DAYS,
+ min_approval: APP_SMALL_TIPPER,
+ min_support: SUP_SMALL_TIPPER,
+ },
+ ),
+ (
+ 15,
+ pallet_referenda::TrackInfo {
+ name: "big_tipper",
+ max_deciding: 100,
+ decision_deposit: 50 * 100 * UNIT,
+ prepare_period: 4,
+ decision_period: 28 * DAYS,
+ confirm_period: 6 * HOURS,
+ min_enactment_period: 28 * DAYS,
+ min_approval: APP_BIG_TIPPER,
+ min_support: SUP_BIG_TIPPER,
+ },
+ ),
+ (
+ 16,
+ pallet_referenda::TrackInfo {
+ name: "small_spender",
+ max_deciding: 50,
+ decision_deposit: 500 * 100 * UNIT,
+ prepare_period: 4,
+ decision_period: 28 * DAYS,
+ confirm_period: 12 * HOURS,
+ min_enactment_period: 28 * DAYS,
+ min_approval: APP_SMALL_SPENDER,
+ min_support: SUP_SMALL_SPENDER,
+ },
+ ),
+ (
+ 17,
+ pallet_referenda::TrackInfo {
+ name: "medium_spender",
+ max_deciding: 20,
+ decision_deposit: 1_500 * 100 * UNIT,
+ prepare_period: 4,
+ decision_period: 28 * DAYS,
+ confirm_period: 24 * HOURS,
+ min_enactment_period: 28 * DAYS,
+ min_approval: APP_MEDIUM_SPENDER,
+ min_support: SUP_MEDIUM_SPENDER,
+ },
+ ),
+ (
+ 18,
+ pallet_referenda::TrackInfo {
+ name: "big_spender",
+ max_deciding: 10,
+ decision_deposit: 5 * KILOUNIT,
+ prepare_period: 4,
+ decision_period: 28 * DAYS,
+ confirm_period: 48 * HOURS,
+ min_enactment_period: 28 * DAYS,
+ min_approval: APP_BIG_SPENDER,
+ min_support: SUP_BIG_SPENDER,
+ },
+ ),
+];
+
+pub struct TracksInfo;
+impl pallet_referenda::TracksInfo for TracksInfo {
+ type Id = u16;
+ type Origin = ::PalletsOrigin;
+ fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] {
+ &TRACKS_DATA[..]
+ }
+ fn track_for(id: &Self::Origin) -> 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),
+ // General admin
+ origins::Origin::Treasurer => Ok(10),
+ origins::Origin::GeneralAdmin => Ok(11),
+ // Referendum admins
+ origins::Origin::ReferendumCanceller => Ok(12),
+ origins::Origin::ReferendumKiller => Ok(13),
+ // Limited treasury spenders
+ origins::Origin::SmallTipper => Ok(14),
+ origins::Origin::BigTipper => Ok(15),
+ origins::Origin::SmallSpender => Ok(16),
+ origins::Origin::MediumSpender => Ok(17),
+ origins::Origin::BigSpender => Ok(18),
+ }
+ } else {
+ Err(())
+ }
+ }
+}
diff --git a/runtime/moonbase/src/lib.rs b/runtime/moonbase/src/lib.rs
index 21c80ac1abf..6de3a77c469 100644
--- a/runtime/moonbase/src/lib.rs
+++ b/runtime/moonbase/src/lib.rs
@@ -111,7 +111,9 @@ pub use sp_runtime::BuildStorage;
pub type Precompiles = MoonbasePrecompiles;
pub mod asset_config;
+pub mod governance;
pub mod xcm_config;
+use governance::{pallet_custom_origins, TreasurySpender};
/// UNIT, the native token, uses 18 decimals of precision.
pub mod currency {
@@ -478,10 +480,20 @@ impl pallet_scheduler::Config for Runtime {
type MaxScheduledPerBlock = ConstU32<50>;
type WeightInfo = pallet_scheduler::weights::SubstrateWeight;
type OriginPrivilegeCmp = EqualPrivilegeOnly;
- type PreimageProvider = ();
+ type PreimageProvider = Preimage;
type NoPreimagePostponement = ();
}
+impl pallet_preimage::Config for Runtime {
+ type WeightInfo = pallet_preimage::weights::SubstrateWeight;
+ type Event = Event;
+ type Currency = Balances;
+ type ManagerOrigin = EnsureRoot;
+ type MaxSize = ConstU32<{ 4096 * 1024 }>;
+ type BaseDeposit = ConstU128<{ 5 * currency::UNIT * currency::SUPPLY_FACTOR }>;
+ type ByteDeposit = ConstU128<{ 1 * currency::UNIT * currency::SUPPLY_FACTOR }>;
+}
+
type CouncilInstance = pallet_collective::Instance1;
type TechCommitteeInstance = pallet_collective::Instance2;
type TreasuryCouncilInstance = pallet_collective::Instance3;
@@ -619,9 +631,10 @@ impl pallet_treasury::Config for Runtime {
type WeightInfo = pallet_treasury::weights::SubstrateWeight;
type SpendFunds = ();
type ProposalBondMaximum = ();
- type SpendOrigin = frame_support::traits::NeverEnsureOrigin; // Same as Polkadot
+ type SpendOrigin = TreasurySpender;
}
+// TODO: name same origin to same type
type IdentityForceOrigin = EitherOfDiverse<
EnsureRoot,
pallet_collective::EnsureProportionMoreThan,
@@ -1263,6 +1276,11 @@ construct_runtime! {
Randomness: pallet_randomness::{Pallet, Call, Storage, Event, Inherent} = 39,
TreasuryCouncilCollective:
pallet_collective::::{Pallet, Call, Storage, Event, Origin, Config} = 40,
+ ConvictionVoting: pallet_conviction_voting::{Pallet, Call, Storage, Event} = 41,
+ Referenda: pallet_referenda::{Pallet, Call, Storage, Event} = 42,
+ Origins: pallet_custom_origins::{Origin} = 43,
+ Preimage: pallet_preimage::{Pallet, Call, Storage, Event} = 44,
+ Whitelist: pallet_whitelist::{Pallet, Call, Storage, Event} = 45,
}
}
diff --git a/runtime/moonbase/tests/common/mod.rs b/runtime/moonbase/tests/common/mod.rs
index cd7edcfdf84..12ed0c41766 100644
--- a/runtime/moonbase/tests/common/mod.rs
+++ b/runtime/moonbase/tests/common/mod.rs
@@ -28,8 +28,8 @@ pub use moonbase_runtime::{
currency::{GIGAWEI, SUPPLY_FACTOR, UNIT, WEI},
AccountId, AssetId, AssetManager, Assets, AuthorInherent, Balance, Balances, Call,
CrowdloanRewards, Ethereum, Event, Executive, FixedGasPrice, InflationInfo, LocalAssets,
- ParachainStaking, Range, Runtime, System, TransactionConverter, UncheckedExtrinsic, HOURS,
- WEEKS,
+ ParachainStaking, Range, Runtime, Scheduler, System, TransactionConverter, UncheckedExtrinsic,
+ HOURS, WEEKS,
};
use nimbus_primitives::{NimbusId, NIMBUS_ENGINE_ID};
use sp_core::{Encode, H160};
@@ -85,6 +85,7 @@ pub fn run_to_block(n: u32, author: Option) {
}
// Initialize the new block
+ Scheduler::on_initialize(System::block_number());
AuthorInherent::on_initialize(System::block_number());
ParachainStaking::on_initialize(System::block_number());
Ethereum::on_initialize(System::block_number());
diff --git a/runtime/moonbase/tests/gov_tests.rs b/runtime/moonbase/tests/gov_tests.rs
new file mode 100644
index 00000000000..573492cfaf7
--- /dev/null
+++ b/runtime/moonbase/tests/gov_tests.rs
@@ -0,0 +1,88 @@
+// Copyright 2019-2022 PureStake Inc.
+// This file is part of Moonbeam.
+
+// Moonbeam is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Moonbeam is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Moonbeam. If not, see .
+
+//! TODO: move to integration tests if any of these are worth keeping
+
+mod common;
+use common::*;
+
+use frame_support::{
+ assert_noop, assert_ok,
+ dispatch::RawOrigin,
+ traits::{schedule::DispatchTime, PreimageRecipient},
+};
+use moonbase_runtime::{governance::*, Preimage, Referenda};
+use nimbus_primitives::NimbusId;
+use pallet_referenda::ReferendumInfo;
+use sp_core::{ByteArray, Encode, H256};
+use sp_runtime::traits::{BlakeTwo256, Hash};
+
+pub fn set_balance_proposal(value: u128) -> Vec {
+ Call::Balances(pallet_balances::Call::set_balance {
+ who: AccountId::from(ALICE),
+ new_free: value,
+ new_reserved: 0,
+ })
+ .encode()
+}
+
+pub fn set_balance_proposal_hash(value: u128) -> H256 {
+ let c = Call::Balances(pallet_balances::Call::set_balance {
+ who: AccountId::from(ALICE),
+ new_free: value,
+ new_reserved: 0,
+ });
+ >::note_preimage(c.encode().try_into().unwrap());
+ BlakeTwo256::hash_of(&c)
+}
+
+#[test]
+fn referenda_times_out_if_inaction() {
+ ExtBuilder::default()
+ .with_balances(vec![(AccountId::from(ALICE), 2_000 * UNIT)])
+ .with_collators(vec![(AccountId::from(ALICE), 1_000 * UNIT)])
+ .with_mappings(vec![(
+ NimbusId::from_slice(&ALICE_NIMBUS).unwrap(),
+ AccountId::from(ALICE),
+ )])
+ .build()
+ .execute_with(|| {
+ run_to_block(0, NimbusId::from_slice(&ALICE_NIMBUS).ok());
+ assert_ok!(Referenda::submit(
+ origin_of(AccountId::from(ALICE)),
+ // TODO: treasury spend from fasttrack origin
+ Box::new(WhitelistedCaller.into()),
+ set_balance_proposal_hash(1),
+ DispatchTime::At(10),
+ ));
+ run_to_block(10, NimbusId::from_slice(&ALICE_NIMBUS).ok());
+ let is_ongoing = match pallet_referenda::ReferendumInfoFor::::get(0) {
+ Some(ReferendumInfo::Ongoing(_)) => true,
+ _ => false,
+ };
+ assert!(is_ongoing);
+ // TODO: bring back once scheduler fixed
+ // TODO: check state in scheduler to see when expected to schedule
+ // and try to figure out why not scheduled
+ // run_to_block(15, NimbusId::from_slice(&ALICE_NIMBUS).ok());
+ // // Timed out - ended.
+ // let is_timed_out = match pallet_referenda::ReferendumInfoFor::::get(0) {
+ // Some(ReferendumInfo::TimedOut(11, _, None)) => true,
+ // _ => false,
+ // };
+ // assert!(is_timed_out, "{:?}", pallet_referenda::ReferendumInfoFor::::get(0));
+ });
+}