diff --git a/Cargo.lock b/Cargo.lock
index e99203bc92..e2e854fa63 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -136,6 +136,7 @@ dependencies = [
"frame-try-runtime",
"hex",
"hex-literal",
+ "lazy_static",
"libsecp256k1",
"log",
"module-aggregated-dex",
@@ -191,11 +192,13 @@ dependencies = [
"pallet-balances",
"pallet-bounties",
"pallet-collective",
+ "pallet-conviction-voting",
"pallet-democracy",
"pallet-membership",
"pallet-multisig",
"pallet-preimage",
"pallet-proxy",
+ "pallet-referenda",
"pallet-scheduler",
"pallet-session",
"pallet-staking",
@@ -206,6 +209,7 @@ dependencies = [
"pallet-transaction-payment-rpc-runtime-api",
"pallet-treasury",
"pallet-utility",
+ "pallet-whitelist",
"pallet-xcm",
"parachain-info",
"parity-scale-codec",
@@ -232,6 +236,8 @@ dependencies = [
"staging-xcm",
"staging-xcm-builder",
"staging-xcm-executor",
+ "strum 0.24.1",
+ "strum_macros 0.24.3",
"substrate-wasm-builder",
]
@@ -5440,6 +5446,7 @@ dependencies = [
"frame-try-runtime",
"hex",
"hex-literal",
+ "lazy_static",
"libsecp256k1",
"log",
"module-aggregated-dex",
@@ -5495,11 +5502,13 @@ dependencies = [
"pallet-balances",
"pallet-bounties",
"pallet-collective",
+ "pallet-conviction-voting",
"pallet-democracy",
"pallet-membership",
"pallet-multisig",
"pallet-preimage",
"pallet-proxy",
+ "pallet-referenda",
"pallet-scheduler",
"pallet-session",
"pallet-staking",
@@ -5510,6 +5519,7 @@ dependencies = [
"pallet-transaction-payment-rpc-runtime-api",
"pallet-treasury",
"pallet-utility",
+ "pallet-whitelist",
"pallet-xcm",
"parachain-info",
"parity-scale-codec",
@@ -5536,6 +5546,8 @@ dependencies = [
"staging-xcm",
"staging-xcm-builder",
"staging-xcm-executor",
+ "strum 0.24.1",
+ "strum_macros 0.24.3",
"substrate-wasm-builder",
]
@@ -6334,6 +6346,7 @@ dependencies = [
"frame-try-runtime",
"hex",
"hex-literal",
+ "lazy_static",
"libsecp256k1",
"log",
"module-aggregated-dex",
@@ -6392,6 +6405,7 @@ dependencies = [
"pallet-balances",
"pallet-bounties",
"pallet-collective",
+ "pallet-conviction-voting",
"pallet-democracy",
"pallet-elections-phragmen",
"pallet-indices",
@@ -6400,6 +6414,7 @@ dependencies = [
"pallet-preimage",
"pallet-proxy",
"pallet-recovery",
+ "pallet-referenda",
"pallet-root-testing",
"pallet-scheduler",
"pallet-session",
@@ -6410,6 +6425,7 @@ dependencies = [
"pallet-transaction-payment-rpc-runtime-api",
"pallet-treasury",
"pallet-utility",
+ "pallet-whitelist",
"pallet-xcm",
"parachain-info",
"parity-scale-codec",
@@ -6437,6 +6453,8 @@ dependencies = [
"staging-xcm",
"staging-xcm-builder",
"staging-xcm-executor",
+ "strum 0.24.1",
+ "strum_macros 0.24.3",
"substrate-wasm-builder",
]
diff --git a/runtime/acala/Cargo.toml b/runtime/acala/Cargo.toml
index cc87888bc4..909bd10dde 100644
--- a/runtime/acala/Cargo.toml
+++ b/runtime/acala/Cargo.toml
@@ -13,6 +13,9 @@ scale-info = { version = "2.9.0", default-features = false, features = ["derive"
serde_json = { version = "1.0.85", default-features = false, features = ["alloc"] }
hex = { version = "0.4", default-features = false }
hex-literal = { version = "0.4.1" }
+strum = { version = "0.24", default-features = false, features = [ "derive" ] }
+strum_macros = "0.24"
+lazy_static = "1.4.0"
# substrate
frame-executive = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
@@ -53,6 +56,9 @@ sp-staking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "rel
sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
+pallet-conviction-voting = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
+pallet-referenda = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
+pallet-whitelist = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
# cumulus
cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
@@ -149,6 +155,7 @@ std = [
"hex/std",
"scale-info/std",
"serde_json/std",
+ "strum/std",
"frame-benchmarking/std",
"frame-executive/std",
@@ -191,6 +198,9 @@ std = [
"sp-transaction-pool/std",
"sp-version/std",
"substrate-wasm-builder",
+ "pallet-conviction-voting/std",
+ "pallet-referenda/std",
+ "pallet-whitelist/std",
"cumulus-pallet-aura-ext/std",
"cumulus-pallet-dmp-queue/std",
@@ -285,6 +295,9 @@ runtime-benchmarks = [
"pallet-utility/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"sp-staking/runtime-benchmarks",
+ "pallet-conviction-voting/runtime-benchmarks",
+ "pallet-referenda/runtime-benchmarks",
+ "pallet-whitelist/runtime-benchmarks",
"cumulus-pallet-parachain-system/runtime-benchmarks",
"cumulus-pallet-xcmp-queue/runtime-benchmarks",
@@ -348,6 +361,9 @@ try-runtime = [
"pallet-treasury/try-runtime",
"pallet-utility/try-runtime",
"pallet-bags-list/try-runtime",
+ "pallet-conviction-voting/try-runtime",
+ "pallet-referenda/try-runtime",
+ "pallet-whitelist/try-runtime",
"cumulus-pallet-aura-ext/try-runtime",
"cumulus-pallet-dmp-queue/try-runtime",
diff --git a/runtime/acala/src/governance/councils.rs b/runtime/acala/src/governance/councils.rs
new file mode 100644
index 0000000000..31bc170ce2
--- /dev/null
+++ b/runtime/acala/src/governance/councils.rs
@@ -0,0 +1,144 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Councils for Gov1 and Gov2
+
+use super::*;
+
+parameter_types! {
+ pub const GeneralCouncilMotionDuration: BlockNumber = 3 * DAYS;
+ pub const CouncilDefaultMaxProposals: u32 = 20;
+ pub const CouncilDefaultMaxMembers: u32 = 30;
+ pub MaxProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block;
+}
+
+impl pallet_collective::Config for Runtime {
+ type RuntimeOrigin = RuntimeOrigin;
+ type Proposal = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type MotionDuration = GeneralCouncilMotionDuration;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type DefaultVote = pallet_collective::PrimeDefaultVote;
+ type SetMembersOrigin = EnsureRoot;
+ type WeightInfo = ();
+ type MaxProposalWeight = MaxProposalWeight;
+}
+
+impl pallet_membership::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type AddOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type RemoveOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type SwapOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type ResetOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type PrimeOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type MembershipInitialized = GeneralCouncil;
+ type MembershipChanged = GeneralCouncil;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type WeightInfo = ();
+}
+
+parameter_types! {
+ pub const FinancialCouncilMotionDuration: BlockNumber = 3 * DAYS;
+}
+
+impl pallet_collective::Config for Runtime {
+ type RuntimeOrigin = RuntimeOrigin;
+ type Proposal = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type MotionDuration = FinancialCouncilMotionDuration;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type DefaultVote = pallet_collective::PrimeDefaultVote;
+ type SetMembersOrigin = EnsureRoot;
+ type WeightInfo = ();
+ type MaxProposalWeight = MaxProposalWeight;
+}
+
+impl pallet_membership::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type MembershipInitialized = FinancialCouncil;
+ type MembershipChanged = FinancialCouncil;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type WeightInfo = ();
+}
+
+parameter_types! {
+ pub const HomaCouncilMotionDuration: BlockNumber = 3 * DAYS;
+}
+
+impl pallet_collective::Config for Runtime {
+ type RuntimeOrigin = RuntimeOrigin;
+ type Proposal = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type MotionDuration = HomaCouncilMotionDuration;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type DefaultVote = pallet_collective::PrimeDefaultVote;
+ type SetMembersOrigin = EnsureRoot;
+ type WeightInfo = ();
+ type MaxProposalWeight = MaxProposalWeight;
+}
+
+impl pallet_membership::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type MembershipInitialized = HomaCouncil;
+ type MembershipChanged = HomaCouncil;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type WeightInfo = ();
+}
+
+parameter_types! {
+ pub const TechnicalCommitteeMotionDuration: BlockNumber = 3 * DAYS;
+}
+
+impl pallet_collective::Config for Runtime {
+ type RuntimeOrigin = RuntimeOrigin;
+ type Proposal = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type MotionDuration = TechnicalCommitteeMotionDuration;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type DefaultVote = pallet_collective::PrimeDefaultVote;
+ type SetMembersOrigin = EnsureRoot;
+ type WeightInfo = ();
+ type MaxProposalWeight = MaxProposalWeight;
+}
+
+impl pallet_membership::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type MembershipInitialized = TechnicalCommittee;
+ type MembershipChanged = TechnicalCommittee;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type WeightInfo = ();
+}
diff --git a/runtime/acala/src/governance/democracy.rs b/runtime/acala/src/governance/democracy.rs
new file mode 100644
index 0000000000..4ec5df6265
--- /dev/null
+++ b/runtime/acala/src/governance/democracy.rs
@@ -0,0 +1,74 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Democracy config for Gov1
+
+use crate::*;
+
+parameter_types! {
+ pub const LaunchPeriod: BlockNumber = 5 * DAYS;
+ pub const VotingPeriod: BlockNumber = 5 * DAYS;
+ pub const FastTrackVotingPeriod: BlockNumber = 3 * HOURS;
+ pub MinimumDeposit: Balance = 1000 * dollar(ACA);
+ pub const EnactmentPeriod: BlockNumber = 2 * DAYS;
+ pub const VoteLockingPeriod: BlockNumber = 14 * DAYS;
+ pub const CooloffPeriod: BlockNumber = 7 * DAYS;
+}
+
+impl pallet_democracy::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type Currency = Balances;
+ type EnactmentPeriod = EnactmentPeriod;
+ type LaunchPeriod = LaunchPeriod;
+ type VotingPeriod = VotingPeriod;
+ type VoteLockingPeriod = VoteLockingPeriod;
+ type MinimumDeposit = MinimumDeposit;
+ /// A straight majority of the council can decide what their next motion is.
+ type ExternalOrigin = EnsureRootOrHalfGeneralCouncil;
+ /// A majority can have the next scheduled referendum be a straight majority-carries vote.
+ type ExternalMajorityOrigin = EnsureRootOrHalfGeneralCouncil;
+ /// A unanimous council can have the next scheduled referendum be a straight default-carries
+ /// (NTB) vote.
+ type ExternalDefaultOrigin = EnsureRootOrAllGeneralCouncil;
+ /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote
+ /// be tabled immediately and with a shorter voting/enactment period.
+ type FastTrackOrigin = EnsureRootOrTwoThirdsTechnicalCommittee;
+ type InstantOrigin = EnsureRootOrAllTechnicalCommittee;
+ type InstantAllowed = ConstBool;
+ type FastTrackVotingPeriod = FastTrackVotingPeriod;
+ // To cancel a proposal which has been passed, 2/3 of the council must agree to it.
+ type CancellationOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type BlacklistOrigin = EnsureRoot;
+ // To cancel a proposal before it has been passed, the technical committee must be unanimous or
+ // Root must agree.
+ type CancelProposalOrigin = EnsureRootOrAllTechnicalCommittee;
+ // Any single technical committee member may veto a coming council proposal, however they can
+ // only do it once and it lasts only for the cooloff period.
+ type VetoOrigin = pallet_collective::EnsureMember;
+ type CooloffPeriod = CooloffPeriod;
+ type Slash = Treasury;
+ type Scheduler = Scheduler;
+ type PalletsOrigin = OriginCaller;
+ type MaxVotes = ConstU32<100>;
+ type WeightInfo = pallet_democracy::weights::SubstrateWeight;
+ type MaxProposals = ConstU32<100>;
+ type Preimages = Preimage;
+ type MaxDeposits = ConstU32<100>;
+ type MaxBlacklisted = ConstU32<100>;
+ type SubmitOrigin = EnsureSigned;
+}
diff --git a/runtime/acala/src/governance/mod.rs b/runtime/acala/src/governance/mod.rs
new file mode 100644
index 0000000000..9d8000ef01
--- /dev/null
+++ b/runtime/acala/src/governance/mod.rs
@@ -0,0 +1,30 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Governance configurations
+
+pub mod councils;
+mod democracy;
+pub mod referenda;
+
+use super::*;
+
+mod origins;
+pub use origins::{custom_origins, GeneralAdmin, ReferendumCanceller, ReferendumKiller, WhitelistedCaller};
+mod tracks;
+pub use tracks::TracksInfo;
diff --git a/runtime/acala/src/governance/origins.rs b/runtime/acala/src/governance/origins.rs
new file mode 100644
index 0000000000..7f7d7237a0
--- /dev/null
+++ b/runtime/acala/src/governance/origins.rs
@@ -0,0 +1,79 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Custom origins for governance interventions.
+
+pub use custom_origins::*;
+
+#[frame_support::pallet]
+pub mod custom_origins {
+ use frame_support::pallet_prelude::*;
+ use strum_macros::EnumString;
+
+ #[pallet::config]
+ pub trait Config: frame_system::Config {}
+
+ #[pallet::pallet]
+ pub struct Pallet(_);
+
+ #[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug, EnumString)]
+ #[strum(serialize_all = "snake_case")]
+ #[pallet::origin]
+ pub enum Origin {
+ /// Origin able to dispatch a whitelisted call.
+ WhitelistedCaller,
+ /// General admin
+ GeneralAdmin,
+ /// Origin able to cancel referenda.
+ ReferendumCanceller,
+ /// Origin able to kill referenda.
+ ReferendumKiller,
+ }
+
+ 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!(ReferendumCanceller, ReferendumKiller, WhitelistedCaller, GeneralAdmin);
+}
diff --git a/runtime/acala/src/governance/referenda.rs b/runtime/acala/src/governance/referenda.rs
new file mode 100644
index 0000000000..cd46634046
--- /dev/null
+++ b/runtime/acala/src/governance/referenda.rs
@@ -0,0 +1,94 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! # Gov2 config
+//! Includes runtime configs for these substrate pallets:
+//! 1. pallet-conviction-voting
+//! 2. pallet-whitelist
+//! 3. pallet-referenda
+
+use super::*;
+use frame_support::traits::{EitherOf, MapSuccess};
+use frame_system::EnsureRootWithSuccess;
+use sp_runtime::traits::Replace;
+
+parameter_types! {
+ pub const VoteLockingPeriod: BlockNumber = 1 * DAYS;
+}
+
+impl pallet_conviction_voting::Config for Runtime {
+ type WeightInfo = ();
+ type RuntimeEvent = RuntimeEvent;
+ type Currency = Balances;
+ type Polls = Referenda;
+ type MaxTurnout = frame_support::traits::TotalIssuanceOf;
+ // Maximum number of concurrent votes an account may have
+ type MaxVotes = ConstU32<20>;
+ // Minimum period of vote locking
+ type VoteLockingPeriod = VoteLockingPeriod;
+}
+
+// Origin for general admin or root
+pub type GeneralAdminOrRoot = EitherOf, origins::GeneralAdmin>;
+
+impl custom_origins::Config for Runtime {}
+
+// The purpose of this pallet is to queue calls to be dispatched as by root later => the Dispatch
+// origin corresponds to the Gov2 Whitelist track.
+impl pallet_whitelist::Config for Runtime {
+ type WeightInfo = ();
+ type RuntimeEvent = RuntimeEvent;
+ type RuntimeCall = RuntimeCall;
+ type WhitelistOrigin = EitherOf<
+ EnsureRootWithSuccess>,
+ MapSuccess<
+ pallet_collective::EnsureProportionAtLeast,
+ Replace>,
+ >,
+ >;
+ type DispatchWhitelistedOrigin = EitherOf, WhitelistedCaller>;
+ type Preimages = Preimage;
+}
+
+pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber);
+
+parameter_types! {
+ pub const AlarmInterval: BlockNumber = 1;
+ pub SubmissionDeposit: Balance = 10 * dollar(ACA);
+ pub const UndecidingTimeout: BlockNumber = 14 * DAYS;
+}
+
+impl pallet_referenda::Config for Runtime {
+ type WeightInfo = ();
+ type RuntimeCall = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type Scheduler = Scheduler;
+ type Currency = Balances;
+ type SubmitOrigin = frame_system::EnsureSigned;
+ type CancelOrigin = EitherOf, ReferendumCanceller>;
+ type KillOrigin = EitherOf, 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;
+ type Preimages = Preimage;
+}
diff --git a/runtime/acala/src/governance/tracks.rs b/runtime/acala/src/governance/tracks.rs
new file mode 100644
index 0000000000..ef053401e9
--- /dev/null
+++ b/runtime/acala/src/governance/tracks.rs
@@ -0,0 +1,178 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Track configurations for governance.
+
+use super::*;
+use pallet_referenda::Curve;
+use sp_std::str::FromStr;
+
+const fn percent(x: i32) -> sp_runtime::FixedI64 {
+ sp_runtime::FixedI64::from_rational(x as u128, 100)
+}
+const fn permill(x: i32) -> sp_runtime::FixedI64 {
+ sp_runtime::FixedI64::from_rational(x as u128, 1000)
+}
+
+lazy_static::lazy_static! {
+static ref TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 5] = [
+ (
+ 0,
+ pallet_referenda::TrackInfo {
+ // Name of this track.
+ name: "root",
+ // A limit for the number of referenda on this track that can be being decided at once.
+ // For Root origin this should generally be just one.
+ max_deciding: 5,
+ // Amount that must be placed on deposit before a decision can be made.
+ decision_deposit: 20 * 1000 * dollar(ACA),
+ // Amount of time this must be submitted for before a decision can be made.
+ prepare_period: 1 * DAYS,
+ // Amount of time that a decision may take to be approved prior to cancellation.
+ decision_period: 14 * DAYS,
+ // Amount of time that the approval criteria must hold before it can be approved.
+ confirm_period: 1 * DAYS,
+ // Minimum amount of time that an approved proposal must be in the dispatch queue.
+ min_enactment_period: 1 * DAYS,
+ // Minimum aye votes as percentage of overall conviction-weighted votes needed for
+ // approval as a function of time into decision period.
+ min_approval: Curve::make_reciprocal(4, 14, percent(80), percent(50), percent(100)),
+ // Minimum pre-conviction aye-votes ("support") as percentage of overall population that
+ // is needed for approval as a function of time into decision period.
+ min_support: Curve::make_linear(14, 14, permill(5), percent(25)),
+ },
+ ),
+ (
+ 1,
+ pallet_referenda::TrackInfo {
+ name: "whitelisted_caller",
+ max_deciding: 100,
+ decision_deposit: 2 * 1000 * dollar(ACA),
+ prepare_period: 10 * MINUTES,
+ decision_period: 14 * DAYS,
+ confirm_period: 10 * MINUTES,
+ min_enactment_period: 30 * MINUTES,
+ min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)),
+ min_support: Curve::make_reciprocal(1, 14 * 24, percent(1), percent(0), percent(2)),
+ },
+ ),
+ (
+ 2,
+ pallet_referenda::TrackInfo {
+ name: "general_admin",
+ max_deciding: 10,
+ decision_deposit: 1000 * dollar(ACA),
+ prepare_period: 1 * HOURS,
+ decision_period: 14 * DAYS,
+ confirm_period: 1 * DAYS,
+ min_enactment_period: 1 * DAYS,
+ min_approval: Curve::make_reciprocal(4, 14, percent(80), percent(50), percent(100)),
+ min_support: Curve::make_reciprocal(7, 14, percent(10), percent(0), percent(50)),
+ },
+ ),
+ (
+ 3,
+ pallet_referenda::TrackInfo {
+ name: "referendum_canceller",
+ max_deciding: 20,
+ decision_deposit: 2 * 1000 * dollar(ACA),
+ prepare_period: 1 * HOURS,
+ decision_period: 14 * DAYS,
+ confirm_period: 3 * HOURS,
+ min_enactment_period: 10 * MINUTES,
+ min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)),
+ min_support: Curve::make_reciprocal(1, 14, percent(1), percent(0), percent(10)),
+ },
+ ),
+ (
+ 4,
+ pallet_referenda::TrackInfo {
+ name: "referendum_killer",
+ max_deciding: 100,
+ decision_deposit: 4 * 1000 * dollar(ACA),
+ prepare_period: 1 * HOURS,
+ decision_period: 14 * DAYS,
+ confirm_period: 3 * HOURS,
+ min_enactment_period: 10 * MINUTES,
+ min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)),
+ min_support: Curve::make_reciprocal(1, 14, percent(1), percent(0), percent(10)),
+ },
+ ),
+];
+}
+
+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 => {
+ if let Some((track_id, _)) = Self::tracks().into_iter().find(|(_, track)| track.name == "root") {
+ Ok(*track_id)
+ } else {
+ Err(())
+ }
+ }
+ _ => Err(()),
+ }
+ } else if let Ok(custom_origin) = custom_origins::Origin::try_from(id.clone()) {
+ if let Some((track_id, _)) = Self::tracks().into_iter().find(|(_, track)| {
+ if let Ok(track_custom_origin) = custom_origins::Origin::from_str(track.name) {
+ track_custom_origin == custom_origin
+ } else {
+ false
+ }
+ }) {
+ Ok(*track_id)
+ } else {
+ Err(())
+ }
+ } else {
+ Err(())
+ }
+ }
+}
+
+#[test]
+/// To ensure voters are always locked into their vote
+fn vote_locking_always_longer_than_enactment_period() {
+ for (_, track) in (&TRACKS_DATA).iter() {
+ assert!(
+ ::VoteLockingPeriod::get() >= track.min_enactment_period,
+ "Track {} has enactment period {} < vote locking period {}",
+ track.name,
+ track.min_enactment_period,
+ ::VoteLockingPeriod::get(),
+ );
+ }
+}
+
+#[test]
+fn all_tracks_have_origins() {
+ for (_, track) in (&TRACKS_DATA).iter() {
+ // check name.into() is successful either converts into "root" or custom origin
+ let track_is_root = track.name == "root";
+ let track_has_custom_origin = custom_origins::Origin::from_str(track.name).is_ok();
+ assert!(track_is_root || track_has_custom_origin);
+ }
+}
diff --git a/runtime/acala/src/lib.rs b/runtime/acala/src/lib.rs
index 7c4e54c522..8b5ed30ec2 100644
--- a/runtime/acala/src/lib.rs
+++ b/runtime/acala/src/lib.rs
@@ -118,9 +118,11 @@ pub use xcm::v3::prelude::*;
mod authority;
mod benchmarking;
pub mod constants;
+pub mod governance;
/// Weights for pallets used in the runtime.
mod weights;
pub mod xcm_config;
+use governance::councils::*;
/// This runtime version.
#[sp_version::runtime_version]
@@ -395,129 +397,6 @@ impl pallet_sudo::Config for Runtime {
type WeightInfo = ();
}
-parameter_types! {
- pub const GeneralCouncilMotionDuration: BlockNumber = 3 * DAYS;
- pub const CouncilDefaultMaxProposals: u32 = 20;
- pub const CouncilDefaultMaxMembers: u32 = 30;
- pub MaxProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block;
-}
-
-impl pallet_collective::Config for Runtime {
- type RuntimeOrigin = RuntimeOrigin;
- type Proposal = RuntimeCall;
- type RuntimeEvent = RuntimeEvent;
- type MotionDuration = GeneralCouncilMotionDuration;
- type MaxProposals = CouncilDefaultMaxProposals;
- type MaxMembers = CouncilDefaultMaxMembers;
- type DefaultVote = pallet_collective::PrimeDefaultVote;
- type SetMembersOrigin = EnsureRoot;
- type WeightInfo = ();
- type MaxProposalWeight = MaxProposalWeight;
-}
-
-impl pallet_membership::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type AddOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type RemoveOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type SwapOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type ResetOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type PrimeOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type MembershipInitialized = GeneralCouncil;
- type MembershipChanged = GeneralCouncil;
- type MaxMembers = CouncilDefaultMaxMembers;
- type WeightInfo = ();
-}
-
-parameter_types! {
- pub const FinancialCouncilMotionDuration: BlockNumber = 3 * DAYS;
-}
-
-impl pallet_collective::Config for Runtime {
- type RuntimeOrigin = RuntimeOrigin;
- type Proposal = RuntimeCall;
- type RuntimeEvent = RuntimeEvent;
- type MotionDuration = FinancialCouncilMotionDuration;
- type MaxProposals = CouncilDefaultMaxProposals;
- type MaxMembers = CouncilDefaultMaxMembers;
- type DefaultVote = pallet_collective::PrimeDefaultVote;
- type SetMembersOrigin = EnsureRoot;
- type WeightInfo = ();
- type MaxProposalWeight = MaxProposalWeight;
-}
-
-impl pallet_membership::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type MembershipInitialized = FinancialCouncil;
- type MembershipChanged = FinancialCouncil;
- type MaxMembers = CouncilDefaultMaxMembers;
- type WeightInfo = ();
-}
-
-parameter_types! {
- pub const HomaCouncilMotionDuration: BlockNumber = 3 * DAYS;
-}
-
-impl pallet_collective::Config for Runtime {
- type RuntimeOrigin = RuntimeOrigin;
- type Proposal = RuntimeCall;
- type RuntimeEvent = RuntimeEvent;
- type MotionDuration = HomaCouncilMotionDuration;
- type MaxProposals = CouncilDefaultMaxProposals;
- type MaxMembers = CouncilDefaultMaxMembers;
- type DefaultVote = pallet_collective::PrimeDefaultVote;
- type SetMembersOrigin = EnsureRoot;
- type WeightInfo = ();
- type MaxProposalWeight = MaxProposalWeight;
-}
-
-impl pallet_membership::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type MembershipInitialized = HomaCouncil;
- type MembershipChanged = HomaCouncil;
- type MaxMembers = CouncilDefaultMaxMembers;
- type WeightInfo = ();
-}
-
-parameter_types! {
- pub const TechnicalCommitteeMotionDuration: BlockNumber = 3 * DAYS;
-}
-
-impl pallet_collective::Config for Runtime {
- type RuntimeOrigin = RuntimeOrigin;
- type Proposal = RuntimeCall;
- type RuntimeEvent = RuntimeEvent;
- type MotionDuration = TechnicalCommitteeMotionDuration;
- type MaxProposals = CouncilDefaultMaxProposals;
- type MaxMembers = CouncilDefaultMaxMembers;
- type DefaultVote = pallet_collective::PrimeDefaultVote;
- type SetMembersOrigin = EnsureRoot;
- type WeightInfo = ();
- type MaxProposalWeight = MaxProposalWeight;
-}
-
-impl pallet_membership::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type MembershipInitialized = TechnicalCommittee;
- type MembershipChanged = TechnicalCommittee;
- type MaxMembers = CouncilDefaultMaxMembers;
- type WeightInfo = ();
-}
-
impl pallet_membership::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
@@ -647,59 +526,6 @@ impl pallet_tips::Config for Runtime {
type WeightInfo = ();
}
-parameter_types! {
- pub const LaunchPeriod: BlockNumber = 5 * DAYS;
- pub const VotingPeriod: BlockNumber = 5 * DAYS;
- pub const FastTrackVotingPeriod: BlockNumber = 3 * HOURS;
- pub MinimumDeposit: Balance = 1000 * dollar(ACA);
- pub const EnactmentPeriod: BlockNumber = 2 * DAYS;
- pub const VoteLockingPeriod: BlockNumber = 14 * DAYS;
- pub const CooloffPeriod: BlockNumber = 7 * DAYS;
-}
-
-impl pallet_democracy::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type Currency = Balances;
- type EnactmentPeriod = EnactmentPeriod;
- type LaunchPeriod = LaunchPeriod;
- type VotingPeriod = VotingPeriod;
- type VoteLockingPeriod = VoteLockingPeriod;
- type MinimumDeposit = MinimumDeposit;
- /// A straight majority of the council can decide what their next motion is.
- type ExternalOrigin = EnsureRootOrHalfGeneralCouncil;
- /// A majority can have the next scheduled referendum be a straight majority-carries vote.
- type ExternalMajorityOrigin = EnsureRootOrHalfGeneralCouncil;
- /// A unanimous council can have the next scheduled referendum be a straight default-carries
- /// (NTB) vote.
- type ExternalDefaultOrigin = EnsureRootOrAllGeneralCouncil;
- /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote
- /// be tabled immediately and with a shorter voting/enactment period.
- type FastTrackOrigin = EnsureRootOrTwoThirdsTechnicalCommittee;
- type InstantOrigin = EnsureRootOrAllTechnicalCommittee;
- type InstantAllowed = ConstBool;
- type FastTrackVotingPeriod = FastTrackVotingPeriod;
- // To cancel a proposal which has been passed, 2/3 of the council must agree to it.
- type CancellationOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type BlacklistOrigin = EnsureRoot;
- // To cancel a proposal before it has been passed, the technical committee must be unanimous or
- // Root must agree.
- type CancelProposalOrigin = EnsureRootOrAllTechnicalCommittee;
- // Any single technical committee member may veto a coming council proposal, however they can
- // only do it once and it lasts only for the cooloff period.
- type VetoOrigin = pallet_collective::EnsureMember;
- type CooloffPeriod = CooloffPeriod;
- type Slash = Treasury;
- type Scheduler = Scheduler;
- type PalletsOrigin = OriginCaller;
- type MaxVotes = ConstU32<100>;
- type WeightInfo = pallet_democracy::weights::SubstrateWeight;
- type MaxProposals = ConstU32<100>;
- type Preimages = Preimage;
- type MaxDeposits = ConstU32<100>;
- type MaxBlacklisted = ConstU32<100>;
- type SubmitOrigin = EnsureSigned;
-}
-
impl orml_auction::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
@@ -1787,6 +1613,10 @@ construct_runtime!(
TechnicalCommittee: pallet_collective:: = 67,
TechnicalCommitteeMembership: pallet_membership:: = 68,
Democracy: pallet_democracy = 69,
+ ConvictionVoting: pallet_conviction_voting = 160,
+ Referenda: pallet_referenda = 161,
+ Origins: governance::custom_origins::{Origin} = 162,
+ Whitelist: pallet_whitelist = 163,
// Oracle
//
diff --git a/runtime/karura/Cargo.toml b/runtime/karura/Cargo.toml
index df78846da3..d5c692b22e 100644
--- a/runtime/karura/Cargo.toml
+++ b/runtime/karura/Cargo.toml
@@ -13,6 +13,9 @@ scale-info = { version = "2.9.0", default-features = false, features = ["derive"
serde_json = { version = "1.0.85", default-features = false, features = ["alloc"] }
hex = { version = "0.4", default-features = false }
hex-literal = { version = "0.4.1" }
+strum = { version = "0.24", default-features = false, features = [ "derive" ] }
+strum_macros = "0.24"
+lazy_static = "1.4.0"
# substrate
frame-executive = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
@@ -53,6 +56,9 @@ sp-staking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "rel
sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
+pallet-conviction-voting = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
+pallet-referenda = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
+pallet-whitelist = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
# cumulus
cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
@@ -149,6 +155,7 @@ std = [
"hex/std",
"scale-info/std",
"serde_json/std",
+ "strum/std",
"frame-benchmarking/std",
"frame-executive/std",
@@ -192,6 +199,9 @@ std = [
"sp-transaction-pool/std",
"sp-version/std",
"substrate-wasm-builder",
+ "pallet-conviction-voting/std",
+ "pallet-referenda/std",
+ "pallet-whitelist/std",
"cumulus-pallet-aura-ext/std",
"cumulus-pallet-dmp-queue/std",
@@ -286,6 +296,9 @@ runtime-benchmarks = [
"pallet-utility/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"sp-staking/runtime-benchmarks",
+ "pallet-conviction-voting/runtime-benchmarks",
+ "pallet-referenda/runtime-benchmarks",
+ "pallet-whitelist/runtime-benchmarks",
"cumulus-pallet-parachain-system/runtime-benchmarks",
"cumulus-pallet-xcmp-queue/runtime-benchmarks",
@@ -349,6 +362,9 @@ try-runtime = [
"pallet-treasury/try-runtime",
"pallet-utility/try-runtime",
"pallet-bags-list/try-runtime",
+ "pallet-conviction-voting/try-runtime",
+ "pallet-referenda/try-runtime",
+ "pallet-whitelist/try-runtime",
"cumulus-pallet-aura-ext/try-runtime",
"cumulus-pallet-dmp-queue/try-runtime",
diff --git a/runtime/karura/src/governance/councils.rs b/runtime/karura/src/governance/councils.rs
new file mode 100644
index 0000000000..31bc170ce2
--- /dev/null
+++ b/runtime/karura/src/governance/councils.rs
@@ -0,0 +1,144 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Councils for Gov1 and Gov2
+
+use super::*;
+
+parameter_types! {
+ pub const GeneralCouncilMotionDuration: BlockNumber = 3 * DAYS;
+ pub const CouncilDefaultMaxProposals: u32 = 20;
+ pub const CouncilDefaultMaxMembers: u32 = 30;
+ pub MaxProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block;
+}
+
+impl pallet_collective::Config for Runtime {
+ type RuntimeOrigin = RuntimeOrigin;
+ type Proposal = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type MotionDuration = GeneralCouncilMotionDuration;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type DefaultVote = pallet_collective::PrimeDefaultVote;
+ type SetMembersOrigin = EnsureRoot;
+ type WeightInfo = ();
+ type MaxProposalWeight = MaxProposalWeight;
+}
+
+impl pallet_membership::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type AddOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type RemoveOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type SwapOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type ResetOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type PrimeOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type MembershipInitialized = GeneralCouncil;
+ type MembershipChanged = GeneralCouncil;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type WeightInfo = ();
+}
+
+parameter_types! {
+ pub const FinancialCouncilMotionDuration: BlockNumber = 3 * DAYS;
+}
+
+impl pallet_collective::Config for Runtime {
+ type RuntimeOrigin = RuntimeOrigin;
+ type Proposal = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type MotionDuration = FinancialCouncilMotionDuration;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type DefaultVote = pallet_collective::PrimeDefaultVote;
+ type SetMembersOrigin = EnsureRoot;
+ type WeightInfo = ();
+ type MaxProposalWeight = MaxProposalWeight;
+}
+
+impl pallet_membership::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type MembershipInitialized = FinancialCouncil;
+ type MembershipChanged = FinancialCouncil;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type WeightInfo = ();
+}
+
+parameter_types! {
+ pub const HomaCouncilMotionDuration: BlockNumber = 3 * DAYS;
+}
+
+impl pallet_collective::Config for Runtime {
+ type RuntimeOrigin = RuntimeOrigin;
+ type Proposal = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type MotionDuration = HomaCouncilMotionDuration;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type DefaultVote = pallet_collective::PrimeDefaultVote;
+ type SetMembersOrigin = EnsureRoot;
+ type WeightInfo = ();
+ type MaxProposalWeight = MaxProposalWeight;
+}
+
+impl pallet_membership::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type MembershipInitialized = HomaCouncil;
+ type MembershipChanged = HomaCouncil;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type WeightInfo = ();
+}
+
+parameter_types! {
+ pub const TechnicalCommitteeMotionDuration: BlockNumber = 3 * DAYS;
+}
+
+impl pallet_collective::Config for Runtime {
+ type RuntimeOrigin = RuntimeOrigin;
+ type Proposal = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type MotionDuration = TechnicalCommitteeMotionDuration;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type DefaultVote = pallet_collective::PrimeDefaultVote;
+ type SetMembersOrigin = EnsureRoot;
+ type WeightInfo = ();
+ type MaxProposalWeight = MaxProposalWeight;
+}
+
+impl pallet_membership::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type MembershipInitialized = TechnicalCommittee;
+ type MembershipChanged = TechnicalCommittee;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type WeightInfo = ();
+}
diff --git a/runtime/karura/src/governance/democracy.rs b/runtime/karura/src/governance/democracy.rs
new file mode 100644
index 0000000000..3a809c556f
--- /dev/null
+++ b/runtime/karura/src/governance/democracy.rs
@@ -0,0 +1,75 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Democracy config for Gov1
+
+use crate::*;
+
+parameter_types! {
+ pub const LaunchPeriod: BlockNumber = 5 * DAYS;
+ pub const VotingPeriod: BlockNumber = 5 * DAYS;
+ pub const FastTrackVotingPeriod: BlockNumber = 3 * HOURS;
+ pub MinimumDeposit: Balance = 100 * dollar(KAR);
+ pub const EnactmentPeriod: BlockNumber = 2 * DAYS;
+ pub const VoteLockingPeriod: BlockNumber = 7 * DAYS;
+ pub const CooloffPeriod: BlockNumber = 7 * DAYS;
+}
+
+impl pallet_democracy::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type Currency = Balances;
+ type EnactmentPeriod = EnactmentPeriod;
+ type LaunchPeriod = LaunchPeriod;
+ type VotingPeriod = VotingPeriod;
+ type VoteLockingPeriod = VoteLockingPeriod;
+ type MinimumDeposit = MinimumDeposit;
+ /// A straight majority of the council can decide what their next motion is.
+ type ExternalOrigin = EnsureRootOrHalfGeneralCouncil;
+ /// A majority can have the next scheduled referendum be a straight majority-carries vote.
+ type ExternalMajorityOrigin = EnsureRootOrHalfGeneralCouncil;
+ /// A unanimous council can have the next scheduled referendum be a straight default-carries
+ /// (NTB) vote.
+ type ExternalDefaultOrigin = EnsureRootOrAllGeneralCouncil;
+ /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote
+ /// be tabled immediately and with a shorter voting/enactment period.
+ type FastTrackOrigin = EnsureRootOrTwoThirdsTechnicalCommittee;
+ type InstantOrigin = EnsureRootOrAllTechnicalCommittee;
+ type InstantAllowed = ConstBool;
+ type FastTrackVotingPeriod = FastTrackVotingPeriod;
+ // To cancel a proposal which has been passed, 2/3 of the council must agree to it.
+ type CancellationOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type BlacklistOrigin = EnsureRoot;
+ // To cancel a proposal before it has been passed, the technical committee must be unanimous or
+ // Root must agree.
+ type CancelProposalOrigin = EnsureRootOrAllTechnicalCommittee;
+ // Any single technical committee member may veto a coming council proposal, however they can
+ // only do it once and it lasts only for the cooloff period.
+ type VetoOrigin = pallet_collective::EnsureMember;
+ type CooloffPeriod = CooloffPeriod;
+ type Slash = Treasury;
+ type Scheduler = Scheduler;
+ type PalletsOrigin = OriginCaller;
+ type MaxVotes = ConstU32<100>;
+ //TODO: might need to weight for Karura
+ type WeightInfo = pallet_democracy::weights::SubstrateWeight;
+ type MaxProposals = ConstU32<100>;
+ type Preimages = Preimage;
+ type MaxDeposits = ConstU32<100>;
+ type MaxBlacklisted = ConstU32<100>;
+ type SubmitOrigin = EnsureSigned;
+}
diff --git a/runtime/karura/src/governance/mod.rs b/runtime/karura/src/governance/mod.rs
new file mode 100644
index 0000000000..9d8000ef01
--- /dev/null
+++ b/runtime/karura/src/governance/mod.rs
@@ -0,0 +1,30 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Governance configurations
+
+pub mod councils;
+mod democracy;
+pub mod referenda;
+
+use super::*;
+
+mod origins;
+pub use origins::{custom_origins, GeneralAdmin, ReferendumCanceller, ReferendumKiller, WhitelistedCaller};
+mod tracks;
+pub use tracks::TracksInfo;
diff --git a/runtime/karura/src/governance/origins.rs b/runtime/karura/src/governance/origins.rs
new file mode 100644
index 0000000000..7f7d7237a0
--- /dev/null
+++ b/runtime/karura/src/governance/origins.rs
@@ -0,0 +1,79 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Custom origins for governance interventions.
+
+pub use custom_origins::*;
+
+#[frame_support::pallet]
+pub mod custom_origins {
+ use frame_support::pallet_prelude::*;
+ use strum_macros::EnumString;
+
+ #[pallet::config]
+ pub trait Config: frame_system::Config {}
+
+ #[pallet::pallet]
+ pub struct Pallet(_);
+
+ #[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug, EnumString)]
+ #[strum(serialize_all = "snake_case")]
+ #[pallet::origin]
+ pub enum Origin {
+ /// Origin able to dispatch a whitelisted call.
+ WhitelistedCaller,
+ /// General admin
+ GeneralAdmin,
+ /// Origin able to cancel referenda.
+ ReferendumCanceller,
+ /// Origin able to kill referenda.
+ ReferendumKiller,
+ }
+
+ 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!(ReferendumCanceller, ReferendumKiller, WhitelistedCaller, GeneralAdmin);
+}
diff --git a/runtime/karura/src/governance/referenda.rs b/runtime/karura/src/governance/referenda.rs
new file mode 100644
index 0000000000..c28801b43b
--- /dev/null
+++ b/runtime/karura/src/governance/referenda.rs
@@ -0,0 +1,94 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! # Gov2 config
+//! Includes runtime configs for these substrate pallets:
+//! 1. pallet-conviction-voting
+//! 2. pallet-whitelist
+//! 3. pallet-referenda
+
+use super::*;
+use frame_support::traits::{EitherOf, MapSuccess};
+use frame_system::EnsureRootWithSuccess;
+use sp_runtime::traits::Replace;
+
+parameter_types! {
+ pub const VoteLockingPeriod: BlockNumber = 1 * DAYS;
+}
+
+impl pallet_conviction_voting::Config for Runtime {
+ type WeightInfo = ();
+ type RuntimeEvent = RuntimeEvent;
+ type Currency = Balances;
+ type Polls = Referenda;
+ type MaxTurnout = frame_support::traits::TotalIssuanceOf;
+ // Maximum number of concurrent votes an account may have
+ type MaxVotes = ConstU32<20>;
+ // Minimum period of vote locking
+ type VoteLockingPeriod = VoteLockingPeriod;
+}
+
+// Origin for general admin or root
+pub type GeneralAdminOrRoot = EitherOf, origins::GeneralAdmin>;
+
+impl custom_origins::Config for Runtime {}
+
+// The purpose of this pallet is to queue calls to be dispatched as by root later => the Dispatch
+// origin corresponds to the Gov2 Whitelist track.
+impl pallet_whitelist::Config for Runtime {
+ type WeightInfo = ();
+ type RuntimeEvent = RuntimeEvent;
+ type RuntimeCall = RuntimeCall;
+ type WhitelistOrigin = EitherOf<
+ EnsureRootWithSuccess>,
+ MapSuccess<
+ pallet_collective::EnsureProportionAtLeast,
+ Replace>,
+ >,
+ >;
+ type DispatchWhitelistedOrigin = EitherOf, WhitelistedCaller>;
+ type Preimages = Preimage;
+}
+
+pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber);
+
+parameter_types! {
+ pub const AlarmInterval: BlockNumber = 1;
+ pub SubmissionDeposit: Balance = 10 * dollar(KAR);
+ pub const UndecidingTimeout: BlockNumber = 14 * DAYS;
+}
+
+impl pallet_referenda::Config for Runtime {
+ type WeightInfo = ();
+ type RuntimeCall = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type Scheduler = Scheduler;
+ type Currency = Balances;
+ type SubmitOrigin = frame_system::EnsureSigned;
+ type CancelOrigin = EitherOf, ReferendumCanceller>;
+ type KillOrigin = EitherOf, 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;
+ type Preimages = Preimage;
+}
diff --git a/runtime/karura/src/governance/tracks.rs b/runtime/karura/src/governance/tracks.rs
new file mode 100644
index 0000000000..df9807e8eb
--- /dev/null
+++ b/runtime/karura/src/governance/tracks.rs
@@ -0,0 +1,178 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Track configurations for governance.
+
+use super::*;
+use pallet_referenda::Curve;
+use sp_std::str::FromStr;
+
+const fn percent(x: i32) -> sp_runtime::FixedI64 {
+ sp_runtime::FixedI64::from_rational(x as u128, 100)
+}
+const fn permill(x: i32) -> sp_runtime::FixedI64 {
+ sp_runtime::FixedI64::from_rational(x as u128, 1000)
+}
+
+lazy_static::lazy_static! {
+static ref TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 5] = [
+ (
+ 0,
+ pallet_referenda::TrackInfo {
+ // Name of this track.
+ name: "root",
+ // A limit for the number of referenda on this track that can be being decided at once.
+ // For Root origin this should generally be just one.
+ max_deciding: 5,
+ // Amount that must be placed on deposit before a decision can be made.
+ decision_deposit: 20 * 1000 * dollar(KAR),
+ // Amount of time this must be submitted for before a decision can be made.
+ prepare_period: 1 * DAYS,
+ // Amount of time that a decision may take to be approved prior to cancellation.
+ decision_period: 14 * DAYS,
+ // Amount of time that the approval criteria must hold before it can be approved.
+ confirm_period: 1 * DAYS,
+ // Minimum amount of time that an approved proposal must be in the dispatch queue.
+ min_enactment_period: 1 * DAYS,
+ // Minimum aye votes as percentage of overall conviction-weighted votes needed for
+ // approval as a function of time into decision period.
+ min_approval: Curve::make_reciprocal(4, 14, percent(80), percent(50), percent(100)),
+ // Minimum pre-conviction aye-votes ("support") as percentage of overall population that
+ // is needed for approval as a function of time into decision period.
+ min_support: Curve::make_linear(14, 14, permill(5), percent(25)),
+ },
+ ),
+ (
+ 1,
+ pallet_referenda::TrackInfo {
+ name: "whitelisted_caller",
+ max_deciding: 100,
+ decision_deposit: 2 * 1000 * dollar(KAR),
+ prepare_period: 10 * MINUTES,
+ decision_period: 14 * DAYS,
+ confirm_period: 10 * MINUTES,
+ min_enactment_period: 30 * MINUTES,
+ min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)),
+ min_support: Curve::make_reciprocal(1, 14 * 24, percent(1), percent(0), percent(2)),
+ },
+ ),
+ (
+ 2,
+ pallet_referenda::TrackInfo {
+ name: "general_admin",
+ max_deciding: 10,
+ decision_deposit: 1000 * dollar(KAR),
+ prepare_period: 1 * HOURS,
+ decision_period: 14 * DAYS,
+ confirm_period: 1 * DAYS,
+ min_enactment_period: 1 * DAYS,
+ min_approval: Curve::make_reciprocal(4, 14, percent(80), percent(50), percent(100)),
+ min_support: Curve::make_reciprocal(7, 14, percent(10), percent(0), percent(50)),
+ },
+ ),
+ (
+ 3,
+ pallet_referenda::TrackInfo {
+ name: "referendum_canceller",
+ max_deciding: 20,
+ decision_deposit: 2 * 1000 * dollar(KAR),
+ prepare_period: 1 * HOURS,
+ decision_period: 14 * DAYS,
+ confirm_period: 3 * HOURS,
+ min_enactment_period: 10 * MINUTES,
+ min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)),
+ min_support: Curve::make_reciprocal(1, 14, percent(1), percent(0), percent(10)),
+ },
+ ),
+ (
+ 4,
+ pallet_referenda::TrackInfo {
+ name: "referendum_killer",
+ max_deciding: 100,
+ decision_deposit: 4 * 1000 * dollar(KAR),
+ prepare_period: 1 * HOURS,
+ decision_period: 14 * DAYS,
+ confirm_period: 3 * HOURS,
+ min_enactment_period: 10 * MINUTES,
+ min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)),
+ min_support: Curve::make_reciprocal(1, 14, percent(1), percent(0), percent(10)),
+ },
+ ),
+];
+}
+
+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 => {
+ if let Some((track_id, _)) = Self::tracks().into_iter().find(|(_, track)| track.name == "root") {
+ Ok(*track_id)
+ } else {
+ Err(())
+ }
+ }
+ _ => Err(()),
+ }
+ } else if let Ok(custom_origin) = custom_origins::Origin::try_from(id.clone()) {
+ if let Some((track_id, _)) = Self::tracks().into_iter().find(|(_, track)| {
+ if let Ok(track_custom_origin) = custom_origins::Origin::from_str(track.name) {
+ track_custom_origin == custom_origin
+ } else {
+ false
+ }
+ }) {
+ Ok(*track_id)
+ } else {
+ Err(())
+ }
+ } else {
+ Err(())
+ }
+ }
+}
+
+#[test]
+/// To ensure voters are always locked into their vote
+fn vote_locking_always_longer_than_enactment_period() {
+ for (_, track) in (&TRACKS_DATA).iter() {
+ assert!(
+ ::VoteLockingPeriod::get() >= track.min_enactment_period,
+ "Track {} has enactment period {} < vote locking period {}",
+ track.name,
+ track.min_enactment_period,
+ ::VoteLockingPeriod::get(),
+ );
+ }
+}
+
+#[test]
+fn all_tracks_have_origins() {
+ for (_, track) in (&TRACKS_DATA).iter() {
+ // check name.into() is successful either converts into "root" or custom origin
+ let track_is_root = track.name == "root";
+ let track_has_custom_origin = custom_origins::Origin::from_str(track.name).is_ok();
+ assert!(track_is_root || track_has_custom_origin);
+ }
+}
diff --git a/runtime/karura/src/lib.rs b/runtime/karura/src/lib.rs
index 95c612e700..769001c133 100644
--- a/runtime/karura/src/lib.rs
+++ b/runtime/karura/src/lib.rs
@@ -121,9 +121,11 @@ pub use nutsfinance_stable_asset;
mod authority;
mod benchmarking;
pub mod constants;
+pub mod governance;
/// Weights for pallets used in the runtime.
mod weights;
pub mod xcm_config;
+use governance::councils::*;
/// This runtime version.
#[sp_version::runtime_version]
@@ -401,129 +403,6 @@ impl pallet_sudo::Config for Runtime {
type WeightInfo = ();
}
-parameter_types! {
- pub const GeneralCouncilMotionDuration: BlockNumber = 3 * DAYS;
- pub const CouncilDefaultMaxProposals: u32 = 20;
- pub const CouncilDefaultMaxMembers: u32 = 30;
- pub MaxProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block;
-}
-
-impl pallet_collective::Config for Runtime {
- type RuntimeOrigin = RuntimeOrigin;
- type Proposal = RuntimeCall;
- type RuntimeEvent = RuntimeEvent;
- type MotionDuration = GeneralCouncilMotionDuration;
- type MaxProposals = CouncilDefaultMaxProposals;
- type MaxMembers = CouncilDefaultMaxMembers;
- type DefaultVote = pallet_collective::PrimeDefaultVote;
- type SetMembersOrigin = EnsureRoot;
- type WeightInfo = ();
- type MaxProposalWeight = MaxProposalWeight;
-}
-
-impl pallet_membership::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type AddOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type RemoveOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type SwapOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type ResetOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type PrimeOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type MembershipInitialized = GeneralCouncil;
- type MembershipChanged = GeneralCouncil;
- type MaxMembers = CouncilDefaultMaxMembers;
- type WeightInfo = ();
-}
-
-parameter_types! {
- pub const FinancialCouncilMotionDuration: BlockNumber = 3 * DAYS;
-}
-
-impl pallet_collective::Config for Runtime {
- type RuntimeOrigin = RuntimeOrigin;
- type Proposal = RuntimeCall;
- type RuntimeEvent = RuntimeEvent;
- type MotionDuration = FinancialCouncilMotionDuration;
- type MaxProposals = CouncilDefaultMaxProposals;
- type MaxMembers = CouncilDefaultMaxMembers;
- type DefaultVote = pallet_collective::PrimeDefaultVote;
- type SetMembersOrigin = EnsureRoot;
- type WeightInfo = ();
- type MaxProposalWeight = MaxProposalWeight;
-}
-
-impl pallet_membership::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type MembershipInitialized = FinancialCouncil;
- type MembershipChanged = FinancialCouncil;
- type MaxMembers = CouncilDefaultMaxMembers;
- type WeightInfo = ();
-}
-
-parameter_types! {
- pub const HomaCouncilMotionDuration: BlockNumber = 3 * DAYS;
-}
-
-impl pallet_collective::Config for Runtime {
- type RuntimeOrigin = RuntimeOrigin;
- type Proposal = RuntimeCall;
- type RuntimeEvent = RuntimeEvent;
- type MotionDuration = HomaCouncilMotionDuration;
- type MaxProposals = CouncilDefaultMaxProposals;
- type MaxMembers = CouncilDefaultMaxMembers;
- type DefaultVote = pallet_collective::PrimeDefaultVote;
- type SetMembersOrigin = EnsureRoot;
- type WeightInfo = ();
- type MaxProposalWeight = MaxProposalWeight;
-}
-
-impl pallet_membership::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type MembershipInitialized = HomaCouncil;
- type MembershipChanged = HomaCouncil;
- type MaxMembers = CouncilDefaultMaxMembers;
- type WeightInfo = ();
-}
-
-parameter_types! {
- pub const TechnicalCommitteeMotionDuration: BlockNumber = 3 * DAYS;
-}
-
-impl pallet_collective::Config for Runtime {
- type RuntimeOrigin = RuntimeOrigin;
- type Proposal = RuntimeCall;
- type RuntimeEvent = RuntimeEvent;
- type MotionDuration = TechnicalCommitteeMotionDuration;
- type MaxProposals = CouncilDefaultMaxProposals;
- type MaxMembers = CouncilDefaultMaxMembers;
- type DefaultVote = pallet_collective::PrimeDefaultVote;
- type SetMembersOrigin = EnsureRoot;
- type WeightInfo = ();
- type MaxProposalWeight = MaxProposalWeight;
-}
-
-impl pallet_membership::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type MembershipInitialized = TechnicalCommittee;
- type MembershipChanged = TechnicalCommittee;
- type MaxMembers = CouncilDefaultMaxMembers;
- type WeightInfo = ();
-}
-
impl pallet_membership::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
@@ -653,60 +532,6 @@ impl pallet_tips::Config for Runtime {
type WeightInfo = ();
}
-parameter_types! {
- pub const LaunchPeriod: BlockNumber = 5 * DAYS;
- pub const VotingPeriod: BlockNumber = 5 * DAYS;
- pub const FastTrackVotingPeriod: BlockNumber = 3 * HOURS;
- pub MinimumDeposit: Balance = 100 * dollar(KAR);
- pub const EnactmentPeriod: BlockNumber = 2 * DAYS;
- pub const VoteLockingPeriod: BlockNumber = 7 * DAYS;
- pub const CooloffPeriod: BlockNumber = 7 * DAYS;
-}
-
-impl pallet_democracy::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type Currency = Balances;
- type EnactmentPeriod = EnactmentPeriod;
- type LaunchPeriod = LaunchPeriod;
- type VotingPeriod = VotingPeriod;
- type VoteLockingPeriod = VoteLockingPeriod;
- type MinimumDeposit = MinimumDeposit;
- /// A straight majority of the council can decide what their next motion is.
- type ExternalOrigin = EnsureRootOrHalfGeneralCouncil;
- /// A majority can have the next scheduled referendum be a straight majority-carries vote.
- type ExternalMajorityOrigin = EnsureRootOrHalfGeneralCouncil;
- /// A unanimous council can have the next scheduled referendum be a straight default-carries
- /// (NTB) vote.
- type ExternalDefaultOrigin = EnsureRootOrAllGeneralCouncil;
- /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote
- /// be tabled immediately and with a shorter voting/enactment period.
- type FastTrackOrigin = EnsureRootOrTwoThirdsTechnicalCommittee;
- type InstantOrigin = EnsureRootOrAllTechnicalCommittee;
- type InstantAllowed = ConstBool;
- type FastTrackVotingPeriod = FastTrackVotingPeriod;
- // To cancel a proposal which has been passed, 2/3 of the council must agree to it.
- type CancellationOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type BlacklistOrigin = EnsureRoot;
- // To cancel a proposal before it has been passed, the technical committee must be unanimous or
- // Root must agree.
- type CancelProposalOrigin = EnsureRootOrAllTechnicalCommittee;
- // Any single technical committee member may veto a coming council proposal, however they can
- // only do it once and it lasts only for the cooloff period.
- type VetoOrigin = pallet_collective::EnsureMember;
- type CooloffPeriod = CooloffPeriod;
- type Slash = Treasury;
- type Scheduler = Scheduler;
- type PalletsOrigin = OriginCaller;
- type MaxVotes = ConstU32<100>;
- //TODO: might need to weight for Karura
- type WeightInfo = pallet_democracy::weights::SubstrateWeight;
- type MaxProposals = ConstU32<100>;
- type Preimages = Preimage;
- type MaxDeposits = ConstU32<100>;
- type MaxBlacklisted = ConstU32<100>;
- type SubmitOrigin = EnsureSigned;
-}
-
impl orml_auction::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
@@ -1779,6 +1604,10 @@ construct_runtime!(
TechnicalCommittee: pallet_collective:: = 67,
TechnicalCommitteeMembership: pallet_membership:: = 68,
Democracy: pallet_democracy = 69,
+ ConvictionVoting: pallet_conviction_voting = 160,
+ Referenda: pallet_referenda = 161,
+ Origins: governance::custom_origins::{Origin} = 162,
+ Whitelist: pallet_whitelist = 163,
// Oracle
//
diff --git a/runtime/mandala/Cargo.toml b/runtime/mandala/Cargo.toml
index f938a4aa68..19e66d62b2 100644
--- a/runtime/mandala/Cargo.toml
+++ b/runtime/mandala/Cargo.toml
@@ -13,6 +13,9 @@ scale-info = { version = "2.9.0", default-features = false, features = ["derive"
serde_json = { version = "1.0.85", default-features = false, features = ["alloc"] }
hex = { version = "0.4", default-features = false }
hex-literal = { version = "0.4.1" }
+strum = { version = "0.24", default-features = false, features = [ "derive" ] }
+strum_macros = "0.24"
+lazy_static = "1.4.0"
# substrate
frame-executive = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
@@ -57,6 +60,9 @@ sp-staking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "rel
sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
+pallet-conviction-voting = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
+pallet-referenda = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
+pallet-whitelist = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
# cumulus
cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false }
@@ -161,6 +167,7 @@ std = [
"hex/std",
"scale-info/std",
"serde_json/std",
+ "strum/std",
"frame-benchmarking/std",
"frame-executive/std",
@@ -208,6 +215,9 @@ std = [
"sp-transaction-pool/std",
"sp-version/std",
"substrate-wasm-builder",
+ "pallet-conviction-voting/std",
+ "pallet-referenda/std",
+ "pallet-whitelist/std",
"cumulus-pallet-aura-ext/std",
"cumulus-pallet-dmp-queue/std",
@@ -306,6 +316,9 @@ runtime-benchmarks = [
"pallet-utility/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"sp-staking/runtime-benchmarks",
+ "pallet-conviction-voting/runtime-benchmarks",
+ "pallet-referenda/runtime-benchmarks",
+ "pallet-whitelist/runtime-benchmarks",
"cumulus-pallet-parachain-system/runtime-benchmarks",
"cumulus-pallet-xcmp-queue/runtime-benchmarks",
@@ -378,6 +391,9 @@ try-runtime = [
"pallet-transaction-payment/try-runtime",
"pallet-treasury/try-runtime",
"pallet-utility/try-runtime",
+ "pallet-conviction-voting/try-runtime",
+ "pallet-referenda/try-runtime",
+ "pallet-whitelist/try-runtime",
"cumulus-pallet-aura-ext/try-runtime",
"cumulus-pallet-dmp-queue/try-runtime",
diff --git a/runtime/mandala/src/governance/councils.rs b/runtime/mandala/src/governance/councils.rs
new file mode 100644
index 0000000000..083513cced
--- /dev/null
+++ b/runtime/mandala/src/governance/councils.rs
@@ -0,0 +1,144 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Councils for Gov1 and Gov2
+
+use super::*;
+
+parameter_types! {
+ pub const GeneralCouncilMotionDuration: BlockNumber = 7 * DAYS;
+ pub const CouncilDefaultMaxProposals: u32 = 100;
+ pub const CouncilDefaultMaxMembers: u32 = 100;
+ pub MaxProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block;
+}
+
+impl pallet_collective::Config for Runtime {
+ type RuntimeOrigin = RuntimeOrigin;
+ type Proposal = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type MotionDuration = GeneralCouncilMotionDuration;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type DefaultVote = pallet_collective::PrimeDefaultVote;
+ type SetMembersOrigin = EnsureRoot;
+ type WeightInfo = ();
+ type MaxProposalWeight = MaxProposalWeight;
+}
+
+impl pallet_membership::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type AddOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type RemoveOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type SwapOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type ResetOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type PrimeOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
+ type MembershipInitialized = GeneralCouncil;
+ type MembershipChanged = GeneralCouncil;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type WeightInfo = ();
+}
+
+parameter_types! {
+ pub const FinancialCouncilMotionDuration: BlockNumber = 7 * DAYS;
+}
+
+impl pallet_collective::Config for Runtime {
+ type RuntimeOrigin = RuntimeOrigin;
+ type Proposal = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type MotionDuration = FinancialCouncilMotionDuration;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type DefaultVote = pallet_collective::PrimeDefaultVote;
+ type SetMembersOrigin = EnsureRoot;
+ type WeightInfo = ();
+ type MaxProposalWeight = MaxProposalWeight;
+}
+
+impl pallet_membership::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type MembershipInitialized = FinancialCouncil;
+ type MembershipChanged = FinancialCouncil;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type WeightInfo = ();
+}
+
+parameter_types! {
+ pub const HomaCouncilMotionDuration: BlockNumber = 7 * DAYS;
+}
+
+impl pallet_collective::Config for Runtime {
+ type RuntimeOrigin = RuntimeOrigin;
+ type Proposal = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type MotionDuration = HomaCouncilMotionDuration;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type DefaultVote = pallet_collective::PrimeDefaultVote;
+ type SetMembersOrigin = EnsureRoot;
+ type WeightInfo = ();
+ type MaxProposalWeight = MaxProposalWeight;
+}
+
+impl pallet_membership::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type MembershipInitialized = HomaCouncil;
+ type MembershipChanged = HomaCouncil;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type WeightInfo = ();
+}
+
+parameter_types! {
+ pub const TechnicalCommitteeMotionDuration: BlockNumber = 7 * DAYS;
+}
+
+impl pallet_collective::Config for Runtime {
+ type RuntimeOrigin = RuntimeOrigin;
+ type Proposal = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type MotionDuration = TechnicalCommitteeMotionDuration;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type DefaultVote = pallet_collective::PrimeDefaultVote;
+ type SetMembersOrigin = EnsureRoot;
+ type WeightInfo = ();
+ type MaxProposalWeight = MaxProposalWeight;
+}
+
+impl pallet_membership::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type MembershipInitialized = TechnicalCommittee;
+ type MembershipChanged = TechnicalCommittee;
+ type MaxMembers = CouncilDefaultMaxMembers;
+ type WeightInfo = ();
+}
diff --git a/runtime/mandala/src/governance/democracy.rs b/runtime/mandala/src/governance/democracy.rs
new file mode 100644
index 0000000000..6373a0300e
--- /dev/null
+++ b/runtime/mandala/src/governance/democracy.rs
@@ -0,0 +1,74 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Democracy config for Gov1
+
+use crate::*;
+
+parameter_types! {
+ pub const LaunchPeriod: BlockNumber = 2 * HOURS;
+ pub const VotingPeriod: BlockNumber = HOURS;
+ pub const FastTrackVotingPeriod: BlockNumber = HOURS;
+ pub MinimumDeposit: Balance = 100 * cent(ACA);
+ pub const EnactmentPeriod: BlockNumber = MINUTES;
+ pub const CooloffPeriod: BlockNumber = MINUTES;
+}
+
+impl pallet_democracy::Config for Runtime {
+ type RuntimeEvent = RuntimeEvent;
+ type Currency = Balances;
+ type EnactmentPeriod = EnactmentPeriod;
+ type LaunchPeriod = LaunchPeriod;
+ type VotingPeriod = VotingPeriod;
+ type VoteLockingPeriod = EnactmentPeriod; // Same as EnactmentPeriod
+ type MinimumDeposit = MinimumDeposit;
+ /// A straight majority of the council can decide what their next motion is.
+ type ExternalOrigin = EnsureRootOrHalfGeneralCouncil;
+ /// A majority can have the next scheduled referendum be a straight majority-carries vote.
+ type ExternalMajorityOrigin = EnsureRootOrHalfGeneralCouncil;
+ /// A unanimous council can have the next scheduled referendum be a straight default-carries
+ /// (NTB) vote.
+ type ExternalDefaultOrigin = EnsureRootOrAllGeneralCouncil;
+ /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote
+ /// be tabled immediately and with a shorter voting/enactment period.
+ type FastTrackOrigin = EnsureRootOrTwoThirdsTechnicalCommittee;
+ type InstantOrigin = EnsureRootOrAllTechnicalCommittee;
+ type InstantAllowed = ConstBool;
+ type FastTrackVotingPeriod = FastTrackVotingPeriod;
+ // To cancel a proposal which has been passed, 2/3 of the council must agree to it.
+ type CancellationOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
+ type BlacklistOrigin = EnsureRoot;
+ // To cancel a proposal before it has been passed, the technical committee must be unanimous or
+ // Root must agree.
+ type CancelProposalOrigin = EnsureRootOrAllTechnicalCommittee;
+ // Any single technical committee member may veto a coming council proposal, however they can
+ // only do it once and it lasts only for the cooloff period.
+ type VetoOrigin = pallet_collective::EnsureMember;
+ type CooloffPeriod = CooloffPeriod;
+ type Slash = Treasury;
+ type Scheduler = Scheduler;
+ type PalletsOrigin = OriginCaller;
+ type MaxVotes = ConstU32<100>;
+ //TODO: might need to weight for Mandala
+ type WeightInfo = pallet_democracy::weights::SubstrateWeight;
+ type MaxProposals = CouncilDefaultMaxProposals;
+ type Preimages = Preimage;
+ type MaxDeposits = ConstU32<100>;
+ type MaxBlacklisted = ConstU32<100>;
+ type SubmitOrigin = EnsureSigned;
+}
diff --git a/runtime/mandala/src/governance/mod.rs b/runtime/mandala/src/governance/mod.rs
new file mode 100644
index 0000000000..9d8000ef01
--- /dev/null
+++ b/runtime/mandala/src/governance/mod.rs
@@ -0,0 +1,30 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Governance configurations
+
+pub mod councils;
+mod democracy;
+pub mod referenda;
+
+use super::*;
+
+mod origins;
+pub use origins::{custom_origins, GeneralAdmin, ReferendumCanceller, ReferendumKiller, WhitelistedCaller};
+mod tracks;
+pub use tracks::TracksInfo;
diff --git a/runtime/mandala/src/governance/origins.rs b/runtime/mandala/src/governance/origins.rs
new file mode 100644
index 0000000000..7f7d7237a0
--- /dev/null
+++ b/runtime/mandala/src/governance/origins.rs
@@ -0,0 +1,79 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Custom origins for governance interventions.
+
+pub use custom_origins::*;
+
+#[frame_support::pallet]
+pub mod custom_origins {
+ use frame_support::pallet_prelude::*;
+ use strum_macros::EnumString;
+
+ #[pallet::config]
+ pub trait Config: frame_system::Config {}
+
+ #[pallet::pallet]
+ pub struct Pallet(_);
+
+ #[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug, EnumString)]
+ #[strum(serialize_all = "snake_case")]
+ #[pallet::origin]
+ pub enum Origin {
+ /// Origin able to dispatch a whitelisted call.
+ WhitelistedCaller,
+ /// General admin
+ GeneralAdmin,
+ /// Origin able to cancel referenda.
+ ReferendumCanceller,
+ /// Origin able to kill referenda.
+ ReferendumKiller,
+ }
+
+ 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!(ReferendumCanceller, ReferendumKiller, WhitelistedCaller, GeneralAdmin);
+}
diff --git a/runtime/mandala/src/governance/referenda.rs b/runtime/mandala/src/governance/referenda.rs
new file mode 100644
index 0000000000..cd46634046
--- /dev/null
+++ b/runtime/mandala/src/governance/referenda.rs
@@ -0,0 +1,94 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! # Gov2 config
+//! Includes runtime configs for these substrate pallets:
+//! 1. pallet-conviction-voting
+//! 2. pallet-whitelist
+//! 3. pallet-referenda
+
+use super::*;
+use frame_support::traits::{EitherOf, MapSuccess};
+use frame_system::EnsureRootWithSuccess;
+use sp_runtime::traits::Replace;
+
+parameter_types! {
+ pub const VoteLockingPeriod: BlockNumber = 1 * DAYS;
+}
+
+impl pallet_conviction_voting::Config for Runtime {
+ type WeightInfo = ();
+ type RuntimeEvent = RuntimeEvent;
+ type Currency = Balances;
+ type Polls = Referenda;
+ type MaxTurnout = frame_support::traits::TotalIssuanceOf;
+ // Maximum number of concurrent votes an account may have
+ type MaxVotes = ConstU32<20>;
+ // Minimum period of vote locking
+ type VoteLockingPeriod = VoteLockingPeriod;
+}
+
+// Origin for general admin or root
+pub type GeneralAdminOrRoot = EitherOf, origins::GeneralAdmin>;
+
+impl custom_origins::Config for Runtime {}
+
+// The purpose of this pallet is to queue calls to be dispatched as by root later => the Dispatch
+// origin corresponds to the Gov2 Whitelist track.
+impl pallet_whitelist::Config for Runtime {
+ type WeightInfo = ();
+ type RuntimeEvent = RuntimeEvent;
+ type RuntimeCall = RuntimeCall;
+ type WhitelistOrigin = EitherOf<
+ EnsureRootWithSuccess>,
+ MapSuccess<
+ pallet_collective::EnsureProportionAtLeast,
+ Replace>,
+ >,
+ >;
+ type DispatchWhitelistedOrigin = EitherOf, WhitelistedCaller>;
+ type Preimages = Preimage;
+}
+
+pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber);
+
+parameter_types! {
+ pub const AlarmInterval: BlockNumber = 1;
+ pub SubmissionDeposit: Balance = 10 * dollar(ACA);
+ pub const UndecidingTimeout: BlockNumber = 14 * DAYS;
+}
+
+impl pallet_referenda::Config for Runtime {
+ type WeightInfo = ();
+ type RuntimeCall = RuntimeCall;
+ type RuntimeEvent = RuntimeEvent;
+ type Scheduler = Scheduler;
+ type Currency = Balances;
+ type SubmitOrigin = frame_system::EnsureSigned;
+ type CancelOrigin = EitherOf, ReferendumCanceller>;
+ type KillOrigin = EitherOf, 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;
+ type Preimages = Preimage;
+}
diff --git a/runtime/mandala/src/governance/tracks.rs b/runtime/mandala/src/governance/tracks.rs
new file mode 100644
index 0000000000..ef053401e9
--- /dev/null
+++ b/runtime/mandala/src/governance/tracks.rs
@@ -0,0 +1,178 @@
+// This file is part of Acala.
+
+// Copyright (C) 2020-2023 Acala Foundation.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program 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.
+
+// This program 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 this program. If not, see .
+
+//! Track configurations for governance.
+
+use super::*;
+use pallet_referenda::Curve;
+use sp_std::str::FromStr;
+
+const fn percent(x: i32) -> sp_runtime::FixedI64 {
+ sp_runtime::FixedI64::from_rational(x as u128, 100)
+}
+const fn permill(x: i32) -> sp_runtime::FixedI64 {
+ sp_runtime::FixedI64::from_rational(x as u128, 1000)
+}
+
+lazy_static::lazy_static! {
+static ref TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 5] = [
+ (
+ 0,
+ pallet_referenda::TrackInfo {
+ // Name of this track.
+ name: "root",
+ // A limit for the number of referenda on this track that can be being decided at once.
+ // For Root origin this should generally be just one.
+ max_deciding: 5,
+ // Amount that must be placed on deposit before a decision can be made.
+ decision_deposit: 20 * 1000 * dollar(ACA),
+ // Amount of time this must be submitted for before a decision can be made.
+ prepare_period: 1 * DAYS,
+ // Amount of time that a decision may take to be approved prior to cancellation.
+ decision_period: 14 * DAYS,
+ // Amount of time that the approval criteria must hold before it can be approved.
+ confirm_period: 1 * DAYS,
+ // Minimum amount of time that an approved proposal must be in the dispatch queue.
+ min_enactment_period: 1 * DAYS,
+ // Minimum aye votes as percentage of overall conviction-weighted votes needed for
+ // approval as a function of time into decision period.
+ min_approval: Curve::make_reciprocal(4, 14, percent(80), percent(50), percent(100)),
+ // Minimum pre-conviction aye-votes ("support") as percentage of overall population that
+ // is needed for approval as a function of time into decision period.
+ min_support: Curve::make_linear(14, 14, permill(5), percent(25)),
+ },
+ ),
+ (
+ 1,
+ pallet_referenda::TrackInfo {
+ name: "whitelisted_caller",
+ max_deciding: 100,
+ decision_deposit: 2 * 1000 * dollar(ACA),
+ prepare_period: 10 * MINUTES,
+ decision_period: 14 * DAYS,
+ confirm_period: 10 * MINUTES,
+ min_enactment_period: 30 * MINUTES,
+ min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)),
+ min_support: Curve::make_reciprocal(1, 14 * 24, percent(1), percent(0), percent(2)),
+ },
+ ),
+ (
+ 2,
+ pallet_referenda::TrackInfo {
+ name: "general_admin",
+ max_deciding: 10,
+ decision_deposit: 1000 * dollar(ACA),
+ prepare_period: 1 * HOURS,
+ decision_period: 14 * DAYS,
+ confirm_period: 1 * DAYS,
+ min_enactment_period: 1 * DAYS,
+ min_approval: Curve::make_reciprocal(4, 14, percent(80), percent(50), percent(100)),
+ min_support: Curve::make_reciprocal(7, 14, percent(10), percent(0), percent(50)),
+ },
+ ),
+ (
+ 3,
+ pallet_referenda::TrackInfo {
+ name: "referendum_canceller",
+ max_deciding: 20,
+ decision_deposit: 2 * 1000 * dollar(ACA),
+ prepare_period: 1 * HOURS,
+ decision_period: 14 * DAYS,
+ confirm_period: 3 * HOURS,
+ min_enactment_period: 10 * MINUTES,
+ min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)),
+ min_support: Curve::make_reciprocal(1, 14, percent(1), percent(0), percent(10)),
+ },
+ ),
+ (
+ 4,
+ pallet_referenda::TrackInfo {
+ name: "referendum_killer",
+ max_deciding: 100,
+ decision_deposit: 4 * 1000 * dollar(ACA),
+ prepare_period: 1 * HOURS,
+ decision_period: 14 * DAYS,
+ confirm_period: 3 * HOURS,
+ min_enactment_period: 10 * MINUTES,
+ min_approval: Curve::make_reciprocal(1, 14, percent(96), percent(50), percent(100)),
+ min_support: Curve::make_reciprocal(1, 14, percent(1), percent(0), percent(10)),
+ },
+ ),
+];
+}
+
+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 => {
+ if let Some((track_id, _)) = Self::tracks().into_iter().find(|(_, track)| track.name == "root") {
+ Ok(*track_id)
+ } else {
+ Err(())
+ }
+ }
+ _ => Err(()),
+ }
+ } else if let Ok(custom_origin) = custom_origins::Origin::try_from(id.clone()) {
+ if let Some((track_id, _)) = Self::tracks().into_iter().find(|(_, track)| {
+ if let Ok(track_custom_origin) = custom_origins::Origin::from_str(track.name) {
+ track_custom_origin == custom_origin
+ } else {
+ false
+ }
+ }) {
+ Ok(*track_id)
+ } else {
+ Err(())
+ }
+ } else {
+ Err(())
+ }
+ }
+}
+
+#[test]
+/// To ensure voters are always locked into their vote
+fn vote_locking_always_longer_than_enactment_period() {
+ for (_, track) in (&TRACKS_DATA).iter() {
+ assert!(
+ ::VoteLockingPeriod::get() >= track.min_enactment_period,
+ "Track {} has enactment period {} < vote locking period {}",
+ track.name,
+ track.min_enactment_period,
+ ::VoteLockingPeriod::get(),
+ );
+ }
+}
+
+#[test]
+fn all_tracks_have_origins() {
+ for (_, track) in (&TRACKS_DATA).iter() {
+ // check name.into() is successful either converts into "root" or custom origin
+ let track_is_root = track.name == "root";
+ let track_has_custom_origin = custom_origins::Origin::from_str(track.name).is_ok();
+ assert!(track_is_root || track_has_custom_origin);
+ }
+}
diff --git a/runtime/mandala/src/lib.rs b/runtime/mandala/src/lib.rs
index a4d53254fb..d45ae2a340 100644
--- a/runtime/mandala/src/lib.rs
+++ b/runtime/mandala/src/lib.rs
@@ -125,9 +125,11 @@ pub use nutsfinance_stable_asset;
mod authority;
mod benchmarking;
pub mod constants;
+pub mod governance;
/// Weights for pallets used in the runtime.
mod weights;
pub mod xcm_config;
+use governance::councils::*;
/// This runtime version.
#[sp_version::runtime_version]
@@ -374,129 +376,6 @@ impl pallet_sudo::Config for Runtime {
type WeightInfo = ();
}
-parameter_types! {
- pub const GeneralCouncilMotionDuration: BlockNumber = 7 * DAYS;
- pub const CouncilDefaultMaxProposals: u32 = 100;
- pub const CouncilDefaultMaxMembers: u32 = 100;
- pub MaxProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block;
-}
-
-impl pallet_collective::Config for Runtime {
- type RuntimeOrigin = RuntimeOrigin;
- type Proposal = RuntimeCall;
- type RuntimeEvent = RuntimeEvent;
- type MotionDuration = GeneralCouncilMotionDuration;
- type MaxProposals = CouncilDefaultMaxProposals;
- type MaxMembers = CouncilDefaultMaxMembers;
- type DefaultVote = pallet_collective::PrimeDefaultVote;
- type SetMembersOrigin = EnsureRoot;
- type WeightInfo = ();
- type MaxProposalWeight = MaxProposalWeight;
-}
-
-impl pallet_membership::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type AddOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type RemoveOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type SwapOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type ResetOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type PrimeOrigin = EnsureRootOrThreeFourthsGeneralCouncil;
- type MembershipInitialized = GeneralCouncil;
- type MembershipChanged = GeneralCouncil;
- type MaxMembers = CouncilDefaultMaxMembers;
- type WeightInfo = ();
-}
-
-parameter_types! {
- pub const FinancialCouncilMotionDuration: BlockNumber = 7 * DAYS;
-}
-
-impl pallet_collective::Config for Runtime {
- type RuntimeOrigin = RuntimeOrigin;
- type Proposal = RuntimeCall;
- type RuntimeEvent = RuntimeEvent;
- type MotionDuration = FinancialCouncilMotionDuration;
- type MaxProposals = CouncilDefaultMaxProposals;
- type MaxMembers = CouncilDefaultMaxMembers;
- type DefaultVote = pallet_collective::PrimeDefaultVote;
- type SetMembersOrigin = EnsureRoot;
- type WeightInfo = ();
- type MaxProposalWeight = MaxProposalWeight;
-}
-
-impl pallet_membership::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type MembershipInitialized = FinancialCouncil;
- type MembershipChanged = FinancialCouncil;
- type MaxMembers = CouncilDefaultMaxMembers;
- type WeightInfo = ();
-}
-
-parameter_types! {
- pub const HomaCouncilMotionDuration: BlockNumber = 7 * DAYS;
-}
-
-impl pallet_collective::Config for Runtime {
- type RuntimeOrigin = RuntimeOrigin;
- type Proposal = RuntimeCall;
- type RuntimeEvent = RuntimeEvent;
- type MotionDuration = HomaCouncilMotionDuration;
- type MaxProposals = CouncilDefaultMaxProposals;
- type MaxMembers = CouncilDefaultMaxMembers;
- type DefaultVote = pallet_collective::PrimeDefaultVote;
- type SetMembersOrigin = EnsureRoot;
- type WeightInfo = ();
- type MaxProposalWeight = MaxProposalWeight;
-}
-
-impl pallet_membership::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type MembershipInitialized = HomaCouncil;
- type MembershipChanged = HomaCouncil;
- type MaxMembers = CouncilDefaultMaxMembers;
- type WeightInfo = ();
-}
-
-parameter_types! {
- pub const TechnicalCommitteeMotionDuration: BlockNumber = 7 * DAYS;
-}
-
-impl pallet_collective::Config for Runtime {
- type RuntimeOrigin = RuntimeOrigin;
- type Proposal = RuntimeCall;
- type RuntimeEvent = RuntimeEvent;
- type MotionDuration = TechnicalCommitteeMotionDuration;
- type MaxProposals = CouncilDefaultMaxProposals;
- type MaxMembers = CouncilDefaultMaxMembers;
- type DefaultVote = pallet_collective::PrimeDefaultVote;
- type SetMembersOrigin = EnsureRoot;
- type WeightInfo = ();
- type MaxProposalWeight = MaxProposalWeight;
-}
-
-impl pallet_membership::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type RemoveOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type SwapOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type ResetOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type PrimeOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type MembershipInitialized = TechnicalCommittee;
- type MembershipChanged = TechnicalCommittee;
- type MaxMembers = CouncilDefaultMaxMembers;
- type WeightInfo = ();
-}
-
impl pallet_membership::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type AddOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
@@ -639,59 +518,6 @@ impl pallet_recovery::Config for Runtime {
type WeightInfo = ();
}
-parameter_types! {
- pub const LaunchPeriod: BlockNumber = 2 * HOURS;
- pub const VotingPeriod: BlockNumber = HOURS;
- pub const FastTrackVotingPeriod: BlockNumber = HOURS;
- pub MinimumDeposit: Balance = 100 * cent(ACA);
- pub const EnactmentPeriod: BlockNumber = MINUTES;
- pub const CooloffPeriod: BlockNumber = MINUTES;
-}
-
-impl pallet_democracy::Config for Runtime {
- type RuntimeEvent = RuntimeEvent;
- type Currency = Balances;
- type EnactmentPeriod = EnactmentPeriod;
- type LaunchPeriod = LaunchPeriod;
- type VotingPeriod = VotingPeriod;
- type VoteLockingPeriod = EnactmentPeriod; // Same as EnactmentPeriod
- type MinimumDeposit = MinimumDeposit;
- /// A straight majority of the council can decide what their next motion is.
- type ExternalOrigin = EnsureRootOrHalfGeneralCouncil;
- /// A majority can have the next scheduled referendum be a straight majority-carries vote.
- type ExternalMajorityOrigin = EnsureRootOrHalfGeneralCouncil;
- /// A unanimous council can have the next scheduled referendum be a straight default-carries
- /// (NTB) vote.
- type ExternalDefaultOrigin = EnsureRootOrAllGeneralCouncil;
- /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote
- /// be tabled immediately and with a shorter voting/enactment period.
- type FastTrackOrigin = EnsureRootOrTwoThirdsTechnicalCommittee;
- type InstantOrigin = EnsureRootOrAllTechnicalCommittee;
- type InstantAllowed = ConstBool;
- type FastTrackVotingPeriod = FastTrackVotingPeriod;
- // To cancel a proposal which has been passed, 2/3 of the council must agree to it.
- type CancellationOrigin = EnsureRootOrTwoThirdsGeneralCouncil;
- type BlacklistOrigin = EnsureRoot;
- // To cancel a proposal before it has been passed, the technical committee must be unanimous or
- // Root must agree.
- type CancelProposalOrigin = EnsureRootOrAllTechnicalCommittee;
- // Any single technical committee member may veto a coming council proposal, however they can
- // only do it once and it lasts only for the cooloff period.
- type VetoOrigin = pallet_collective::EnsureMember;
- type CooloffPeriod = CooloffPeriod;
- type Slash = Treasury;
- type Scheduler = Scheduler;
- type PalletsOrigin = OriginCaller;
- type MaxVotes = ConstU32<100>;
- //TODO: might need to weight for Mandala
- type WeightInfo = pallet_democracy::weights::SubstrateWeight;
- type MaxProposals = CouncilDefaultMaxProposals;
- type Preimages = Preimage;
- type MaxDeposits = ConstU32<100>;
- type MaxBlacklisted = ConstU32<100>;
- type SubmitOrigin = EnsureSigned;
-}
-
impl orml_auction::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
@@ -2004,6 +1830,10 @@ construct_runtime!(
HomaCouncilMembership: pallet_membership:: = 55,
TechnicalCommittee: pallet_collective:: = 56,
TechnicalCommitteeMembership: pallet_membership:: = 57,
+ ConvictionVoting: pallet_conviction_voting = 150,
+ Referenda: pallet_referenda = 151,
+ Origins: governance::custom_origins::{Origin} = 152,
+ Whitelist: pallet_whitelist = 153,
Authority: orml_authority = 70,
PhragmenElection: pallet_elections_phragmen = 71,