#![cfg_attr(not(feature = "std"), no_std)] #![recursion_limit = "512"] #![allow(clippy::too_many_arguments)] #![allow(clippy::zero_prefixed_literal)] // Edit this file to define custom logic or remove it if it is not needed. // Learn more about FRAME and the core library of Substrate FRAME pallets: // use frame_system::{self as system, ensure_signed}; pub use pallet::*; use codec::{Decode, Encode}; use frame_support::{ dispatch::{self, DispatchResult, DispatchResultWithPostInfo}, ensure, pallet_macros::import_section, pallet_prelude::*, traits::tokens::fungible, weights::WeightMeter, }; use scale_info::TypeInfo; use sp_core::Get; use sp_runtime::{DispatchError, PerU16}; use sp_std::marker::PhantomData; use subtensor_runtime_common::{AlphaBalance, NetUid, TaoBalance, Token, TokenReserve}; // ============================ // ==== Benchmark Imports ===== // ============================ mod benchmarks; // ========================= // ==== Pallet Imports ===== // ========================= pub mod coinbase; pub mod epoch; pub mod extensions; pub mod guards; pub mod macros; pub mod migrations; pub mod rpc_info; pub mod staking; pub mod subnets; pub mod swap; pub mod utils; pub mod weights; use crate::utils::rate_limiting::{Hyperparameter, TransactionType}; use macros::{config, dispatches, errors, events, genesis, hooks}; pub use extensions::*; pub use guards::*; #[cfg(test)] pub(crate) mod tests; // apparently this is stabilized since rust 1.36 extern crate alloc; pub type OriginFor = ::RuntimeOrigin; pub const MAX_CRV3_COMMIT_SIZE_BYTES: u32 = 5000; pub const ALPHA_MAP_BATCH_SIZE: usize = 30; pub const MAX_NUM_ROOT_CLAIMS: u64 = 50; pub const MAX_SUBNET_CLAIMS: usize = 5; pub const MAX_ROOT_CLAIM_THRESHOLD: u64 = 10_000_000; pub struct SubtensorDustRemoval(PhantomData); impl frame_support::traits::OnUnbalanced> for SubtensorDustRemoval where T: Config + pallet_balances::Config, ::Balance: Into + Copy, { fn on_nonzero_unbalanced(dust: pallet_balances::CreditOf) { let amount: TaoBalance = frame_support::traits::Imbalance::peek(&dust).into(); TotalIssuance::::mutate(|total| { *total = total.saturating_sub(amount); }); } } /// Maximum number of UIDs (per subnet) that may be associated with a single EVM address. /// /// This bounds the size of the `AssociatedUidsByEvmAddress` reverse-index value, keeping /// `uid_lookup` reads and association writes cheap and their PoV footprint small. Only the /// holder of an EVM key's private key can grow its bucket (each association requires a /// signature from that key), so this only limits how many of one's own UIDs may point at a /// single EVM address. pub const MAX_ASSOCIATED_UIDS_PER_EVM_ADDRESS: u32 = 32; /// Account flag bit that opts into receiving locked alpha transfers. pub const ACCOUNT_FLAGS_ACCEPT_LOCKED_ALPHA: u128 = 1u128 << 0; #[allow(deprecated)] #[deny(missing_docs)] #[import_section(errors::errors)] #[import_section(events::events)] #[import_section(dispatches::dispatches)] #[import_section(genesis::genesis)] #[import_section(hooks::hooks)] #[import_section(config::config)] #[frame_support::pallet] #[allow(clippy::expect_used)] pub mod pallet { use crate::migrations; use crate::staking::lock::LockState; use crate::subnets::dissolution::DissolveCleanupStatus; use crate::subnets::leasing::{LeaseId, SubnetLeaseOf}; use crate::subnets::subnet::NetworkRegistrationInfo; use crate::weights::WeightInfo; use crate::{MAX_ASSOCIATED_UIDS_PER_EVM_ADDRESS, RateLimitKey}; use frame_support::Twox64Concat; use frame_support::{ BoundedVec, dispatch::GetDispatchInfo, pallet_prelude::{DispatchResult, StorageMap, ValueQuery, *}, traits::{ OriginTrait, QueryPreimage, StorePreimage, UnfilteredDispatchable, tokens::fungible, }, weights::Weight, }; use frame_system::pallet_prelude::*; use pallet_drand::types::RoundNumber; use runtime_common::prod_or_fast; use share_pool::SafeFloat; use sp_core::{ConstU32, H160, H256}; use sp_runtime::PerU16; use sp_runtime::traits::{Dispatchable, TrailingZeroInput}; use sp_std::collections::btree_map::BTreeMap; use sp_std::collections::btree_set::BTreeSet; use sp_std::collections::vec_deque::VecDeque; use sp_std::vec; use sp_std::vec::Vec; use substrate_fixed::types::{I64F64, I96F32, U64F64, U96F32}; use subtensor_macros::freeze_struct; use subtensor_runtime_common::{ AlphaBalance, MechId, NetUid, NetUidStorageIndex, TaoBalance, Token, }; /// Origin for the pallet pub type PalletsOriginOf = <::RuntimeOrigin as OriginTrait>::PalletsOrigin; /// Call type for the pallet pub type CallOf = ::RuntimeCall; /// Tracks version for migrations. Should be monotonic with respect to the /// order of migrations. (i.e. always increasing) const STORAGE_VERSION: StorageVersion = StorageVersion::new(7); /// Minimum balance required to perform a coldkey swap pub const MIN_BALANCE_TO_PERFORM_COLDKEY_SWAP: TaoBalance = TaoBalance::new(100_000_000); // 0.1 TAO in RAO /// Minimum commit reveal periods pub const MIN_COMMIT_REVEAL_PEROIDS: u64 = 1; /// Maximum commit reveal periods pub const MAX_COMMIT_REVEAL_PEROIDS: u64 = 100; #[pallet::pallet] #[pallet::without_storage_info] #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(_); /// Alias for the account ID. pub type AccountIdOf = ::AccountId; /// Struct for Axon. pub type AxonInfoOf = AxonInfo; /// local one pub type LocalCallOf = ::RuntimeCall; /// Data structure for Axon information. #[crate::freeze_struct("3545cfb0cac4c1f5")] #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] pub struct AxonInfo { /// Axon serving block. pub block: u64, /// Axon version pub version: u32, /// Axon u128 encoded ip address of type v6 or v4. pub ip: u128, /// Axon u16 encoded port. pub port: u16, /// Axon ip type, 4 for ipv4 and 6 for ipv6. pub ip_type: u8, /// Axon protocol. TCP, UDP, other. pub protocol: u8, /// Axon proto placeholder 1. pub placeholder1: u8, /// Axon proto placeholder 2. pub placeholder2: u8, } /// Struct for NeuronCertificate. pub type NeuronCertificateOf = NeuronCertificate; /// Data structure for NeuronCertificate information. #[freeze_struct("1c232be200d9ec6c")] #[derive(Decode, Encode, Default, TypeInfo, PartialEq, Eq, Clone, Debug)] pub struct NeuronCertificate { /// The neuron TLS public key pub public_key: BoundedVec>, /// The algorithm used to generate the public key pub algorithm: u8, } impl TryFrom> for NeuronCertificate { type Error = (); fn try_from(value: Vec) -> Result { if value.len() > 65 { return Err(()); } // take the first byte as the algorithm let algorithm = value.first().ok_or(())?; // and the rest as the public_key let certificate = value.get(1..).ok_or(())?.to_vec(); Ok(Self { public_key: BoundedVec::try_from(certificate).map_err(|_| ())?, algorithm: *algorithm, }) } } /// Struct for Prometheus. pub type PrometheusInfoOf = PrometheusInfo; /// Data structure for Prometheus information. #[crate::freeze_struct("5dde687e63baf0cd")] #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] pub struct PrometheusInfo { /// Prometheus serving block. pub block: u64, /// Prometheus version. pub version: u32, /// Prometheus u128 encoded ip address of type v6 or v4. pub ip: u128, /// Prometheus u16 encoded port. pub port: u16, /// Prometheus ip type, 4 for ipv4 and 6 for ipv6. pub ip_type: u8, } /// Struct for ChainIdentities. (DEPRECATED for V2) pub type ChainIdentityOf = ChainIdentity; /// Data structure for Chain Identities. (DEPRECATED for V2) #[crate::freeze_struct("bbfd00438dbe2b58")] #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] pub struct ChainIdentity { /// The name of the chain identity pub name: Vec, /// The URL associated with the chain identity pub url: Vec, /// The image representation of the chain identity pub image: Vec, /// The Discord information for the chain identity pub discord: Vec, /// A description of the chain identity pub description: Vec, /// Additional information about the chain identity pub additional: Vec, } /// Struct for ChainIdentities. pub type ChainIdentityOfV2 = ChainIdentityV2; /// Data structure for Chain Identities. #[crate::freeze_struct("ad72a270be7b59d7")] #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] pub struct ChainIdentityV2 { /// The name of the chain identity pub name: Vec, /// The URL associated with the chain identity pub url: Vec, /// The github repository associated with the identity pub github_repo: Vec, /// The image representation of the chain identity pub image: Vec, /// The Discord information for the chain identity pub discord: Vec, /// A description of the chain identity pub description: Vec, /// Additional information about the chain identity pub additional: Vec, } /// Struct for SubnetIdentities. (DEPRECATED for V2) pub type SubnetIdentityOf = SubnetIdentity; /// Data structure for Subnet Identities. (DEPRECATED for V2) #[crate::freeze_struct("f448dc3dad763108")] #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] pub struct SubnetIdentity { /// The name of the subnet pub subnet_name: Vec, /// The github repository associated with the chain identity pub github_repo: Vec, /// The subnet's contact pub subnet_contact: Vec, } /// Struct for SubnetIdentitiesV2. (DEPRECATED for V3) pub type SubnetIdentityOfV2 = SubnetIdentityV2; /// Data structure for Subnet Identities (DEPRECATED for V3) #[crate::freeze_struct("e002be4cd05d7b3e")] #[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)] pub struct SubnetIdentityV2 { /// The name of the subnet pub subnet_name: Vec, /// The github repository associated with the subnet pub github_repo: Vec, /// The subnet's contact pub subnet_contact: Vec, /// The subnet's website pub subnet_url: Vec, /// The subnet's discord pub discord: Vec, /// The subnet's description pub description: Vec, /// Additional information about the subnet pub additional: Vec, } /// Struct for SubnetIdentitiesV3. pub type SubnetIdentityOfV3 = SubnetIdentityV3; /// Data structure for Subnet Identities #[crate::freeze_struct("6a441335f985a0b")] #[derive( Encode, Decode, DecodeWithMemTracking, Default, TypeInfo, Clone, PartialEq, Eq, Debug, )] pub struct SubnetIdentityV3 { /// The name of the subnet pub subnet_name: Vec, /// The github repository associated with the subnet pub github_repo: Vec, /// The subnet's contact pub subnet_contact: Vec, /// The subnet's website pub subnet_url: Vec, /// The subnet's discord pub discord: Vec, /// The subnet's description pub description: Vec, /// The subnet's logo pub logo_url: Vec, /// Additional information about the subnet pub additional: Vec, } /// Enum for recycle or burn for the owner_uid(s) #[derive(TypeInfo, Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, Debug)] pub enum RecycleOrBurnEnum { /// Burn the miner emission sent to the burn UID Burn, /// Recycle the miner emission sent to the recycle UID Recycle, } // Staking + Accounts #[derive( Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug, DecodeWithMemTracking, )] /// Enum for the per-coldkey root claim setting. pub enum RootClaimTypeEnum { /// Swap any alpha emission for TAO. #[default] Swap, /// Keep all alpha emission. Keep, /// Keep all alpha emission for specified subnets. KeepSubnets { /// Subnets to keep alpha emissions (swap everything else). subnets: BTreeSet, }, } /// The Max Burn HalfLife Settable #[pallet::type_value] pub fn MaxBurnHalfLife() -> u16 { 36_100 } /// Default burn half-life (in blocks) for subnet registration price decay. #[pallet::type_value] pub fn DefaultBurnHalfLife() -> u16 { 360 } /// Default multiplier applied to the burn price after a successful registration. #[pallet::type_value] pub fn DefaultBurnIncreaseMult() -> U64F64 { U64F64::from_num(1.26) } /// Default Neuron Burn Cost #[pallet::type_value] pub fn DefaultNeuronBurnCost() -> TaoBalance { TaoBalance::from(1_000_000_000u64) } /// Default minimum root claim amount. /// This is the minimum amount of root claim that can be made. /// Any amount less than this will not be claimed. #[pallet::type_value] pub fn DefaultMinRootClaimAmount() -> I96F32 { 500_000u64.into() } /// Default root claim type. /// This is the type of root claim that will be made. /// This is set by the user. Either swap to TAO or keep as alpha. #[pallet::type_value] pub fn DefaultRootClaimType() -> RootClaimTypeEnum { RootClaimTypeEnum::default() } /// Default number of root claims per claim call. /// Ideally this is calculated using the number of staking coldkey /// and the block time. #[pallet::type_value] pub fn DefaultNumRootClaim() -> u64 { // once per week (+ spare keys for skipped tries) 5 } /// Default value for zero. #[pallet::type_value] pub fn DefaultZeroU64() -> u64 { 0 } /// Default value for zero. #[pallet::type_value] pub fn DefaultZeroI64() -> i64 { 0 } /// Default value for Alpha currency. #[pallet::type_value] pub fn DefaultZeroAlpha() -> AlphaBalance { AlphaBalance::ZERO } /// Default value for Tao currency. #[pallet::type_value] pub fn DefaultZeroTao() -> TaoBalance { TaoBalance::ZERO } /// Default value for zero. #[pallet::type_value] pub fn DefaultZeroU128() -> u128 { 0 } /// Default value for zero. #[pallet::type_value] pub fn DefaultZeroU16() -> u16 { 0 } /// Default value for false. #[pallet::type_value] pub fn DefaultFalse() -> bool { false } /// Default value for true. #[pallet::type_value] pub fn DefaultTrue() -> bool { true } /// Total Rao in circulation. #[pallet::type_value] pub fn TotalSupply() -> u64 { 21_000_000_000_000_000 } /// Default Delegate Take. #[pallet::type_value] pub fn DefaultDelegateTake() -> PerU16 { PerU16::from_parts(T::InitialDefaultDelegateTake::get()) } /// Default childkey take. #[pallet::type_value] pub fn DefaultChildKeyTake() -> PerU16 { PerU16::from_parts(T::InitialDefaultChildKeyTake::get()) } /// Default minimum delegate take. #[pallet::type_value] pub fn DefaultMinDelegateTake() -> PerU16 { PerU16::from_parts(T::InitialMinDelegateTake::get()) } /// Default minimum childkey take. #[pallet::type_value] pub fn DefaultMinChildKeyTake() -> PerU16 { PerU16::from_parts(T::InitialMinChildKeyTake::get()) } /// Default maximum childkey take. #[pallet::type_value] pub fn DefaultMaxChildKeyTake() -> PerU16 { PerU16::from_parts(T::InitialMaxChildKeyTake::get()) } /// Default account take. #[pallet::type_value] pub fn DefaultAccountTake() -> u64 { 0 } /// Default value for global weight. #[pallet::type_value] pub fn DefaultTaoWeight() -> u64 { T::InitialTaoWeight::get() } /// Default emission per block. #[pallet::type_value] pub fn DefaultBlockEmission() -> u64 { 1_000_000_000 } /// Default allowed delegation. #[pallet::type_value] pub fn DefaultAllowsDelegation() -> bool { false } /// Default total issuance. #[pallet::type_value] pub fn DefaultTotalIssuance() -> TaoBalance { T::InitialIssuance::get().into() } /// Default account, derived from zero trailing bytes. #[pallet::type_value] pub fn DefaultAccount() -> T::AccountId { #[allow(clippy::expect_used)] T::AccountId::decode(&mut TrailingZeroInput::zeroes()) .expect("trailing zeroes always produce a valid account ID; qed") } // pub fn DefaultStakeInterval() -> u64 { // 360 // } (DEPRECATED) /// Default account linkage #[pallet::type_value] pub fn DefaultAccountLinkage() -> Vec<(u64, T::AccountId)> { vec![] } /// Default pending childkeys #[pallet::type_value] pub fn DefaultPendingChildkeys() -> (Vec<(u64, T::AccountId)>, u64) { (vec![], 0) } /// Default account linkage #[pallet::type_value] pub fn DefaultProportion() -> u64 { 0 } /// Default accumulated emission for a hotkey #[pallet::type_value] pub fn DefaultAccumulatedEmission() -> u64 { 0 } /// Default last adjustment block. #[pallet::type_value] pub fn DefaultLastAdjustmentBlock() -> u64 { 0 } /// Default last adjustment block. #[pallet::type_value] pub fn DefaultRegistrationsThisBlock() -> u16 { 0 } /// Default EMA price halving blocks #[pallet::type_value] pub fn DefaultEMAPriceMovingBlocks() -> u64 { T::InitialEmaPriceHalvingPeriod::get() } /// Default registrations this block. #[pallet::type_value] pub fn DefaultBurn() -> TaoBalance { T::InitialBurn::get().into() } /// Default burn token. #[pallet::type_value] pub fn DefaultMinBurn() -> TaoBalance { T::InitialMinBurn::get().into() } /// Default min burn token. #[pallet::type_value] pub fn DefaultMaxBurn() -> TaoBalance { T::InitialMaxBurn::get().into() } /// Default max burn token. #[pallet::type_value] pub fn DefaultDifficulty() -> u64 { T::InitialDifficulty::get() } /// Default difficulty value. #[pallet::type_value] pub fn DefaultMinDifficulty() -> u64 { T::InitialMinDifficulty::get() } /// Default min difficulty value. #[pallet::type_value] pub fn DefaultMaxDifficulty() -> u64 { T::InitialMaxDifficulty::get() } /// Default max difficulty value. #[pallet::type_value] pub fn DefaultMaxRegistrationsPerBlock() -> u16 { T::InitialMaxRegistrationsPerBlock::get() } /// Default max registrations per block. #[pallet::type_value] pub fn DefaultRAORecycledForRegistration() -> TaoBalance { T::InitialRAORecycledForRegistration::get().into() } /// Default number of networks. #[pallet::type_value] pub fn DefaultN() -> u16 { 0 } /// Default value for hotkeys. #[pallet::type_value] pub fn DefaultHotkeys() -> Vec { vec![] } /// Default value if network is added. #[pallet::type_value] pub fn DefaultNeworksAdded() -> bool { false } /// Default value for network member. #[pallet::type_value] pub fn DefaultIsNetworkMember() -> bool { false } /// Default value for registration allowed. #[pallet::type_value] pub fn DefaultRegistrationAllowed() -> bool { true } /// Default value for network registered at. #[pallet::type_value] pub fn DefaultNetworkRegisteredAt() -> u64 { 0 } /// Default value for network immunity period. #[pallet::type_value] pub fn DefaultNetworkImmunityPeriod() -> u64 { T::InitialNetworkImmunityPeriod::get() } /// Default value for network min lock cost. #[pallet::type_value] pub fn DefaultNetworkMinLockCost() -> TaoBalance { T::InitialNetworkMinLockCost::get().into() } /// Default value for network lock reduction interval. #[pallet::type_value] pub fn DefaultNetworkLockReductionInterval() -> u64 { T::InitialNetworkLockReductionInterval::get() } /// Default value for subnet owner cut. #[pallet::type_value] pub fn DefaultSubnetOwnerCut() -> u16 { T::InitialSubnetOwnerCut::get() } /// Default value for recycle or burn. #[pallet::type_value] pub fn DefaultRecycleOrBurn() -> RecycleOrBurnEnum { RecycleOrBurnEnum::Burn // default to burn } /// Default value for network rate limit. #[pallet::type_value] pub fn DefaultNetworkRateLimit() -> u64 { if cfg!(feature = "pow-faucet") { return 0; } T::InitialNetworkRateLimit::get() } /// Default value for network rate limit. #[pallet::type_value] pub fn DefaultNetworkRegistrationStartBlock() -> u64 { 0 } /// Default value for TAO-in refund deployment block. #[pallet::type_value] pub fn DefaultTaoInRefundDeploymentBlock() -> u64 { 0 } /// Default value for weights version key rate limit. /// In units of tempos. #[pallet::type_value] pub fn DefaultWeightsVersionKeyRateLimit() -> u64 { 5 // 5 tempos } /// Default value for pending emission. #[pallet::type_value] pub fn DefaultPendingEmission() -> AlphaBalance { 0.into() } /// Default value for blocks since last step. #[pallet::type_value] pub fn DefaultBlocksSinceLastStep() -> u64 { 0 } /// Default value for last mechanism step block. #[pallet::type_value] pub fn DefaultLastMechanismStepBlock() -> u64 { 0 } /// Default value for subnet owner. #[pallet::type_value] pub fn DefaultSubnetOwner() -> T::AccountId { #[allow(clippy::expect_used)] T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) .expect("trailing zeroes always produce a valid account ID; qed") } /// Default value for subnet locked. #[pallet::type_value] pub fn DefaultSubnetLocked() -> u64 { 0 } /// Default value for network tempo #[pallet::type_value] pub fn DefaultTempo() -> u16 { T::InitialTempo::get() } /// Default value for weights set rate limit. #[pallet::type_value] pub fn DefaultWeightsSetRateLimit() -> u64 { 100 } /// Default block number at registration. #[pallet::type_value] pub fn DefaultBlockAtRegistration() -> u64 { 0 } /// Default value for rho parameter. #[pallet::type_value] pub fn DefaultRho() -> u16 { T::InitialRho::get() } /// Default value for alpha sigmoid steepness. #[pallet::type_value] pub fn DefaultAlphaSigmoidSteepness() -> i16 { T::InitialAlphaSigmoidSteepness::get() } /// Default value for kappa parameter. #[pallet::type_value] pub fn DefaultKappa() -> u16 { T::InitialKappa::get() } /// Default value for network min allowed UIDs. #[pallet::type_value] pub fn DefaultMinAllowedUids() -> u16 { T::InitialMinAllowedUids::get() } /// Default maximum allowed UIDs. #[pallet::type_value] pub fn DefaultMaxAllowedUids() -> u16 { T::InitialMaxAllowedUids::get() } /// Rate limit for set max allowed UIDs #[pallet::type_value] pub fn MaxUidsTrimmingRateLimit() -> u64 { prod_or_fast!(30 * 7200, 1) } /// Default immunity period. #[pallet::type_value] pub fn DefaultImmunityPeriod() -> u16 { T::InitialImmunityPeriod::get() } /// Default activity cutoff. #[pallet::type_value] pub fn DefaultActivityCutoff() -> u16 { T::InitialActivityCutoff::get() } /// Default weights version key. #[pallet::type_value] pub fn DefaultWeightsVersionKey() -> u64 { T::InitialWeightsVersionKey::get() } /// Default minimum allowed weights. #[pallet::type_value] pub fn DefaultMinAllowedWeights() -> u16 { T::InitialMinAllowedWeights::get() } /// Default maximum allowed validators. #[pallet::type_value] pub fn DefaultMaxAllowedValidators() -> u16 { T::InitialMaxAllowedValidators::get() } /// Default adjustment interval. #[pallet::type_value] pub fn DefaultAdjustmentInterval() -> u16 { T::InitialAdjustmentInterval::get() } /// Default bonds moving average. #[pallet::type_value] pub fn DefaultBondsMovingAverage() -> u64 { T::InitialBondsMovingAverage::get() } /// Default bonds penalty. #[pallet::type_value] pub fn DefaultBondsPenalty() -> u16 { T::InitialBondsPenalty::get() } /// Default value for bonds reset - will not reset bonds #[pallet::type_value] pub fn DefaultBondsResetOn() -> bool { T::InitialBondsResetOn::get() } /// Default validator prune length. #[pallet::type_value] pub fn DefaultValidatorPruneLen() -> u64 { T::InitialValidatorPruneLen::get() } /// Default scaling law power. #[pallet::type_value] pub fn DefaultScalingLawPower() -> u16 { T::InitialScalingLawPower::get() } /// Default target registrations per interval. #[pallet::type_value] pub fn DefaultTargetRegistrationsPerInterval() -> u16 { T::InitialTargetRegistrationsPerInterval::get() } /// Default adjustment alpha. #[pallet::type_value] pub fn DefaultAdjustmentAlpha() -> u64 { T::InitialAdjustmentAlpha::get() } /// Default minimum stake for weights. #[pallet::type_value] pub fn DefaultStakeThreshold() -> u64 { 0 } /// Default Reveal Period Epochs #[pallet::type_value] pub fn DefaultRevealPeriodEpochs() -> u64 { 1 } /// Value definition for vector of u16. #[pallet::type_value] pub fn EmptyU16Vec() -> Vec { vec![] } /// Value definition for vector of PerU16. #[pallet::type_value] pub fn EmptyPerU16Vec() -> Vec { vec![] } /// Value definition for vector of u64. #[pallet::type_value] pub fn EmptyU64Vec() -> Vec { vec![] } /// Value definition for vector of bool. #[pallet::type_value] pub fn EmptyBoolVec() -> Vec { vec![] } /// Value definition for bonds with type vector of (u16, u16). #[pallet::type_value] pub fn DefaultBonds() -> Vec<(u16, u16)> { vec![] } /// Value definition for weights with vector of (u16, u16). #[pallet::type_value] pub fn DefaultWeights() -> Vec<(u16, u16)> { vec![] } /// Default value for key with type T::AccountId derived from trailing zeroes. #[pallet::type_value] pub fn DefaultKey() -> T::AccountId { #[allow(clippy::expect_used)] T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) .expect("trailing zeroes always produce a valid account ID; qed") } // pub fn DefaultHotkeyEmissionTempo() -> u64 { // T::InitialHotkeyEmissionTempo::get() // } (DEPRECATED) /// Default per-block epoch cap, seeded from the runtime-configured initial value. #[pallet::type_value] pub fn DefaultMaxEpochsPerBlock() -> u8 { T::InitialMaxEpochsPerBlock::get() } /// Default value for rate limiting #[pallet::type_value] pub fn DefaultTxRateLimit() -> u64 { T::InitialTxRateLimit::get() } /// Default value for delegate take rate limiting #[pallet::type_value] pub fn DefaultTxDelegateTakeRateLimit() -> u64 { T::InitialTxDelegateTakeRateLimit::get() } /// Default value for chidlkey take rate limiting #[pallet::type_value] pub fn DefaultTxChildKeyTakeRateLimit() -> u64 { T::InitialTxChildKeyTakeRateLimit::get() } /// Default value for last extrinsic block. #[pallet::type_value] pub fn DefaultLastTxBlock() -> u64 { 0 } /// Default value for serving rate limit. #[pallet::type_value] pub fn DefaultServingRateLimit() -> u64 { T::InitialServingRateLimit::get() } /// Default value for weight commit/reveal enabled. #[pallet::type_value] pub fn DefaultCommitRevealWeightsEnabled() -> bool { true } /// Default value for weight commit/reveal version. #[pallet::type_value] pub fn DefaultCommitRevealWeightsVersion() -> u16 { 4 } /// ITEM (switches liquid alpha on) #[pallet::type_value] pub fn DefaultLiquidAlpha() -> bool { false } /// ITEM (switches liquid alpha on) #[pallet::type_value] pub fn DefaultYuma3() -> bool { false } /// (alpha_low: 0.7, alpha_high: 0.9) #[pallet::type_value] pub fn DefaultAlphaValues() -> (u16, u16) { (45875, 58982) } /// Default value for coldkey swap announcement delay. #[pallet::type_value] pub fn DefaultColdkeySwapAnnouncementDelay() -> BlockNumberFor { T::InitialColdkeySwapAnnouncementDelay::get() } /// Default value for coldkey swap reannouncement delay. #[pallet::type_value] pub fn DefaultColdkeySwapReannouncementDelay() -> BlockNumberFor { T::InitialColdkeySwapReannouncementDelay::get() } /// Default value for applying pending items (e.g. childkeys). #[pallet::type_value] pub fn DefaultPendingCooldown() -> u64 { prod_or_fast!(7_200, 15) } /// Default minimum stake. #[pallet::type_value] pub fn DefaultMinStake() -> TaoBalance { T::InitialMinStake::get().into() } /// Default unicode vector for tau symbol. #[pallet::type_value] pub fn DefaultUnicodeVecU8() -> Vec { b"\xF0\x9D\x9C\x8F".to_vec() // Unicode for tau (𝜏) } /// Default value for dissolve network schedule duration #[pallet::type_value] pub fn DefaultDissolveNetworkScheduleDuration() -> BlockNumberFor { T::InitialDissolveNetworkScheduleDuration::get() } /// Default moving alpha for the moving price. #[pallet::type_value] pub fn DefaultMovingAlpha() -> I96F32 { // Moving average take 30 days to reach 50% of the price // and 3.5 months to reach 90%. I96F32::saturating_from_num(0.000003) } /// Default subnet moving price. #[pallet::type_value] pub fn DefaultMovingPrice() -> I96F32 { I96F32::saturating_from_num(0.0) } /// Default subnet root proportion. #[pallet::type_value] pub fn DefaultRootProp() -> U96F32 { U96F32::saturating_from_num(0.0) } /// Default subnet root claimable #[pallet::type_value] pub fn DefaultRootClaimable() -> BTreeMap { Default::default() } /// Default value for Share Pool variables #[pallet::type_value] pub fn DefaultSharePoolZero() -> U64F64 { U64F64::saturating_from_num(0) } /// Default value for minimum activity cutoff #[pallet::type_value] pub fn DefaultMinActivityCutoff() -> u16 { 360 } /// Default value for setting subnet owner hotkey rate limit #[pallet::type_value] pub fn DefaultSetSNOwnerHotkeyRateLimit() -> u64 { 50400 } /// Default last Alpha map key for iteration #[pallet::type_value] pub fn DefaultAlphaIterationLastKey() -> Option> { None } /// Default number of terminal blocks in a tempo during which admin operations are prohibited #[pallet::type_value] pub fn DefaultAdminFreezeWindow() -> u16 { 10 } /// Default number of tempos for owner hyperparameter update rate limit #[pallet::type_value] pub fn DefaultOwnerHyperparamRateLimit() -> u16 { 2 } /// Default value for ck burn, 0%. #[pallet::type_value] pub fn DefaultCKBurn() -> u64 { 0 } /// Default value for subnet limit. #[pallet::type_value] pub fn DefaultSubnetLimit() -> u16 { 128 } /// Default value for MinNonImmuneUids. #[pallet::type_value] pub fn DefaultMinNonImmuneUids() -> u16 { 10u16 } /// Default value for AutoParentDelegationEnabled. #[pallet::type_value] pub fn DefaultAutoParentDelegationEnabled() -> bool { true } #[pallet::storage] pub type MinActivityCutoff = StorageValue<_, u16, ValueQuery, DefaultMinActivityCutoff>; /// Global window (in blocks) at the end of each tempo where admin ops are disallowed #[pallet::storage] pub type AdminFreezeWindow = StorageValue<_, u16, ValueQuery, DefaultAdminFreezeWindow>; /// Global number of epochs used to rate limit subnet owner hyperparameter updates #[pallet::storage] pub type OwnerHyperparamRateLimit = StorageValue<_, u16, ValueQuery, DefaultOwnerHyperparamRateLimit>; /// Duration of dissolve network schedule before execution #[pallet::storage] pub type DissolveNetworkScheduleDuration = StorageValue<_, BlockNumberFor, ValueQuery, DefaultDissolveNetworkScheduleDuration>; /// DMap ( netuid, coldkey ) --> blocknumber | last hotkey swap on network. #[pallet::storage] pub type LastHotkeySwapOnNetuid = StorageDoubleMap< _, Identity, NetUid, Blake2_128Concat, T::AccountId, u64, ValueQuery, DefaultZeroU64, >; /// Ensures unique IDs for StakeJobs storage map #[pallet::storage] pub type NextStakeJobId = StorageValue<_, u64, ValueQuery, DefaultZeroU64>; // Staking Variables /// The Subtensor [`TotalIssuance`] represents the total issuance of tokens on the Bittensor network. /// /// It is comprised of three parts: /// * The total amount of issued tokens, tracked in the TotalIssuance of the Balances pallet /// * The total amount of tokens staked in the system, tracked in [`TotalStake`] /// * The total amount of tokens locked up for subnet reg, tracked in [`TotalSubnetLocked`] attained by iterating over subnet lock. /// /// Eventually, Bittensor should migrate to using Holds afterwhich time we will not require this /// separate accounting. /// ITEM --> Global weight #[pallet::storage] pub type TaoWeight = StorageValue<_, u64, ValueQuery, DefaultTaoWeight>; /// ITEM --> CK burn #[pallet::storage] pub type CKBurn = StorageValue<_, u64, ValueQuery, DefaultCKBurn>; /// ITEM ( default_delegate_take ) #[pallet::storage] pub type MaxDelegateTake = StorageValue<_, PerU16, ValueQuery, DefaultDelegateTake>; /// ITEM ( min_delegate_take ) #[pallet::storage] pub type MinDelegateTake = StorageValue<_, PerU16, ValueQuery, DefaultMinDelegateTake>; /// ITEM ( default_childkey_take ) #[pallet::storage] pub type MaxChildkeyTake = StorageValue<_, PerU16, ValueQuery, DefaultMaxChildKeyTake>; /// ITEM ( min_childkey_take ) #[pallet::storage] pub type MinChildkeyTake = StorageValue<_, PerU16, ValueQuery, DefaultMinChildKeyTake>; /// MAP ( netuid ) --> take | Returns the subnet-specific minimum childkey take. #[pallet::storage] pub type MinChildkeyTakePerSubnet = StorageMap<_, Identity, NetUid, PerU16, ValueQuery>; /// MAP ( hot ) --> cold | Returns the controlling coldkey for a hotkey #[pallet::storage] pub type Owner = StorageMap<_, Blake2_128Concat, T::AccountId, T::AccountId, ValueQuery, DefaultAccount>; /// MAP ( coldkey ) --> flags | Account-level flags. Defaults to zero. #[pallet::storage] pub type AccountFlags = StorageMap<_, Blake2_128Concat, T::AccountId, u128, ValueQuery>; /// MAP ( hot ) --> take | Returns the hotkey delegation take. And signals that this key is open for delegation #[pallet::storage] pub type Delegates = StorageMap<_, Blake2_128Concat, T::AccountId, PerU16, ValueQuery, DefaultDelegateTake>; /// DMAP ( hot, netuid ) --> take | Returns the hotkey childkey take for a specific subnet #[pallet::storage] pub type ChildkeyTake = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, // First key: hotkey Identity, NetUid, // Second key: netuid PerU16, // Value: take ValueQuery, >; /// DMAP ( netuid, parent ) --> (Vec<(proportion,child)>, cool_down_block) #[pallet::storage] pub type PendingChildKeys = StorageDoubleMap< _, Identity, NetUid, Blake2_128Concat, T::AccountId, (Vec<(u64, T::AccountId)>, u64), ValueQuery, DefaultPendingChildkeys, >; /// DMAP ( parent, netuid ) --> Vec<(proportion,child)> #[pallet::storage] pub type ChildKeys = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, Identity, NetUid, Vec<(u64, T::AccountId)>, ValueQuery, DefaultAccountLinkage, >; /// DMAP ( child, netuid ) --> Vec<(proportion,parent)> #[pallet::storage] pub type ParentKeys = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, Identity, NetUid, Vec<(u64, T::AccountId)>, ValueQuery, DefaultAccountLinkage, >; /// DMAP ( netuid, hotkey ) --> u64 | Last alpha dividend this hotkey got on tempo. #[pallet::storage] pub type AlphaDividendsPerSubnet = StorageDoubleMap< _, Identity, NetUid, Blake2_128Concat, T::AccountId, AlphaBalance, ValueQuery, DefaultZeroAlpha, >; /// DMAP ( netuid, hotkey ) --> u64 | Last root alpha dividend this hotkey got on tempo. #[pallet::storage] pub type RootAlphaDividendsPerSubnet = StorageDoubleMap< _, Identity, NetUid, Blake2_128Concat, T::AccountId, AlphaBalance, ValueQuery, DefaultZeroAlpha, >; // Coinbase /// ITEM ( global_block_emission ) #[deprecated(note = "Use calculate_block_emission() or the block emission RPC instead.")] #[pallet::storage] pub type BlockEmission = StorageValue<_, u64, ValueQuery, DefaultBlockEmission>; /// DMap ( hot, netuid ) --> emission | last hotkey emission on network. #[pallet::storage] pub type LastHotkeyEmissionOnNetuid = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, Identity, NetUid, AlphaBalance, ValueQuery, DefaultZeroAlpha, >; // Staking Counters /// The Subtensor [`TotalIssuance`] represents the total issuance of tokens on the Bittensor network. /// /// It is comprised of three parts: /// * The total amount of issued tokens, tracked in the TotalIssuance of the Balances pallet /// * The total amount of tokens staked in the system, tracked in [`TotalStake`] /// * The total amount of tokens locked up for subnet reg, tracked in [`TotalSubnetLocked`] attained by iterating over subnet lock. /// /// Eventually, Bittensor should migrate to using Holds afterwhich time we will not require this /// separate accounting. /// ITEM ( maximum_number_of_networks ) #[pallet::storage] pub type SubnetLimit = StorageValue<_, u16, ValueQuery, DefaultSubnetLimit>; /// ITEM ( total_issuance ) #[pallet::storage] pub type TotalIssuance = StorageValue<_, TaoBalance, ValueQuery, DefaultTotalIssuance>; /// ITEM ( total_stake ) #[pallet::storage] pub type TotalStake = StorageValue<_, TaoBalance, ValueQuery, DefaultZeroTao>; /// ITEM ( moving_alpha ) -- subnet moving alpha. #[pallet::storage] pub type SubnetMovingAlpha = StorageValue<_, I96F32, ValueQuery, DefaultMovingAlpha>; /// MAP ( netuid ) --> moving_price | The subnet moving price. #[pallet::storage] pub type SubnetMovingPrice = StorageMap<_, Identity, NetUid, I96F32, ValueQuery, DefaultMovingPrice>; /// MAP ( netuid ) --> root_prop | The subnet root proportion. #[pallet::storage] pub type RootProp = StorageMap<_, Identity, NetUid, U96F32, ValueQuery, DefaultRootProp>; /// MAP ( netuid ) --> total_volume | The total amount of TAO bought and sold since the start of the network. #[pallet::storage] pub type SubnetVolume = StorageMap<_, Identity, NetUid, u128, ValueQuery, DefaultZeroU128>; /// MAP ( netuid ) --> tao_in_subnet | Returns the amount of TAO in the subnet. #[pallet::storage] pub type SubnetTAO = StorageMap<_, Identity, NetUid, TaoBalance, ValueQuery, DefaultZeroTao>; /// MAP ( netuid ) --> alpha_in_emission | Returns the amount of alph in emission into the pool per block. #[pallet::storage] pub type SubnetAlphaInEmission = StorageMap<_, Identity, NetUid, AlphaBalance, ValueQuery, DefaultZeroAlpha>; /// MAP ( netuid ) --> subnet_emission_enabled /// /// When false, subnet pool-side emission is disabled for this subnet: /// `alpha_in`, `tao_in`, and `excess_tao` chain buys are all treated as zero. /// `alpha_out`, owner cut, root proportion, pending server emission, and pending /// validator emission are intentionally left unchanged. /// /// Defaults to true so existing subnets keep current behavior. #[pallet::storage] pub type SubnetEmissionEnabled = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultTrue>; /// MAP ( netuid ) --> alpha_out_emission | Returns the amount of alpha out emission into the network per block. #[pallet::storage] pub type SubnetAlphaOutEmission = StorageMap<_, Identity, NetUid, AlphaBalance, ValueQuery, DefaultZeroAlpha>; /// MAP ( netuid ) --> tao_in_emission | Returns the amount of tao emitted into this subent on the last block. #[pallet::storage] pub type SubnetTaoInEmission = StorageMap<_, Identity, NetUid, TaoBalance, ValueQuery, DefaultZeroTao>; /// MAP ( netuid ) --> excess_tao | Returns the excess TAO swapped (chain buys) into this subnet on the last block. #[pallet::storage] pub type SubnetExcessTao = StorageMap<_, Identity, NetUid, TaoBalance, ValueQuery, DefaultZeroTao>; /// MAP ( netuid ) --> root_sell_tao | Returns the TAO received from root dividend sells on this subnet on the last block. #[pallet::storage] pub type SubnetRootSellTao = StorageMap<_, Identity, NetUid, TaoBalance, ValueQuery, DefaultZeroTao>; /// MAP ( netuid ) --> alpha_supply_in_pool | Returns the amount of alpha in the pool. #[pallet::storage] pub type SubnetAlphaIn = StorageMap<_, Identity, NetUid, AlphaBalance, ValueQuery, DefaultZeroAlpha>; /// MAP ( netuid ) --> alpha_supply_in_subnet | Returns the amount of alpha in the subnet. #[pallet::storage] pub type SubnetAlphaOut = StorageMap<_, Identity, NetUid, AlphaBalance, ValueQuery, DefaultZeroAlpha>; /// MAP ( netuid ) --> protocol_alpha | Returns the protocol-owned alpha cached for the subnet. #[pallet::storage] pub type SubnetProtocolAlpha = StorageMap<_, Identity, NetUid, AlphaBalance, ValueQuery, DefaultZeroAlpha>; /// MAP ( cold ) --> Vec | Maps coldkey to hotkeys that stake to it #[pallet::storage] pub type StakingHotkeys = StorageMap<_, Blake2_128Concat, T::AccountId, Vec, ValueQuery>; /// MAP ( cold ) --> Vec | Returns the vector of hotkeys controlled by this coldkey. #[pallet::storage] pub type OwnedHotkeys = StorageMap<_, Blake2_128Concat, T::AccountId, Vec, ValueQuery>; /// DMAP ( cold, netuid )--> hot | Returns the hotkey a coldkey will autostake to with mining rewards. #[pallet::storage] pub type AutoStakeDestination = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, Identity, NetUid, T::AccountId, OptionQuery, >; /// DMAP ( hot, netuid )--> Vec | Returns a list of coldkeys that are autostaking to a hotkey #[pallet::storage] pub type AutoStakeDestinationColdkeys = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, Identity, NetUid, Vec, ValueQuery, >; /// The delay after an announcement before a coldkey swap can be performed. #[pallet::storage] pub type ColdkeySwapAnnouncementDelay = StorageValue<_, BlockNumberFor, ValueQuery, DefaultColdkeySwapAnnouncementDelay>; /// The delay after the initial delay has passed before a new announcement can be made. #[pallet::storage] pub type ColdkeySwapReannouncementDelay = StorageValue<_, BlockNumberFor, ValueQuery, DefaultColdkeySwapReannouncementDelay>; /// A map of the coldkey swap announcements from a coldkey /// to the block number the coldkey swap can be performed. #[pallet::storage] pub type ColdkeySwapAnnouncements = StorageMap<_, Twox64Concat, T::AccountId, (BlockNumberFor, T::Hash), OptionQuery>; /// A map of the coldkey swap disputes from a coldkey to the /// block number the coldkey swap was disputed. #[pallet::storage] pub type ColdkeySwapDisputes = StorageMap<_, Twox64Concat, T::AccountId, BlockNumberFor, OptionQuery>; /// DMAP ( hot, netuid ) --> alpha | Returns the total amount of alpha a hotkey owns. #[pallet::storage] pub type TotalHotkeyAlpha = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, Identity, NetUid, AlphaBalance, ValueQuery, DefaultZeroAlpha, >; /// DMAP ( hot, netuid ) --> alpha | Returns the total amount of alpha a hotkey owned in the last epoch. #[pallet::storage] pub type TotalHotkeyAlphaLastEpoch = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, Identity, NetUid, AlphaBalance, ValueQuery, DefaultZeroAlpha, >; /// DMAP ( hot, netuid ) --> total_alpha_shares | Returns the number of alpha shares for a hotkey on a subnet. #[pallet::storage] pub type TotalHotkeyShares = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, Identity, NetUid, U64F64, ValueQuery, DefaultSharePoolZero, >; /// NMAP ( hot, cold, netuid ) --> alpha | Returns the alpha shares for a hotkey, coldkey, netuid triplet. #[pallet::storage] pub type Alpha = StorageNMap< _, ( NMapKey, // hot NMapKey, // cold NMapKey, // subnet ), U64F64, // Shares ValueQuery, >; /// DMAP ( hot, netuid ) --> total_alpha_shares | Returns the number of alpha shares for a hotkey on a subnet, stores SafeFloat. #[pallet::storage] pub type TotalHotkeySharesV2 = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, // hot Identity, NetUid, // subnet SafeFloat, // Hotkey shares in unlimited precision ValueQuery, >; /// NMAP ( hot, cold, netuid ) --> alpha | Returns the alpha shares for a hotkey, coldkey, netuid triplet, stores SafeFloat. #[pallet::storage] pub type AlphaV2 = StorageNMap< _, ( NMapKey, // hot NMapKey, // cold NMapKey, // subnet ), SafeFloat, // Shares in unlimited precision ValueQuery, >; /// DMAP ( coldkey, netuid, hotkey ) --> LockState | Exponential lock per coldkey per subnet. #[pallet::storage] pub type Lock = StorageNMap< _, ( NMapKey, // coldkey NMapKey, // subnet NMapKey, // hotkey ), LockState, OptionQuery, >; /// NMAP ( netuid, hotkey, coldkey ) --> () | Reverse index for non-zero locks targeting this hotkey on this subnet. #[pallet::storage] pub type LockingColdkeys = StorageNMap< _, ( NMapKey, // subnet NMapKey, // hotkey NMapKey, // coldkey ), (), OptionQuery, >; /// DMAP ( netuid, hotkey ) --> LockState | Total lock per hotkey per subnet. #[pallet::storage] pub type HotkeyLock = StorageDoubleMap< _, Identity, NetUid, // subnet Blake2_128Concat, T::AccountId, // hotkey LockState, // Total merged lock OptionQuery, >; /// DMAP ( netuid, hotkey ) --> LockState | Total decaying non-owner lock per hotkey per subnet. #[pallet::storage] pub type DecayingHotkeyLock = StorageDoubleMap< _, Identity, NetUid, // subnet Blake2_128Concat, T::AccountId, // hotkey LockState, // Total merged decaying lock OptionQuery, >; /// MAP ( netuid ) --> LockState | Total perpetual lock to the owner hotkey for a subnet. #[pallet::storage] pub type OwnerLock = StorageMap<_, Identity, NetUid, LockState, OptionQuery>; /// MAP ( netuid ) --> LockState | Total decaying lock to the owner hotkey for a subnet. #[pallet::storage] pub type DecayingOwnerLock = StorageMap<_, Identity, NetUid, LockState, OptionQuery>; /// DMAP ( coldkey, netuid ) --> false | When present and false, this coldkey's lock is perpetual. /// Missing entries mean the lock decays by default. #[pallet::storage] pub type DecayingLock = StorageDoubleMap<_, Blake2_128Concat, T::AccountId, Identity, NetUid, bool, OptionQuery>; /// Default value for owner cut auto-locking. #[pallet::type_value] pub fn DefaultOwnerCutAutoLockEnabled() -> bool { false } /// MAP ( netuid ) --> bool | Whether subnet owner cut should be auto-locked. /// Missing entries default to false, so auto-locking is disabled unless explicitly enabled. #[pallet::storage] pub type OwnerCutAutoLockEnabled = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultOwnerCutAutoLockEnabled>; /// Default unlock timescale: 50% lock back in ~90 days. #[pallet::type_value] pub fn DefaultUnlockRate() -> u64 { 934_866 } /// Default maturity timescale: 50% conviction in ~90 days. #[pallet::type_value] pub fn DefaultMaturityRate() -> u64 { 934_866 } /// ITEM( maturity_rate ) | Decay timescale in blocks for lock conviction. #[pallet::storage] pub type MaturityRate = StorageValue<_, u64, ValueQuery, DefaultMaturityRate>; /// ITEM( unlock_rate ) | Decay timescale in blocks for locked mass. #[pallet::storage] pub type UnlockRate = StorageValue<_, u64, ValueQuery, DefaultUnlockRate>; /// Contains last Alpha storage map key to iterate (check first) #[pallet::storage] pub type AlphaMapLastKey = StorageValue<_, Option>, ValueQuery, DefaultAlphaIterationLastKey>; /// Contains last AlphaV2 storage map key to iterate (check first) #[pallet::storage] pub type AlphaV2MapLastKey = StorageValue<_, Option>, ValueQuery, DefaultAlphaIterationLastKey>; /// MAP ( netuid ) --> token_symbol | Returns the token symbol for a subnet. #[pallet::storage] pub type TokenSymbol = StorageMap<_, Identity, NetUid, Vec, ValueQuery, DefaultUnicodeVecU8>; /// MAP ( netuid ) --> subnet_tao_flow | Returns the TAO inflow-outflow balance. #[pallet::storage] pub type SubnetTaoFlow = StorageMap<_, Identity, NetUid, i64, ValueQuery, DefaultZeroI64>; /// MAP ( netuid ) --> subnet_ema_tao_flow | Returns the EMA of TAO inflow-outflow balance. #[pallet::storage] pub type SubnetEmaTaoFlow = StorageMap<_, Identity, NetUid, (u64, I64F64), OptionQuery>; /// ITEM --> net_tao_flow_enabled | When true, emission shares use net flow (user - protocol). When false, uses gross user flow only. #[pallet::type_value] pub fn DefaultNetTaoFlowEnabled() -> bool { true } #[pallet::storage] pub type NetTaoFlowEnabled = StorageValue<_, bool, ValueQuery, DefaultNetTaoFlowEnabled>; /// MAP ( netuid ) --> subnet_protocol_flow | Per-block accumulator for protocol cost (emission + chain buys - root sells). #[pallet::storage] pub type SubnetProtocolFlow = StorageMap<_, Identity, NetUid, i64, ValueQuery, DefaultZeroI64>; /// MAP ( netuid ) --> subnet_ema_protocol_flow | EMA of protocol cost flow, same smoothing as SubnetEmaTaoFlow. #[pallet::storage] pub type SubnetEmaProtocolFlow = StorageMap<_, Identity, NetUid, (u64, I64F64), OptionQuery>; /// Default value for flow cutoff. #[pallet::type_value] pub fn DefaultFlowCutoff() -> I64F64 { I64F64::saturating_from_num(0) } #[pallet::storage] /// ITEM --> TAO Flow Cutoff pub type TaoFlowCutoff = StorageValue<_, I64F64, ValueQuery, DefaultFlowCutoff>; #[pallet::type_value] /// Default value for flow normalization exponent. pub fn DefaultFlowNormExponent() -> U64F64 { U64F64::saturating_from_num(1) } #[pallet::storage] /// ITEM --> Flow Normalization Exponent (p) pub type FlowNormExponent = StorageValue<_, U64F64, ValueQuery, DefaultFlowNormExponent>; #[pallet::type_value] /// Default value for flow EMA smoothing. pub fn DefaultFlowEmaSmoothingFactor() -> u64 { // Example values: // half-life factor value i64 normalized (x 2^63) // 216000 (1 month) --> 0.000003209009576 ( 29_597_889_189_277) // 50400 (1 week) --> 0.000013752825678 (126_847_427_788_335) 29_597_889_189_277 } #[pallet::type_value] /// Flow EMA smoothing half-life. pub fn FlowHalfLife() -> u64 { 216_000 } #[pallet::storage] /// ITEM --> Flow EMA smoothing factor (flow alpha), u64 normalized pub type FlowEmaSmoothingFactor = StorageValue<_, u64, ValueQuery, DefaultFlowEmaSmoothingFactor>; // Global Parameters /// StorageItem Global Used Work. #[pallet::storage] pub type UsedWork = StorageMap<_, Identity, Vec, u64, ValueQuery>; /// ITEM( global_max_registrations_per_block ) #[pallet::storage] pub type MaxRegistrationsPerBlock = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMaxRegistrationsPerBlock>; /// ITEM( total_number_of_existing_networks ) #[pallet::storage] pub type TotalNetworks = StorageValue<_, u16, ValueQuery>; /// ITEM( network_immunity_period ) #[pallet::storage] pub type NetworkImmunityPeriod = StorageValue<_, u64, ValueQuery, DefaultNetworkImmunityPeriod>; /// ITEM( start_call_delay ) #[pallet::storage] pub type StartCallDelay = StorageValue<_, u64, ValueQuery, T::InitialStartCallDelay>; /// ITEM( min_network_lock_cost ) #[pallet::storage] pub type NetworkMinLockCost = StorageValue<_, TaoBalance, ValueQuery, DefaultNetworkMinLockCost>; /// ITEM( last_network_lock_cost ) #[pallet::storage] pub type NetworkLastLockCost = StorageValue<_, TaoBalance, ValueQuery, DefaultNetworkMinLockCost>; /// ITEM( network_lock_reduction_interval ) #[pallet::storage] pub type NetworkLockReductionInterval = StorageValue<_, u64, ValueQuery, DefaultNetworkLockReductionInterval>; /// ITEM( subnet_owner_cut ) #[pallet::storage] pub type SubnetOwnerCut = StorageValue<_, u16, ValueQuery, DefaultSubnetOwnerCut>; /// Default value for subnet owner cut enabled flag. #[pallet::type_value] pub fn DefaultOwnerCutEnabled() -> bool { true } /// MAP ( netuid ) --> owner_cut_enabled #[pallet::storage] pub type OwnerCutEnabled = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultOwnerCutEnabled>; /// ITEM( network_rate_limit ) #[pallet::storage] pub type NetworkRateLimit = StorageValue<_, u64, ValueQuery, DefaultNetworkRateLimit>; /// ITEM( nominator_min_required_stake ) --- Factor of DefaultMinStake in per-mill format. #[pallet::storage] pub type NominatorMinRequiredStake = StorageValue<_, u64, ValueQuery, DefaultZeroU64>; /// ITEM( weights_version_key_rate_limit ) --- Rate limit in tempos. #[pallet::storage] pub type WeightsVersionKeyRateLimit = StorageValue<_, u64, ValueQuery, DefaultWeightsVersionKeyRateLimit>; // Rate Limiting /// MAP ( RateLimitKey ) --> Block number in which the last rate limited operation occured #[pallet::storage] pub type LastRateLimitedBlock = StorageMap<_, Identity, RateLimitKey, u64, ValueQuery, DefaultZeroU64>; // Subnet Locks /// MAP ( netuid ) --> transfer_toggle #[pallet::storage] pub type TransferToggle = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultTrue>; /// MAP ( netuid ) --> total_subnet_locked #[pallet::storage] pub type SubnetLocked = StorageMap<_, Identity, NetUid, TaoBalance, ValueQuery, DefaultZeroTao>; /// MAP ( netuid ) --> largest_locked #[pallet::storage] pub type LargestLocked = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; // Tempos /// MAP ( netuid ) --> tempo #[pallet::storage] pub type Tempo = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultTempo>; /// Lower bound for owner-set tempo. Also the fixed cooldown for `sudo_set_tempo`. pub const MIN_TEMPO: u16 = 360; /// Upper bound for owner-set tempo (≈ 7 days at 12 s/block). pub const MAX_TEMPO: u16 = 50_400; /// Lower bound for activity-cutoff factor (per-mille). 1_000 = one full tempo. pub const MIN_ACTIVITY_CUTOFF_FACTOR_MILLI: u32 = 1_000; /// Upper bound for activity-cutoff factor (per-mille). 50_000 = 50 tempos. pub const MAX_ACTIVITY_CUTOFF_FACTOR_MILLI: u32 = 50_000; /// Default activity-cutoff factor (per-mille). 13_889 ≈ legacy 5000-block cutoff /// at default tempo 360 (`13_889 * 360 / 1000 = 5_000`, exact via ceiling rounding). pub const INITIAL_ACTIVITY_CUTOFF_FACTOR_MILLI: u32 = 13_889; /// Default value for activity-cutoff factor (per-mille). #[pallet::type_value] pub fn DefaultActivityCutoffFactorMilli() -> u32 { INITIAL_ACTIVITY_CUTOFF_FACTOR_MILLI } /// MAP ( netuid ) --> last epoch attempt block (consumed slot). /// Drives normal-cadence scheduling and the admin freeze window. /// Advances on every `should_run_epoch == true` slot — including consistency-skipped slots — /// and on a successful `sudo_set_tempo` (cycle reset). #[pallet::storage] pub type LastEpochBlock = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; /// MAP ( netuid ) --> block at which a manually triggered epoch should fire. /// `0` means no trigger pending. Cleared after the triggered epoch runs. #[pallet::storage] pub type PendingEpochAt = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; /// MAP ( netuid ) --> monotonic epoch counter. /// Incremented by exactly one each time the subnet's epoch slot is consumed in `run_coinbase` #[pallet::storage] pub type SubnetEpochIndex = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultZeroU64>; /// MAP ( netuid ) --> activity-cutoff factor in per-mille epochs (1/1000 granularity). /// Effective cutoff in blocks = `(factor × tempo) / 1000`, clamped to ≥ 1. #[pallet::storage] pub type ActivityCutoffFactorMilli = StorageMap<_, Identity, NetUid, u32, ValueQuery, DefaultActivityCutoffFactorMilli>; // Subnet Parameters /// MAP ( netuid ) --> block number of first emission #[pallet::storage] pub type FirstEmissionBlockNumber = StorageMap<_, Identity, NetUid, u64, OptionQuery>; /// MAP ( netuid ) --> subnet mechanism #[pallet::storage] pub type SubnetMechanism = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultZeroU16>; /// MAP ( netuid ) --> subnetwork_n (Number of UIDs in the network). #[pallet::storage] pub type SubnetworkN = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultN>; /// MAP ( netuid ) --> network_is_added #[pallet::storage] pub type NetworksAdded = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultNeworksAdded>; /// DMAP ( hotkey, netuid ) --> bool #[pallet::storage] pub type IsNetworkMember = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, Identity, NetUid, bool, ValueQuery, DefaultIsNetworkMember, >; /// MAP ( netuid ) --> network_registration_allowed #[pallet::storage] pub type NetworkRegistrationAllowed = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultRegistrationAllowed>; /// MAP ( netuid ) --> network_pow_allowed #[pallet::storage] pub type NetworkPowRegistrationAllowed = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultRegistrationAllowed>; /// MAP ( netuid ) --> block_created #[pallet::storage] pub type NetworkRegisteredAt = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultNetworkRegisteredAt>; /// MAP ( netuid ) --> registered_subnet_counter /// /// Monotonic counter incremented on every successful `do_register_network` /// for a given netuid. Consumers that persist per-netuid state keyed by /// `(user, netuid)` (e.g. the staking precompile `AllowancesStorage`) can /// mix the current counter value into their storage key so that entries /// written under a previous registration of the same netuid become /// unreachable after the netuid is re-registered, without requiring /// unbounded storage iteration on deregistration. #[pallet::storage] pub type RegisteredSubnetCounter = StorageMap<_, Identity, NetUid, u64, ValueQuery>; /// MAP ( netuid ) --> pending_server_emission #[pallet::storage] pub type PendingServerEmission = StorageMap<_, Identity, NetUid, AlphaBalance, ValueQuery, DefaultZeroAlpha>; /// MAP ( netuid ) --> pending_validator_emission #[pallet::storage] pub type PendingValidatorEmission = StorageMap<_, Identity, NetUid, AlphaBalance, ValueQuery, DefaultZeroAlpha>; /// MAP ( netuid ) --> pending_root_alpha_emission #[pallet::storage] pub type PendingRootAlphaDivs = StorageMap<_, Identity, NetUid, AlphaBalance, ValueQuery, DefaultZeroAlpha>; /// MAP ( netuid ) --> pending_owner_cut #[pallet::storage] pub type PendingOwnerCut = StorageMap<_, Identity, NetUid, AlphaBalance, ValueQuery, DefaultZeroAlpha>; /// Default miner-burned proportion. #[pallet::type_value] pub fn DefaultMinerBurned() -> U96F32 { U96F32::saturating_from_num(0.0) } /// MAP ( netuid ) --> miner_burned | Proportion (0..1) of this tempo's miner /// (incentive) emission that was withheld from miners during emission distribution /// because the recipient hotkey is owned by the subnet owner (immune key). Counts /// emission that is either recycled or burned, so the value is independent of the /// subnet's RecycleOrBurn configuration. #[pallet::storage] pub type MinerBurned = StorageMap<_, Identity, NetUid, U96F32, ValueQuery, DefaultMinerBurned>; /// MAP ( netuid ) --> blocks_since_last_step #[pallet::storage] pub type BlocksSinceLastStep = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultBlocksSinceLastStep>; /// MAP ( netuid ) --> last_mechanism_step_block #[pallet::storage] pub type LastMechansimStepBlock = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultLastMechanismStepBlock>; /// MAP ( netuid ) --> subnet_owner #[pallet::storage] pub type SubnetOwner = StorageMap<_, Identity, NetUid, T::AccountId, ValueQuery, DefaultSubnetOwner>; /// MAP ( netuid ) --> subnet_owner_hotkey #[pallet::storage] pub type SubnetOwnerHotkey = StorageMap<_, Identity, NetUid, T::AccountId, ValueQuery, DefaultSubnetOwner>; /// MAP ( netuid ) --> recycle_or_burn #[pallet::storage] pub type RecycleOrBurn = StorageMap<_, Identity, NetUid, RecycleOrBurnEnum, ValueQuery, DefaultRecycleOrBurn>; /// MAP ( netuid ) --> serving_rate_limit #[pallet::storage] pub type ServingRateLimit = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultServingRateLimit>; /// MAP ( netuid ) --> Rho #[pallet::storage] pub type Rho = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultRho>; /// MAP ( netuid ) --> AlphaSigmoidSteepness #[pallet::storage] pub type AlphaSigmoidSteepness = StorageMap<_, Identity, NetUid, i16, ValueQuery, DefaultAlphaSigmoidSteepness>; /// MAP ( netuid ) --> Kappa #[pallet::storage] pub type Kappa = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultKappa>; /// MAP ( netuid ) --> registrations_this_interval #[pallet::storage] pub type RegistrationsThisInterval = StorageMap<_, Identity, NetUid, u16, ValueQuery>; /// MAP ( netuid ) --> pow_registrations_this_interval #[pallet::storage] pub type POWRegistrationsThisInterval = StorageMap<_, Identity, NetUid, u16, ValueQuery>; /// MAP ( netuid ) --> burn_registrations_this_interval #[pallet::storage] pub type BurnRegistrationsThisInterval = StorageMap<_, Identity, NetUid, u16, ValueQuery>; /// MAP ( netuid ) --> min_allowed_uids #[pallet::storage] pub type MinAllowedUids = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMinAllowedUids>; /// MAP ( netuid ) --> max_allowed_uids #[pallet::storage] pub type MaxAllowedUids = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMaxAllowedUids>; /// MAP ( netuid ) --> immunity_period #[pallet::storage] pub type ImmunityPeriod = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultImmunityPeriod>; /// MAP ( netuid ) --> activity_cutoff // #[deprecated(note = "Replaced by `ActivityCutoffFactorMilli` (per-mille of `Tempo`).")] #[pallet::storage] pub type ActivityCutoff = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultActivityCutoff>; #[pallet::type_value] /// Default maximum weights limit. pub fn DefaultMaxWeightsLimit() -> u16 { u16::MAX } /// MAP ( netuid ) --> max_weight_limit #[pallet::storage] pub type MaxWeightsLimit = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMaxWeightsLimit>; /// MAP ( netuid ) --> weights_version_key #[pallet::storage] pub type WeightsVersionKey = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultWeightsVersionKey>; /// MAP ( netuid ) --> min_allowed_weights #[pallet::storage] pub type MinAllowedWeights = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMinAllowedWeights>; /// MAP ( netuid ) --> max_allowed_validators #[pallet::storage] pub type MaxAllowedValidators = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMaxAllowedValidators>; /// MAP ( netuid ) --> adjustment_interval #[pallet::storage] pub type AdjustmentInterval = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultAdjustmentInterval>; /// MAP ( netuid ) --> bonds_moving_average #[pallet::storage] pub type BondsMovingAverage = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultBondsMovingAverage>; /// MAP ( netuid ) --> bonds_penalty #[pallet::storage] pub type BondsPenalty = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultBondsPenalty>; /// MAP ( netuid ) --> bonds_reset #[pallet::storage] pub type BondsResetOn = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultBondsResetOn>; /// MAP ( netuid ) --> weights_set_rate_limit #[pallet::storage] pub type WeightsSetRateLimit = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultWeightsSetRateLimit>; /// MAP ( netuid ) --> validator_prune_len #[pallet::storage] pub type ValidatorPruneLen = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultValidatorPruneLen>; /// MAP ( netuid ) --> scaling_law_power #[pallet::storage] pub type ScalingLawPower = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultScalingLawPower>; /// MAP ( netuid ) --> target_registrations_this_interval #[pallet::storage] pub type TargetRegistrationsPerInterval = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultTargetRegistrationsPerInterval>; /// MAP ( netuid ) --> adjustment_alpha #[pallet::storage] pub type AdjustmentAlpha = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultAdjustmentAlpha>; /// MAP ( netuid ) --> commit reveal v2 weights are enabled #[pallet::storage] pub type CommitRevealWeightsEnabled = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultCommitRevealWeightsEnabled>; /// MAP ( netuid ) --> Burn #[pallet::storage] pub type Burn = StorageMap<_, Identity, NetUid, TaoBalance, ValueQuery, DefaultBurn>; /// MAP ( netuid ) --> Difficulty #[pallet::storage] pub type Difficulty = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultDifficulty>; /// MAP ( netuid ) --> MinBurn #[pallet::storage] pub type MinBurn = StorageMap<_, Identity, NetUid, TaoBalance, ValueQuery, DefaultMinBurn>; /// MAP ( netuid ) --> MaxBurn #[pallet::storage] pub type MaxBurn = StorageMap<_, Identity, NetUid, TaoBalance, ValueQuery, DefaultMaxBurn>; /// MAP ( netuid ) --> MinDifficulty #[pallet::storage] pub type MinDifficulty = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultMinDifficulty>; /// MAP ( netuid ) --> MaxDifficulty #[pallet::storage] pub type MaxDifficulty = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultMaxDifficulty>; /// MAP ( netuid ) --> Block at last adjustment. #[pallet::storage] pub type LastAdjustmentBlock = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultLastAdjustmentBlock>; /// MAP ( netuid ) --> Registrations of this Block. #[pallet::storage] pub type RegistrationsThisBlock = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultRegistrationsThisBlock>; /// MAP ( netuid ) --> Halving time of average moving price. #[pallet::storage] pub type EMAPriceHalvingBlocks = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultEMAPriceMovingBlocks>; /// MAP ( netuid ) --> global_RAO_recycled_for_registration #[pallet::storage] pub type RAORecycledForRegistration = StorageMap< _, Identity, NetUid, TaoBalance, ValueQuery, DefaultRAORecycledForRegistration, >; /// ITEM ( max_epochs_per_block ) #[pallet::storage] pub type MaxEpochsPerBlock = StorageValue<_, u8, ValueQuery, DefaultMaxEpochsPerBlock>; /// ITEM ( tx_rate_limit ) #[pallet::storage] pub type TxRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxRateLimit>; /// ITEM ( tx_delegate_take_rate_limit ) #[pallet::storage] pub type TxDelegateTakeRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxDelegateTakeRateLimit>; /// ITEM ( tx_childkey_take_rate_limit ) #[pallet::storage] pub type TxChildkeyTakeRateLimit = StorageValue<_, u64, ValueQuery, DefaultTxChildKeyTakeRateLimit>; /// MAP ( netuid ) --> Whether or not Liquid Alpha is enabled #[pallet::storage] pub type LiquidAlphaOn = StorageMap<_, Blake2_128Concat, NetUid, bool, ValueQuery, DefaultLiquidAlpha>; /// MAP ( netuid ) --> Whether or not Yuma3 is enabled #[pallet::storage] pub type Yuma3On = StorageMap<_, Blake2_128Concat, NetUid, bool, ValueQuery, DefaultYuma3>; /// MAP ( netuid ) --> (alpha_low, alpha_high) #[pallet::storage] pub type AlphaValues = StorageMap<_, Identity, NetUid, (u16, u16), ValueQuery, DefaultAlphaValues>; /// MAP ( netuid ) --> If subtoken trading enabled #[pallet::storage] pub type SubtokenEnabled = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultFalse>; /// ITEM ( dissolve_cleanup_queue ) Networks dissolved but some storage not removed yet #[pallet::storage] pub type DissolveCleanupQueue = StorageValue<_, Vec, ValueQuery>; /// ITEM ( current_dissolve_cleanup_status ) dissolve status for the network #[pallet::storage] pub type CurrentDissolveCleanupStatus = StorageValue<_, DissolveCleanupStatus, OptionQuery>; /// ITEM ( network_registration_queue ) Network registrations waiting to be executed. #[pallet::storage] pub type NetworkRegistrationQueue = StorageValue<_, Vec>>, ValueQuery>; /// MAP ( coldkey ) --> lock_id #[pallet::storage] pub type NetworkRegistrationLockId = StorageValue<_, u32, ValueQuery>; // ======================================= // ==== VotingPower Storage ==== // ======================================= #[pallet::type_value] /// Default VotingPower EMA alpha value (0.1 represented as u64 with 18 decimals) /// alpha = 0.1 means slow response, 10% weight to new values per epoch pub fn DefaultVotingPowerEmaAlpha() -> u64 { 0_003_570_000_000_000_000 // 0.00357 * 10^18 = 2 weeks e-folding (time-constant) @ 361 // blocks per tempo // After 2 weeks -> EMA reaches 63.2% of a step change // After ~4 weeks -> 86.5% // After ~6 weeks -> 95% } #[pallet::storage] /// DMAP ( netuid, hotkey ) --> voting_power | EMA of stake for voting /// This tracks stake EMA updated every epoch when VotingPowerTrackingEnabled is true. /// Used by smart contracts to determine validator voting power for subnet governance. pub type VotingPower = StorageDoubleMap<_, Identity, NetUid, Blake2_128Concat, T::AccountId, u64, ValueQuery>; #[pallet::storage] /// MAP ( netuid ) --> bool | Whether voting power tracking is enabled for this subnet. /// When enabled, VotingPower EMA is updated every epoch. Default is false. /// When disabled with disable_at_block set, tracking continues until that block. pub type VotingPowerTrackingEnabled = StorageMap<_, Identity, NetUid, bool, ValueQuery, DefaultFalse>; #[pallet::storage] /// MAP ( netuid ) --> block_number | Block at which voting power tracking will be disabled. /// When set (non-zero), tracking continues until this block, then automatically disables /// and clears VotingPower entries for the subnet. Provides a 14-day grace period. pub type VotingPowerDisableAtBlock = StorageMap<_, Identity, NetUid, u64, ValueQuery>; #[pallet::storage] /// MAP ( netuid ) --> u64 | EMA alpha value for voting power calculation. /// Higher alpha = faster response to stake changes. /// Stored as u64 with 18 decimal precision (1.0 = 10^18). /// Only settable by sudo/root. pub type VotingPowerEmaAlpha = StorageMap<_, Identity, NetUid, u64, ValueQuery, DefaultVotingPowerEmaAlpha>; #[pallet::type_value] /// Default value for burn keys limit pub fn DefaultImmuneOwnerUidsLimit() -> u16 { 1 } /// Maximum value for burn keys limit #[pallet::type_value] pub fn MaxImmuneOwnerUidsLimit() -> u16 { 10 } /// Minimum value for burn keys limit #[pallet::type_value] pub fn MinImmuneOwnerUidsLimit() -> u16 { 1 } /// MAP ( netuid ) --> Burn key limit #[pallet::storage] pub type ImmuneOwnerUidsLimit = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultImmuneOwnerUidsLimit>; // Subnetwork Consensus Storage /// DMAP ( netuid ) --> stake_weight | weight for stake used in YC. #[pallet::storage] pub type StakeWeight = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyU16Vec>; /// DMAP ( netuid, hotkey ) --> uid #[pallet::storage] pub type Uids = StorageDoubleMap<_, Identity, NetUid, Blake2_128Concat, T::AccountId, u16, OptionQuery>; /// DMAP ( netuid, uid ) --> hotkey #[pallet::storage] pub type Keys = StorageDoubleMap< _, Identity, NetUid, Identity, u16, T::AccountId, ValueQuery, DefaultKey, >; /// MAP ( netuid ) --> (hotkey, se, ve) #[pallet::storage] pub type LoadedEmission = StorageMap<_, Identity, NetUid, Vec<(T::AccountId, u64, u64)>, OptionQuery>; /// MAP ( netuid ) --> active #[pallet::storage] pub type Active = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyBoolVec>; /// MAP ( netuid ) --> consensus #[pallet::storage] pub type Consensus = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyPerU16Vec>; /// MAP ( netuid ) --> incentive #[pallet::storage] pub type Incentive = StorageMap<_, Identity, NetUidStorageIndex, Vec, ValueQuery, EmptyPerU16Vec>; /// MAP ( netuid ) --> dividends #[pallet::storage] pub type Dividends = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyPerU16Vec>; /// MAP ( netuid ) --> emission #[pallet::storage] pub type Emission = StorageMap<_, Identity, NetUid, Vec, ValueQuery>; /// MAP ( netuid ) --> last_update #[pallet::storage] pub type LastUpdate = StorageMap<_, Identity, NetUidStorageIndex, Vec, ValueQuery, EmptyU64Vec>; /// MAP ( netuid ) --> validator_trust #[pallet::storage] pub type ValidatorTrust = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyPerU16Vec>; /// MAP ( netuid ) --> validator_permit #[pallet::storage] pub type ValidatorPermit = StorageMap<_, Identity, NetUid, Vec, ValueQuery, EmptyBoolVec>; /// DMAP ( netuid, uid ) --> weights #[pallet::storage] pub type Weights = StorageDoubleMap< _, Identity, NetUidStorageIndex, Identity, u16, Vec<(u16, u16)>, ValueQuery, DefaultWeights, >; /// DMAP ( netuid, uid ) --> bonds #[pallet::storage] pub type Bonds = StorageDoubleMap< _, Identity, NetUidStorageIndex, Identity, u16, Vec<(u16, u16)>, ValueQuery, DefaultBonds, >; /// DMAP ( netuid, uid ) --> block_at_registration #[pallet::storage] pub type BlockAtRegistration = StorageDoubleMap< _, Identity, NetUid, Identity, u16, u64, ValueQuery, DefaultBlockAtRegistration, >; /// MAP ( netuid, hotkey ) --> axon_info #[pallet::storage] pub type Axons = StorageDoubleMap< _, Identity, NetUid, Blake2_128Concat, T::AccountId, AxonInfoOf, OptionQuery, >; /// MAP ( netuid, hotkey ) --> certificate #[pallet::storage] pub type NeuronCertificates = StorageDoubleMap< _, Identity, NetUid, Blake2_128Concat, T::AccountId, NeuronCertificateOf, OptionQuery, >; /// MAP ( netuid, hotkey ) --> prometheus_info #[pallet::storage] pub type Prometheus = StorageDoubleMap< _, Identity, NetUid, Blake2_128Concat, T::AccountId, PrometheusInfoOf, OptionQuery, >; /// MAP ( coldkey ) --> identity #[pallet::storage] pub type IdentitiesV2 = StorageMap<_, Blake2_128Concat, T::AccountId, ChainIdentityOfV2, OptionQuery>; /// MAP ( netuid ) --> SubnetIdentityOfV3 #[pallet::storage] pub type SubnetIdentitiesV3 = StorageMap<_, Blake2_128Concat, NetUid, SubnetIdentityOfV3, OptionQuery>; // Axon / Promo Endpoints /// NMAP ( hot, netuid, name ) --> last_block | Returns the last block of a transaction for a given key, netuid, and name. #[pallet::storage] pub type TransactionKeyLastBlock = StorageNMap< _, ( NMapKey, // hot NMapKey, // netuid NMapKey, // extrinsic enum. ), u64, ValueQuery, >; /// MAP ( key ) --> last_block #[deprecated] #[pallet::storage] pub type LastTxBlock = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultLastTxBlock>; /// MAP ( key ) --> last_tx_block_childkey_take #[deprecated] #[pallet::storage] pub type LastTxBlockChildKeyTake = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultLastTxBlock>; /// MAP ( key ) --> last_tx_block_delegate_take #[deprecated] #[pallet::storage] pub type LastTxBlockDelegateTake = StorageMap<_, Identity, T::AccountId, u64, ValueQuery, DefaultLastTxBlock>; /// ITEM( weights_min_stake ) // FIXME: this storage is used interchangably for alpha/tao #[pallet::storage] pub type StakeThreshold = StorageValue<_, u64, ValueQuery, DefaultStakeThreshold>; /// MAP (netuid, who) --> VecDeque<(hash, commit_epoch, commit_block, _unused)> /// Stores a queue of commit-reveal-v2 commits for an account on a given netuid. #[pallet::storage] pub type WeightCommits = StorageDoubleMap< _, Twox64Concat, NetUidStorageIndex, Twox64Concat, T::AccountId, VecDeque<(H256, u64, u64, u64)>, OptionQuery, >; /// MAP (netuid, epoch) → VecDeque<(who, commit_block, ciphertext, reveal_round)> /// Stores a queue of weight commits for an account on a given subnet. #[pallet::storage] pub type TimelockedWeightCommits = StorageDoubleMap< _, Twox64Concat, NetUidStorageIndex, Twox64Concat, u64, // epoch key VecDeque<( T::AccountId, u64, // commit_block BoundedVec>, RoundNumber, )>, ValueQuery, >; /// MAP (netuid, epoch) → VecDeque<(who, ciphertext, reveal_round)> /// Deprecated: superseded by `CRV3WeightCommitsV2`. #[pallet::storage] pub type CRV3WeightCommits = StorageDoubleMap< _, Twox64Concat, NetUidStorageIndex, Twox64Concat, u64, // epoch key VecDeque<( T::AccountId, BoundedVec>, RoundNumber, )>, ValueQuery, >; /// MAP (netuid, epoch) → VecDeque<(who, commit_block, ciphertext, reveal_round)> /// Deprecated: superseded by `TimelockedWeightCommits`. #[pallet::storage] pub type CRV3WeightCommitsV2 = StorageDoubleMap< _, Twox64Concat, NetUidStorageIndex, Twox64Concat, u64, // epoch key VecDeque<( T::AccountId, u64, // commit_block BoundedVec>, RoundNumber, )>, ValueQuery, >; /// Map (netuid) --> Number of epochs allowed for commit reveal periods #[pallet::storage] pub type RevealPeriodEpochs = StorageMap<_, Twox64Concat, NetUid, u64, ValueQuery, DefaultRevealPeriodEpochs>; /// Map (coldkey, hotkey) --> u64 the last block at which stake was added/removed. #[pallet::storage] pub type LastColdkeyHotkeyStakeBlock = StorageDoubleMap< _, Twox64Concat, T::AccountId, Twox64Concat, T::AccountId, u64, OptionQuery, >; #[pallet::storage] // --- MAP(netuid ) --> Root claim threshold pub type RootClaimableThreshold = StorageMap<_, Blake2_128Concat, NetUid, I96F32, ValueQuery, DefaultMinRootClaimAmount>; #[pallet::storage] // --- MAP ( hot ) --> MAP(netuid ) --> claimable_dividends | Root claimable dividends. pub type RootClaimable = StorageMap< _, Blake2_128Concat, T::AccountId, BTreeMap, ValueQuery, DefaultRootClaimable, >; // Already claimed root alpha. #[pallet::storage] pub type RootClaimed = StorageNMap< _, ( NMapKey, // subnet NMapKey, // hot NMapKey, // cold ), u128, ValueQuery, >; #[pallet::storage] // -- MAP ( cold ) --> root_claim_type enum pub type RootClaimType = StorageMap< _, Blake2_128Concat, T::AccountId, RootClaimTypeEnum, ValueQuery, DefaultRootClaimType, >; #[pallet::storage] // --- MAP ( u64 ) --> coldkey | Maps coldkeys that have stake to an index pub type StakingColdkeysByIndex = StorageMap<_, Identity, u64, T::AccountId, OptionQuery>; #[pallet::storage] // --- MAP ( coldkey ) --> index | Maps index that have stake to a coldkey pub type StakingColdkeys = StorageMap<_, Identity, T::AccountId, u64, OptionQuery>; #[pallet::storage] // --- Value --> num_staking_coldkeys pub type NumStakingColdkeys = StorageValue<_, u64, ValueQuery, DefaultZeroU64>; #[pallet::storage] // --- Value --> num_root_claim | Number of coldkeys to claim each auto-claim. pub type NumRootClaim = StorageValue<_, u64, ValueQuery, DefaultNumRootClaim>; // EVM related storage /// DMAP (netuid, uid) --> (H160, last_block_where_ownership_was_proven) #[pallet::storage] pub type AssociatedEvmAddress = StorageDoubleMap<_, Twox64Concat, NetUid, Twox64Concat, u16, (H160, u64), OptionQuery>; /// DMAP (netuid, H160) --> associated UIDs and last block where ownership was proven. #[pallet::storage] pub type AssociatedUidsByEvmAddress = StorageDoubleMap< _, Twox64Concat, NetUid, Twox64Concat, H160, BoundedVec<(u16, u64), ConstU32>, ValueQuery, >; // Subnet Leasing /// MAP ( lease_id ) --> subnet lease | The subnet lease for a given lease id. #[pallet::storage] pub type SubnetLeases = StorageMap<_, Twox64Concat, LeaseId, SubnetLeaseOf, OptionQuery>; /// DMAP ( lease_id, contributor ) --> shares | The shares of a contributor for a given lease. #[pallet::storage] pub type SubnetLeaseShares = StorageDoubleMap<_, Twox64Concat, LeaseId, Identity, T::AccountId, U64F64, ValueQuery>; /// MAP ( netuid ) --> lease_id | The lease id for a given netuid. #[pallet::storage] pub type SubnetUidToLeaseId = StorageMap<_, Twox64Concat, NetUid, LeaseId, OptionQuery>; /// ITEM ( next_lease_id ) | The next lease id. #[pallet::storage] pub type NextSubnetLeaseId = StorageValue<_, LeaseId, ValueQuery, ConstU32<0>>; /// MAP ( lease_id ) --> accumulated_dividends | The accumulated dividends for a given lease that needs to be distributed. #[pallet::storage] pub type AccumulatedLeaseDividends = StorageMap<_, Twox64Concat, LeaseId, AlphaBalance, ValueQuery, DefaultZeroAlpha>; /// ITEM ( CommitRevealWeightsVersion ) #[pallet::storage] pub type CommitRevealWeightsVersion = StorageValue<_, u16, ValueQuery, DefaultCommitRevealWeightsVersion>; /// ITEM( NetworkRegistrationStartBlock ) #[pallet::storage] pub type NetworkRegistrationStartBlock = StorageValue<_, u64, ValueQuery, DefaultNetworkRegistrationStartBlock>; /// ITEM( TaoInRefundDeploymentBlock ) #[pallet::storage] pub type TaoInRefundDeploymentBlock = StorageValue<_, u64, ValueQuery, DefaultTaoInRefundDeploymentBlock>; /// MAP ( netuid ) --> minimum required number of non-immortal & non-immune UIDs #[pallet::storage] pub type MinNonImmuneUids = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultMinNonImmuneUids>; // Subnet Mechanisms /// ITEM (Default number of sub-subnets) #[pallet::type_value] pub fn DefaultMechanismCount() -> MechId { MechId::from(1) } /// ITEM (Maximum number of mechanisms) #[pallet::type_value] pub fn DefaultMaxMechanismCount() -> MechId { MechId::from(2) } /// ITEM( max_mechanism_count ) #[pallet::storage] pub type MaxMechanismCount = StorageValue<_, MechId, ValueQuery, DefaultMaxMechanismCount>; /// ITEM (Rate limit for mechanism count updates) #[pallet::type_value] pub fn MechanismCountSetRateLimit() -> u64 { prod_or_fast!(7_200, 1) } /// ITEM (Rate limit for mechanism emission distribution updates) #[pallet::type_value] pub fn MechanismEmissionRateLimit() -> u64 { prod_or_fast!(7_200, 1) } /// MAP ( netuid ) --> Current number of subnet mechanisms #[pallet::storage] pub type MechanismCountCurrent = StorageMap<_, Twox64Concat, NetUid, MechId, ValueQuery, DefaultMechanismCount>; /// MAP ( netuid ) --> Normalized vector of emission split proportion between subnet mechanisms #[pallet::storage] pub type MechanismEmissionSplit = StorageMap<_, Twox64Concat, NetUid, Vec, OptionQuery>; /// MAP ( netuid ) --> BurnHalfLife (blocks) #[pallet::storage] pub type BurnHalfLife = StorageMap<_, Identity, NetUid, u16, ValueQuery, DefaultBurnHalfLife>; /// MAP ( netuid ) --> BurnIncreaseMult #[pallet::storage] pub type BurnIncreaseMult = StorageMap<_, Identity, NetUid, U64F64, ValueQuery, DefaultBurnIncreaseMult>; /// MAP ( hotkey ) --> parent_delegation_enabled /// /// When `true`, this root validator allows auto parent delegation. /// Defaults to `true`; validators can opt out at any time /// by calling `set_auto_parent_delegation_enabled(false)`. #[pallet::storage] pub type AutoParentDelegationEnabled = StorageMap< _, Blake2_128Concat, T::AccountId, bool, ValueQuery, DefaultAutoParentDelegationEnabled, // default = true >; // Genesis /// Storage for migration run status #[pallet::storage] pub type HasMigrationRun = StorageMap<_, Identity, Vec, bool, ValueQuery>; /// Default value for pending childkey cooldown (settable by root). /// Uses the same value as DefaultPendingCooldown for consistency. #[pallet::type_value] pub fn DefaultPendingChildKeyCooldown() -> u64 { DefaultPendingCooldown::::get() } /// Storage value for pending childkey cooldown, settable by root. #[pallet::storage] pub type PendingChildKeyCooldown = StorageValue<_, u64, ValueQuery, DefaultPendingChildKeyCooldown>; #[pallet::genesis_config] pub struct GenesisConfig { /// Stakes record in genesis. pub stakes: Vec<(T::AccountId, Vec<(T::AccountId, (u64, u16))>)>, /// The total issued balance in genesis pub balances_issuance: TaoBalance, /// The delay before a subnet can call start pub start_call_delay: Option, } impl Default for GenesisConfig { fn default() -> Self { Self { stakes: Default::default(), balances_issuance: TaoBalance::ZERO, start_call_delay: None, } } } // ---- Subtensor helper functions. impl Pallet { /// Is the caller allowed to set weights pub fn check_weights_min_stake(hotkey: &T::AccountId, netuid: NetUid) -> bool { // Allow the subnet owner hotkey to set weights regardless of stake. if let Some(owner_uid) = Self::get_owner_uid(netuid) && Uids::::get(netuid, hotkey) == Some(owner_uid) { return true; } // Blacklist weights transactions for low stake peers. let (total_stake, _, _) = Self::get_stake_weights_for_hotkey_on_subnet(hotkey, netuid); total_stake >= Self::get_stake_threshold() } /// Helper function to check if register is allowed pub fn checked_allowed_register(netuid: NetUid) -> bool { if netuid.is_root() { return false; } if !Self::if_subnet_exist(netuid) { return false; } if !Self::get_network_registration_allowed(netuid) { return false; } if Self::get_registrations_this_block(netuid) >= Self::get_max_registrations_per_block(netuid) { return false; } if Self::get_registrations_this_interval(netuid) >= Self::get_target_registrations_per_interval(netuid).saturating_mul(3) { return false; } true } /// Ensure subtoken enalbed pub fn ensure_subtoken_enabled(subnet: NetUid) -> Result<(), Error> { ensure!( SubtokenEnabled::::get(subnet), Error::::SubtokenDisabled ); Ok(()) } } } use sp_std::vec; // TODO: unravel this rats nest, for some reason rustc thinks this is unused even though it's // used not 25 lines below #[allow(unused)] use sp_std::vec::Vec; use subtensor_macros::freeze_struct; #[derive(Clone)] pub struct TaoBalanceReserve(PhantomData); impl TokenReserve for TaoBalanceReserve { #![deny(clippy::expect_used)] fn reserve(netuid: NetUid) -> TaoBalance { SubnetTAO::::get(netuid) } fn increase_provided(netuid: NetUid, tao: TaoBalance) { Pallet::::increase_provided_tao_reserve(netuid, tao); } fn decrease_provided(netuid: NetUid, tao: TaoBalance) { Pallet::::decrease_provided_tao_reserve(netuid, tao); } } #[derive(Clone)] pub struct AlphaBalanceReserve(PhantomData); impl TokenReserve for AlphaBalanceReserve { #![deny(clippy::expect_used)] fn reserve(netuid: NetUid) -> AlphaBalance { SubnetAlphaIn::::get(netuid) } fn increase_provided(netuid: NetUid, alpha: AlphaBalance) { Pallet::::increase_provided_alpha_reserve(netuid, alpha); } fn decrease_provided(netuid: NetUid, alpha: AlphaBalance) { Pallet::::decrease_provided_alpha_reserve(netuid, alpha); } } pub type GetAlphaForTao = subtensor_swap_interface::GetAlphaForTao, AlphaBalanceReserve>; pub type GetTaoForAlpha = subtensor_swap_interface::GetTaoForAlpha, TaoBalanceReserve>; impl> subtensor_runtime_common::SubnetInfo for Pallet { #![deny(clippy::expect_used)] fn exists(netuid: NetUid) -> bool { Self::if_subnet_exist(netuid) } fn mechanism(netuid: NetUid) -> u16 { SubnetMechanism::::get(netuid) } fn is_owner(account_id: &T::AccountId, netuid: NetUid) -> bool { SubnetOwner::::get(netuid) == *account_id } fn is_subtoken_enabled(netuid: NetUid) -> bool { SubtokenEnabled::::get(netuid) } fn get_validator_trust(netuid: NetUid) -> Vec { ValidatorTrust::::get(netuid) .into_iter() .map(PerU16::deconstruct) .collect() } fn get_validator_permit(netuid: NetUid) -> Vec { ValidatorPermit::::get(netuid) } fn hotkey_of_uid(netuid: NetUid, uid: u16) -> Option { Keys::::try_get(netuid, uid).ok() } } impl> subtensor_runtime_common::BalanceOps for Pallet { #![deny(clippy::expect_used)] fn tao_balance(account_id: &T::AccountId) -> TaoBalance { pallet_balances::Pallet::::free_balance(account_id).into() } fn alpha_balance( netuid: NetUid, coldkey: &T::AccountId, hotkey: &T::AccountId, ) -> AlphaBalance { Self::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid) } fn increase_stake( coldkey: &T::AccountId, hotkey: &T::AccountId, netuid: NetUid, alpha: AlphaBalance, ) -> Result<(), DispatchError> { ensure!( Self::hotkey_account_exists(hotkey), Error::::HotKeyAccountNotExists ); // Increse alpha out counter SubnetAlphaOut::::mutate(netuid, |total| { *total = total.saturating_add(alpha); }); Self::increase_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid, alpha); Ok(()) } fn decrease_stake( coldkey: &T::AccountId, hotkey: &T::AccountId, netuid: NetUid, alpha: AlphaBalance, ) -> Result<(), DispatchError> { ensure!( Self::hotkey_account_exists(hotkey), Error::::HotKeyAccountNotExists ); ensure!( Self::get_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid) >= alpha, Error::::InsufficientAlphaBalance ); // Decrese alpha out counter SubnetAlphaOut::::mutate(netuid, |total| { *total = total.saturating_sub(alpha); }); Self::decrease_stake_for_hotkey_and_coldkey_on_subnet(hotkey, coldkey, netuid, alpha); Ok(()) } } /// Enum that defines types of rate limited operations for /// storing last block when this operation occured #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo)] pub enum RateLimitKey { // The setting sn owner hotkey operation is rate limited per netuid #[codec(index = 0)] SetSNOwnerHotkey(NetUid), // Generic rate limit for subnet-owner hyperparameter updates (per netuid) #[codec(index = 1)] OwnerHyperparamUpdate(NetUid, Hyperparameter), // Subnet registration rate limit #[codec(index = 2)] NetworkLastRegistered, // Last tx block limit per account ID #[codec(index = 3)] LastTxBlock(AccountId), // Last tx block child key limit per account ID #[codec(index = 4)] LastTxBlockChildKeyTake(AccountId), // Last tx block delegate key limit per account ID #[codec(index = 5)] LastTxBlockDelegateTake(AccountId), // "Add stake and burn" rate limit #[codec(index = 6)] AddStakeBurn(NetUid), } pub trait ProxyInterface { fn add_lease_beneficiary_proxy(beneficiary: &AccountId, lease: &AccountId) -> DispatchResult; fn remove_lease_beneficiary_proxy(beneficiary: &AccountId, lease: &AccountId) -> DispatchResult; } impl ProxyInterface for () { fn add_lease_beneficiary_proxy(_: &T, _: &T) -> DispatchResult { Ok(()) } fn remove_lease_beneficiary_proxy(_: &T, _: &T) -> DispatchResult { Ok(()) } } /// Pallets that hold per-subnet commitments implement this to purge all state for `netuid`. pub trait CommitmentsInterface { fn purge_netuid(netuid: NetUid, weight_meter: &mut WeightMeter) -> bool; }