diff --git a/Cargo.lock b/Cargo.lock index f18bdf3..b0ac510 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7233,15 +7233,21 @@ dependencies = [ "pallet-authorship", "pallet-balances", "pallet-collator-selection", + "pallet-conviction-voting", "pallet-message-queue", "pallet-multisig", + "pallet-preimage", "pallet-proxy", + "pallet-referenda", + "pallet-scheduler", "pallet-session", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", + "pallet-treasury", "pallet-utility", + "pallet-whitelist", "pallet-xcm", "parachains-common", "parity-scale-codec", @@ -7250,6 +7256,7 @@ dependencies = [ "scale-info", "smallvec", "sp-api", + "sp-arithmetic", "sp-block-builder", "sp-consensus-aura", "sp-core", diff --git a/Cargo.toml b/Cargo.toml index 8a08b8c..1767137 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,16 +38,22 @@ pallet-assets = { git = "https://github.com/paritytech/polkadot-sdk", default-fe pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } pallet-authorship = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } +pallet-conviction-voting = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } pallet-message-queue = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } pallet-multisig = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } +pallet-preimage = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } pallet-proxy = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } +pallet-referenda = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } +pallet-scheduler = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } pallet-session = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } +pallet-treasury = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } pallet-utility = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } +pallet-whitelist = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } sc-basic-authorship = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } sc-chain-spec = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } sc-cli = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } @@ -65,6 +71,7 @@ sc-tracing = { git = "https://github.com/paritytech/polkadot-sdk", default-featu sc-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } sc-transaction-pool-api = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } sp-api = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } +sp-arithmetic = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } sp-blockchain = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, tag = "polkadot-v1.7.0" } diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 324037a..9d8f71b 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -199,6 +199,7 @@ fn testnet_genesis( }) .collect::>(), }, + "treasury": {}, "polkadotXcm": { "safeXcmVersion": Some(SAFE_XCM_VERSION), }, diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index ca49c9e..14bc210 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -29,16 +29,23 @@ pallet-assets = { workspace = true } pallet-aura = { workspace = true } pallet-authorship = { workspace = true } pallet-balances = { workspace = true } +pallet-conviction-voting = { workspace = true } pallet-message-queue = { workspace = true } pallet-multisig = { workspace = true } +pallet-preimage = { workspace = true } pallet-proxy = { workspace = true } +pallet-referenda = { workspace = true } +pallet-scheduler = { workspace = true } pallet-session = { workspace = true } pallet-sudo = { workspace = true } pallet-timestamp = { workspace = true } pallet-transaction-payment = { workspace = true } pallet-transaction-payment-rpc-runtime-api = { workspace = true } +pallet-treasury = { workspace = true } pallet-utility = { workspace = true } +pallet-whitelist = { workspace = true } sp-api = { workspace = true } +sp-arithmetic = { workspace = true } sp-block-builder = { workspace = true } sp-consensus-aura = { workspace = true } sp-core = { workspace = true } @@ -104,15 +111,21 @@ std = [ "pallet-authorship/std", "pallet-balances/std", "pallet-collator-selection/std", + "pallet-conviction-voting/std", "pallet-message-queue/std", "pallet-multisig/std", + "pallet-preimage/std", "pallet-proxy/std", + "pallet-referenda/std", + "pallet-scheduler/std", "pallet-session/std", "pallet-sudo/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", + "pallet-treasury/std", "pallet-utility/std", + "pallet-whitelist/std", "pallet-xcm/std", "parachain-info/std", "parachains-common/std", @@ -121,6 +134,7 @@ std = [ "polkadot-runtime-common/std", "scale-info/std", "sp-api/std", + "sp-arithmetic/std", "sp-block-builder/std", "sp-consensus-aura/std", "sp-core/std", @@ -151,11 +165,17 @@ runtime-benchmarks = [ "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", + "pallet-conviction-voting/runtime-benchmarks", "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", + "pallet-preimage/runtime-benchmarks", + "pallet-referenda/runtime-benchmarks", + "pallet-scheduler/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", + "pallet-treasury/runtime-benchmarks", "pallet-utility/runtime-benchmarks", + "pallet-whitelist/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", @@ -179,15 +199,21 @@ try-runtime = [ "pallet-authorship/try-runtime", "pallet-balances/try-runtime", "pallet-collator-selection/try-runtime", + "pallet-conviction-voting/try-runtime", "pallet-message-queue/try-runtime", "pallet-multisig/try-runtime", + "pallet-preimage/try-runtime", "pallet-proxy/try-runtime", + "pallet-referenda/try-runtime", + "pallet-scheduler/try-runtime", "pallet-session/try-runtime", "pallet-session/try-runtime", "pallet-sudo/try-runtime", "pallet-timestamp/try-runtime", "pallet-transaction-payment/try-runtime", + "pallet-treasury/try-runtime", "pallet-utility/try-runtime", + "pallet-whitelist/try-runtime", "pallet-xcm/try-runtime", "parachain-info/try-runtime", "polkadot-runtime-common/try-runtime", diff --git a/runtime/src/constants.rs b/runtime/src/constants.rs index b3a1690..97386ce 100644 --- a/runtime/src/constants.rs +++ b/runtime/src/constants.rs @@ -5,6 +5,7 @@ pub mod currency { pub const MILLICENTS: Balance = 1_000_000_000; pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent. pub const DOLLARS: Balance = 100 * CENTS; + pub const GRAND: Balance = 1_000 * DOLLARS; pub const EXISTENTIAL_DEPOSIT: Balance = MILLICENTS; diff --git a/runtime/src/governance/mod.rs b/runtime/src/governance/mod.rs new file mode 100644 index 0000000..cb7d758 --- /dev/null +++ b/runtime/src/governance/mod.rs @@ -0,0 +1,74 @@ +//! OpenGov governance config + +pub mod origins; +pub use origins::{ + pallet_custom_origins, ReferendumCanceller, ReferendumKiller, Spender, Treasurer, + WhitelistedCaller, +}; +mod tracks; + +use frame_support::traits::EitherOf; +use frame_system::EnsureRootWithSuccess; + +use super::*; +use crate::{ + constants::currency::{CENTS, GRAND}, + Balance, +}; + +parameter_types! { + pub const VoteLockingPeriod: BlockNumber = 7 * DAYS; +} + +impl pallet_conviction_voting::Config for Runtime { + type Currency = Balances; + type MaxTurnout = + frame_support::traits::tokens::currency::ActiveIssuanceOf; + type MaxVotes = ConstU32<512>; + type Polls = Referenda; + type RuntimeEvent = RuntimeEvent; + type VoteLockingPeriod = VoteLockingPeriod; + type WeightInfo = pallet_conviction_voting::weights::SubstrateWeight; +} + +parameter_types! { + pub const MaxBalance: Balance = Balance::max_value(); +} +pub type TreasurySpender = EitherOf, Spender>; + +impl origins::pallet_custom_origins::Config for Runtime {} + +impl pallet_whitelist::Config for Runtime { + type DispatchWhitelistedOrigin = EitherOf, WhitelistedCaller>; + type Preimages = Preimage; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_whitelist::weights::SubstrateWeight; + type WhitelistOrigin = EnsureRoot; +} + +parameter_types! { + pub const AlarmInterval: BlockNumber = 1; + pub const SubmissionDeposit: Balance = 3 * CENTS; + pub const UndecidingTimeout: BlockNumber = 14 * DAYS; +} + +impl pallet_referenda::Config for Runtime { + type AlarmInterval = AlarmInterval; + type CancelOrigin = EnsureRoot; + type Currency = Balances; + type KillOrigin = EnsureRoot; + type MaxQueued = ConstU32<20>; + type Preimages = Preimage; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type Scheduler = Scheduler; + type Slash = Treasury; + type SubmissionDeposit = SubmissionDeposit; + type SubmitOrigin = EnsureSigned; + type Tally = pallet_conviction_voting::TallyOf; + type Tracks = tracks::TracksInfo; + type UndecidingTimeout = UndecidingTimeout; + type Votes = pallet_conviction_voting::VotesOf; + type WeightInfo = pallet_referenda::weights::SubstrateWeight; +} diff --git a/runtime/src/governance/origins.rs b/runtime/src/governance/origins.rs new file mode 100644 index 0000000..1ea9c48 --- /dev/null +++ b/runtime/src/governance/origins.rs @@ -0,0 +1,115 @@ +//! Custom origins for governance interventions. + +pub use pallet_custom_origins::*; + +#[frame_support::pallet] +pub mod pallet_custom_origins { + use frame_support::pallet_prelude::*; + + use crate::governance::{Balance, CENTS, GRAND}; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet(_); + + #[derive(PartialEq, Eq, Clone, MaxEncodedLen, Encode, Decode, TypeInfo, RuntimeDebug)] + #[pallet::origin] + pub enum Origin { + /// Origin for spending (any amount of) funds. + Treasurer, + /// Origin able to cancel referenda. + ReferendumCanceller, + /// Origin able to kill referenda. + ReferendumKiller, + /// Origin able to spend the amount specified in Spender. + SmallTipper, + /// Origin able to spend the amount specified in Spender. + BigTipper, + /// Origin able to spend the amount specified in Spender. + SmallSpender, + /// Origin able to spend the amount specified in Spender. + MediumSpender, + /// Origin able to spend the amount specified in Spender. + BigSpender, + /// Origin able to dispatch a whitelisted call. + WhitelistedCaller, + } + + macro_rules! decl_unit_ensures { + ( $name:ident: $success_type:ty = $success:expr ) => { + pub struct $name; + impl> + From> + EnsureOrigin for $name + { + type Success = $success_type; + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + Origin::$name => Ok($success), + r => Err(O::from(r)), + }) + } + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin() -> Result { + Ok(O::from(Origin::$name)) + } + } + }; + ( $name:ident ) => { decl_unit_ensures! { $name : () = () } }; + ( $name:ident: $success_type:ty = $success:expr, $( $rest:tt )* ) => { + decl_unit_ensures! { $name: $success_type = $success } + decl_unit_ensures! { $( $rest )* } + }; + ( $name:ident, $( $rest:tt )* ) => { + decl_unit_ensures! { $name } + decl_unit_ensures! { $( $rest )* } + }; + () => {} + } + decl_unit_ensures!(Treasurer, ReferendumCanceller, ReferendumKiller, WhitelistedCaller,); + + macro_rules! decl_ensure { + ( + $vis:vis type $name:ident: EnsureOrigin { + $( $item:ident = $success:expr, )* + } + ) => { + $vis struct $name; + impl> + From> + EnsureOrigin for $name + { + type Success = $success_type; + fn try_origin(o: O) -> Result { + o.into().and_then(|o| match o { + $( + Origin::$item => Ok($success), + )* + r => Err(O::from(r)), + }) + } + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin() -> Result { + // By convention the more privileged origins go later, so for greatest chance + // of success, we want the last one. + let _result: Result = Err(()); + $( + let _result: Result = Ok(O::from(Origin::$item)); + )* + _result + } + } + } + } + + decl_ensure! { + pub type Spender: EnsureOrigin { + SmallTipper = 250 * 3 * CENTS, + BigTipper = GRAND, + SmallSpender = 10 * GRAND, + MediumSpender = 100 * GRAND, + BigSpender = 1_000 * GRAND, + Treasurer = 10_000 * GRAND, + } + } +} diff --git a/runtime/src/governance/tracks.rs b/runtime/src/governance/tracks.rs new file mode 100644 index 0000000..5038407 --- /dev/null +++ b/runtime/src/governance/tracks.rs @@ -0,0 +1,213 @@ +//! Track configurations for governance. + +use super::*; + +const fn percent(x: i32) -> sp_arithmetic::FixedI64 { + sp_arithmetic::FixedI64::from_rational(x as u128, 100) +} +use pallet_referenda::Curve; +const APP_ROOT: Curve = Curve::make_reciprocal(4, 28, percent(80), percent(50), percent(100)); +const SUP_ROOT: Curve = Curve::make_linear(28, 28, percent(0), percent(50)); +const APP_TREASURER: Curve = Curve::make_reciprocal(4, 28, percent(80), percent(50), percent(100)); +const SUP_TREASURER: Curve = Curve::make_linear(28, 28, percent(0), percent(50)); +const APP_REFERENDUM_CANCELLER: Curve = Curve::make_linear(17, 28, percent(50), percent(100)); +const SUP_REFERENDUM_CANCELLER: Curve = + Curve::make_reciprocal(12, 28, percent(1), percent(0), percent(50)); +const APP_REFERENDUM_KILLER: Curve = Curve::make_linear(17, 28, percent(50), percent(100)); +const SUP_REFERENDUM_KILLER: Curve = + Curve::make_reciprocal(12, 28, percent(1), percent(0), percent(50)); +const APP_SMALL_TIPPER: Curve = Curve::make_linear(10, 28, percent(50), percent(100)); +const SUP_SMALL_TIPPER: Curve = Curve::make_reciprocal(1, 28, percent(4), percent(0), percent(50)); +const APP_BIG_TIPPER: Curve = Curve::make_linear(10, 28, percent(50), percent(100)); +const SUP_BIG_TIPPER: Curve = Curve::make_reciprocal(8, 28, percent(1), percent(0), percent(50)); +const APP_SMALL_SPENDER: Curve = Curve::make_linear(17, 28, percent(50), percent(100)); +const SUP_SMALL_SPENDER: Curve = + Curve::make_reciprocal(12, 28, percent(1), percent(0), percent(50)); +const APP_MEDIUM_SPENDER: Curve = Curve::make_linear(23, 28, percent(50), percent(100)); +const SUP_MEDIUM_SPENDER: Curve = + Curve::make_reciprocal(16, 28, percent(1), percent(0), percent(50)); +const APP_BIG_SPENDER: Curve = Curve::make_linear(28, 28, percent(50), percent(100)); +const SUP_BIG_SPENDER: Curve = Curve::make_reciprocal(20, 28, percent(1), percent(0), percent(50)); +const APP_WHITELISTED_CALLER: Curve = + Curve::make_reciprocal(16, 28 * 24, percent(96), percent(50), percent(100)); +const SUP_WHITELISTED_CALLER: Curve = + Curve::make_reciprocal(1, 28, percent(20), percent(5), percent(50)); + +const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 10] = [ + ( + 0, + pallet_referenda::TrackInfo { + name: "root", + max_deciding: 1, + decision_deposit: 100 * GRAND, + prepare_period: 8 * MINUTES, + decision_period: 20 * MINUTES, + confirm_period: 12 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: APP_ROOT, + min_support: SUP_ROOT, + }, + ), + ( + 1, + pallet_referenda::TrackInfo { + name: "whitelisted_caller", + max_deciding: 100, + decision_deposit: 10 * GRAND, + prepare_period: 6 * MINUTES, + decision_period: 20 * MINUTES, + confirm_period: 4 * MINUTES, + min_enactment_period: 3 * MINUTES, + min_approval: APP_WHITELISTED_CALLER, + min_support: SUP_WHITELISTED_CALLER, + }, + ), + ( + 11, + pallet_referenda::TrackInfo { + name: "treasurer", + max_deciding: 10, + decision_deposit: GRAND, + prepare_period: 8 * MINUTES, + decision_period: 20 * MINUTES, + confirm_period: 8 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: APP_TREASURER, + min_support: SUP_TREASURER, + }, + ), + ( + 20, + pallet_referenda::TrackInfo { + name: "referendum_canceller", + max_deciding: 1_000, + decision_deposit: 10 * GRAND, + prepare_period: 8 * MINUTES, + decision_period: 14 * MINUTES, + confirm_period: 8 * MINUTES, + min_enactment_period: 3 * MINUTES, + min_approval: APP_REFERENDUM_CANCELLER, + min_support: SUP_REFERENDUM_CANCELLER, + }, + ), + ( + 21, + pallet_referenda::TrackInfo { + name: "referendum_killer", + max_deciding: 1_000, + decision_deposit: 50 * GRAND, + prepare_period: 8 * MINUTES, + decision_period: 20 * MINUTES, + confirm_period: 8 * MINUTES, + min_enactment_period: 3 * MINUTES, + min_approval: APP_REFERENDUM_KILLER, + min_support: SUP_REFERENDUM_KILLER, + }, + ), + ( + 30, + pallet_referenda::TrackInfo { + name: "small_tipper", + max_deciding: 200, + decision_deposit: 3 * CENTS, + prepare_period: MINUTES, + decision_period: 14 * MINUTES, + confirm_period: 4 * MINUTES, + min_enactment_period: MINUTES, + min_approval: APP_SMALL_TIPPER, + min_support: SUP_SMALL_TIPPER, + }, + ), + ( + 31, + pallet_referenda::TrackInfo { + name: "big_tipper", + max_deciding: 100, + decision_deposit: 10 * 3 * CENTS, + prepare_period: 4 * MINUTES, + decision_period: 14 * MINUTES, + confirm_period: 12 * MINUTES, + min_enactment_period: 3 * MINUTES, + min_approval: APP_BIG_TIPPER, + min_support: SUP_BIG_TIPPER, + }, + ), + ( + 32, + pallet_referenda::TrackInfo { + name: "small_spender", + max_deciding: 50, + decision_deposit: 100 * 3 * CENTS, + prepare_period: 10 * MINUTES, + decision_period: 20 * MINUTES, + confirm_period: 10 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: APP_SMALL_SPENDER, + min_support: SUP_SMALL_SPENDER, + }, + ), + ( + 33, + pallet_referenda::TrackInfo { + name: "medium_spender", + max_deciding: 50, + decision_deposit: 200 * 3 * CENTS, + prepare_period: 10 * MINUTES, + decision_period: 20 * MINUTES, + confirm_period: 12 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: APP_MEDIUM_SPENDER, + min_support: SUP_MEDIUM_SPENDER, + }, + ), + ( + 34, + pallet_referenda::TrackInfo { + name: "big_spender", + max_deciding: 50, + decision_deposit: 400 * 3 * CENTS, + prepare_period: 10 * MINUTES, + decision_period: 20 * MINUTES, + confirm_period: 14 * MINUTES, + min_enactment_period: 5 * MINUTES, + min_approval: APP_BIG_SPENDER, + min_support: SUP_BIG_SPENDER, + }, + ), +]; + +pub struct TracksInfo; +impl pallet_referenda::TracksInfo for TracksInfo { + type Id = u16; + type RuntimeOrigin = ::PalletsOrigin; + + fn tracks() -> &'static [(Self::Id, pallet_referenda::TrackInfo)] { + &TRACKS_DATA[..] + } + + fn track_for(id: &Self::RuntimeOrigin) -> Result { + if let Ok(system_origin) = frame_system::RawOrigin::try_from(id.clone()) { + match system_origin { + frame_system::RawOrigin::Root => Ok(0), + _ => Err(()), + } + } else if let Ok(custom_origin) = origins::Origin::try_from(id.clone()) { + match custom_origin { + origins::Origin::WhitelistedCaller => Ok(1), + origins::Origin::Treasurer => Ok(11), + // Referendum admins + origins::Origin::ReferendumCanceller => Ok(20), + origins::Origin::ReferendumKiller => Ok(21), + // Limited treasury spenders + origins::Origin::SmallTipper => Ok(30), + origins::Origin::BigTipper => Ok(31), + origins::Origin::SmallSpender => Ok(32), + origins::Origin::MediumSpender => Ok(33), + origins::Origin::BigSpender => Ok(34), + } + } else { + Err(()) + } + } +} +pallet_referenda::impl_tracksinfo_get!(TracksInfo, Balance, BlockNumber); diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 8672aaa..5197a62 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -7,6 +7,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod constants; +pub mod governance; mod weights; pub mod xcm_config; @@ -31,6 +32,10 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, EnsureSigned, }; +use governance::{ + origins::{pallet_custom_origins, Treasurer}, + TreasurySpender, +}; use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; @@ -56,7 +61,7 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; // XCM Imports -use xcm::latest::prelude::BodyId; +use xcm::latest::{prelude::BodyId, InteriorLocation, Junction::PalletInstance}; use crate::{ constants::currency::{deposit, CENTS, EXISTENTIAL_DEPOSIT, MICROCENTS, MILLICENTS}, @@ -340,6 +345,49 @@ impl frame_system::Config for Runtime { type Version = Version; } +parameter_types! { + pub MaximumSchedulerWeight: frame_support::weights::Weight = Perbill::from_percent(80) * + RuntimeBlockWeights::get().max_block; + pub const MaxScheduledPerBlock: u32 = 50; + pub const NoPreimagePostponement: Option = Some(10); +} + +impl pallet_scheduler::Config for Runtime { + type MaxScheduledPerBlock = MaxScheduledPerBlock; + type MaximumWeight = MaximumSchedulerWeight; + type OriginPrivilegeCmp = frame_support::traits::EqualPrivilegeOnly; + type PalletsOrigin = OriginCaller; + type Preimages = Preimage; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type ScheduleOrigin = EnsureRoot; + type WeightInfo = pallet_scheduler::weights::SubstrateWeight; +} + +parameter_types! { + pub const PreimageBaseDeposit: Balance = deposit(2, 64); + pub const PreimageByteDeposit: Balance = deposit(0, 1); + pub const PreimageHoldReason: RuntimeHoldReason = RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage); +} + +impl pallet_preimage::Config for Runtime { + type Consideration = frame_support::traits::fungible::HoldConsideration< + AccountId, + Balances, + PreimageHoldReason, + frame_support::traits::LinearStoragePrice< + PreimageBaseDeposit, + PreimageByteDeposit, + Balance, + >, + >; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_preimage::weights::SubstrateWeight; +} + impl pallet_timestamp::Config for Runtime { type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; /// A timestamp: milliseconds since the unix epoch. @@ -553,7 +601,7 @@ impl pallet_message_queue::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ServiceWeight = MessageQueueServiceWeight; type Size = u32; - type WeightInfo = (); + type WeightInfo = pallet_message_queue::weights::SubstrateWeight; } impl cumulus_pallet_aura_ext::Config for Runtime {} @@ -669,6 +717,51 @@ impl pallet_utility::Config for Runtime { type WeightInfo = pallet_utility::weights::SubstrateWeight; } +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: Balance = 2000; // * CENTS + pub const ProposalBondMaximum: Balance = 1;// * GRAND; + pub const SpendPeriod: BlockNumber = 6 * DAYS; + pub const Burn: Permill = Permill::from_perthousand(2); + pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry"); + pub const PayoutSpendPeriod: BlockNumber = 30 * DAYS; + // The asset's interior location for the paying account. This is the Treasury + // pallet instance (which sits at index 13). + pub TreasuryInteriorLocation: InteriorLocation = PalletInstance(13).into(); + pub const MaxApprovals: u32 = 100; +} + +parameter_types! { + pub TreasuryAccount: AccountId = Treasury::account_id(); +} + +impl pallet_treasury::Config for Runtime { + type ApproveOrigin = EitherOfDiverse, Treasurer>; + type AssetKind = (); + type BalanceConverter = frame_support::traits::tokens::UnityAssetBalanceConversion; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = runtime_common::impls::benchmarks::TreasuryArguments; + type Beneficiary = Self::AccountId; + type BeneficiaryLookup = sp_runtime::traits::IdentityLookup; + type Burn = (); + type BurnDestination = (); + type Currency = Balances; + type MaxApprovals = MaxApprovals; + type OnSlash = Treasury; + type PalletId = TreasuryPalletId; + type Paymaster = frame_support::traits::tokens::PayFromAccount; + type PayoutPeriod = PayoutSpendPeriod; + type ProposalBond = ProposalBond; + type ProposalBondMaximum = ProposalBondMaximum; + type ProposalBondMinimum = ProposalBondMinimum; + type RejectOrigin = EitherOfDiverse, Treasurer>; + type RuntimeEvent = RuntimeEvent; + type SpendFunds = (); + type SpendOrigin = TreasurySpender; + type SpendPeriod = SpendPeriod; + type WeightInfo = pallet_treasury::weights::SubstrateWeight; +} + // Create the runtime by composing the FRAME pallets that were previously // configured. construct_runtime!( @@ -682,15 +775,21 @@ construct_runtime!( Proxy: pallet_proxy = 4, Utility: pallet_utility = 5, Multisig: pallet_multisig = 6, - + Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event} = 7, + Preimage: pallet_preimage::{Pallet, Call, Storage, Event, HoldReason} = 8, // Monetary Balances: pallet_balances = 10, TransactionPayment: pallet_transaction_payment = 11, Assets: pallet_assets = 12, + Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event} = 13, // Governance Sudo: pallet_sudo = 15, + ConvictionVoting: pallet_conviction_voting::{Pallet, Call, Storage, Event} = 16, + Referenda: pallet_referenda::{Pallet, Call, Storage, Event} = 17, + Origins: pallet_custom_origins::{Origin} = 18, + Whitelist: pallet_whitelist::{Pallet, Call, Storage, Event} = 19, // Collator Support. The order of these 4 are important and shall not change. Authorship: pallet_authorship = 20, diff --git a/template-fuzzer/src/main.rs b/template-fuzzer/src/main.rs index a496da0..230e669 100644 --- a/template-fuzzer/src/main.rs +++ b/template-fuzzer/src/main.rs @@ -61,6 +61,7 @@ fn main() { assets: Default::default(), transaction_payment: Default::default(), sudo: SudoConfig { key: Some(root) }, + treasury: Default::default(), } .build_storage() .unwrap()