// Copyright 2017-2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see .
//! The Kusama runtime. This can be compiled with `#[no_std]`, ready for Wasm.
#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit = "256"]
use pallet_transaction_payment::CurrencyAdapter;
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use primitives::v1::{
AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CommittedCandidateReceipt,
CoreState, GroupRotationInfo, Hash, Id as ParaId, InboundDownwardMessage, InboundHrmpMessage,
Moment, Nonce, OccupiedCoreAssumption, PersistedValidationData, ScrapedOnChainVotes,
SessionInfo, Signature, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex,
};
use runtime_common::{
auctions, claims, crowdloan, impls::DealWithFees, paras_registrar, slots, xcm_sender,
BlockHashCount, BlockLength, BlockWeights, CurrencyToVote, OffchainSolutionLengthLimit,
OffchainSolutionWeightLimit, RocksDbWeight, SlowAdjustingFeeUpdate, ToAuthor,
};
use sp_core::u32_trait::{_1, _2, _3, _5};
use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*};
use runtime_parachains::{
configuration as parachains_configuration, disputes as parachains_disputes,
dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion,
initializer as parachains_initializer, origin as parachains_origin, paras as parachains_paras,
paras_inherent as parachains_paras_inherent, reward_points as parachains_reward_points,
runtime_api_impl::v1 as parachains_runtime_api_impl, scheduler as parachains_scheduler,
session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump,
};
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
use beefy_primitives::crypto::AuthorityId as BeefyId;
use frame_support::{
construct_runtime, match_type, parameter_types,
traits::{
Contains, Everything, InstanceFilter, KeyOwnerProofSystem, LockIdentifier, Nothing,
OnRuntimeUpgrade, PrivilegeCmp,
},
weights::Weight,
PalletId, RuntimeDebug,
};
use frame_system::{EnsureOneOf, EnsureRoot};
use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId};
use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use pallet_mmr_primitives as mmr;
use pallet_session::historical as session_historical;
use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo};
use sp_arithmetic::Perquintill;
use sp_core::OpaqueMetadata;
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{
AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, Extrinsic as ExtrinsicT,
OpaqueKeys, SaturatedConversion, Verify,
},
transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity},
ApplyExtrinsicResult, KeyTypeId, Perbill, Percent, Permill,
};
use sp_staking::SessionIndex;
#[cfg(any(feature = "std", test))]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use static_assertions::const_assert;
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, BackingToPlurality,
ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
CurrencyAdapter as XcmCurrencyAdapter, FixedWeightBounds, IsChildSystemParachain, IsConcrete,
LocationInverter, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation,
TakeWeightCredit, UsingComponents,
};
use xcm_executor::XcmExecutor;
pub use pallet_balances::Call as BalancesCall;
pub use pallet_election_provider_multi_phase::Call as EPMCall;
#[cfg(feature = "std")]
pub use pallet_staking::StakerStatus;
pub use pallet_timestamp::Call as TimestampCall;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
/// Constant values used within the runtime.
pub mod constants;
use constants::{currency::*, fee::*, time::*};
// Weights used in the runtime.
mod weights;
// Voter bag threshold definitions.
mod bag_thresholds;
#[cfg(test)]
mod tests;
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
/// Runtime version (Kusama).
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("kusama"),
impl_name: create_runtime_str!("parity-kusama"),
authoring_version: 2,
spec_version: 9130,
impl_version: 0,
#[cfg(not(feature = "disable-runtime-api"))]
apis: RUNTIME_API_VERSIONS,
#[cfg(feature = "disable-runtime-api")]
apis: version::create_apis_vec![[]],
transaction_version: 7,
};
/// The BABE epoch configuration at genesis.
pub const BABE_GENESIS_EPOCH_CONFIG: babe_primitives::BabeEpochConfiguration =
babe_primitives::BabeEpochConfiguration {
c: PRIMARY_PROBABILITY,
allowed_slots: babe_primitives::AllowedSlots::PrimaryAndSecondaryVRFSlots,
};
/// Native version.
#[cfg(any(feature = "std", test))]
pub fn native_version() -> NativeVersion {
NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
}
/// Don't allow swaps until parathread story is more mature.
pub struct BaseFilter;
impl Contains for BaseFilter {
fn contains(c: &Call) -> bool {
!matches!(c, Call::Registrar(paras_registrar::Call::swap { .. }))
}
}
type MoreThanHalfCouncil = EnsureOneOf<
AccountId,
EnsureRoot,
pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>,
>;
parameter_types! {
pub const Version: RuntimeVersion = VERSION;
pub const SS58Prefix: u8 = 2;
}
impl frame_system::Config for Runtime {
type BaseCallFilter = BaseFilter;
type BlockWeights = BlockWeights;
type BlockLength = BlockLength;
type Origin = Origin;
type Call = Call;
type Index = Nonce;
type BlockNumber = BlockNumber;
type Hash = Hash;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
type Lookup = AccountIdLookup;
type Header = generic::Header;
type Event = Event;
type BlockHashCount = BlockHashCount;
type DbWeight = RocksDbWeight;
type Version = Version;
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = weights::frame_system::WeightInfo;
type SS58Prefix = SS58Prefix;
type OnSetCode = ();
}
parameter_types! {
pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) *
BlockWeights::get().max_block;
pub const MaxScheduledPerBlock: u32 = 50;
}
type ScheduleOrigin = EnsureOneOf<
AccountId,
EnsureRoot,
pallet_collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>,
>;
/// Used the compare the privilege of an origin inside the scheduler.
pub struct OriginPrivilegeCmp;
impl PrivilegeCmp for OriginPrivilegeCmp {
fn cmp_privilege(left: &OriginCaller, right: &OriginCaller) -> Option {
if left == right {
return Some(Ordering::Equal)
}
match (left, right) {
// Root is greater than anything.
(OriginCaller::system(frame_system::RawOrigin::Root), _) => Some(Ordering::Greater),
// Check which one has more yes votes.
(
OriginCaller::Council(pallet_collective::RawOrigin::Members(l_yes_votes, l_count)),
OriginCaller::Council(pallet_collective::RawOrigin::Members(r_yes_votes, r_count)),
) => Some((l_yes_votes * r_count).cmp(&(r_yes_votes * l_count))),
// For every other origin we don't care, as they are not used for `ScheduleOrigin`.
_ => None,
}
}
}
impl pallet_scheduler::Config for Runtime {
type Event = Event;
type Origin = Origin;
type PalletsOrigin = OriginCaller;
type Call = Call;
type MaximumWeight = MaximumSchedulerWeight;
type ScheduleOrigin = ScheduleOrigin;
type MaxScheduledPerBlock = MaxScheduledPerBlock;
type WeightInfo = weights::pallet_scheduler::WeightInfo;
type OriginPrivilegeCmp = OriginPrivilegeCmp;
}
parameter_types! {
pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS as u64;
pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
pub const ReportLongevity: u64 =
BondingDuration::get() as u64 * SessionsPerEra::get() as u64 * EpochDuration::get();
}
impl pallet_babe::Config for Runtime {
type EpochDuration = EpochDuration;
type ExpectedBlockTime = ExpectedBlockTime;
// session module is the trigger
type EpochChangeTrigger = pallet_babe::ExternalTrigger;
type DisabledValidators = Session;
type KeyOwnerProof = >::Proof;
type KeyOwnerIdentification = >::IdentificationTuple;
type KeyOwnerProofSystem = Historical;
type HandleEquivocation =
pallet_babe::EquivocationHandler;
type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
}
parameter_types! {
pub const IndexDeposit: Balance = 100 * CENTS;
}
impl pallet_indices::Config for Runtime {
type AccountIndex = AccountIndex;
type Currency = Balances;
type Deposit = IndexDeposit;
type Event = Event;
type WeightInfo = weights::pallet_indices::WeightInfo;
}
parameter_types! {
pub const ExistentialDeposit: Balance = 1 * CENTS;
pub const MaxLocks: u32 = 50;
pub const MaxReserves: u32 = 50;
}
impl pallet_balances::Config for Runtime {
type Balance = Balance;
type DustRemoval = ();
type Event = Event;
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
type MaxLocks = MaxLocks;
type MaxReserves = MaxReserves;
type ReserveIdentifier = [u8; 8];
type WeightInfo = weights::pallet_balances::WeightInfo;
}
parameter_types! {
pub const TransactionByteFee: Balance = 10 * MILLICENTS;
/// This value increases the priority of `Operational` transactions by adding
/// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.
pub const OperationalFeeMultiplier: u8 = 5;
}
impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = CurrencyAdapter>;
type TransactionByteFee = TransactionByteFee;
type OperationalFeeMultiplier = OperationalFeeMultiplier;
type WeightToFee = WeightToFee;
type FeeMultiplierUpdate = SlowAdjustingFeeUpdate;
}
parameter_types! {
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
}
impl pallet_timestamp::Config for Runtime {
type Moment = u64;
type OnTimestampSet = Babe;
type MinimumPeriod = MinimumPeriod;
type WeightInfo = weights::pallet_timestamp::WeightInfo;
}
parameter_types! {
pub const UncleGenerations: u32 = 0;
}
impl pallet_authorship::Config for Runtime {
type FindAuthor = pallet_session::FindAccountFromAuthorIndex;
type UncleGenerations = UncleGenerations;
type FilterUncle = ();
type EventHandler = (Staking, ImOnline);
}
parameter_types! {
pub const Period: BlockNumber = 10 * MINUTES;
pub const Offset: BlockNumber = 0;
}
impl_opaque_keys! {
pub struct SessionKeys {
pub grandpa: Grandpa,
pub babe: Babe,
pub im_online: ImOnline,
pub para_validator: Initializer,
pub para_assignment: ParaSessionInfo,
pub authority_discovery: AuthorityDiscovery,
}
}
impl pallet_session::Config for Runtime {
type Event = Event;
type ValidatorId = AccountId;
type ValidatorIdOf = pallet_staking::StashOf;
type ShouldEndSession = Babe;
type NextSessionRotation = Babe;
type SessionManager = pallet_session::historical::NoteHistoricalRoot;
type SessionHandler = ::KeyTypeIdProviders;
type Keys = SessionKeys;
type WeightInfo = weights::pallet_session::WeightInfo;
}
impl pallet_session::historical::Config for Runtime {
type FullIdentification = pallet_staking::Exposure;
type FullIdentificationOf = pallet_staking::ExposureOf;
}
parameter_types! {
// phase durations. 1/4 of the last session for each.
pub const SignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
pub const UnsignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
// signed config
pub const SignedMaxSubmissions: u32 = 16;
pub const SignedDepositBase: Balance = deposit(2, 0);
pub const SignedDepositByte: Balance = deposit(0, 10) / 1024;
// Each good submission will get 1/10 KSM as reward
pub SignedRewardBase: Balance = UNITS / 10;
pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(5u32, 10_000);
// 1 hour session, 15 minutes unsigned phase, 8 offchain executions.
pub OffchainRepeat: BlockNumber = UnsignedPhase::get() / 8;
/// Whilst `UseNominatorsAndUpdateBagsList` or `UseNominatorsMap` is in use, this can still be a
/// very large value. Once the `BagsList` is in full motion, staking might open its door to many
/// more nominators, and this value should instead be what is a "safe" number (e.g. 22500).
pub const VoterSnapshotPerBlock: u32 = 22_500;
}
sp_npos_elections::generate_solution_type!(
#[compact]
pub struct NposCompactSolution24::<
VoterIndex = u32,
TargetIndex = u16,
Accuracy = sp_runtime::PerU16,
>(24)
);
impl pallet_election_provider_multi_phase::Config for Runtime {
type Event = Event;
type Currency = Balances;
type EstimateCallFee = TransactionPayment;
type UnsignedPhase = UnsignedPhase;
type SignedMaxSubmissions = SignedMaxSubmissions;
type SignedRewardBase = SignedRewardBase;
type SignedDepositBase = SignedDepositBase;
type SignedDepositByte = SignedDepositByte;
type SignedDepositWeight = ();
type SignedMaxWeight = Self::MinerMaxWeight;
type SlashHandler = (); // burn slashes
type RewardHandler = (); // nothing to do upon rewards
type SignedPhase = SignedPhase;
type SolutionImprovementThreshold = SolutionImprovementThreshold;
type MinerMaxWeight = OffchainSolutionWeightLimit; // For now use the one from staking.
type MinerMaxLength = OffchainSolutionLengthLimit;
type OffchainRepeat = OffchainRepeat;
type MinerTxPriority = NposSolutionPriority;
type DataProvider = Staking;
type Solution = NposCompactSolution24;
type Fallback = pallet_election_provider_multi_phase::NoFallback;
type Solver = frame_election_provider_support::SequentialPhragmen<
AccountId,
pallet_election_provider_multi_phase::SolutionAccuracyOf,
runtime_common::elections::OffchainRandomBalancing,
>;
type BenchmarkingConfig = runtime_common::elections::BenchmarkConfig;
type ForceOrigin = EnsureOneOf<
AccountId,
EnsureRoot,
pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>,
>;
type WeightInfo = weights::pallet_election_provider_multi_phase::WeightInfo;
type VoterSnapshotPerBlock = VoterSnapshotPerBlock;
}
parameter_types! {
pub const BagThresholds: &'static [u64] = &bag_thresholds::THRESHOLDS;
}
impl pallet_bags_list::Config for Runtime {
type Event = Event;
type VoteWeightProvider = Staking;
type WeightInfo = weights::pallet_bags_list::WeightInfo;
type BagThresholds = BagThresholds;
}
fn era_payout(
total_staked: Balance,
non_gilt_issuance: Balance,
max_annual_inflation: Perquintill,
period_fraction: Perquintill,
auctioned_slots: u64,
) -> (Balance, Balance) {
use pallet_staking_reward_fn::compute_inflation;
use sp_arithmetic::traits::Saturating;
let min_annual_inflation = Perquintill::from_rational(25u64, 1000u64);
let delta_annual_inflation = max_annual_inflation.saturating_sub(min_annual_inflation);
// 30% reserved for up to 60 slots.
let auction_proportion = Perquintill::from_rational(auctioned_slots.min(60), 200u64);
// Therefore the ideal amount at stake (as a percentage of total issuance) is 75% less the amount that we expect
// to be taken up with auctions.
let ideal_stake = Perquintill::from_percent(75).saturating_sub(auction_proportion);
let stake = Perquintill::from_rational(total_staked, non_gilt_issuance);
let falloff = Perquintill::from_percent(5);
let adjustment = compute_inflation(stake, ideal_stake, falloff);
let staking_inflation =
min_annual_inflation.saturating_add(delta_annual_inflation * adjustment);
let max_payout = period_fraction * max_annual_inflation * non_gilt_issuance;
let staking_payout = (period_fraction * staking_inflation) * non_gilt_issuance;
let rest = max_payout.saturating_sub(staking_payout);
let other_issuance = non_gilt_issuance.saturating_sub(total_staked);
if total_staked > other_issuance {
let _cap_rest = Perquintill::from_rational(other_issuance, total_staked) * staking_payout;
// We don't do anything with this, but if we wanted to, we could introduce a cap on the treasury amount
// with: `rest = rest.min(cap_rest);`
}
(staking_payout, rest)
}
pub struct EraPayout;
impl pallet_staking::EraPayout for EraPayout {
fn era_payout(
total_staked: Balance,
_total_issuance: Balance,
era_duration_millis: u64,
) -> (Balance, Balance) {
// TODO: #3011 Update with proper auctioned slots tracking.
// This should be fine for the first year of parachains.
let auctioned_slots: u64 = auctions::Pallet::::auction_counter().into();
const MAX_ANNUAL_INFLATION: Perquintill = Perquintill::from_percent(10);
const MILLISECONDS_PER_YEAR: u64 = 1000 * 3600 * 24 * 36525 / 100;
era_payout(
total_staked,
Gilt::issuance().non_gilt,
MAX_ANNUAL_INFLATION,
Perquintill::from_rational(era_duration_millis, MILLISECONDS_PER_YEAR),
auctioned_slots,
)
}
}
parameter_types! {
// Six sessions in an era (6 hours).
pub const SessionsPerEra: SessionIndex = 6;
// 28 eras for unbonding (7 days).
pub const BondingDuration: pallet_staking::EraIndex = 28;
// 27 eras in which slashes can be cancelled (slightly less than 7 days).
pub const SlashDeferDuration: pallet_staking::EraIndex = 27;
pub const MaxNominatorRewardedPerValidator: u32 = 256;
pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17);
}
type SlashCancelOrigin = EnsureOneOf<
AccountId,
EnsureRoot,
pallet_collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>,
>;
impl frame_election_provider_support::onchain::Config for Runtime {
type Accuracy = runtime_common::elections::OnOnChainAccuracy;
type DataProvider = Staking;
}
impl pallet_staking::Config for Runtime {
const MAX_NOMINATIONS: u32 =
::LIMIT as u32;
type Currency = Balances;
type UnixTime = Timestamp;
type CurrencyToVote = CurrencyToVote;
type ElectionProvider = ElectionProviderMultiPhase;
type GenesisElectionProvider = runtime_common::elections::GenesisElectionOf;
type RewardRemainder = Treasury;
type Event = Event;
type Slash = Treasury;
type Reward = ();
type SessionsPerEra = SessionsPerEra;
type BondingDuration = BondingDuration;
type SlashDeferDuration = SlashDeferDuration;
// A majority of the council or root can cancel the slash.
type SlashCancelOrigin = SlashCancelOrigin;
type SessionInterface = Self;
type EraPayout = EraPayout;
type NextNewSession = Session;
type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator;
type OffendingValidatorsThreshold = OffendingValidatorsThreshold;
// Use the nominators map to iter voters, but also keep bags-list up-to-date.
type SortedListProvider = BagsList;
type BenchmarkingConfig = runtime_common::StakingBenchmarkingConfig;
type WeightInfo = weights::pallet_staking::WeightInfo;
}
parameter_types! {
pub const LaunchPeriod: BlockNumber = 7 * DAYS;
pub const VotingPeriod: BlockNumber = 7 * DAYS;
pub const FastTrackVotingPeriod: BlockNumber = 3 * HOURS;
pub const MinimumDeposit: Balance = 100 * CENTS;
pub const EnactmentPeriod: BlockNumber = 8 * DAYS;
pub const CooloffPeriod: BlockNumber = 7 * DAYS;
// One cent: $10,000 / MB
pub const PreimageByteDeposit: Balance = 10 * MILLICENTS;
pub const InstantAllowed: bool = true;
pub const MaxVotes: u32 = 100;
pub const MaxProposals: u32 = 100;
}
impl pallet_democracy::Config for Runtime {
type Proposal = Call;
type Event = Event;
type Currency = Balances;
type EnactmentPeriod = EnactmentPeriod;
type VoteLockingPeriod = EnactmentPeriod;
type LaunchPeriod = LaunchPeriod;
type VotingPeriod = VotingPeriod;
type MinimumDeposit = MinimumDeposit;
/// A straight majority of the council can decide what their next motion is.
type ExternalOrigin =
pallet_collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>;
/// A majority can have the next scheduled referendum be a straight majority-carries vote.
type ExternalMajorityOrigin =
pallet_collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>;
/// A unanimous council can have the next scheduled referendum be a straight default-carries
/// (NTB) vote.
type ExternalDefaultOrigin =
pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, CouncilCollective>;
/// 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<_2, _3, AccountId, TechnicalCollective>;
type InstantOrigin =
pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, TechnicalCollective>;
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 = EnsureOneOf<
AccountId,
EnsureRoot,
pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>,
>;
type BlacklistOrigin = EnsureRoot;
// To cancel a proposal before it has been passed, the technical committee must be unanimous or
// Root must agree.
type CancelProposalOrigin = EnsureOneOf<
AccountId,
EnsureRoot,
pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, TechnicalCollective>,
>;
// 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 PreimageByteDeposit = PreimageByteDeposit;
type OperationalPreimageOrigin = pallet_collective::EnsureMember;
type Slash = Treasury;
type Scheduler = Scheduler;
type PalletsOrigin = OriginCaller;
type MaxVotes = MaxVotes;
type WeightInfo = weights::pallet_democracy::WeightInfo;
type MaxProposals = MaxProposals;
}
parameter_types! {
pub const CouncilMotionDuration: BlockNumber = 3 * DAYS;
pub const CouncilMaxProposals: u32 = 100;
pub const CouncilMaxMembers: u32 = 100;
}
type CouncilCollective = pallet_collective::Instance1;
impl pallet_collective::Config for Runtime {
type Origin = Origin;
type Proposal = Call;
type Event = Event;
type MotionDuration = CouncilMotionDuration;
type MaxProposals = CouncilMaxProposals;
type MaxMembers = CouncilMaxMembers;
type DefaultVote = pallet_collective::PrimeDefaultVote;
type WeightInfo = weights::pallet_collective_council::WeightInfo;
}
parameter_types! {
pub const CandidacyBond: Balance = 100 * CENTS;
// 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 const TermDuration: BlockNumber = 24 * HOURS;
pub const DesiredMembers: u32 = 19;
pub const DesiredRunnersUp: u32 = 19;
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 Event = Event;
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 PalletId = PhragmenElectionPalletId;
type WeightInfo = weights::pallet_elections_phragmen::WeightInfo;
}
parameter_types! {
pub const TechnicalMotionDuration: BlockNumber = 3 * DAYS;
pub const TechnicalMaxProposals: u32 = 100;
pub const TechnicalMaxMembers: u32 = 100;
}
type TechnicalCollective = pallet_collective::Instance2;
impl pallet_collective::Config for Runtime {
type Origin = Origin;
type Proposal = Call;
type Event = Event;
type MotionDuration = TechnicalMotionDuration;
type MaxProposals = TechnicalMaxProposals;
type MaxMembers = TechnicalMaxMembers;
type DefaultVote = pallet_collective::PrimeDefaultVote;
type WeightInfo = weights::pallet_collective_technical_committee::WeightInfo;
}
impl pallet_membership::Config for Runtime {
type Event = Event;
type AddOrigin = MoreThanHalfCouncil;
type RemoveOrigin = MoreThanHalfCouncil;
type SwapOrigin = MoreThanHalfCouncil;
type ResetOrigin = MoreThanHalfCouncil;
type PrimeOrigin = MoreThanHalfCouncil;
type MembershipInitialized = TechnicalCommittee;
type MembershipChanged = TechnicalCommittee;
type MaxMembers = TechnicalMaxMembers;
type WeightInfo = weights::pallet_membership::WeightInfo;
}
parameter_types! {
pub const ProposalBond: Permill = Permill::from_percent(5);
pub const ProposalBondMinimum: Balance = 2000 * CENTS;
pub const SpendPeriod: BlockNumber = 6 * DAYS;
pub const Burn: Permill = Permill::from_perthousand(2);
pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry");
pub const TipCountdown: BlockNumber = 1 * DAYS;
pub const TipFindersFee: Percent = Percent::from_percent(20);
pub const TipReportDepositBase: Balance = 100 * CENTS;
pub const DataDepositPerByte: Balance = 1 * CENTS;
pub const BountyDepositBase: Balance = 100 * CENTS;
pub const BountyDepositPayoutDelay: BlockNumber = 4 * DAYS;
pub const BountyUpdatePeriod: BlockNumber = 90 * DAYS;
pub const MaximumReasonLength: u32 = 16384;
pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);
pub const BountyValueMinimum: Balance = 200 * CENTS;
pub const MaxApprovals: u32 = 100;
pub const MaxAuthorities: u32 = 100_000;
pub const MaxKeys: u32 = 10_000;
pub const MaxPeerInHeartbeats: u32 = 10_000;
pub const MaxPeerDataEncodingSize: u32 = 1_000;
}
type ApproveOrigin = EnsureOneOf<
AccountId,
EnsureRoot,
pallet_collective::EnsureProportionAtLeast<_3, _5, AccountId, CouncilCollective>,
>;
impl pallet_treasury::Config for Runtime {
type PalletId = TreasuryPalletId;
type Currency = Balances;
type ApproveOrigin = ApproveOrigin;
type RejectOrigin = MoreThanHalfCouncil;
type Event = Event;
type OnSlash = Treasury;
type ProposalBond = ProposalBond;
type ProposalBondMinimum = ProposalBondMinimum;
type SpendPeriod = SpendPeriod;
type Burn = Burn;
type BurnDestination = Society;
type MaxApprovals = MaxApprovals;
type WeightInfo = weights::pallet_treasury::WeightInfo;
type SpendFunds = Bounties;
}
impl pallet_bounties::Config for Runtime {
type BountyDepositBase = BountyDepositBase;
type BountyDepositPayoutDelay = BountyDepositPayoutDelay;
type BountyUpdatePeriod = BountyUpdatePeriod;
type BountyCuratorDeposit = BountyCuratorDeposit;
type BountyValueMinimum = BountyValueMinimum;
type DataDepositPerByte = DataDepositPerByte;
type Event = Event;
type MaximumReasonLength = MaximumReasonLength;
type WeightInfo = weights::pallet_bounties::WeightInfo;
}
impl pallet_tips::Config for Runtime {
type MaximumReasonLength = MaximumReasonLength;
type DataDepositPerByte = DataDepositPerByte;
type Tippers = PhragmenElection;
type TipCountdown = TipCountdown;
type TipFindersFee = TipFindersFee;
type TipReportDepositBase = TipReportDepositBase;
type Event = Event;
type WeightInfo = weights::pallet_tips::WeightInfo;
}
impl pallet_offences::Config for Runtime {
type Event = Event;
type IdentificationTuple = pallet_session::historical::IdentificationTuple;
type OnOffenceHandler = Staking;
}
impl pallet_authority_discovery::Config for Runtime {
type MaxAuthorities = MaxAuthorities;
}
parameter_types! {
pub NposSolutionPriority: TransactionPriority =
Perbill::from_percent(90) * TransactionPriority::max_value();
pub const ImOnlineUnsignedPriority: TransactionPriority = TransactionPriority::max_value();
}
impl pallet_im_online::Config for Runtime {
type AuthorityId = ImOnlineId;
type Event = Event;
type ValidatorSet = Historical;
type NextSessionRotation = Babe;
type ReportUnresponsiveness = Offences;
type UnsignedPriority = ImOnlineUnsignedPriority;
type WeightInfo = weights::pallet_im_online::WeightInfo;
type MaxKeys = MaxKeys;
type MaxPeerInHeartbeats = MaxPeerInHeartbeats;
type MaxPeerDataEncodingSize = MaxPeerDataEncodingSize;
}
impl pallet_grandpa::Config for Runtime {
type Event = Event;
type Call = Call;
type KeyOwnerProof =
>::Proof;
type KeyOwnerIdentification = >::IdentificationTuple;
type KeyOwnerProofSystem = Historical;
type HandleEquivocation = pallet_grandpa::EquivocationHandler<
Self::KeyOwnerIdentification,
Offences,
ReportLongevity,
>;
type WeightInfo = ();
type MaxAuthorities = MaxAuthorities;
}
/// Submits transaction with the node's public and signature type. Adheres to the signed extension
/// format of the chain.
impl frame_system::offchain::CreateSignedTransaction for Runtime
where
Call: From,
{
fn create_transaction>(
call: Call,
public: ::Signer,
account: AccountId,
nonce: ::Index,
) -> Option<(Call, ::SignaturePayload)> {
use sp_runtime::traits::StaticLookup;
// take the biggest period possible.
let period =
BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64;
let current_block = System::block_number()
.saturated_into::()
// The `System::block_number` is initialized with `n+1`,
// so the actual block number is `n`.
.saturating_sub(1);
let tip = 0;
let extra: SignedExtra = (
frame_system::CheckSpecVersion::::new(),
frame_system::CheckTxVersion::::new(),
frame_system::CheckGenesis::::new(),
frame_system::CheckMortality::::from(generic::Era::mortal(
period,
current_block,
)),
frame_system::CheckNonce::::from(nonce),
frame_system::CheckWeight::::new(),
pallet_transaction_payment::ChargeTransactionPayment::::from(tip),
);
let raw_payload = SignedPayload::new(call, extra)
.map_err(|e| {
log::warn!("Unable to create signed payload: {:?}", e);
})
.ok()?;
let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?;
let (call, extra, _) = raw_payload.deconstruct();
let address = ::Lookup::unlookup(account);
Some((call, (address, signature, extra)))
}
}
impl frame_system::offchain::SigningTypes for Runtime {
type Public = ::Signer;
type Signature = Signature;
}
impl frame_system::offchain::SendTransactionTypes for Runtime
where
Call: From,
{
type Extrinsic = UncheckedExtrinsic;
type OverarchingCall = Call;
}
parameter_types! {
pub Prefix: &'static [u8] = b"Pay KSMs to the Kusama account:";
}
impl claims::Config for Runtime {
type Event = Event;
type VestingSchedule = Vesting;
type Prefix = Prefix;
type MoveClaimOrigin =
pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
type WeightInfo = weights::runtime_common_claims::WeightInfo;
}
parameter_types! {
// Minimum 100 bytes/KSM deposited (1 CENT/byte)
pub const BasicDeposit: Balance = 1000 * CENTS; // 258 bytes on-chain
pub const FieldDeposit: Balance = 250 * CENTS; // 66 bytes on-chain
pub const SubAccountDeposit: Balance = 200 * CENTS; // 53 bytes on-chain
pub const MaxSubAccounts: u32 = 100;
pub const MaxAdditionalFields: u32 = 100;
pub const MaxRegistrars: u32 = 20;
}
impl pallet_identity::Config for Runtime {
type Event = Event;
type Currency = Balances;
type BasicDeposit = BasicDeposit;
type FieldDeposit = FieldDeposit;
type SubAccountDeposit = SubAccountDeposit;
type MaxSubAccounts = MaxSubAccounts;
type MaxAdditionalFields = MaxAdditionalFields;
type MaxRegistrars = MaxRegistrars;
type Slashed = Treasury;
type ForceOrigin = MoreThanHalfCouncil;
type RegistrarOrigin = MoreThanHalfCouncil;
type WeightInfo = weights::pallet_identity::WeightInfo;
}
impl pallet_utility::Config for Runtime {
type Event = Event;
type Call = Call;
type PalletsOrigin = OriginCaller;
type WeightInfo = weights::pallet_utility::WeightInfo;
}
parameter_types! {
// One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes.
pub const DepositBase: Balance = deposit(1, 88);
// Additional storage item size of 32 bytes.
pub const DepositFactor: Balance = deposit(0, 32);
pub const MaxSignatories: u16 = 100;
}
impl pallet_multisig::Config for Runtime {
type Event = Event;
type Call = Call;
type Currency = Balances;
type DepositBase = DepositBase;
type DepositFactor = DepositFactor;
type MaxSignatories = MaxSignatories;
type WeightInfo = weights::pallet_multisig::WeightInfo;
}
parameter_types! {
pub const ConfigDepositBase: Balance = 500 * CENTS;
pub const FriendDepositFactor: Balance = 50 * CENTS;
pub const MaxFriends: u16 = 9;
pub const RecoveryDeposit: Balance = 500 * CENTS;
}
impl pallet_recovery::Config for Runtime {
type Event = Event;
type Call = Call;
type Currency = Balances;
type ConfigDepositBase = ConfigDepositBase;
type FriendDepositFactor = FriendDepositFactor;
type MaxFriends = MaxFriends;
type RecoveryDeposit = RecoveryDeposit;
}
parameter_types! {
pub const CandidateDeposit: Balance = 1000 * CENTS;
pub const WrongSideDeduction: Balance = 200 * CENTS;
pub const MaxStrikes: u32 = 10;
pub const RotationPeriod: BlockNumber = 7 * DAYS;
pub const PeriodSpend: Balance = 50000 * CENTS;
pub const MaxLockDuration: BlockNumber = 36 * 30 * DAYS;
pub const ChallengePeriod: BlockNumber = 7 * DAYS;
pub const MaxCandidateIntake: u32 = 1;
pub const SocietyPalletId: PalletId = PalletId(*b"py/socie");
}
impl pallet_society::Config for Runtime {
type Event = Event;
type Currency = Balances;
type Randomness = pallet_babe::RandomnessFromOneEpochAgo;
type CandidateDeposit = CandidateDeposit;
type WrongSideDeduction = WrongSideDeduction;
type MaxStrikes = MaxStrikes;
type PeriodSpend = PeriodSpend;
type MembershipChanged = ();
type RotationPeriod = RotationPeriod;
type MaxLockDuration = MaxLockDuration;
type FounderSetOrigin =
pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>;
type SuspensionJudgementOrigin = pallet_society::EnsureFounder;
type ChallengePeriod = ChallengePeriod;
type MaxCandidateIntake = MaxCandidateIntake;
type PalletId = SocietyPalletId;
}
parameter_types! {
pub const MinVestedTransfer: Balance = 100 * CENTS;
}
impl pallet_vesting::Config for Runtime {
type Event = Event;
type Currency = Balances;
type BlockNumberToBalance = ConvertInto;
type MinVestedTransfer = MinVestedTransfer;
type WeightInfo = weights::pallet_vesting::WeightInfo;
const MAX_VESTING_SCHEDULES: u32 = 28;
}
parameter_types! {
// One storage item; key size 32, value size 8; .
pub const ProxyDepositBase: Balance = deposit(1, 8);
// Additional storage item size of 33 bytes.
pub const ProxyDepositFactor: Balance = deposit(0, 33);
pub const MaxProxies: u16 = 32;
pub const AnnouncementDepositBase: Balance = deposit(1, 8);
pub const AnnouncementDepositFactor: Balance = deposit(0, 66);
pub const MaxPending: u16 = 32;
}
/// The type used to represent the kinds of proxying allowed.
#[derive(
Copy,
Clone,
Eq,
PartialEq,
Ord,
PartialOrd,
Encode,
Decode,
RuntimeDebug,
MaxEncodedLen,
scale_info::TypeInfo,
)]
pub enum ProxyType {
Any,
NonTransfer,
Governance,
Staking,
IdentityJudgement,
CancelProxy,
Auction,
}
impl Default for ProxyType {
fn default() -> Self {
Self::Any
}
}
impl InstanceFilter for ProxyType {
fn filter(&self, c: &Call) -> bool {
match self {
ProxyType::Any => true,
ProxyType::NonTransfer => matches!(
c,
Call::System(..) |
Call::Babe(..) |
Call::Timestamp(..) |
Call::Indices(pallet_indices::Call::claim {..}) |
Call::Indices(pallet_indices::Call::free {..}) |
Call::Indices(pallet_indices::Call::freeze {..}) |
// Specifically omitting Indices `transfer`, `force_transfer`
// Specifically omitting the entire Balances pallet
Call::Authorship(..) |
Call::Staking(..) |
Call::Session(..) |
Call::Grandpa(..) |
Call::ImOnline(..) |
Call::Democracy(..) |
Call::Council(..) |
Call::TechnicalCommittee(..) |
Call::PhragmenElection(..) |
Call::TechnicalMembership(..) |
Call::Treasury(..) |
Call::Bounties(..) |
Call::Tips(..) |
Call::Claims(..) |
Call::Utility(..) |
Call::Identity(..) |
Call::Society(..) |
Call::Recovery(pallet_recovery::Call::as_recovered {..}) |
Call::Recovery(pallet_recovery::Call::vouch_recovery {..}) |
Call::Recovery(pallet_recovery::Call::claim_recovery {..}) |
Call::Recovery(pallet_recovery::Call::close_recovery {..}) |
Call::Recovery(pallet_recovery::Call::remove_recovery {..}) |
Call::Recovery(pallet_recovery::Call::cancel_recovered {..}) |
// Specifically omitting Recovery `create_recovery`, `initiate_recovery`
Call::Vesting(pallet_vesting::Call::vest {..}) |
Call::Vesting(pallet_vesting::Call::vest_other {..}) |
// Specifically omitting Vesting `vested_transfer`, and `force_vested_transfer`
Call::Scheduler(..) |
Call::Proxy(..) |
Call::Multisig(..) |
Call::Gilt(..) |
Call::Registrar(paras_registrar::Call::register {..}) |
Call::Registrar(paras_registrar::Call::deregister {..}) |
// Specifically omitting Registrar `swap`
Call::Registrar(paras_registrar::Call::reserve {..}) |
Call::Crowdloan(..) |
Call::Slots(..) |
Call::Auctions(..) | // Specifically omitting the entire XCM Pallet
Call::BagsList(..)
),
ProxyType::Governance => matches!(
c,
Call::Democracy(..) |
Call::Council(..) | Call::TechnicalCommittee(..) |
Call::PhragmenElection(..) |
Call::Treasury(..) | Call::Bounties(..) |
Call::Tips(..) | Call::Utility(..)
),
ProxyType::Staking => {
matches!(c, Call::Staking(..) | Call::Session(..) | Call::Utility(..))
},
ProxyType::IdentityJudgement => matches!(
c,
Call::Identity(pallet_identity::Call::provide_judgement { .. }) | Call::Utility(..)
),
ProxyType::CancelProxy => {
matches!(c, Call::Proxy(pallet_proxy::Call::reject_announcement { .. }))
},
ProxyType::Auction => matches!(
c,
Call::Auctions(..) | Call::Crowdloan(..) | Call::Registrar(..) | Call::Slots(..)
),
}
}
fn is_superset(&self, o: &Self) -> bool {
match (self, o) {
(x, y) if x == y => true,
(ProxyType::Any, _) => true,
(_, ProxyType::Any) => false,
(ProxyType::NonTransfer, _) => true,
_ => false,
}
}
}
impl pallet_proxy::Config for Runtime {
type Event = Event;
type Call = Call;
type Currency = Balances;
type ProxyType = ProxyType;
type ProxyDepositBase = ProxyDepositBase;
type ProxyDepositFactor = ProxyDepositFactor;
type MaxProxies = MaxProxies;
type WeightInfo = weights::pallet_proxy::WeightInfo;
type MaxPending = MaxPending;
type CallHasher = BlakeTwo256;
type AnnouncementDepositBase = AnnouncementDepositBase;
type AnnouncementDepositFactor = AnnouncementDepositFactor;
}
impl parachains_origin::Config for Runtime {}
impl parachains_configuration::Config for Runtime {
type WeightInfo = weights::runtime_parachains_configuration::WeightInfo;
}
impl parachains_shared::Config for Runtime {}
impl parachains_session_info::Config for Runtime {}
impl parachains_inclusion::Config for Runtime {
type Event = Event;
type DisputesHandler = ParasDisputes;
type RewardValidators = parachains_reward_points::RewardValidatorsWithEraPoints;
}
impl parachains_paras::Config for Runtime {
type Event = Event;
type WeightInfo = weights::runtime_parachains_paras::WeightInfo;
}
parameter_types! {
pub const FirstMessageFactorPercent: u64 = 100;
}
impl parachains_ump::Config for Runtime {
type Event = Event;
type UmpSink = crate::parachains_ump::XcmSink, Runtime>;
type FirstMessageFactorPercent = FirstMessageFactorPercent;
type ExecuteOverweightOrigin = EnsureRoot;
}
impl parachains_dmp::Config for Runtime {}
impl parachains_hrmp::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Currency = Balances;
}
impl parachains_paras_inherent::Config for Runtime {
type WeightInfo = weights::runtime_parachains_paras_inherent::WeightInfo;
}
impl parachains_scheduler::Config for Runtime {}
impl parachains_initializer::Config for Runtime {
type Randomness = pallet_babe::RandomnessFromOneEpochAgo;
type ForceOrigin = EnsureRoot;
type WeightInfo = weights::runtime_parachains_initializer::WeightInfo;
}
impl parachains_disputes::Config for Runtime {
type Event = Event;
type RewardValidators = ();
type PunishValidators = ();
type WeightInfo = weights::runtime_parachains_disputes::WeightInfo;
}
parameter_types! {
pub const ParaDeposit: Balance = 40 * UNITS;
}
impl paras_registrar::Config for Runtime {
type Event = Event;
type Origin = Origin;
type Currency = Balances;
type OnSwap = (Crowdloan, Slots);
type ParaDeposit = ParaDeposit;
type DataDepositPerByte = DataDepositPerByte;
type WeightInfo = weights::runtime_common_paras_registrar::WeightInfo;
}
parameter_types! {
// 6 weeks
pub const LeasePeriod: BlockNumber = 6 * WEEKS;
}
impl slots::Config for Runtime {
type Event = Event;
type Currency = Balances;
type Registrar = Registrar;
type LeasePeriod = LeasePeriod;
type LeaseOffset = ();
type WeightInfo = weights::runtime_common_slots::WeightInfo;
}
parameter_types! {
pub const CrowdloanId: PalletId = PalletId(*b"py/cfund");
pub const SubmissionDeposit: Balance = 3 * GRAND; // ~ 10 KSM
pub const MinContribution: Balance = 3_000 * CENTS; // ~ .1 KSM
pub const RemoveKeysLimit: u32 = 1000;
// Allow 32 bytes for an additional memo to a crowdloan.
pub const MaxMemoLength: u8 = 32;
}
impl crowdloan::Config for Runtime {
type Event = Event;
type PalletId = CrowdloanId;
type SubmissionDeposit = SubmissionDeposit;
type MinContribution = MinContribution;
type RemoveKeysLimit = RemoveKeysLimit;
type Registrar = Registrar;
type Auctioneer = Auctions;
type MaxMemoLength = MaxMemoLength;
type WeightInfo = weights::runtime_common_crowdloan::WeightInfo;
}
parameter_types! {
// The average auction is 7 days long, so this will be 70% for ending period.
// 5 Days = 72000 Blocks @ 6 sec per block
pub const EndingPeriod: BlockNumber = 5 * DAYS;
// ~ 1000 samples per day -> ~ 20 blocks per sample -> 2 minute samples
pub const SampleLength: BlockNumber = 2 * MINUTES;
}
type AuctionInitiate = EnsureOneOf<
AccountId,
EnsureRoot,
pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>,
>;
impl auctions::Config for Runtime {
type Event = Event;
type Leaser = Slots;
type Registrar = Registrar;
type EndingPeriod = EndingPeriod;
type SampleLength = SampleLength;
type Randomness = pallet_babe::RandomnessFromOneEpochAgo;
type InitiateOrigin = AuctionInitiate;
type WeightInfo = weights::runtime_common_auctions::WeightInfo;
}
parameter_types! {
/// The location of the KSM token, from the context of this chain. Since this token is native to this
/// chain, we make it synonymous with it and thus it is the `Here` location, which means "equivalent to
/// the context".
pub const KsmLocation: MultiLocation = Here.into();
/// The Kusama network ID. This is named.
pub const KusamaNetwork: NetworkId = NetworkId::Kusama;
/// Our XCM location ancestry - i.e. what, if anything, `Parent` means evaluated in our context. Since
/// Kusama is a top-level relay-chain, there is no ancestry.
pub const Ancestry: MultiLocation = Here.into();
/// The check account, which holds any native assets that have been teleported out and not back in (yet).
pub CheckAccount: AccountId = XcmPallet::check_account();
}
/// The canonical means of converting a `MultiLocation` into an `AccountId`, used when we want to determine
/// the sovereign account controlled by a location.
pub type SovereignAccountOf = (
// We can convert a child parachain using the standard `AccountId` conversion.
ChildParachainConvertsVia,
// We can directly alias an `AccountId32` into a local account.
AccountId32Aliases,
);
/// Our asset transactor. This is what allows us to interest with the runtime facilities from the point of
/// view of XCM-only concepts like `MultiLocation` and `MultiAsset`.
///
/// Ours is only aware of the Balances pallet, which is mapped to `KsmLocation`.
pub type LocalAssetTransactor = XcmCurrencyAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
IsConcrete,
// We can convert the MultiLocations with our converter above:
SovereignAccountOf,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We track our teleports in/out to keep total issuance correct.
CheckAccount,
>;
/// The means that we convert an the XCM message origin location into a local dispatch origin.
type LocalOriginConverter = (
// A `Signed` origin of the sovereign account that the original location controls.
SovereignSignedViaLocation,
// A child parachain, natively expressed, has the `Parachain` origin.
ChildParachainAsNative,
// The AccountId32 location type can be expressed natively as a `Signed` origin.
SignedAccountId32AsNative,
// A system child parachain, expressed as a Superuser, converts to the `Root` origin.
ChildSystemParachainAsSuperuser,
);
parameter_types! {
/// The amount of weight an XCM operation takes. This is a safe overestimate.
pub const BaseXcmWeight: Weight = 1_000_000_000;
/// Maximum number of instructions in a single XCM fragment. A sanity check against weight
/// calculations getting too crazy.
pub const MaxInstructions: u32 = 100;
}
/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our
/// individual routers.
pub type XcmRouter = (
// Only one router so far - use DMP to communicate with child parachains.
xcm_sender::ChildParachainRouter,
);
parameter_types! {
pub const Kusama: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(KsmLocation::get()) });
pub const KusamaForStatemine: (MultiAssetFilter, MultiLocation) = (Kusama::get(), Parachain(1000).into());
}
pub type TrustedTeleporters = (xcm_builder::Case,);
match_type! {
pub type OnlyParachains: impl Contains = {
MultiLocation { parents: 0, interior: X1(Parachain(_)) }
};
}
/// The barriers one of which must be passed for an XCM message to be executed.
pub type Barrier = (
// Weight that is paid for may be consumed.
TakeWeightCredit,
// If the message is one that immediately attemps to pay for execution, then allow it.
AllowTopLevelPaidExecutionFrom,
// Messages coming from system parachains need not pay for execution.
AllowUnpaidExecutionFrom>,
// Expected responses are OK.
AllowKnownQueryResponses,
// Subscriptions for version tracking are OK.
AllowSubscriptionsFrom,
);
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type Call = Call;
type XcmSender = XcmRouter;
type AssetTransactor = LocalAssetTransactor;
type OriginConverter = LocalOriginConverter;
type IsReserve = ();
type IsTeleporter = TrustedTeleporters;
type LocationInverter = LocationInverter;
type Barrier = Barrier;
type Weigher = FixedWeightBounds;
// The weight trader piggybacks on the existing transaction-fee conversion logic.
type Trader = UsingComponents>;
type ResponseHandler = XcmPallet;
type AssetTrap = XcmPallet;
type AssetClaims = XcmPallet;
type SubscriptionService = XcmPallet;
}
parameter_types! {
pub const CouncilBodyId: BodyId = BodyId::Executive;
}
/// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior location
/// of this chain.
pub type LocalOriginToLocation = (
// We allow an origin from the Collective pallet to be used in XCM as a corresponding Plurality of the
// `Unit` body.
BackingToPlurality<
Origin,
pallet_collective::Origin,
CouncilBodyId,
>,
// And a usual Signed origin to be used in XCM as a corresponding AccountId32
SignedToAccountId32,
);
impl pallet_xcm::Config for Runtime {
type Event = Event;
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin;
type XcmRouter = XcmRouter;
// Anyone can execute XCM messages locally...
type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin;
// ...but they must match our filter, which rejects all.
type XcmExecuteFilter = Nothing;
type XcmExecutor = XcmExecutor;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Everything;
type Weigher = FixedWeightBounds;
type LocationInverter = LocationInverter;
type Origin = Origin;
type Call = Call;
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
}
parameter_types! {
pub IgnoredIssuance: Balance = Treasury::pot();
pub const QueueCount: u32 = 300;
pub const MaxQueueLen: u32 = 1000;
pub const FifoQueueLen: u32 = 250;
pub const GiltPeriod: BlockNumber = 30 * DAYS;
pub const MinFreeze: Balance = 10_000 * CENTS;
pub const IntakePeriod: BlockNumber = 5 * MINUTES;
pub const MaxIntakeBids: u32 = 100;
}
impl pallet_gilt::Config for Runtime {
type Event = Event;
type Currency = Balances;
type CurrencyBalance = Balance;
type AdminOrigin = MoreThanHalfCouncil;
type Deficit = (); // Mint
type Surplus = (); // Burn
type IgnoredIssuance = IgnoredIssuance;
type QueueCount = QueueCount;
type MaxQueueLen = MaxQueueLen;
type FifoQueueLen = FifoQueueLen;
type Period = GiltPeriod;
type MinFreeze = MinFreeze;
type IntakePeriod = IntakePeriod;
type MaxIntakeBids = MaxIntakeBids;
type WeightInfo = weights::pallet_gilt::WeightInfo;
}
construct_runtime! {
pub enum Runtime where
Block = Block,
NodeBlock = primitives::v1::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
// Basic stuff; balances is uncallable initially.
System: frame_system::{Pallet, Call, Storage, Config, Event} = 0,
// Must be before session.
Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned} = 1,
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 2,
Indices: pallet_indices::{Pallet, Call, Storage, Config, Event} = 3,
Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 4,
TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,
// Consensus support.
Authorship: pallet_authorship::{Pallet, Call, Storage} = 5,
Staking: pallet_staking::{Pallet, Call, Storage, Config, Event} = 6,
Offences: pallet_offences::{Pallet, Storage, Event} = 7,
Historical: session_historical::{Pallet} = 34,
Session: pallet_session::{Pallet, Call, Storage, Event, Config} = 8,
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event, ValidateUnsigned} = 10,
ImOnline: pallet_im_online::{Pallet, Call, Storage, Event, ValidateUnsigned, Config} = 11,
AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config} = 12,
// Governance stuff; uncallable initially.
Democracy: pallet_democracy::{Pallet, Call, Storage, Config, Event} = 13,
Council: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config} = 14,
TechnicalCommittee: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config} = 15,
PhragmenElection: pallet_elections_phragmen::{Pallet, Call, Storage, Event, Config} = 16,
TechnicalMembership: pallet_membership::::{Pallet, Call, Storage, Event, Config} = 17,
Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event} = 18,
// Claims. Usable initially.
Claims: claims::{Pallet, Call, Storage, Event, Config, ValidateUnsigned} = 19,
// Utility module.
Utility: pallet_utility::{Pallet, Call, Event} = 24,
// Less simple identity module.
Identity: pallet_identity::{Pallet, Call, Storage, Event} = 25,
// Society module.
Society: pallet_society::{Pallet, Call, Storage, Event} = 26,
// Social recovery module.
Recovery: pallet_recovery::{Pallet, Call, Storage, Event} = 27,
// Vesting. Usable initially, but removed once all vesting is finished.
Vesting: pallet_vesting::{Pallet, Call, Storage, Event, Config} = 28,
// System scheduler.
Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event} = 29,
// Proxy module. Late addition.
Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 30,
// Multisig module. Late addition.
Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 31,
// Bounties module.
Bounties: pallet_bounties::{Pallet, Call, Storage, Event} = 35,
// Tips module.
Tips: pallet_tips::{Pallet, Call, Storage, Event} = 36,
// Election pallet. Only works with staking, but placed here to maintain indices.
ElectionProviderMultiPhase: pallet_election_provider_multi_phase::{Pallet, Call, Storage, Event, ValidateUnsigned} = 37,
// Gilts pallet.
Gilt: pallet_gilt::{Pallet, Call, Storage, Event, Config} = 38,
// Provides a semi-sorted list of nominators for staking.
BagsList: pallet_bags_list::{Pallet, Call, Storage, Event} = 39,
// Parachains pallets. Start indices at 50 to leave room.
ParachainsOrigin: parachains_origin::{Pallet, Origin} = 50,
Configuration: parachains_configuration::{Pallet, Call, Storage, Config} = 51,
ParasShared: parachains_shared::{Pallet, Call, Storage} = 52,
ParaInclusion: parachains_inclusion::{Pallet, Call, Storage, Event} = 53,
ParaInherent: parachains_paras_inherent::{Pallet, Call, Storage, Inherent} = 54,
ParaScheduler: parachains_scheduler::{Pallet, Storage} = 55,
Paras: parachains_paras::{Pallet, Call, Storage, Event, Config} = 56,
Initializer: parachains_initializer::{Pallet, Call, Storage} = 57,
Dmp: parachains_dmp::{Pallet, Call, Storage} = 58,
Ump: parachains_ump::{Pallet, Call, Storage, Event} = 59,
Hrmp: parachains_hrmp::{Pallet, Call, Storage, Event, Config} = 60,
ParaSessionInfo: parachains_session_info::{Pallet, Storage} = 61,
ParasDisputes: parachains_disputes::{Pallet, Call, Storage, Event} = 62,
// Parachain Onboarding Pallets. Start indices at 70 to leave room.
Registrar: paras_registrar::{Pallet, Call, Storage, Event} = 70,
Slots: slots::{Pallet, Call, Storage, Event} = 71,
Auctions: auctions::{Pallet, Call, Storage, Event} = 72,
Crowdloan: crowdloan::{Pallet, Call, Storage, Event} = 73,
// Pallet for sending XCM.
XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99,
}
}
/// The address format for describing accounts.
pub type Address = sp_runtime::MultiAddress;
/// Block header type as expected by this runtime.
pub type Header = generic::Header;
/// Block type as expected by this runtime.
pub type Block = generic::Block;
/// A Block signed with a Justification
pub type SignedBlock = generic::SignedBlock;
/// `BlockId` type as expected by this runtime.
pub type BlockId = generic::BlockId;
/// The `SignedExtension` to the basic transaction logic.
pub type SignedExtra = (
frame_system::CheckSpecVersion,
frame_system::CheckTxVersion,
frame_system::CheckGenesis,
frame_system::CheckMortality,
frame_system::CheckNonce,
frame_system::CheckWeight,
pallet_transaction_payment::ChargeTransactionPayment,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic;
/// Executive: handles dispatch to the various modules.
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext,
Runtime,
AllPallets,
(SessionHistoricalPalletPrefixMigration,),
>;
/// The payload being signed in the transactions.
pub type SignedPayload = generic::SignedPayload;
/// Migrate session-historical from `Session` to the new pallet prefix `Historical`
pub struct SessionHistoricalPalletPrefixMigration;
impl OnRuntimeUpgrade for SessionHistoricalPalletPrefixMigration {
fn on_runtime_upgrade() -> frame_support::weights::Weight {
pallet_session::migrations::v1::migrate::()
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<(), &'static str> {
pallet_session::migrations::v1::pre_migrate::();
Ok(())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade() -> Result<(), &'static str> {
pallet_session::migrations::v1::post_migrate::();
Ok(())
}
}
#[cfg(not(feature = "disable-runtime-api"))]
sp_api::impl_runtime_apis! {
impl sp_api::Core for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn execute_block(block: Block) {
Executive::execute_block(block);
}
fn initialize_block(header: &::Header) {
Executive::initialize_block(header)
}
}
impl sp_api::Metadata for Runtime {
fn metadata() -> OpaqueMetadata {
OpaqueMetadata::new(Runtime::metadata().into())
}
}
impl block_builder_api::BlockBuilder for Runtime {
fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult {
Executive::apply_extrinsic(extrinsic)
}
fn finalize_block() -> ::Header {
Executive::finalize_block()
}
fn inherent_extrinsics(data: inherents::InherentData) -> Vec<::Extrinsic> {
data.create_extrinsics()
}
fn check_inherents(
block: Block,
data: inherents::InherentData,
) -> inherents::CheckInherentsResult {
data.check_extrinsics(&block)
}
}
impl tx_pool_api::runtime_api::TaggedTransactionQueue for Runtime {
fn validate_transaction(
source: TransactionSource,
tx: ::Extrinsic,
block_hash: ::Hash,
) -> TransactionValidity {
Executive::validate_transaction(source, tx, block_hash)
}
}
impl offchain_primitives::OffchainWorkerApi for Runtime {
fn offchain_worker(header: &::Header) {
Executive::offchain_worker(header)
}
}
impl primitives::v1::ParachainHost for Runtime {
fn validators() -> Vec {
parachains_runtime_api_impl::validators::()
}
fn validator_groups() -> (Vec>, GroupRotationInfo) {
parachains_runtime_api_impl::validator_groups::()
}
fn availability_cores() -> Vec> {
parachains_runtime_api_impl::availability_cores::()
}
fn persisted_validation_data(para_id: ParaId, assumption: OccupiedCoreAssumption)
-> Option> {
parachains_runtime_api_impl::persisted_validation_data::(para_id, assumption)
}
fn assumed_validation_data(
para_id: ParaId,
expected_persisted_validation_data_hash: Hash,
) -> Option<(PersistedValidationData, ValidationCodeHash)> {
parachains_runtime_api_impl::assumed_validation_data::(
para_id,
expected_persisted_validation_data_hash,
)
}
fn check_validation_outputs(
para_id: ParaId,
outputs: primitives::v1::CandidateCommitments,
) -> bool {
parachains_runtime_api_impl::check_validation_outputs::(para_id, outputs)
}
fn session_index_for_child() -> SessionIndex {
parachains_runtime_api_impl::session_index_for_child::()
}
fn validation_code(para_id: ParaId, assumption: OccupiedCoreAssumption)
-> Option {
parachains_runtime_api_impl::validation_code::(para_id, assumption)
}
fn candidate_pending_availability(para_id: ParaId) -> Option> {
parachains_runtime_api_impl::candidate_pending_availability::(para_id)
}
fn candidate_events() -> Vec> {
parachains_runtime_api_impl::candidate_events::(|ev| {
match ev {
Event::ParaInclusion(ev) => {
Some(ev)
}
_ => None,
}
})
}
fn session_info(index: SessionIndex) -> Option {
parachains_runtime_api_impl::session_info::(index)
}
fn dmq_contents(recipient: ParaId) -> Vec> {
parachains_runtime_api_impl::dmq_contents::(recipient)
}
fn inbound_hrmp_channels_contents(
recipient: ParaId
) -> BTreeMap>> {
parachains_runtime_api_impl::inbound_hrmp_channels_contents::(recipient)
}
fn validation_code_by_hash(hash: ValidationCodeHash) -> Option {
parachains_runtime_api_impl::validation_code_by_hash::(hash)
}
fn on_chain_votes() -> Option> {
parachains_runtime_api_impl::on_chain_votes::()
}
}
impl beefy_primitives::BeefyApi for Runtime {
fn validator_set() -> beefy_primitives::ValidatorSet {
// dummy implementation due to lack of BEEFY pallet.
beefy_primitives::ValidatorSet { validators: Vec::new(), id: 0 }
}
}
impl mmr::MmrApi for Runtime {
fn generate_proof(_leaf_index: u64)
-> Result<(mmr::EncodableOpaqueLeaf, mmr::Proof), mmr::Error>
{
// dummy implementation due to lack of MMR pallet.
Err(mmr::Error::GenerateProof)
}
fn verify_proof(_leaf: mmr::EncodableOpaqueLeaf, _proof: mmr::Proof)
-> Result<(), mmr::Error>
{
// dummy implementation due to lack of MMR pallet.
Err(mmr::Error::Verify)
}
fn verify_proof_stateless(
_root: Hash,
_leaf: mmr::EncodableOpaqueLeaf,
_proof: mmr::Proof
) -> Result<(), mmr::Error> {
// dummy implementation due to lack of MMR pallet.
Err(mmr::Error::Verify)
}
}
impl fg_primitives::GrandpaApi for Runtime {
fn grandpa_authorities() -> Vec<(GrandpaId, u64)> {
Grandpa::grandpa_authorities()
}
fn current_set_id() -> fg_primitives::SetId {
Grandpa::current_set_id()
}
fn submit_report_equivocation_unsigned_extrinsic(
equivocation_proof: fg_primitives::EquivocationProof<
::Hash,
sp_runtime::traits::NumberFor,
>,
key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,
) -> Option<()> {
let key_owner_proof = key_owner_proof.decode()?;
Grandpa::submit_unsigned_equivocation_report(
equivocation_proof,
key_owner_proof,
)
}
fn generate_key_ownership_proof(
_set_id: fg_primitives::SetId,
authority_id: fg_primitives::AuthorityId,
) -> Option {
use parity_scale_codec::Encode;
Historical::prove((fg_primitives::KEY_TYPE, authority_id))
.map(|p| p.encode())
.map(fg_primitives::OpaqueKeyOwnershipProof::new)
}
}
impl babe_primitives::BabeApi for Runtime {
fn configuration() -> babe_primitives::BabeGenesisConfiguration {
// The choice of `c` parameter (where `1 - c` represents the
// probability of a slot being empty), is done in accordance to the
// slot duration and expected target block time, for safely
// resisting network delays of maximum two seconds.
//
babe_primitives::BabeGenesisConfiguration {
slot_duration: Babe::slot_duration(),
epoch_length: EpochDuration::get(),
c: BABE_GENESIS_EPOCH_CONFIG.c,
genesis_authorities: Babe::authorities().to_vec(),
randomness: Babe::randomness(),
allowed_slots: BABE_GENESIS_EPOCH_CONFIG.allowed_slots,
}
}
fn current_epoch_start() -> babe_primitives::Slot {
Babe::current_epoch_start()
}
fn current_epoch() -> babe_primitives::Epoch {
Babe::current_epoch()
}
fn next_epoch() -> babe_primitives::Epoch {
Babe::next_epoch()
}
fn generate_key_ownership_proof(
_slot: babe_primitives::Slot,
authority_id: babe_primitives::AuthorityId,
) -> Option {
use parity_scale_codec::Encode;
Historical::prove((babe_primitives::KEY_TYPE, authority_id))
.map(|p| p.encode())
.map(babe_primitives::OpaqueKeyOwnershipProof::new)
}
fn submit_report_equivocation_unsigned_extrinsic(
equivocation_proof: babe_primitives::EquivocationProof<::Header>,
key_owner_proof: babe_primitives::OpaqueKeyOwnershipProof,
) -> Option<()> {
let key_owner_proof = key_owner_proof.decode()?;
Babe::submit_unsigned_equivocation_report(
equivocation_proof,
key_owner_proof,
)
}
}
impl authority_discovery_primitives::AuthorityDiscoveryApi for Runtime {
fn authorities() -> Vec {
parachains_runtime_api_impl::relevant_authority_ids::()
}
}
impl sp_session::SessionKeys