Skip to content

Commit

Permalink
Add governance to a runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
F3Joule committed Mar 15, 2024
1 parent 01fb722 commit 0331225
Show file tree
Hide file tree
Showing 5 changed files with 311 additions and 2 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions node/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,17 @@ fn parachain_genesis(
},
transaction_payment: Default::default(),
treasury: Default::default(),
phragmen_election: Default::default(),
democracy: Default::default(),
council: subsocial_parachain_runtime::CouncilConfig {
members: vec![],
phantom: Default::default(),
},
technical_committee: subsocial_parachain_runtime::TechnicalCommitteeConfig {
members: vec![],
phantom: Default::default(),
},
technical_membership: Default::default(),
}
}

Expand Down
25 changes: 25 additions & 0 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ hex-literal = { version = "0.3.4", optional = true }
log = { version = "0.4.17", default-features = false }
scale-info = { version = "2.3.1", default-features = false, features = ["derive"] }
smallvec = "1.10.0"
static_assertions = "1.1.0"

# Local
pallet-account-follows = { path = "../pallets/account-follows", default-features = false }
Expand Down Expand Up @@ -53,7 +54,13 @@ frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-f
pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }
Expand Down Expand Up @@ -127,8 +134,14 @@ std = [
"pallet-aura/std",
"pallet-authorship/std",
"pallet-balances/std",
"pallet-collective/std",
"pallet-democracy/std",
"pallet-elections-phragmen/std",
"pallet-membership/std",
"pallet-multisig/std",
"pallet-collator-selection/std",
"pallet-preimage/std",
"pallet-scheduler/std",
"pallet-session/std",
"pallet-sudo/std",
"pallet-timestamp/std",
Expand Down Expand Up @@ -189,8 +202,14 @@ runtime-benchmarks = [
"frame-system-benchmarking/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-democracy/runtime-benchmarks",
"pallet-elections-phragmen/runtime-benchmarks",
"pallet-collective/runtime-benchmarks",
"pallet-collator-selection/runtime-benchmarks",
"pallet-membership/runtime-benchmarks",
"pallet-multisig/runtime-benchmarks",
"pallet-preimage/runtime-benchmarks",
"pallet-scheduler/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-treasury/runtime-benchmarks",
"pallet-xcm/runtime-benchmarks",
Expand Down Expand Up @@ -229,10 +248,16 @@ try-runtime = [
"pallet-aura/try-runtime",
"pallet-authorship/try-runtime",
"pallet-balances/try-runtime",
"pallet-democracy/try-runtime",
"pallet-elections-phragmen/try-runtime",
"pallet-collective/try-runtime",
"pallet-collator-selection/try-runtime",
"pallet-membership/try-runtime",
"pallet-multisig/try-runtime",
"pallet-preimage/try-runtime",
"pallet-proxy/try-runtime",
"pallet-insecure-randomness-collective-flip/try-runtime",
"pallet-scheduler/try-runtime",
"pallet-session/try-runtime",
"pallet-sudo/try-runtime",
"pallet-timestamp/try-runtime",
Expand Down
193 changes: 193 additions & 0 deletions runtime/src/governance/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
//! Governance configurations for the Subsocial runtime.

use crate::*;
use frame_support::{parameter_types, traits::EitherOfDiverse};
use frame_support::traits::LockIdentifier;
use static_assertions::const_assert;

/// Macro to set a value (e.g. when using the `parameter_types` macro) to either a production value
/// or to an environment variable or testing value (in case the `fast-runtime` feature is selected).
/// Note that the environment variable is evaluated _at compile time_.
///
/// Usage:
/// ```Rust
/// parameter_types! {
/// // Note that the env variable version parameter cannot be const.
/// pub LaunchPeriod: BlockNumber = prod_or_fast!(7 * DAYS, 1, "KSM_LAUNCH_PERIOD");
/// pub const VotingPeriod: BlockNumber = prod_or_fast!(7 * DAYS, 1 * MINUTES);
/// }
/// ```
#[macro_export]
macro_rules! prod_or_fast {
($prod:expr, $test:expr) => {
if cfg!(feature = "fast-runtime") {
$test
} else {
$prod
}
};
($prod:expr, $test:expr, $env:expr) => {
if cfg!(feature = "fast-runtime") {
core::option_env!($env).map(|s| s.parse().ok()).flatten().unwrap_or($test)
} else {
$prod
}
};
}

parameter_types! {
pub LaunchPeriod: BlockNumber = prod_or_fast!(7 * DAYS, 1, "KSM_LAUNCH_PERIOD");
pub VotingPeriod: BlockNumber = prod_or_fast!(7 * DAYS, 1 * MINUTES, "KSM_VOTING_PERIOD");
pub FastTrackVotingPeriod: BlockNumber = prod_or_fast!(3 * HOURS, 1 * MINUTES, "KSM_FAST_TRACK_VOTING_PERIOD");
pub const MinimumDeposit: Balance = 100 * UNIT;
pub EnactmentPeriod: BlockNumber = prod_or_fast!(8 * DAYS, 1, "KSM_ENACTMENT_PERIOD");
pub CooloffPeriod: BlockNumber = prod_or_fast!(7 * DAYS, 1 * MINUTES, "KSM_COOLOFF_PERIOD");
pub const InstantAllowed: bool = true;
pub const MaxVotes: u32 = 100;
pub const MaxProposals: u32 = 100;
}

impl pallet_democracy::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type EnactmentPeriod = EnactmentPeriod;
type VoteLockingPeriod = EnactmentPeriod;
type LaunchPeriod = LaunchPeriod;
type VotingPeriod = VotingPeriod;
type MinimumDeposit = MinimumDeposit;
type SubmitOrigin = frame_system::EnsureSigned<AccountId>;
/// A straight majority of the council can decide what their next motion is.
type ExternalOrigin =
pallet_collective::EnsureProportionAtLeast<AccountId, CouncilCollective, 1, 2>;
/// A majority can have the next scheduled referendum be a straight majority-carries vote.
type ExternalMajorityOrigin =
pallet_collective::EnsureProportionAtLeast<AccountId, CouncilCollective, 1, 2>;
/// A unanimous council can have the next scheduled referendum be a straight default-carries
/// (NTB) vote.
type ExternalDefaultOrigin =
pallet_collective::EnsureProportionAtLeast<AccountId, CouncilCollective, 1, 1>;
/// Two thirds of the technical committee can have an `ExternalMajority/ExternalDefault` vote
/// be tabled immediately and with a shorter voting/enactment period.
type FastTrackOrigin =
pallet_collective::EnsureProportionAtLeast<AccountId, TechnicalCollective, 2, 3>;
type InstantOrigin =
pallet_collective::EnsureProportionAtLeast<AccountId, TechnicalCollective, 1, 1>;
type InstantAllowed = InstantAllowed;
type FastTrackVotingPeriod = FastTrackVotingPeriod;
// To cancel a proposal which has been passed, 2/3 of the council must agree to it.
type CancellationOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
pallet_collective::EnsureProportionAtLeast<AccountId, CouncilCollective, 2, 3>,
>;
type BlacklistOrigin = EnsureRoot<AccountId>;
// To cancel a proposal before it has been passed, the technical committee must be unanimous or
// Root must agree.
type CancelProposalOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
pallet_collective::EnsureProportionAtLeast<AccountId, TechnicalCollective, 1, 1>,
>;
// 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<AccountId, TechnicalCollective>;
type CooloffPeriod = CooloffPeriod;
type Slash = Treasury;
type Scheduler = Scheduler;
type PalletsOrigin = OriginCaller;
type MaxVotes = MaxVotes;
type WeightInfo = pallet_democracy::weights::SubstrateWeight<Runtime>;
type MaxProposals = MaxProposals;
type Preimages = Preimage;
type MaxDeposits = ConstU32<100>;
type MaxBlacklisted = ConstU32<100>;
}

parameter_types! {
pub CouncilMotionDuration: BlockNumber = prod_or_fast!(3 * DAYS, 2 * MINUTES, "KSM_MOTION_DURATION");
pub const CouncilMaxProposals: u32 = 100;
pub const CouncilMaxMembers: u32 = 100;
}

pub type CouncilCollective = pallet_collective::Instance1;
impl pallet_collective::Config<CouncilCollective> for Runtime {
type RuntimeOrigin = RuntimeOrigin;
type Proposal = RuntimeCall;
type RuntimeEvent = RuntimeEvent;
type MotionDuration = CouncilMotionDuration;
type MaxProposals = CouncilMaxProposals;
type MaxMembers = CouncilMaxMembers;
type DefaultVote = pallet_collective::PrimeDefaultVote;
type SetMembersOrigin = EnsureRoot<AccountId>;
type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
}

parameter_types! {
pub const CandidacyBond: Balance = 100 * UNIT;
// 1 storage item created, key size is 32 bytes, value size is 16+16.
pub const VotingBondBase: Balance = deposit(1, 64);
// additional data per vote is 32 bytes (account id).
pub const VotingBondFactor: Balance = deposit(0, 32);
/// Daily council elections
pub TermDuration: BlockNumber = prod_or_fast!(24 * HOURS, 2 * MINUTES, "KSM_TERM_DURATION");
pub const DesiredMembers: u32 = 19;
pub const DesiredRunnersUp: u32 = 19;
pub const MaxVotesPerVoter: u32 = 16;
pub const MaxVoters: u32 = 10 * 1000;
pub const MaxCandidates: u32 = 1000;
pub const PhragmenElectionPalletId: LockIdentifier = *b"phrelect";
}

// Make sure that there are no more than `MaxMembers` members elected via Phragmen.
const_assert!(DesiredMembers::get() <= CouncilMaxMembers::get());

impl pallet_elections_phragmen::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type ChangeMembers = Council;
type InitializeMembers = Council;
type CurrencyToVote = frame_support::traits::U128CurrencyToVote;
type CandidacyBond = CandidacyBond;
type VotingBondBase = VotingBondBase;
type VotingBondFactor = VotingBondFactor;
type LoserCandidate = Treasury;
type KickedMember = Treasury;
type DesiredMembers = DesiredMembers;
type DesiredRunnersUp = DesiredRunnersUp;
type TermDuration = TermDuration;
type MaxVoters = MaxVoters;
type MaxCandidates = MaxCandidates;
type MaxVotesPerVoter = MaxVotesPerVoter;
type PalletId = PhragmenElectionPalletId;
type WeightInfo = pallet_elections_phragmen::weights::SubstrateWeight<Runtime>;
}

parameter_types! {
pub TechnicalMotionDuration: BlockNumber = prod_or_fast!(3 * DAYS, 2 * MINUTES, "KSM_MOTION_DURATION");
pub const TechnicalMaxProposals: u32 = 100;
pub const TechnicalMaxMembers: u32 = 100;
}

pub type TechnicalCollective = pallet_collective::Instance2;
impl pallet_collective::Config<TechnicalCollective> for Runtime {
type RuntimeOrigin = RuntimeOrigin;
type Proposal = RuntimeCall;
type RuntimeEvent = RuntimeEvent;
type MotionDuration = TechnicalMotionDuration;
type MaxProposals = TechnicalMaxProposals;
type MaxMembers = TechnicalMaxMembers;
type DefaultVote = pallet_collective::PrimeDefaultVote;
type SetMembersOrigin = EnsureRoot<AccountId>;
type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
}

impl pallet_membership::Config<pallet_membership::Instance1> for Runtime {
type RuntimeEvent = RuntimeEvent;
type AddOrigin = EnsureRoot<AccountId>;
type RemoveOrigin = EnsureRoot<AccountId>;
type SwapOrigin = EnsureRoot<AccountId>;
type ResetOrigin = EnsureRoot<AccountId>;
type PrimeOrigin = EnsureRoot<AccountId>;
type MembershipInitialized = TechnicalCommittee;
type MembershipChanged = TechnicalCommittee;
type MaxMembers = TechnicalMaxMembers;
type WeightInfo = pallet_membership::weights::SubstrateWeight<Runtime>;
}
Loading

0 comments on commit 0331225

Please sign in to comment.