diff --git a/Cargo.lock b/Cargo.lock index 2868bde70..e4ee5fa7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2844,6 +2844,7 @@ dependencies = [ "pallet-collator-assignment-runtime-api", "pallet-configuration", "pallet-im-online", + "pallet-inflation-rewards", "pallet-initializer", "pallet-invulnerables", "pallet-maintenance-mode", @@ -7199,6 +7200,7 @@ dependencies = [ name = "pallet-author-noting" version = "0.1.0" dependencies = [ + "bounded-collections", "cumulus-pallet-parachain-system", "cumulus-primitives-core", "frame-benchmarking", @@ -7883,6 +7885,30 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-inflation-rewards" +version = "0.1.0" +dependencies = [ + "bounded-collections", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "nimbus-primitives", + "num-traits", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "serde", + "similar-asserts", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "tp-core", + "tp-traits", +] + [[package]] name = "pallet-initializer" version = "0.1.0" @@ -7916,6 +7942,7 @@ dependencies = [ "sp-runtime", "sp-staking", "sp-std", + "tp-traits", ] [[package]] @@ -8149,6 +8176,8 @@ dependencies = [ "sp-runtime", "sp-std", "tp-core", + "tp-maths", + "tp-traits", ] [[package]] @@ -15170,11 +15199,20 @@ dependencies = [ "sp-std", ] +[[package]] +name = "tp-maths" +version = "0.1.0" +dependencies = [ + "sp-core", + "sp-runtime", +] + [[package]] name = "tp-traits" version = "0.1.0" dependencies = [ "cumulus-primitives-core", + "frame-support", "sp-std", ] diff --git a/Cargo.toml b/Cargo.toml index 2302a4e6e..7afb36e84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ authors = [ "Moondance Labs" ] repository = "https://github.com/moondance-labs/tanssi" [workspace.dependencies] + # Members pallet-author-noting = { path = "pallets/author-noting", default-features = false } pallet-author-noting-runtime-api = { path = "pallets/author-noting/rpc/runtime-api", default-features = false } @@ -28,6 +29,7 @@ pallet-authority-mapping = { path = "pallets/authority-mapping", default-feature pallet-collator-assignment = { path = "pallets/collator-assignment", default-features = false } pallet-collator-assignment-runtime-api = { path = "pallets/collator-assignment/rpc/runtime-api", default-features = false } pallet-configuration = { path = "pallets/configuration", default-features = false } +pallet-inflation-rewards = { path = "pallets/inflation-rewards", default-features = false } pallet-initializer = { path = "pallets/initializer", default-features = false } pallet-invulnerables = { path = "pallets/invulnerables", default-features = false } pallet-pooled-staking = { path = "pallets/pooled-staking", default-features = false } @@ -52,6 +54,7 @@ tp-collator-assignment = { path = "primitives/collator-assignment", default-feat tp-consensus = { path = "primitives/consensus", default-features = false } tp-container-chain-genesis-data = { path = "primitives/container-chain-genesis-data", default-features = false } tp-core = { path = "primitives/core", default-features = false } +tp-maths = { path = "primitives/maths", default-features = false } tp-traits = { path = "primitives/traits", default-features = false } # Moonkit (wasm) @@ -217,6 +220,7 @@ fc-rpc-core = { git = "https://github.com/moondance-labs/frontier", branch = "ta fc-storage = { git = "https://github.com/moondance-labs/frontier", branch = "tanssi-polkadot-v1.1.0", default-features = false } # General (wasm) +bounded-collections = { version = "0.1.8", default-features = false } hex-literal = { version = "0.3.4" } log = { version = "0.4.17", default-features = false } serde = { version = "1.0.152", default-features = false } diff --git a/container-chains/primitives/authorities-noting-inherent/src/tests.rs b/container-chains/primitives/authorities-noting-inherent/src/tests.rs index a72abc8fe..c2861f3a6 100644 --- a/container-chains/primitives/authorities-noting-inherent/src/tests.rs +++ b/container-chains/primitives/authorities-noting-inherent/src/tests.rs @@ -18,18 +18,17 @@ use { super::*, crate::ContainerChainAuthoritiesInherentData, async_trait::async_trait, - cumulus_primitives_core::relay_chain::BlockId, cumulus_primitives_core::{ relay_chain::{ - CommittedCandidateReceipt, HeadData, OccupiedCoreAssumption, SessionIndex, ValidatorId, + BlockId, CommittedCandidateReceipt, HeadData, OccupiedCoreAssumption, SessionIndex, + ValidatorId, }, InboundDownwardMessage, InboundHrmpMessage, ParaId, PersistedValidationData, }, cumulus_relay_chain_interface::{PHash, PHeader, RelayChainInterface, RelayChainResult}, futures::Stream, polkadot_overseer::Handle, - sc_client_api::HeaderBackend, - sc_client_api::{StorageKey, StorageProvider}, + sc_client_api::{HeaderBackend, StorageKey, StorageProvider}, sp_inherents::{InherentData, InherentDataProvider}, sp_state_machine::{prove_read, StorageValue}, std::{collections::BTreeMap, pin::Pin, sync::Arc}, diff --git a/container-chains/templates/frontier/node/src/service.rs b/container-chains/templates/frontier/node/src/service.rs index 88e9d310e..9a28d6178 100644 --- a/container-chains/templates/frontier/node/src/service.rs +++ b/container-chains/templates/frontier/node/src/service.rs @@ -22,23 +22,23 @@ use { sc_network::config::FullNetworkConfiguration, }; // std -use futures::FutureExt; -use sc_client_api::Backend; -use sc_transaction_pool_api::OffchainTransactionPoolFactory; -use std::{ - collections::BTreeMap, - sync::{Arc, Mutex}, - time::Duration, -}; use { cumulus_client_cli::CollatorOptions, cumulus_primitives_parachain_inherent::{ MockValidationDataInherentDataProvider, MockXcmConfig, }, fc_consensus::FrontierBlockImport, + futures::FutureExt, nimbus_primitives::NimbusId, + sc_client_api::Backend, + sc_transaction_pool_api::OffchainTransactionPoolFactory, sp_consensus_aura::SlotDuration, sp_core::Pair, + std::{ + collections::BTreeMap, + sync::{Arc, Mutex}, + time::Duration, + }, }; // Local Runtime Types use { diff --git a/container-chains/templates/simple/node/src/service.rs b/container-chains/templates/simple/node/src/service.rs index c7c1a13f0..550bc33d9 100644 --- a/container-chains/templates/simple/node/src/service.rs +++ b/container-chains/templates/simple/node/src/service.rs @@ -37,8 +37,8 @@ use { }; // Substrate Imports -use futures::FutureExt; use { + futures::FutureExt, sc_client_api::Backend, sc_consensus::ImportQueue, sc_executor::NativeElseWasmExecutor, diff --git a/node/src/service.rs b/node/src/service.rs index 387e5f67f..4d85901b3 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -16,8 +16,6 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. -use futures::FutureExt; -use sc_transaction_pool_api::OffchainTransactionPoolFactory; #[allow(deprecated)] use { crate::{ @@ -82,6 +80,7 @@ use { }, tokio::sync::mpsc::{unbounded_channel, UnboundedSender}, }; +use {futures::FutureExt, sc_transaction_pool_api::OffchainTransactionPoolFactory}; type FullBackend = TFullBackend; type MaybeSelectChain = Option>; diff --git a/pallets/author-noting/Cargo.toml b/pallets/author-noting/Cargo.toml index 9d83b363a..488f2890d 100644 --- a/pallets/author-noting/Cargo.toml +++ b/pallets/author-noting/Cargo.toml @@ -33,6 +33,7 @@ tp-core = { workspace = true } tp-traits = { workspace = true } [dev-dependencies] +bounded-collections = { workspace = true } hex-literal = { workspace = true } polkadot-parachain-primitives = { workspace = true } polkadot-primitives = { workspace = true } diff --git a/pallets/author-noting/src/lib.rs b/pallets/author-noting/src/lib.rs index 78d16a25d..9dcc42e6b 100644 --- a/pallets/author-noting/src/lib.rs +++ b/pallets/author-noting/src/lib.rs @@ -45,7 +45,7 @@ use { sp_runtime::{traits::Header, DispatchResult, RuntimeString}, tp_author_noting_inherent::INHERENT_IDENTIFIER, tp_core::well_known_keys::PARAS_HEADS_INDEX, - tp_traits::{GetContainerChainAuthor, GetCurrentContainerChains}, + tp_traits::{AuthorNotingHook, GetContainerChainAuthor, GetCurrentContainerChains}, }; #[cfg(test)] @@ -81,6 +81,11 @@ pub mod pallet { type RelayChainStateProvider: cumulus_pallet_parachain_system::RelaychainStateProvider; + /// An entry-point for higher-level logic to react to containers chains authoring. + /// + /// Typically, this can be a hook to reward block authors. + type AuthorNotingHook: AuthorNotingHook; + /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; } @@ -140,7 +145,7 @@ pub mod pallet { ); let registered_para_ids = T::ContainerChains::current_container_chains(); - let total_weight = + let mut total_weight = T::WeightInfo::set_latest_author_data(registered_para_ids.len() as u32); // We do this first to make sure we dont do 2 reads (parachains and relay state) @@ -151,15 +156,49 @@ pub mod pallet { relay_storage_proof, } = data; - let relay_storage_root = - T::RelayChainStateProvider::current_relay_chain_state().state_root; + let relay_chain_state = T::RelayChainStateProvider::current_relay_chain_state(); + let relay_storage_root = relay_chain_state.state_root; let relay_storage_rooted_proof = GenericStateProof::new(relay_storage_root, relay_storage_proof) .expect("Invalid relay chain state proof"); + // TODO: we should probably fetch all authors-containers first + // then pass the vector to the hook, this would allow for a better estimation for para_id in registered_para_ids { match Self::fetch_block_info_from_proof(&relay_storage_rooted_proof, para_id) { - Ok(block_info) => LatestAuthor::::insert(para_id, block_info), + Ok(block_info) => { + LatestAuthor::::mutate( + para_id, + |maybe_old_block_info: &mut Option>| { + if let Some(ref mut old_block_info) = maybe_old_block_info { + if block_info.block_number > old_block_info.block_number { + // We only reward author if the block increases + total_weight = total_weight.saturating_add( + T::AuthorNotingHook::on_container_author_noted( + &block_info.author, + block_info.block_number, + para_id, + ), + ); + let _ = core::mem::replace(old_block_info, block_info); + } + } else { + // If there is no previous block, we should reward the author of the first block + total_weight = total_weight.saturating_add( + T::AuthorNotingHook::on_container_author_noted( + &block_info.author, + block_info.block_number, + para_id, + ), + ); + let _ = core::mem::replace( + maybe_old_block_info, + Some(block_info), + ); + } + }, + ); + } Err(e) => log::warn!( "Author-noting error {:?} found in para {:?}", e, diff --git a/pallets/author-noting/src/mock.rs b/pallets/author-noting/src/mock.rs index 9f10f421f..c772568a5 100644 --- a/pallets/author-noting/src/mock.rs +++ b/pallets/author-noting/src/mock.rs @@ -16,6 +16,7 @@ use { crate::{self as author_noting_pallet, Config}, + bounded_collections::bounded_vec, cumulus_pallet_parachain_system::{RelayChainState, RelaychainStateProvider}, cumulus_primitives_core::ParaId, frame_support::{ @@ -25,14 +26,15 @@ use { ConstU32, ConstU64, Everything, OnFinalize, OnInitialize, UnfilteredDispatchable, }, }, - frame_system::pallet_prelude::BlockNumberFor, - frame_system::RawOrigin, + frame_system::{pallet_prelude::BlockNumberFor, RawOrigin}, parity_scale_codec::{Decode, Encode}, polkadot_parachain_primitives::primitives::RelayChainBlockNumber, polkadot_primitives::Slot, sp_core::H256, - sp_runtime::traits::{BlakeTwo256, IdentityLookup}, - sp_runtime::BuildStorage, + sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + BoundedVec, BuildStorage, + }, sp_state_machine::StorageProof, test_relay_sproof_builder::ParaHeaderSproofBuilder, }; @@ -116,13 +118,13 @@ impl mock_data::Config for Test {} #[derive(Clone, Encode, Decode, PartialEq, sp_core::RuntimeDebug, scale_info::TypeInfo)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub struct Mocks { - pub container_chains: Vec, + pub container_chains: BoundedVec>, } impl Default for Mocks { fn default() -> Self { Self { - container_chains: vec![1001.into()], + container_chains: bounded_vec![1001.into()], } } } @@ -141,7 +143,9 @@ impl tp_traits::GetContainerChainAuthor for MockAuthorFetcher { pub struct MockContainerChainGetter; impl tp_traits::GetCurrentContainerChains for MockContainerChainGetter { - fn current_container_chains() -> Vec { + type MaxContainerChains = ConstU32<5>; + + fn current_container_chains() -> BoundedVec { MockData::mock().container_chains } @@ -181,6 +185,7 @@ impl Config for Test { type ContainerChainAuthor = MockAuthorFetcher; type SelfParaId = ParachainId; type ContainerChains = MockContainerChainGetter; + type AuthorNotingHook = (); type RelayChainStateProvider = MockRelayStateProvider; } diff --git a/pallets/author-noting/src/tests.rs b/pallets/author-noting/src/tests.rs index e2e885e36..412497738 100644 --- a/pallets/author-noting/src/tests.rs +++ b/pallets/author-noting/src/tests.rs @@ -16,6 +16,7 @@ use { crate::{mock::*, ContainerChainBlockInfo, Event}, + bounded_collections::bounded_vec, cumulus_primitives_core::ParaId, frame_support::{ assert_ok, @@ -166,7 +167,7 @@ fn test_author_id_insertion_many_paras() { // Writing to this pallet storage will only change the sproofs of the next block, // not the ones of the current block MockData::mutate(|m| { - m.container_chains = vec![1001.into(), 1002.into()]; + m.container_chains = bounded_vec![1001.into(), 1002.into()]; }); assert_eq!( AuthorNoting::latest_author(ParaId::from(1001)), diff --git a/pallets/collator-assignment/src/lib.rs b/pallets/collator-assignment/src/lib.rs index f52307f05..5ec6480b0 100644 --- a/pallets/collator-assignment/src/lib.rs +++ b/pallets/collator-assignment/src/lib.rs @@ -93,6 +93,7 @@ pub mod pallet { // which guarantees that at least one full session has passed before any changes are applied. type HostConfiguration: GetHostConfiguration; type ContainerChains: GetSessionContainerChains; + type SelfParaId: Get; type ShouldRotateAllCollators: ShouldRotateAllCollators; type GetRandomnessForNextBlock: GetRandomnessForNextBlock>; type RemoveInvulnerables: RemoveInvulnerables; @@ -411,9 +412,15 @@ pub mod pallet { } impl GetContainerChainAuthor for Pallet { + // TODO: pending collator container chain if the block is a session change! fn author_for_slot(slot: Slot, para_id: ParaId) -> Option { let assigned_collators = Pallet::::collator_container_chain(); - let collators = assigned_collators.container_chains.get(¶_id)?; + let collators = if para_id == T::SelfParaId::get() { + Some(&assigned_collators.orchestrator_chain) + } else { + assigned_collators.container_chains.get(¶_id) + }?; + if collators.is_empty() { // Avoid division by zero below return None; diff --git a/pallets/collator-assignment/src/mock.rs b/pallets/collator-assignment/src/mock.rs index 31ad6d91c..a80d4a837 100644 --- a/pallets/collator-assignment/src/mock.rs +++ b/pallets/collator-assignment/src/mock.rs @@ -122,6 +122,10 @@ impl mock_data::Config for Test {} pub struct HostConfigurationGetter; +parameter_types! { + pub const ParachainId: ParaId = ParaId::new(200); +} + impl pallet_collator_assignment::GetHostConfiguration for HostConfigurationGetter { fn min_collators_for_orchestrator(_session_index: u32) -> u32 { MockData::mock().min_orchestrator_chain_collators @@ -185,6 +189,7 @@ impl pallet_collator_assignment::Config for Test { type SessionIndex = u32; type HostConfiguration = HostConfigurationGetter; type ContainerChains = ContainerChainsGetter; + type SelfParaId = ParachainId; type ShouldRotateAllCollators = RotateCollatorsEveryNSessions; type GetRandomnessForNextBlock = MockGetRandomnessForNextBlock; type RemoveInvulnerables = RemoveAccountIdsAbove100; diff --git a/pallets/inflation-rewards/Cargo.toml b/pallets/inflation-rewards/Cargo.toml new file mode 100644 index 000000000..3b472b32a --- /dev/null +++ b/pallets/inflation-rewards/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "pallet-inflation-rewards" +authors = { workspace = true } +description = "A pallet to handle token inflation and rewards" +edition = "2021" +license = "GPL-3.0-only" +version = "0.1.0" + +[package.metadata.docs.rs] +targets = [ "x86_64-unknown-linux-gnu" ] + +[dependencies] + +log = { workspace = true } +serde = { workspace = true, optional = true } +tp-core = { workspace = true } +tp-traits = { workspace = true } + +# Substrate +frame-benchmarking = { workspace = true, optional = true } +frame-support = { workspace = true } +frame-system = { workspace = true } + +# Nimbus +nimbus-primitives = { workspace = true } +parity-scale-codec = { workspace = true } +scale-info = { workspace = true } +sp-core = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } + +[dev-dependencies] +bounded-collections = { workspace = true } +num-traits = { workspace = true } +pallet-balances = { workspace = true, features = [ "std" ] } +similar-asserts = { workspace = true } +sp-io = { workspace = true, features = [ "std" ] } + +[features] +default = [ "std" ] +std = [ + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "log/std", + "nimbus-primitives/std", + "parity-scale-codec/std", + "scale-info/std", + "serde", + "sp-runtime/std", + "sp-std/std", + "tp-core/std", + "tp-traits/std", +] +runtime-benchmarks = [ "frame-benchmarking" ] +try-runtime = [ "frame-support/try-runtime" ] diff --git a/pallets/inflation-rewards/src/lib.rs b/pallets/inflation-rewards/src/lib.rs new file mode 100644 index 000000000..9669b526e --- /dev/null +++ b/pallets/inflation-rewards/src/lib.rs @@ -0,0 +1,282 @@ +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. + +// Tanssi 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. + +// Tanssi 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 Tanssi. If not, see + +//! # Inflation Rewards Pallet +//! +//! This pallet handle native token inflation and rewards distribution. + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use pallet::*; + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +use { + frame_support::{ + pallet_prelude::*, + traits::{ + fungible::{Balanced, Credit, Inspect}, + tokens::{Fortitude, Precision, Preservation}, + Imbalance, OnUnbalanced, + }, + }, + frame_system::pallet_prelude::*, + sp_runtime::{ + traits::{Get, Saturating}, + Perbill, + }, + tp_core::{BlockNumber, ParaId}, + tp_traits::{AuthorNotingHook, DistributeRewards, GetCurrentContainerChains}, +}; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + pub type BalanceOf = + <::Currency as Inspect<::AccountId>>::Balance; + pub type CreditOf = Credit<::AccountId, ::Currency>; + + /// Inflation rewards pallet. + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(core::marker::PhantomData); + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(_: BlockNumberFor) -> Weight { + let mut weight = T::DbWeight::get().reads(1); + + // Collect indistributed rewards, if any + // Any parachain we have not rewarded is handled by onUnbalanced + let not_distributed_rewards = + if let Some(chains_to_reward) = ChainsToReward::::take() { + // Collect and sum all undistributed rewards + let rewards_not_distributed: BalanceOf = chains_to_reward + .rewards_per_chain + .saturating_mul((chains_to_reward.para_ids.len() as u32).into()); + T::Currency::withdraw( + &T::PendingRewardsAccount::get(), + rewards_not_distributed, + Precision::BestEffort, + Preservation::Expendable, + Fortitude::Force, + ) + .unwrap_or(CreditOf::::zero()) + } else { + CreditOf::::zero() + }; + + // Get the number of chains at this block (tanssi + container chain blocks) + weight += T::DbWeight::get().reads_writes(1, 1); + let registered_para_ids = T::ContainerChains::current_container_chains(); + let number_of_chains: BalanceOf = + ((registered_para_ids.len() as u32).saturating_add(1)).into(); + + // Issue new supply + let new_supply = + T::Currency::issue(T::InflationRate::get() * T::Currency::total_issuance()); + + // Split staking reward portion + let total_rewards = T::RewardsPortion::get() * new_supply.peek(); + let (rewards_credit, reminder_credit) = new_supply.split(total_rewards); + + let rewards_per_chain: BalanceOf = rewards_credit.peek() / number_of_chains; + let (mut total_reminder, staking_rewards) = rewards_credit.split_merge( + total_rewards % number_of_chains, + (reminder_credit, CreditOf::::zero()), + ); + + // Deposit the new supply dedicated to rewards in the pending rewards account + if let Err(undistributed_rewards) = + T::Currency::resolve(&T::PendingRewardsAccount::get(), staking_rewards) + { + total_reminder = total_reminder.merge(undistributed_rewards); + } + + // Keep track of chains to reward + ChainsToReward::::put(ChainsToRewardValue { + para_ids: registered_para_ids, + rewards_per_chain, + }); + + // Let the runtime handle the non-staking part + T::OnUnbalanced::on_unbalanced(not_distributed_rewards.merge(total_reminder)); + + weight += Self::reward_orchestrator_author(); + + weight + } + } + + #[pallet::config] + pub trait Config: frame_system::Config { + /// Overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + type Currency: Inspect + Balanced; + + type ContainerChains: GetCurrentContainerChains; + + /// Get block author for self chain + type GetSelfChainBlockAuthor: Get; + + /// Inflation rate per orchestrator block (proportion of the total issuance) + type InflationRate: Get; + + /// What to do with the new supply not dedicated to staking + type OnUnbalanced: OnUnbalanced>; + + /// The account that will store rewards waiting to be paid out + type PendingRewardsAccount: Get; + + /// Staking rewards distribution implementation + type StakingRewardsDistributor: DistributeRewards>; + + /// Proportion of the new supply dedicated to staking + type RewardsPortion: Get; + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Rewarding orchestrator author + RewardedOrchestrator { + account_id: T::AccountId, + balance: BalanceOf, + }, + /// Rewarding container author + RewardedContainer { + account_id: T::AccountId, + para_id: ParaId, + balance: BalanceOf, + }, + } + + /// Container chains to reward per block + #[pallet::storage] + #[pallet::getter(fn container_chains_to_reward)] + pub(super) type ChainsToReward = + StorageValue<_, ChainsToRewardValue, OptionQuery>; + #[derive(Clone, Encode, Decode, PartialEq, sp_core::RuntimeDebug, scale_info::TypeInfo)] + #[scale_info(skip_type_params(T))] + pub struct ChainsToRewardValue { + pub para_ids: BoundedVec< + ParaId, + ::MaxContainerChains, + >, + pub rewards_per_chain: BalanceOf, + } + + impl Pallet { + fn reward_orchestrator_author() -> Weight { + let mut total_weight = T::DbWeight::get().reads(1); + let orchestrator_author = T::GetSelfChainBlockAuthor::get(); + + if let Some(chains_to_reward) = ChainsToReward::::get() { + total_weight += T::DbWeight::get().reads(1); + match T::StakingRewardsDistributor::distribute_rewards( + orchestrator_author.clone(), + T::Currency::withdraw( + &T::PendingRewardsAccount::get(), + chains_to_reward.rewards_per_chain, + Precision::BestEffort, + Preservation::Expendable, + Fortitude::Force, + ) + .unwrap_or(CreditOf::::zero()), + ) { + Ok(frame_support::dispatch::PostDispatchInfo { actual_weight, .. }) => { + Self::deposit_event(Event::RewardedOrchestrator { + account_id: orchestrator_author, + balance: chains_to_reward.rewards_per_chain, + }); + + if let Some(weight) = actual_weight { + total_weight += weight + } + } + Err(e) => { + log::debug!("Fail to distribute rewards: {:?}", e) + } + } + } else { + panic!("ChainsToReward not filled"); + } + + total_weight + } + } +} + +// This function should only be used to **reward** a container author. +// There will be no additional check other than checking if we have already +// rewarded this author for **in this tanssi block** +// Any additional check should be done in the calling function +// TODO: consider passing a vector here +impl AuthorNotingHook for Pallet { + fn on_container_author_noted( + author: &T::AccountId, + _block_number: BlockNumber, + para_id: ParaId, + ) -> Weight { + let mut total_weight = T::DbWeight::get().reads_writes(1, 0); + // We take chains to reward, to see what containers are left to reward + if let Some(mut container_chains_to_reward) = ChainsToReward::::get() { + // If we find the index is because we still have not rewarded it + if let Ok(index) = container_chains_to_reward.para_ids.binary_search(¶_id) { + // we distribute rewards to the author + match T::StakingRewardsDistributor::distribute_rewards( + author.clone(), + T::Currency::withdraw( + &T::PendingRewardsAccount::get(), + container_chains_to_reward.rewards_per_chain, + Precision::BestEffort, + Preservation::Expendable, + Fortitude::Force, + ) + .unwrap_or(CreditOf::::zero()), + ) { + Ok(frame_support::dispatch::PostDispatchInfo { actual_weight, .. }) => { + Self::deposit_event(Event::RewardedContainer { + account_id: author.clone(), + balance: container_chains_to_reward.rewards_per_chain, + para_id, + }); + if let Some(weight) = actual_weight { + total_weight += weight + } + } + Err(e) => { + log::debug!("Fail to distribute rewards: {:?}", e) + } + } + // we remove the para id from container-chains to reward + // this makes sure we dont reward it twice in the same block + container_chains_to_reward.para_ids.remove(index); + + total_weight += T::DbWeight::get().writes(1); + // Keep track of chains to reward + ChainsToReward::::put(container_chains_to_reward); + } + } + total_weight + } +} diff --git a/pallets/inflation-rewards/src/mock.rs b/pallets/inflation-rewards/src/mock.rs new file mode 100644 index 000000000..7bc467b89 --- /dev/null +++ b/pallets/inflation-rewards/src/mock.rs @@ -0,0 +1,227 @@ +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. + +// Tanssi 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. + +// Tanssi 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 Tanssi. If not, see + +use { + crate::{self as pallet_inflation_rewards}, + bounded_collections::bounded_vec, + frame_support::{ + pallet_prelude::*, + parameter_types, + traits::{ + fungible::{Balanced, Credit}, + ConstU64, Everything, + }, + }, + sp_core::H256, + sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, Perbill, + }, + tp_core::ParaId, +}; + +type Block = frame_system::mocking::MockBlock; +pub type AccountId = u64; +pub type Balance = u128; + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + Balances: pallet_balances, + InflationRewards: pallet_inflation_rewards, + MockData: mock_data, + } +); + +impl frame_system::Config for Test { + type BaseCallFilter = Everything; + type Block = Block; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +parameter_types! { + pub const ExistentialDeposit: u128 = 1; +} + +impl pallet_balances::Config for Test { + type MaxReserves = (); + type ReserveIdentifier = [u8; 4]; + type MaxLocks = (); + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type FreezeIdentifier = (); + type MaxFreezes = (); + type RuntimeHoldReason = (); + type MaxHolds = ConstU32<5>; + type WeightInfo = (); +} + +// Pallet to provide some mock data, used to test +#[frame_support::pallet] +pub mod mock_data { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::call] + impl Pallet {} + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn mock)] + pub(super) type Mock = StorageValue<_, Mocks, ValueQuery>; + + impl Pallet { + pub fn get() -> Mocks { + Mock::::get() + } + pub fn mutate(f: F) -> R + where + F: FnOnce(&mut Mocks) -> R, + { + Mock::::mutate(f) + } + } +} + +impl mock_data::Config for Test {} + +#[derive(Clone, Encode, Decode, PartialEq, sp_core::RuntimeDebug, scale_info::TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct Mocks { + pub container_chains: BoundedVec>, + pub orchestrator_author: AccountId, +} + +impl Default for Mocks { + fn default() -> Self { + Self { + container_chains: bounded_vec![1001.into()], + orchestrator_author: 1, + } + } +} + +pub struct MockContainerChainGetter; + +impl tp_traits::GetCurrentContainerChains for MockContainerChainGetter { + type MaxContainerChains = ConstU32<5>; + + fn current_container_chains() -> BoundedVec { + MockData::mock().container_chains + } + + #[cfg(feature = "runtime-benchmarks")] + fn set_current_container_chains(container_chains: &[ParaId]) { + MockData::mutate(|m| { + m.container_chains = container_chains.to_vec(); + }); + } +} + +pub struct MockGetSelfChainBlockAuthor; + +impl Get for MockGetSelfChainBlockAuthor { + fn get() -> AccountId { + MockData::mock().orchestrator_author + } +} + +pub struct OnUnbalancedInflation; +impl frame_support::traits::OnUnbalanced> for OnUnbalancedInflation { + fn on_nonzero_unbalanced(credit: Credit) { + let _ = >::resolve(&OnUnbalancedInflationAccount::get(), credit); + } +} + +pub struct MockRewardsDistributor; +impl tp_traits::DistributeRewards> + for MockRewardsDistributor +{ + fn distribute_rewards( + rewarded: AccountId, + amount: Credit, + ) -> DispatchResultWithPostInfo { + <::Currency as Balanced>::resolve( + &rewarded, amount, + ) + .map_err(|_| DispatchError::NoProviders)?; + Ok(().into()) + } +} + +parameter_types! { + pub OnUnbalancedInflationAccount: AccountId = 0; + pub PendingRewardsAccount: AccountId = 99; + pub const RewardsPortion: Perbill = Perbill::from_percent(70); + pub const InflationRate: Perbill = Perbill::from_percent(1); +} + +impl pallet_inflation_rewards::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type ContainerChains = MockContainerChainGetter; + type GetSelfChainBlockAuthor = MockGetSelfChainBlockAuthor; + type InflationRate = InflationRate; + type OnUnbalanced = OnUnbalancedInflation; + type PendingRewardsAccount = PendingRewardsAccount; + type StakingRewardsDistributor = MockRewardsDistributor; + type RewardsPortion = RewardsPortion; +} + +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default() + .build_storage() + .unwrap(); + + let balances = vec![(0, 10_000)]; + + pallet_balances::GenesisConfig:: { balances } + .assimilate_storage(&mut t) + .unwrap(); + + t.into() +} diff --git a/pallets/inflation-rewards/src/tests.rs b/pallets/inflation-rewards/src/tests.rs new file mode 100644 index 000000000..f23f0de74 --- /dev/null +++ b/pallets/inflation-rewards/src/tests.rs @@ -0,0 +1,249 @@ +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. + +// Tanssi 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. + +// Tanssi 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 Tanssi. If not, see + +use { + crate::{mock::*, Config, *}, + frame_support::{pallet_prelude::*, traits::fungible::Inspect}, + sp_runtime::Permill, +}; + +fn get_balance(who: &AccountId) -> Balance { + <::Currency as Inspect>::balance(who) +} + +fn get_total_issuance() -> Balance { + <::Currency as Inspect>::total_issuance() +} + +#[test] +fn test_increase_supply() { + new_test_ext().execute_with(|| { + let total_supply_0 = get_total_issuance(); + + as Hooks>::on_initialize(1); + let total_supply_1 = get_total_issuance(); + assert_eq!( + total_supply_1, + total_supply_0 + (::InflationRate::get() * total_supply_0), + ); + + as Hooks>::on_initialize(2); + let total_supply_2 = get_total_issuance(); + assert_eq!( + total_supply_2, + total_supply_1 + (::InflationRate::get() * total_supply_1), + ); + }); +} + +#[test] +fn test_undistributed_rewards() { + new_test_ext().execute_with(|| { + let total_supply_0 = get_total_issuance(); + let initial_balance = get_balance(&OnUnbalancedInflationAccount::get()); + + as Hooks>::on_initialize(1); + let total_supply_1 = get_total_issuance(); + + let new_supply = total_supply_1 - total_supply_0; + + // The OnUnbalancedInflationAccount should receive 30% of the new supply + assert_eq!( + get_balance(&OnUnbalancedInflationAccount::get()), + initial_balance + (Permill::from_percent(30) * new_supply), + ); + }); +} + +#[test] +fn test_reward_orchestrator_author() { + new_test_ext().execute_with(|| { + let author = ::GetSelfChainBlockAuthor::get(); + let author_balance = get_balance(&author); + + let total_supply_0 = get_total_issuance(); + as Hooks>::on_initialize(1); + let total_supply_1 = get_total_issuance(); + + let new_supply = total_supply_1 - total_supply_0; + + assert_eq!( + get_balance(&author), + // 70% rewards for 2 chains, so 35% per chain + author_balance + (Permill::from_percent(35) * new_supply), + ); + }); +} + +#[test] +fn test_reward_orchestrator_author_less_if_more_chains() { + new_test_ext().execute_with(|| { + // Add 2 container chains + MockData::mutate(|data| { + data.container_chains.try_push(1002.into()).unwrap(); + data.container_chains.try_push(1003.into()).unwrap(); + }); + + let author = ::GetSelfChainBlockAuthor::get(); + let author_balance = get_balance(&author); + + let total_supply_0 = get_total_issuance(); + as Hooks>::on_initialize(1); + let total_supply_1 = get_total_issuance(); + + let new_supply = total_supply_1 - total_supply_0; + + assert_eq!( + get_balance(&author), + // 70% rewards for 3 chains, so 17.5% per chain + author_balance + (Permill::from_perthousand(175) * new_supply), + ); + }); +} + +#[test] +fn test_reward_container_chain_author() { + new_test_ext().execute_with(|| { + let container_author = 2; + let container_author_2 = 3; + let container_author_balance = get_balance(&container_author); + let container_author_balance_2 = get_balance(&container_author_2); + + let total_supply_0 = get_total_issuance(); + as Hooks>::on_initialize(1); + let total_supply_1 = get_total_issuance(); + + let new_supply_1 = total_supply_1 - total_supply_0; + + // Note container author + let registered_para_ids = ::ContainerChains::current_container_chains(); + as AuthorNotingHook>::on_container_author_noted( + &container_author, + 1, + registered_para_ids[0], + ); + + // Author should be rewarded immediately + assert_eq!( + get_balance(&container_author), + // 70% rewards for 2 chains, so 35% per chain + container_author_balance + (Permill::from_percent(35) * new_supply_1), + ); + + as Hooks>::on_initialize(2); + let total_supply_2 = get_total_issuance(); + let new_supply_2 = total_supply_2 - total_supply_1; + + // Note next container author + as AuthorNotingHook>::on_container_author_noted( + &container_author_2, + 2, + registered_para_ids[0], + ); + + // Author should be rewarded immediately + assert_eq!( + get_balance(&container_author_2), + // 70% rewards for 2 chains, so 35% per chain + container_author_balance_2 + (Permill::from_percent(35) * new_supply_2), + ); + }); +} + +#[test] +fn test_cannot_reward_twice_in_same_tanssi_block() { + new_test_ext().execute_with(|| { + let container_author = 2; + let container_author_balance = get_balance(&container_author); + + let total_supply_0 = get_total_issuance(); + as Hooks>::on_initialize(1); + let total_supply_1 = get_total_issuance(); + + let new_supply_1 = total_supply_1 - total_supply_0; + + // Note container author + let registered_para_ids = ::ContainerChains::current_container_chains(); + as AuthorNotingHook>::on_container_author_noted( + &container_author, + 1, + registered_para_ids[0], + ); + + // Regardless if we inject a new block, we cannot reward twice the same paraId + as AuthorNotingHook>::on_container_author_noted( + &container_author, + 2, + registered_para_ids[0], + ); + + // Author should be rewarded only once + assert_eq!( + get_balance(&container_author), + // 70% rewards for 2 chains, so 35% per chain + container_author_balance + (Permill::from_percent(35) * new_supply_1), + ); + }); +} + +#[test] +fn test_non_claimed_rewards_go_to_on_unbalanced() { + new_test_ext().execute_with(|| { + let container_author = 2; + let container_author_balance = get_balance(&container_author); + + as Hooks>::on_initialize(1); + let on_unbalanced_account = get_balance(&OnUnbalancedInflationAccount::get()); + + let total_supply_1 = get_total_issuance(); + + // We initilize the next block without claiming rewards for the container + // author should have not been rewarded and the onUNbalanced hook should kick in + // we use block 2 because it has reminder + as Hooks>::on_initialize(2); + + let total_supply_2 = get_total_issuance(); + + let new_supply_2 = total_supply_2 - total_supply_1; + + // OnUnbalancedInflationAccount::get() should be rewarded with the non-claimed + // rewards + // The onUnbalanedInflationAccount should have: + // the non-reward portion ((Permill::from_percent(30) * new_supply_1)) + // the reminder ((Permill::from_percent(70) * suppl7 % number of container chains)) + // the non-claimed rewards + let staking_rewards = Permill::from_percent(70) * new_supply_2; + let non_staking_rewards = new_supply_2 - staking_rewards; + // (orchestrator plus container); + let reminder = staking_rewards % 2; + + assert_eq!( + get_balance(&OnUnbalancedInflationAccount::get()), + // 70% rewards for 2 chains, so 35% per chain + on_unbalanced_account + + non_staking_rewards + + reminder + + (Permill::from_percent(35) * new_supply_2), + ); + + // and the author is not rewarded + assert_eq!( + get_balance(&container_author), + // 70% rewards for 2 chains, so 35% per chain + container_author_balance, + ); + }); +} diff --git a/pallets/invulnerables/Cargo.toml b/pallets/invulnerables/Cargo.toml index 319ed20f4..ebf37d024 100644 --- a/pallets/invulnerables/Cargo.toml +++ b/pallets/invulnerables/Cargo.toml @@ -20,6 +20,7 @@ frame-system = { workspace = true } sp-runtime = { workspace = true } sp-staking = { workspace = true } sp-std = { workspace = true } +tp-traits = { workspace = true } frame-benchmarking = { workspace = true } @@ -43,6 +44,7 @@ std = [ "scale-info/std", "sp-runtime/std", "sp-std/std", + "tp-traits/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", diff --git a/pallets/invulnerables/src/benchmarking.rs b/pallets/invulnerables/src/benchmarking.rs index f1535df69..4665b9f1d 100644 --- a/pallets/invulnerables/src/benchmarking.rs +++ b/pallets/invulnerables/src/benchmarking.rs @@ -26,13 +26,14 @@ use { frame_benchmarking::{account, impl_benchmark_test_suite, v2::*, BenchmarkError}, frame_support::{ pallet_prelude::*, - traits::{Currency, EnsureOrigin, Get}, + traits::{tokens::fungible::Balanced, Currency, EnsureOrigin, Get}, }, frame_system::{EventRecord, RawOrigin}, pallet_session::{self as session, SessionManager}, + sp_runtime::traits::AtLeast32BitUnsigned, sp_std::prelude::*, + tp_traits::DistributeRewards, }; - const SEED: u32 = 0; fn assert_last_event(generic_event: ::RuntimeEvent) { @@ -94,7 +95,18 @@ fn invulnerables< invulnerables.into_iter().map(|(who, _)| who).collect() } -#[benchmarks(where T: session::Config + pallet_balances::Config)] +pub type BalanceOf = + <::Currency as frame_support::traits::fungible::Inspect< + ::AccountId, + >>::Balance; + +pub(crate) fn currency_issue( + amount: BalanceOf, +) -> crate::CreditOf { + <::Currency as Balanced>::issue(amount) +} + +#[benchmarks(where T: session::Config + pallet_balances::Config, BalanceOf: AtLeast32BitUnsigned)] mod benchmarks { use super::*; @@ -106,16 +118,14 @@ mod benchmarks { T::UpdateOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let new_invulnerables = invulnerables::(b); - let mut sorted_new_invulnerables = new_invulnerables.clone(); - sorted_new_invulnerables.sort(); #[extrinsic_call] - _(origin as T::RuntimeOrigin, new_invulnerables); + _(origin as T::RuntimeOrigin, new_invulnerables.clone()); // assert that it comes out sorted assert_last_event::( Event::NewInvulnerables { - invulnerables: sorted_new_invulnerables, + invulnerables: new_invulnerables, } .into(), ); @@ -196,6 +206,27 @@ mod benchmarks { Ok(()) } + #[benchmark] + fn reward_invulnerable( + b: Linear<{ 1 }, { T::MaxInvulnerables::get() }>, + ) -> Result<(), BenchmarkError> where { + let mut invulnerables = invulnerables::(b); + invulnerables.sort(); + let invulnerables: frame_support::BoundedVec<_, T::MaxInvulnerables> = + frame_support::BoundedVec::try_from(invulnerables).unwrap(); + >::put(invulnerables); + let to_reward = >::get().first().unwrap().clone(); + // Create new supply for rewards + let new_supply = currency_issue::(1000u32.into()); + #[block] + { + let _ = InvulnerableRewardDistribution::::distribute_rewards( + to_reward, new_supply, + ); + } + + Ok(()) + } impl_benchmark_test_suite!( InvulnerablesPallet, crate::mock::new_test_ext(), diff --git a/pallets/invulnerables/src/lib.rs b/pallets/invulnerables/src/lib.rs index 0a87195dc..57695c468 100644 --- a/pallets/invulnerables/src/lib.rs +++ b/pallets/invulnerables/src/lib.rs @@ -26,6 +26,7 @@ #![cfg_attr(not(feature = "std"), no_std)] pub use pallet::*; +use {core::marker::PhantomData, sp_runtime::TokenError}; #[cfg(test)] mod mock; @@ -39,8 +40,12 @@ pub mod weights; #[frame_support::pallet] pub mod pallet { + pub use crate::weights::WeightInfo; + + #[cfg(feature = "runtime-benchmarks")] + use frame_support::traits::Currency; + use { - crate::weights::WeightInfo, frame_support::{ dispatch::DispatchResultWithPostInfo, pallet_prelude::*, @@ -91,6 +96,10 @@ pub mod pallet { /// The weight information of this pallet. type WeightInfo: WeightInfo; + + #[cfg(feature = "runtime-benchmarks")] + type Currency: Currency + + frame_support::traits::fungible::Balanced; } #[pallet::pallet] @@ -282,3 +291,43 @@ pub mod pallet { } } } + +/// If the rewarded account is an Invulnerable, distribute the entire reward +/// amount to them. Otherwise use the `Fallback` distribution. +pub struct InvulnerableRewardDistribution( + PhantomData<(Runtime, Currency, Fallback)>, +); + +use {frame_support::pallet_prelude::Weight, sp_runtime::traits::Get}; + +type CreditOf = + frame_support::traits::fungible::Credit<::AccountId, Currency>; +pub type AccountIdOf = ::AccountId; + +impl + tp_traits::DistributeRewards, CreditOf> + for InvulnerableRewardDistribution +where + Runtime: frame_system::Config + Config, + Fallback: tp_traits::DistributeRewards, CreditOf>, + Currency: frame_support::traits::fungible::Balanced>, +{ + fn distribute_rewards( + rewarded: AccountIdOf, + amount: CreditOf, + ) -> frame_support::pallet_prelude::DispatchResultWithPostInfo { + let mut total_weight = Weight::zero(); + // weight to read invulnerables + total_weight += Runtime::DbWeight::get().reads(1); + if !Invulnerables::::get().contains(&rewarded) { + let post_info = Fallback::distribute_rewards(rewarded, amount)?; + if let Some(weight) = post_info.actual_weight { + total_weight += weight; + } + } else { + Currency::resolve(&rewarded, amount).map_err(|_| TokenError::NotExpendable)?; + total_weight += Runtime::WeightInfo::reward_invulnerable() + } + Ok(Some(total_weight).into()) + } +} diff --git a/pallets/invulnerables/src/mock.rs b/pallets/invulnerables/src/mock.rs index eba0d9f79..73bd16ff8 100644 --- a/pallets/invulnerables/src/mock.rs +++ b/pallets/invulnerables/src/mock.rs @@ -114,6 +114,8 @@ impl Config for Test { type CollatorIdOf = IdentityCollator; type CollatorRegistration = IsRegistered; type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type Currency = Balances; } sp_runtime::impl_opaque_keys! { diff --git a/pallets/invulnerables/src/weights.rs b/pallets/invulnerables/src/weights.rs index b5f59b518..367d83f0a 100644 --- a/pallets/invulnerables/src/weights.rs +++ b/pallets/invulnerables/src/weights.rs @@ -54,6 +54,7 @@ pub trait WeightInfo { fn add_invulnerable(_b: u32) -> Weight; fn remove_invulnerable(_b: u32) -> Weight; fn new_session(_b: u32) -> Weight; + fn reward_invulnerable() -> Weight; } /// Weight functions for `pallet_invulnerables`. @@ -120,6 +121,22 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } + + /// Storage: `Invulnerables::Invulnerables` (r:1 w:0) + /// Proof: `Invulnerables::Invulnerables` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `b` is `[1, 100]`. + fn reward_invulnerable() -> Weight { + // Proof Size summary in bytes: + // Measured: `218 + b * (33 ±0)` + // Estimated: `4687` + // Minimum execution time: 51_037_000 picoseconds. + Weight::from_parts(68_315_971, 4687) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + } // For backwards compatibility and tests @@ -187,4 +204,20 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(1)) } + /// Storage: `Invulnerables::Invulnerables` (r:1 w:0) + /// Proof: `Invulnerables::Invulnerables` (`max_values`: Some(1), `max_size`: Some(3202), added: 3697, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + /// The range of component `b` is `[1, 100]`. + fn reward_invulnerable() -> Weight { + // Proof Size summary in bytes: + // Measured: `218 + b * (33 ±0)` + // Estimated: `4687` + // Minimum execution time: 51_037_000 picoseconds. + Weight::from_parts(68_315_971, 4687) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + + } diff --git a/pallets/pooled-staking/Cargo.toml b/pallets/pooled-staking/Cargo.toml index 47a6eca9b..31bdfb081 100644 --- a/pallets/pooled-staking/Cargo.toml +++ b/pallets/pooled-staking/Cargo.toml @@ -13,6 +13,8 @@ targets = [ "x86_64-unknown-linux-gnu" ] log = { workspace = true } serde = { workspace = true, optional = true } tp-core = { workspace = true } +tp-maths = { workspace = true } +tp-traits = { workspace = true } # Substrate frame-benchmarking = { workspace = true, optional = true } @@ -46,6 +48,8 @@ std = [ "sp-runtime/std", "sp-std/std", "tp-core/std", + "tp-maths/std", + "tp-traits/std", ] runtime-benchmarks = [ "frame-benchmarking" ] -try-runtime = [ "frame-support/try-runtime" ] +try-runtime = [ "frame-support/try-runtime" ] \ No newline at end of file diff --git a/pallets/pooled-staking/src/benchmarking.rs b/pallets/pooled-staking/src/benchmarking.rs index 74cb15317..555c454cc 100644 --- a/pallets/pooled-staking/src/benchmarking.rs +++ b/pallets/pooled-staking/src/benchmarking.rs @@ -29,7 +29,7 @@ use { dispatch::RawOrigin, traits::{ fungible::{InspectHold, Mutate, MutateHold}, - tokens::Precision, + tokens::{fungible::Balanced, Precision}, Get, }, }, @@ -66,6 +66,12 @@ fn create_funded_user( (user, total) } +pub(crate) fn currency_issue( + amount: T::Balance, +) -> crate::CreditOf { + <::Currency as Balanced>::issue(amount) +} + #[benchmarks] mod benchmarks { use super::*; @@ -577,7 +583,7 @@ mod benchmarks { #[block] { - crate::pools::distribute_rewards::(&caller, source_stake)?; + crate::pools::distribute_rewards::(&caller, currency_issue::(source_stake))?; } Ok(()) diff --git a/pallets/pooled-staking/src/calls.rs b/pallets/pooled-staking/src/calls.rs index ac3ae96a7..3daa88f8c 100644 --- a/pallets/pooled-staking/src/calls.rs +++ b/pallets/pooled-staking/src/calls.rs @@ -18,7 +18,7 @@ use { crate::{ candidate::Candidates, pools::{self, Pool}, - traits::{ErrAdd, ErrSub, Timer}, + traits::Timer, AllTargetPool, Candidate, Config, Delegator, Error, Event, Pallet, PendingOperationKey, PendingOperationQuery, PendingOperationQueryOf, PendingOperations, Shares, SharesOrStake, Stake, TargetPool, @@ -33,6 +33,7 @@ use { }, sp_runtime::traits::{CheckedSub, Zero}, sp_std::vec::Vec, + tp_maths::{ErrAdd, ErrSub}, }; pub struct Calls(PhantomData); diff --git a/pallets/pooled-staking/src/candidate.rs b/pallets/pooled-staking/src/candidate.rs index 856f6b418..1682c9306 100644 --- a/pallets/pooled-staking/src/candidate.rs +++ b/pallets/pooled-staking/src/candidate.rs @@ -17,7 +17,7 @@ use { crate::{ pools::{self, Pool}, - traits::{ErrAdd, ErrSub, IsCandidateEligible}, + traits::IsCandidateEligible, Candidate, Config, Error, Event, Pallet, Pools, PoolsKey, SortedEligibleCandidates, Stake, }, core::{cmp::Ordering, marker::PhantomData}, @@ -25,6 +25,7 @@ use { scale_info::TypeInfo, sp_core::{Get, RuntimeDebug}, sp_runtime::traits::Zero, + tp_maths::{ErrAdd, ErrSub}, }; #[cfg(feature = "std")] diff --git a/pallets/pooled-staking/src/lib.rs b/pallets/pooled-staking/src/lib.rs index 9e593af1e..81010cb2c 100644 --- a/pallets/pooled-staking/src/lib.rs +++ b/pallets/pooled-staking/src/lib.rs @@ -75,6 +75,7 @@ pub mod pallet { sp_core::Get, sp_runtime::{BoundedVec, Perbill}, sp_std::vec::Vec, + tp_maths::MulDiv, }; #[cfg(feature = "std")] @@ -82,6 +83,8 @@ pub mod pallet { // Type aliases for better readability. pub type Candidate = ::AccountId; + pub type CreditOf = + fungible::Credit<::AccountId, ::Currency>; pub type Delegator = ::AccountId; /// Key used by the `Pools` StorageDoubleMap, avoiding lots of maps. @@ -237,7 +240,7 @@ pub mod pallet { /// Same as Currency::Balance. Must impl `MulDiv` which perform /// multiplication followed by division using a bigger type to avoid /// overflows. - type Balance: Balance + traits::MulDiv; + type Balance: Balance + MulDiv; /// Identifier reserved for this pallet holding account funds. type CurrencyHoldReason: Get< @@ -453,6 +456,18 @@ pub mod pallet { SwapResultsInZeroShares, } + impl From for Error { + fn from(_: tp_maths::OverflowError) -> Self { + Error::MathOverflow + } + } + + impl From for Error { + fn from(_: tp_maths::UnderflowError) -> Self { + Error::MathUnderflow + } + } + #[pallet::call] impl Pallet { #[pallet::call_index(0)] @@ -568,10 +583,10 @@ pub mod pallet { } } - impl tp_core::DistributeRewards, T::Balance> for Pallet { + impl tp_traits::DistributeRewards, CreditOf> for Pallet { fn distribute_rewards( candidate: Candidate, - rewards: T::Balance, + rewards: CreditOf, ) -> DispatchResultWithPostInfo { pools::distribute_rewards::(&candidate, rewards) } diff --git a/pallets/pooled-staking/src/mock.rs b/pallets/pooled-staking/src/mock.rs index 9880a7a74..0de2ea354 100644 --- a/pallets/pooled-staking/src/mock.rs +++ b/pallets/pooled-staking/src/mock.rs @@ -110,8 +110,20 @@ impl frame_system::Config for Runtime { type MaxConsumers = ConstU32<16>; } +/// Allows to change ED mid-test. +pub struct MockExistentialDeposit; +impl MockExistentialDeposit { + pub fn get() -> Balance { + frame_support::storage::unhashed::get(b":mock_ed").unwrap_or(1) + } + + pub fn set(amount: Balance) { + frame_support::storage::unhashed::put(b":mock_ed", &amount); + } +} + parameter_types! { - pub const ExistentialDeposit: u128 = 1; + pub ExistentialDeposit: u128 = MockExistentialDeposit::get(); } impl pallet_balances::Config for Runtime { diff --git a/pallets/pooled-staking/src/pools.rs b/pallets/pooled-staking/src/pools.rs index a358db954..d761e3300 100644 --- a/pallets/pooled-staking/src/pools.rs +++ b/pallets/pooled-staking/src/pools.rs @@ -16,18 +16,18 @@ use { crate::{ - candidate::Candidates, - traits::{ErrAdd, ErrMul, ErrSub, MulDiv}, - Candidate, Config, Delegator, Error, Event, Pallet, Pools, PoolsKey, Shares, Stake, + candidate::Candidates, weights::WeightInfo, Candidate, Config, CreditOf, Delegator, Error, + Event, Pallet, Pools, PoolsKey, Shares, Stake, }, core::marker::PhantomData, frame_support::{ ensure, - pallet_prelude::DispatchResultWithPostInfo, - traits::{fungible::Mutate, tokens::Preservation}, + pallet_prelude::*, + traits::{fungible::Balanced, Imbalance}, }, sp_core::Get, sp_runtime::traits::{CheckedAdd, CheckedDiv, Zero}, + tp_maths::{ErrAdd, ErrMul, ErrSub, MulDiv}, }; pub trait Pool { @@ -455,22 +455,24 @@ impl ManualRewards { /// AutoCompounding shares. This can lead to some rounding, which will be /// absorbed in the ManualRewards distribution, which simply consist of /// transfering the funds to the candidate account. +#[frame_support::transactional] pub fn distribute_rewards( candidate: &Candidate, - rewards: T::Balance, + rewards: CreditOf, ) -> DispatchResultWithPostInfo { - let candidate_manual_rewards = distribute_rewards_inner::(candidate, rewards)?; - - if !candidate_manual_rewards.is_zero() { - T::Currency::transfer( - &T::StakingAccount::get(), - &candidate, - candidate_manual_rewards, - Preservation::Preserve, - )?; + let candidate_manual_rewards = distribute_rewards_inner::(candidate, rewards.peek())?; + + let (candidate_manual_rewards, other_rewards) = rewards.split(candidate_manual_rewards); + + if !candidate_manual_rewards.peek().is_zero() { + T::Currency::resolve(&candidate, candidate_manual_rewards) + .map_err(|_| DispatchError::NoProviders)?; } - Ok(().into()) + T::Currency::resolve(&T::StakingAccount::get(), other_rewards) + .map_err(|_| DispatchError::NoProviders)?; + + Ok(Some(T::WeightInfo::distribute_rewards()).into()) } fn distribute_rewards_inner( diff --git a/pallets/pooled-staking/src/tests/mod.rs b/pallets/pooled-staking/src/tests/mod.rs index 4d1acea5f..668aabab3 100644 --- a/pallets/pooled-staking/src/tests/mod.rs +++ b/pallets/pooled-staking/src/tests/mod.rs @@ -30,7 +30,10 @@ use { AllTargetPool, Error, Event, PendingOperationKey, PendingOperationQuery, PendingOperations, Shares, SharesOrStake, Stake, TargetPool, }, - frame_support::{assert_noop, assert_ok, traits::tokens::fungible::Mutate}, + frame_support::{ + assert_noop, assert_ok, + traits::tokens::fungible::{Balanced, Mutate}, + }, sp_runtime::TokenError, }; @@ -482,6 +485,10 @@ pub(crate) fn do_rebalance_hold>( assert_fields_eq!(pool_before, pool_after, stake); } +pub(crate) fn currency_issue(amount: Balance) -> crate::CreditOf { + <::Currency as Balanced>::issue(amount) +} + #[must_use] pub(crate) struct Swap { candidate: AccountId, diff --git a/pallets/pooled-staking/src/tests/rewards.rs b/pallets/pooled-staking/src/tests/rewards.rs index bfa2ad59f..26b19ef6e 100644 --- a/pallets/pooled-staking/src/tests/rewards.rs +++ b/pallets/pooled-staking/src/tests/rewards.rs @@ -21,7 +21,9 @@ use { pools::{AutoCompounding, ManualRewards}, Pallet, TargetPool, }, - tp_core::DistributeRewards, + frame_support::assert_err, + sp_runtime::DispatchError, + tp_traits::DistributeRewards, }; struct Delegation { @@ -64,6 +66,11 @@ fn test_distribution( use crate::traits::Timer; let block_number = ::JoiningRequestTimer::now(); + // Create new supply for rewards + let new_supply = currency_issue(reward.rewards); + use frame_support::traits::Imbalance; + let new_supply_amount = new_supply.peek(); + // Request all delegations for d in delegations { assert_ok!(Staking::request_delegate( @@ -103,7 +110,7 @@ fn test_distribution( let candidate_balance_before = total_balance(&ACCOUNT_CANDIDATE_1); assert_ok!(Pallet::::distribute_rewards( reward.collator, - reward.rewards + new_supply )); let candidate_balance_after = total_balance(&ACCOUNT_CANDIDATE_1); @@ -165,7 +172,7 @@ fn test_distribution( + distribution.collator_manual + distribution.delegators_auto + distribution.delegators_manual, - reward.rewards, + new_supply_amount, "Distribution total doesn't match requested reward" ); @@ -577,3 +584,54 @@ fn delegator_only_candidate_no_stake_auto_compounding() { ) }); } + +#[test] +fn reward_distribution_is_transactional() { + ExtBuilder::default().build().execute_with(|| { + use crate::traits::Timer; + let request_time = ::JoiningRequestTimer::now(); + + assert_ok!(Staking::request_delegate( + RuntimeOrigin::signed(ACCOUNT_CANDIDATE_1.into()), + ACCOUNT_CANDIDATE_1.into(), + TargetPool::AutoCompounding, + 1_000_000_000, + )); + + // Wait for delegation to be executable + for _ in 0..BLOCKS_TO_WAIT { + roll_one_block(); + } + + assert_ok!(Staking::execute_pending_operations( + RuntimeOrigin::signed(ACCOUNT_CANDIDATE_1.into()), + vec![PendingOperationQuery { + delegator: ACCOUNT_CANDIDATE_1.into(), + operation: PendingOperationKey::JoiningAutoCompounding { + candidate: ACCOUNT_CANDIDATE_1.into(), + at: request_time + }, + }] + )); + + let total_staked_before = + pools::AutoCompounding::::total_staked(&ACCOUNT_CANDIDATE_1.into()); + + // Increase ED to make reward destribution fail when resolving + // credit to Staking account. + MockExistentialDeposit::set(u128::MAX); + + let rewards = Balances::issue(1_000_000_000); + assert_err!( + Staking::distribute_rewards(ACCOUNT_CANDIDATE_1.into(), rewards), + DispatchError::NoProviders + ); + + let total_staked_after = + pools::AutoCompounding::::total_staked(&ACCOUNT_CANDIDATE_1.into()); + assert_eq!( + total_staked_before, total_staked_after, + "distribution should be reverted" + ); + }) +} diff --git a/pallets/pooled-staking/src/traits.rs b/pallets/pooled-staking/src/traits.rs index 7a53ef1b6..f59706655 100644 --- a/pallets/pooled-staking/src/traits.rs +++ b/pallets/pooled-staking/src/traits.rs @@ -15,14 +15,11 @@ // along with Tanssi. If not, see use { - crate::{Config, Error}, core::{fmt::Debug, marker::PhantomData}, frame_system::pallet_prelude::BlockNumberFor, parity_scale_codec::FullCodec, scale_info::TypeInfo, - sp_core::U256, - sp_runtime::traits::{CheckedAdd, CheckedMul, CheckedSub, Get, Zero}, - sp_std::convert::TryInto, + sp_runtime::traits::{CheckedAdd, Get}, }; /// Allows to get the current instant and check if some duration is elapsed. @@ -102,109 +99,3 @@ impl IsCandidateEligible for () { #[cfg(feature = "runtime-benchmarks")] fn make_candidate_eligible(_: &AccountId, _: bool) {} } - -/// Error returned by math operations which can overflow. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct OverflowError; - -impl From for Error { - fn from(_: OverflowError) -> Self { - Error::MathOverflow - } -} - -/// Error returned by math operations which can underflow. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct UnderflowError; - -impl From for Error { - fn from(_: UnderflowError) -> Self { - Error::MathUnderflow - } -} - -/// Helper to compute ratios by multiplying then dividing by some values, while -/// performing the intermediary computation using a bigger type to avoid -/// overflows. -pub trait MulDiv: Sized { - /// Multiply self by `a` then divide the result by `b`. - /// Computation will be performed in a bigger type to avoid overflows. - /// After the division, will return `None` if the result is to big for - /// the real type or if `b` is zero. - fn mul_div(self, a: Self, b: Self) -> Result; -} - -macro_rules! impl_mul_div { - ($type:ty, $bigger:ty) => { - impl MulDiv for $type { - fn mul_div(self, a: Self, b: Self) -> Result { - if b.is_zero() { - return Err(OverflowError); - } - - if self.is_zero() { - return Ok(<$type>::zero()); - } - - let s: $bigger = self.into(); - let a: $bigger = a.into(); - let b: $bigger = b.into(); - - let r: $bigger = s * a / b; - - r.try_into().map_err(|_| OverflowError) - } - } - }; -} - -impl_mul_div!(u8, u16); -impl_mul_div!(u16, u32); -impl_mul_div!(u32, u64); -impl_mul_div!(u64, u128); -impl_mul_div!(u128, U256); - -/// Returns directly an error on overflow. -pub trait ErrAdd: CheckedAdd { - /// Returns directly an error on overflow. - fn err_add(&self, v: &Self) -> Result { - self.checked_add(v).ok_or(OverflowError) - } -} - -impl ErrAdd for T {} - -/// Returns directly an error on underflow. -pub trait ErrSub: CheckedSub { - /// Returns directly an error on underflow. - fn err_sub(&self, v: &Self) -> Result { - self.checked_sub(v).ok_or(UnderflowError) - } -} - -impl ErrSub for T {} - -/// Returns directly an error on overflow. -pub trait ErrMul: CheckedMul { - /// Returns directly an error on overflow. - fn err_mul(&self, v: &Self) -> Result { - self.checked_mul(v).ok_or(OverflowError) - } -} - -impl ErrMul for T {} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn mul_div() { - assert_eq!(42u128.mul_div(0, 0), Err(OverflowError)); - assert_eq!(42u128.mul_div(1, 0), Err(OverflowError)); - - assert_eq!(u128::MAX.mul_div(2, 4), Ok(u128::MAX / 2)); - assert_eq!(u128::MAX.mul_div(2, 2), Ok(u128::MAX)); - assert_eq!(u128::MAX.mul_div(4, 2), Err(OverflowError)); - } -} diff --git a/pallets/registrar/src/benchmarks.rs b/pallets/registrar/src/benchmarks.rs index e3f6046c8..c9a2cddab 100644 --- a/pallets/registrar/src/benchmarks.rs +++ b/pallets/registrar/src/benchmarks.rs @@ -23,8 +23,7 @@ use { frame_support::{traits::Currency, BoundedVec}, frame_system::RawOrigin, sp_core::Get, - sp_std::vec, - sp_std::vec::Vec, + sp_std::{vec, vec::Vec}, tp_container_chain_genesis_data::{ContainerChainGenesisData, ContainerChainGenesisDataItem}, tp_traits::ParaId, }; diff --git a/pallets/registrar/src/lib.rs b/pallets/registrar/src/lib.rs index 0a1ae411f..34e80abb5 100644 --- a/pallets/registrar/src/lib.rs +++ b/pallets/registrar/src/lib.rs @@ -570,8 +570,10 @@ pub mod pallet { } impl GetCurrentContainerChains for Pallet { - fn current_container_chains() -> Vec { - Self::registered_para_ids().into_iter().collect() + type MaxContainerChains = T::MaxLengthParaIds; + + fn current_container_chains() -> BoundedVec { + Self::registered_para_ids() } #[cfg(feature = "runtime-benchmarks")] diff --git a/primitives/author-noting-inherent/src/mock.rs b/primitives/author-noting-inherent/src/mock.rs index 3ba78a057..5bcc505e4 100644 --- a/primitives/author-noting-inherent/src/mock.rs +++ b/primitives/author-noting-inherent/src/mock.rs @@ -76,7 +76,7 @@ impl InherentDataProvider for MockAuthorNotingInherentDataProvider { let header = HeaderAs::NonEncoded(sp_runtime::generic::Header:: { parent_hash: Default::default(), - number: Default::default(), + number: self.current_para_block, state_root: Default::default(), extrinsics_root: Default::default(), digest: sp_runtime::generic::Digest { @@ -158,7 +158,7 @@ impl MockAuthorNotingInherentDataProvider { let header = HeaderAs::NonEncoded(sp_runtime::generic::Header:: { parent_hash: Default::default(), - number: Default::default(), + number: self.current_para_block, state_root: Default::default(), extrinsics_root: Default::default(), digest: sp_runtime::generic::Digest { diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index 1a0b697f5..cefa4c69e 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -16,13 +16,12 @@ #![cfg_attr(not(feature = "std"), no_std)] -use { - frame_support::pallet_prelude::DispatchResultWithPostInfo, - sp_runtime::{ - generic, - traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiAddress, MultiSignature, OpaqueExtrinsic, - }, +pub use cumulus_primitives_core::ParaId; + +use sp_runtime::{ + generic, + traits::{BlakeTwo256, IdentifyAccount, Verify}, + MultiAddress, MultiSignature, OpaqueExtrinsic, }; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. @@ -99,8 +98,3 @@ pub mod well_known_keys { pub const SESSION_INDEX: &[u8] = &hex_literal::hex!["cec5070d609dd3497f72bde07fc96ba072763800a36a99fdfc7c10f6415f6ee6"]; } - -/// Distribute rewards to an account. -pub trait DistributeRewards { - fn distribute_rewards(rewarded: AccountId, amount: Balance) -> DispatchResultWithPostInfo; -} diff --git a/primitives/maths/Cargo.toml b/primitives/maths/Cargo.toml new file mode 100644 index 000000000..2280cf032 --- /dev/null +++ b/primitives/maths/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "tp-maths" +authors = { workspace = true } +description = "Tanssi mathematics primitives" +edition = "2021" +license = "GPL-3.0-only" +version = "0.1.0" + +[dependencies] +sp-core = { workspace = true } +sp-runtime = { workspace = true } + + +[features] +default = [ "std" ] +std = [ + "sp-core/std", + "sp-runtime/std", +] +runtime-benchmarks = [] diff --git a/primitives/maths/src/lib.rs b/primitives/maths/src/lib.rs new file mode 100644 index 000000000..6253c5a23 --- /dev/null +++ b/primitives/maths/src/lib.rs @@ -0,0 +1,116 @@ +// Copyright (C) Moondance Labs Ltd. +// This file is part of Tanssi. + +// Tanssi 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. + +// Tanssi 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 Tanssi. If not, see + +#![cfg_attr(not(feature = "std"), no_std)] + +use { + sp_core::U256, + sp_runtime::traits::{CheckedAdd, CheckedMul, CheckedSub, Zero}, +}; + +/// Error returned by math operations which can overflow. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct OverflowError; + +/// Error returned by math operations which can underflow. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct UnderflowError; + +/// Helper to compute ratios by multiplying then dividing by some values, while +/// performing the intermediary computation using a bigger type to avoid +/// overflows. +pub trait MulDiv: Sized { + /// Multiply self by `a` then divide the result by `b`. + /// Computation will be performed in a bigger type to avoid overflows. + /// After the division, will return `None` if the result is to big for + /// the real type or if `b` is zero. + fn mul_div(self, a: Self, b: Self) -> Result; +} + +macro_rules! impl_mul_div { + ($type:ty, $bigger:ty) => { + impl MulDiv for $type { + fn mul_div(self, a: Self, b: Self) -> Result { + if b.is_zero() { + return Err(OverflowError); + } + + if self.is_zero() { + return Ok(<$type>::zero()); + } + + let s: $bigger = self.into(); + let a: $bigger = a.into(); + let b: $bigger = b.into(); + + let r: $bigger = s * a / b; + + r.try_into().map_err(|_| OverflowError) + } + } + }; +} + +impl_mul_div!(u8, u16); +impl_mul_div!(u16, u32); +impl_mul_div!(u32, u64); +impl_mul_div!(u64, u128); +impl_mul_div!(u128, U256); + +/// Returns directly an error on overflow. +pub trait ErrAdd: CheckedAdd { + /// Returns directly an error on overflow. + fn err_add(&self, v: &Self) -> Result { + self.checked_add(v).ok_or(OverflowError) + } +} + +impl ErrAdd for T {} + +/// Returns directly an error on underflow. +pub trait ErrSub: CheckedSub { + /// Returns directly an error on underflow. + fn err_sub(&self, v: &Self) -> Result { + self.checked_sub(v).ok_or(UnderflowError) + } +} + +impl ErrSub for T {} + +/// Returns directly an error on overflow. +pub trait ErrMul: CheckedMul { + /// Returns directly an error on overflow. + fn err_mul(&self, v: &Self) -> Result { + self.checked_mul(v).ok_or(OverflowError) + } +} + +impl ErrMul for T {} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn mul_div() { + assert_eq!(42u128.mul_div(0, 0), Err(OverflowError)); + assert_eq!(42u128.mul_div(1, 0), Err(OverflowError)); + + assert_eq!(u128::MAX.mul_div(2, 4), Ok(u128::MAX / 2)); + assert_eq!(u128::MAX.mul_div(2, 2), Ok(u128::MAX)); + assert_eq!(u128::MAX.mul_div(4, 2), Err(OverflowError)); + } +} diff --git a/primitives/traits/Cargo.toml b/primitives/traits/Cargo.toml index 861838700..deb38c889 100644 --- a/primitives/traits/Cargo.toml +++ b/primitives/traits/Cargo.toml @@ -5,7 +5,9 @@ description = "Tanssi primitive traits" edition = "2021" license = "GPL-3.0-only" version = "0.1.0" + [dependencies] +frame-support = { workspace = true } sp-std = { workspace = true } # Cumulus @@ -14,6 +16,7 @@ cumulus-primitives-core = { workspace = true } [features] default = [ "std" ] std = [ + "frame-support/std", "cumulus-primitives-core/std", ] runtime-benchmarks = [] diff --git a/primitives/traits/src/lib.rs b/primitives/traits/src/lib.rs index e042db35d..6f370701e 100644 --- a/primitives/traits/src/lib.rs +++ b/primitives/traits/src/lib.rs @@ -19,12 +19,51 @@ #![cfg_attr(not(feature = "std"), no_std)] -pub use cumulus_primitives_core::{relay_chain::Slot, ParaId}; -use sp_std::vec::Vec; +pub use cumulus_primitives_core::{ + relay_chain::{BlockNumber, Slot}, + ParaId, +}; +use { + frame_support::{ + pallet_prelude::{DispatchResultWithPostInfo, Get, Weight}, + BoundedVec, + }, + sp_std::vec::Vec, +}; + +/// The author-noting hook to react to container chains authoring. +pub trait AuthorNotingHook { + /// This hook is called partway through the `set_latest_author_data` inherent in author-noting. + /// + /// The hook should never panic and is required to return the weight consumed. + fn on_container_author_noted( + author: &AccountId, + block_number: BlockNumber, + para_id: ParaId, + ) -> Weight; +} + +impl AuthorNotingHook for () { + fn on_container_author_noted(_: &AccountId, _: BlockNumber, _: ParaId) -> Weight { + Weight::zero() + } +} + +pub trait DistributeRewards { + fn distribute_rewards(rewarded: AccountId, amount: Imbalance) -> DispatchResultWithPostInfo; +} + +impl DistributeRewards for () { + fn distribute_rewards(_rewarded: AccountId, _amount: Imbalance) -> DispatchResultWithPostInfo { + Ok(().into()) + } +} /// Get the current list of container chains parachain ids. pub trait GetCurrentContainerChains { - fn current_container_chains() -> Vec; + type MaxContainerChains: Get; + + fn current_container_chains() -> BoundedVec; #[cfg(feature = "runtime-benchmarks")] fn set_current_container_chains(container_chains: &[ParaId]); diff --git a/runtime/dancebox/Cargo.toml b/runtime/dancebox/Cargo.toml index 5b4441cea..085d46251 100644 --- a/runtime/dancebox/Cargo.toml +++ b/runtime/dancebox/Cargo.toml @@ -25,6 +25,7 @@ pallet-authority-mapping = { workspace = true } pallet-collator-assignment = { workspace = true } pallet-collator-assignment-runtime-api = { workspace = true } pallet-configuration = { workspace = true } +pallet-inflation-rewards = { workspace = true } pallet-initializer = { workspace = true } pallet-pooled-staking = { workspace = true } pallet-proxy = { workspace = true } @@ -144,6 +145,7 @@ std = [ "pallet-balances/std", "pallet-collator-assignment-runtime-api/std", "pallet-configuration/std", + "pallet-inflation-rewards/std", "pallet-initializer/std", "pallet-invulnerables/std", "pallet-maintenance-mode/std", @@ -224,6 +226,7 @@ try-runtime = [ "pallet-balances/try-runtime", "pallet-collator-assignment/try-runtime", "pallet-configuration/try-runtime", + "pallet-inflation-rewards/try-runtime", "pallet-initializer/try-runtime", "pallet-invulnerables/try-runtime", "pallet-maintenance-mode/try-runtime", diff --git a/runtime/dancebox/src/lib.rs b/runtime/dancebox/src/lib.rs index 526ab16f2..0ba103194 100644 --- a/runtime/dancebox/src/lib.rs +++ b/runtime/dancebox/src/lib.rs @@ -49,6 +49,7 @@ use { pallet_prelude::DispatchResult, parameter_types, traits::{ + fungible::{Balanced, Credit}, ConstU128, ConstU32, ConstU64, ConstU8, Contains, InstanceFilter, OffchainWorker, OnFinalize, OnIdle, OnInitialize, OnRuntimeUpgrade, ValidatorRegistration, }, @@ -68,6 +69,7 @@ use { }, nimbus_primitives::NimbusId, pallet_collator_assignment::{GetRandomnessForNextBlock, RotateCollatorsEveryNSessions}, + pallet_invulnerables::InvulnerableRewardDistribution, pallet_pooled_staking::traits::{IsCandidateEligible, Timer}, pallet_registrar_runtime_api::ContainerChainGenesisData, pallet_session::{SessionManager, ShouldEndSession}, @@ -689,6 +691,7 @@ impl pallet_collator_assignment::Config for Runtime { type HostConfiguration = Configuration; type ContainerChains = Registrar; type SessionIndex = u32; + type SelfParaId = ParachainInfo; type ShouldRotateAllCollators = RotateCollatorsEveryNSessions; type GetRandomnessForNextBlock = BabeGetRandomnessForNextBlock; @@ -707,6 +710,7 @@ impl pallet_author_noting::Config for Runtime { type SelfParaId = parachain_info::Pallet; type ContainerChainAuthor = CollatorAssignment; type RelayChainStateProvider = cumulus_pallet_parachain_system::RelaychainDataProvider; + type AuthorNotingHook = InflationRewards; type WeightInfo = pallet_author_noting::weights::SubstrateWeight; } @@ -727,6 +731,8 @@ impl pallet_invulnerables::Config for Runtime { type CollatorIdOf = pallet_invulnerables::IdentityCollator; type CollatorRegistration = Session; type WeightInfo = pallet_invulnerables::weights::SubstrateWeight; + #[cfg(feature = "runtime-benchmarks")] + type Currency = Balances; } parameter_types! { @@ -1116,6 +1122,55 @@ impl pallet_pooled_staking::Config for Runtime { type WeightInfo = pallet_pooled_staking::weights::SubstrateWeight; } +parameter_types! { + pub ParachainBondAccount: AccountId32 = PalletId(*b"ParaBond").into_account_truncating(); + pub PendingRewardsAccount: AccountId32 = PalletId(*b"PENDREWD").into_account_truncating(); + // The equation to solve is: + // initial_supply * (1.05) = initial_supply * (1+x)^2_629_800 + // we should solve for x = (1.05)^(1/2_629_800) -1 -> 0.000000019 per block or 19/1_000_000_000 + // 1% in the case of dev moed + // TODO: check if we can put the prod inflation for tests too + // TODO: better calculus for going from annual to block inflation (if it can be done) + pub const InflationRate: Perbill = prod_or_fast!(Perbill::from_parts(19), Perbill::from_percent(1)); + + // 30% for parachain bond, so 70% for staking + pub const RewardsPortion: Perbill = Perbill::from_percent(70); +} + +use {nimbus_primitives::SlotBeacon, tp_traits::GetContainerChainAuthor}; + +pub struct GetSelfChainBlockAuthor; +impl Get for GetSelfChainBlockAuthor { + fn get() -> AccountId32 { + // TODO: we should do a refactor here, and use either authority-mapping or collator-assignemnt + // we should also make sure we actually account for the weight of these + // although most of these should be cached as they are read every block + let slot = ::SlotBeacon::slot() as u64; + let self_para_id = ParachainInfo::get(); + let author = CollatorAssignment::author_for_slot(slot.into(), self_para_id); + author.expect("author should be set") + } +} + +pub struct OnUnbalancedInflation; +impl frame_support::traits::OnUnbalanced> for OnUnbalancedInflation { + fn on_nonzero_unbalanced(credit: Credit) { + let _ = >::resolve(&ParachainBondAccount::get(), credit); + } +} + +impl pallet_inflation_rewards::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type ContainerChains = Registrar; + type GetSelfChainBlockAuthor = GetSelfChainBlockAuthor; + type InflationRate = InflationRate; + type OnUnbalanced = OnUnbalancedInflation; + type PendingRewardsAccount = PendingRewardsAccount; + type StakingRewardsDistributor = InvulnerableRewardDistribution; + type RewardsPortion = RewardsPortion; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -1143,12 +1198,14 @@ construct_runtime!( AuthorNoting: pallet_author_noting = 24, AuthorityAssignment: pallet_authority_assignment = 25, - // Collator support. The order of these 4 are important and shall not change. + // Collator support. The order of these 6 are important and shall not change. Invulnerables: pallet_invulnerables = 30, Session: pallet_session = 31, AuthorityMapping: pallet_authority_mapping = 32, AuthorInherent: pallet_author_inherent = 33, PooledStaking: pallet_pooled_staking = 34, + // InflationRewards must be after Session and AuthorInherent + InflationRewards: pallet_inflation_rewards = 35, //XCM XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 50, @@ -1529,6 +1586,7 @@ impl_runtime_apis! { /// Return the current authorities assigned to a given paraId fn para_id_authorities(para_id: ParaId) -> Option> { let parent_number = System::block_number(); + let should_end_session = ::ShouldEndSession::should_end_session(parent_number + 1); let session_index = if should_end_session { @@ -1539,6 +1597,7 @@ impl_runtime_apis! { }; let assigned_authorities = AuthorityAssignment::collator_container_chain(session_index)?; + let self_para_id = ParachainInfo::get(); if para_id == self_para_id { diff --git a/runtime/dancebox/tests/common/mod.rs b/runtime/dancebox/tests/common/mod.rs index 4954b2807..7fb40a8a4 100644 --- a/runtime/dancebox/tests/common/mod.rs +++ b/runtime/dancebox/tests/common/mod.rs @@ -18,7 +18,8 @@ use { cumulus_primitives_core::{ParaId, PersistedValidationData}, cumulus_primitives_parachain_inherent::ParachainInherentData, dancebox_runtime::{ - AuthorInherent, AuthorityAssignment, CollatorAssignment, MaxLengthTokenSymbol, + AuthorInherent, AuthorityAssignment, CollatorAssignment, InflationRewards, + MaxLengthTokenSymbol, }, frame_support::{ assert_ok, @@ -32,6 +33,7 @@ use { sp_consensus_aura::AURA_ENGINE_ID, sp_core::{Get, Pair}, sp_runtime::{traits::Dispatchable, BuildStorage, Digest, DigestItem}, + sp_std::collections::btree_map::BTreeMap, test_relay_sproof_builder::ParaHeaderSproofBuilder, tp_consensus::runtime_decl_for_tanssi_authority_assignment_api::TanssiAuthorityAssignmentApi, }; @@ -51,48 +53,77 @@ pub fn session_to_block(n: u32) -> u32 { block_number + 1 } +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct RunSummary { + pub author_id: AccountId, + pub inflation: Balance, +} + pub fn run_to_session(n: u32) { run_to_block(session_to_block(n)); } /// Utility function that advances the chain to the desired block number. -pub fn run_to_block(n: u32) { +pub fn run_to_block(n: u32) -> BTreeMap { + let mut summaries = BTreeMap::new(); + while System::block_number() < n { - let slot = current_slot() + 1; - - let authorities = - Runtime::para_id_authorities(ParachainInfo::get()).expect("authorities should be set"); - - let authority: NimbusId = authorities[slot as usize % authorities.len()].clone(); - - let pre_digest = Digest { - logs: vec![ - DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode()), - DigestItem::PreRuntime(NIMBUS_ENGINE_ID, authority.encode()), - ], - }; - - System::reset_events(); - System::initialize( - &(System::block_number() + 1), - &System::parent_hash(), - &pre_digest, - ); - - // Initialize the new block - CollatorAssignment::on_initialize(System::block_number()); - Initializer::on_initialize(System::block_number()); - Session::on_initialize(System::block_number()); - AuthorInherent::on_initialize(System::block_number()); - - pallet_author_inherent::Pallet::::kick_off_authorship_validation(None.into()) - .expect("author inherent to dispatch correctly"); - - // Finalize the block - CollatorAssignment::on_finalize(System::block_number()); - Initializer::on_finalize(System::block_number()); - Session::on_finalize(System::block_number()); - AuthorInherent::on_finalize(System::block_number()); + let summary = run_block(); + let block_number = System::block_number(); + summaries.insert(block_number, summary); + } + + summaries +} + +pub fn run_block() -> RunSummary { + let slot = current_slot() + 1; + + let authorities = + Runtime::para_id_authorities(ParachainInfo::get()).expect("authorities should be set"); + + let authority: NimbusId = authorities[slot as usize % authorities.len()].clone(); + + let pre_digest = Digest { + logs: vec![ + DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode()), + DigestItem::PreRuntime(NIMBUS_ENGINE_ID, authority.encode()), + ], + }; + + System::reset_events(); + System::initialize( + &(System::block_number() + 1), + &System::parent_hash(), + &pre_digest, + ); + + // Initialize the new block + CollatorAssignment::on_initialize(System::block_number()); + Session::on_initialize(System::block_number()); + Initializer::on_initialize(System::block_number()); + AuthorInherent::on_initialize(System::block_number()); + + // `Initializer::on_finalize` needs to run at least one to have + // author mapping setup. + let author_id = current_author(); + + let current_issuance = Balances::total_issuance(); + InflationRewards::on_initialize(System::block_number()); + let new_issuance = Balances::total_issuance(); + + pallet_author_inherent::Pallet::::kick_off_authorship_validation(None.into()) + .expect("author inherent to dispatch correctly"); + + // Finalize the block + CollatorAssignment::on_finalize(System::block_number()); + Session::on_finalize(System::block_number()); + Initializer::on_finalize(System::block_number()); + AuthorInherent::on_finalize(System::block_number()); + + RunSummary { + author_id, + inflation: new_issuance - current_issuance, } } @@ -123,8 +154,10 @@ pub fn set_parachain_inherent_data() { } pub fn set_parachain_inherent_data_random_seed(random_seed: [u8; 32]) { - use cumulus_primitives_core::relay_chain::well_known_keys; - use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; + use { + cumulus_primitives_core::relay_chain::well_known_keys, + cumulus_test_relay_sproof_builder::RelayStateSproofBuilder, + }; let (relay_parent_storage_root, relay_chain_state) = { let mut sproof = RelayStateSproofBuilder::default(); diff --git a/runtime/dancebox/tests/common/xcm/mocknets.rs b/runtime/dancebox/tests/common/xcm/mocknets.rs index e3e8d1751..9995112a1 100644 --- a/runtime/dancebox/tests/common/xcm/mocknets.rs +++ b/runtime/dancebox/tests/common/xcm/mocknets.rs @@ -13,16 +13,14 @@ // You should have received a copy of the GNU General Public License // along with Tanssi. If not, see -use cumulus_primitives_core::relay_chain::runtime_api::runtime_decl_for_parachain_host::ParachainHostV6; pub use sp_core::{sr25519, storage::Storage, Get}; use { super::constants::{ accounts::{ALICE, BOB, RANDOM}, frontier_template, simple_template, westend, }, + cumulus_primitives_core::relay_chain::runtime_api::runtime_decl_for_parachain_host::ParachainHostV6, frame_support::parameter_types, -}; -use { staging_xcm::prelude::*, staging_xcm_builder::{ParentIsPreset, SiblingParachainConvertsVia}, staging_xcm_executor::traits::ConvertLocation, diff --git a/runtime/dancebox/tests/integration_test.rs b/runtime/dancebox/tests/integration_test.rs index 98304b7f3..262db8093 100644 --- a/runtime/dancebox/tests/integration_test.rs +++ b/runtime/dancebox/tests/integration_test.rs @@ -25,7 +25,7 @@ use { MigrateInvulnerables, }, AuthorNoting, AuthorityAssignment, AuthorityMapping, CollatorAssignment, Configuration, - Invulnerables, MinimumSelfDelegation, PooledStaking, Proxy, ProxyType, + Invulnerables, MinimumSelfDelegation, PooledStaking, Proxy, ProxyType, RewardsPortion, }, frame_support::{assert_noop, assert_ok, BoundedVec}, nimbus_primitives::NIMBUS_KEY_ID, @@ -3076,11 +3076,6 @@ fn test_staking_leave_execute_before_time() { // Session 4 starts at block 1200, but run_to_session runs to block 1201, so subtract 2 here to go to 1999 run_to_block(start_of_session_4 - 2); - assert_eq!( - balance_before, - System::account(AccountId::from(ALICE)).data.free - ); - assert_noop!( PooledStaking::execute_pending_operations( origin_of(ALICE.into()), @@ -3127,10 +3122,7 @@ fn test_staking_leave_execute_any_origin() { run_to_session(4); - assert_eq!( - balance_before, - System::account(AccountId::from(ALICE)).data.free - ); + let balance_before = System::account(AccountId::from(ALICE)).data.free; assert_ok!(PooledStaking::execute_pending_operations( // Any signed origin can execute this, the stake will go to Alice account @@ -3598,6 +3590,277 @@ fn test_migration_holds() { }); } +#[test] +fn test_reward_to_staking_candidate() { + // Alice, Bob, Charlie are invulnerables + ExtBuilder::default() + .with_balances(vec![ + // Alice gets 10k extra tokens for her mapping deposit + (AccountId::from(ALICE), 210_000 * UNIT), + (AccountId::from(BOB), 100_000 * UNIT), + (AccountId::from(CHARLIE), 100_000 * UNIT), + (AccountId::from(DAVE), 100_000 * UNIT), + ]) + .with_collators(vec![(AccountId::from(ALICE), 210 * UNIT)]) + .with_para_ids(vec![ + (1001, empty_genesis_data(), vec![]), + (1002, empty_genesis_data(), vec![]), + ]) + .with_config(pallet_configuration::HostConfiguration { + max_collators: 100, + min_orchestrator_collators: 2, + max_orchestrator_collators: 2, + collators_per_container: 2, + full_rotation_period: 24, + }) + .build() + .execute_with(|| { + run_to_block(2); + + let dave_account_id = get_aura_id_from_seed(&AccountId::from(DAVE).to_string()); + assert_ok!(Session::set_keys( + origin_of(DAVE.into()), + dancebox_runtime::SessionKeys { + nimbus: dave_account_id, + }, + vec![] + )); + + // We make delegations to DAVE so that she is an elligible candidate. + + let stake = 10 * MinimumSelfDelegation::get(); + + assert_ok!(PooledStaking::request_delegate( + origin_of(DAVE.into()), + DAVE.into(), + TargetPool::ManualRewards, + stake, + )); + assert_ok!(PooledStaking::request_delegate( + origin_of(BOB.into()), + DAVE.into(), + TargetPool::AutoCompounding, + stake, + )); + + // wait few sessions for the request to be executable + run_to_session(3u32); + assert_ok!(PooledStaking::execute_pending_operations( + origin_of(ALICE.into()), + vec![ + PendingOperationQuery { + delegator: DAVE.into(), + operation: PendingOperationKey::JoiningManualRewards { + candidate: DAVE.into(), + at: 0 + } + }, + PendingOperationQuery { + delegator: BOB.into(), + operation: PendingOperationKey::JoiningAutoCompounding { + candidate: DAVE.into(), + at: 0 + } + } + ] + )); + + // wait for next session so that DAVE is elected + run_to_session(4u32); + + assert_eq!( + Session::validators(), + vec![AccountId::from(ALICE), AccountId::from(DAVE)] + ); + + let account: AccountId = DAVE.into(); + let balance_before = System::account(account.clone()).data.free; + let summary = (0..100) + .find_map(|_| { + let summary = run_block(); + if summary.author_id == DAVE.into() { + Some(summary) + } else { + None + } + }) + .unwrap_or_else(|| panic!("DAVE doesn't seem to author any blocks")); + let balance_after = System::account(account).data.free; + + let all_rewards = RewardsPortion::get() * summary.inflation; + // rewards are shared between orchestrator and registered paras + let orchestrator_rewards = all_rewards / 3; + let candidate_rewards = orchestrator_rewards * 2 / 10; + + assert_eq!( + candidate_rewards + 1, // TODO: account for rounding properly :p + balance_after - balance_before, + "dave should get the correct reward portion" + ); + }); +} + +#[test] +fn test_reward_to_invulnerable() { + // Alice, Bob, Charlie are invulnerables + ExtBuilder::default() + .with_balances(vec![ + // Alice gets 10k extra tokens for her mapping deposit + (AccountId::from(ALICE), 210_000 * UNIT), + (AccountId::from(BOB), 100_000 * UNIT), + (AccountId::from(CHARLIE), 100_000 * UNIT), + (AccountId::from(DAVE), 100_000 * UNIT), + ]) + .with_collators(vec![ + (AccountId::from(ALICE), 210 * UNIT), + (AccountId::from(BOB), 100 * UNIT), + (AccountId::from(CHARLIE), 100 * UNIT), + ]) + .with_para_ids(vec![ + (1001, empty_genesis_data(), vec![]), + (1002, empty_genesis_data(), vec![]), + ]) + .with_config(pallet_configuration::HostConfiguration { + max_collators: 100, + min_orchestrator_collators: 2, + max_orchestrator_collators: 2, + collators_per_container: 2, + full_rotation_period: 24, + }) + .build() + .execute_with(|| { + run_to_block(2); + + // We make delegations to ALICE so that she is an elligible candidate. + // However since she is an invulnerable she should get all the + // rewards. + + let stake = 10 * MinimumSelfDelegation::get(); + + assert_ok!(PooledStaking::request_delegate( + origin_of(ALICE.into()), + ALICE.into(), + TargetPool::ManualRewards, + stake, + )); + assert_ok!(PooledStaking::request_delegate( + origin_of(BOB.into()), + ALICE.into(), + TargetPool::AutoCompounding, + stake, + )); + + // wait few sessions for the request to be executable + run_to_session(3u32); + assert_ok!(PooledStaking::execute_pending_operations( + origin_of(ALICE.into()), + vec![ + PendingOperationQuery { + delegator: ALICE.into(), + operation: PendingOperationKey::JoiningAutoCompounding { + candidate: ALICE.into(), + at: 0 + } + }, + PendingOperationQuery { + delegator: BOB.into(), + operation: PendingOperationKey::JoiningAutoCompounding { + candidate: ALICE.into(), + at: 0 + } + } + ] + )); + + // wait for next session so that ALICE is elected + run_to_session(4u32); + + let account: AccountId = ALICE.into(); + let balance_before = System::account(account.clone()).data.free; + + let summary = (0..100) + .find_map(|_| { + let summary = run_block(); + if summary.author_id == ALICE.into() { + Some(summary) + } else { + None + } + }) + .unwrap_or_else(|| panic!("ALICE doesn't seem to author any blocks")); + + let balance_after = System::account(account).data.free; + + let all_rewards = RewardsPortion::get() * summary.inflation; + // rewards are shared between orchestrator and registered paras + let orchestrator_rewards = all_rewards / 3; + assert_eq!( + orchestrator_rewards, + balance_after - balance_before, + "alice should get the correct reward portion" + ); + }); +} + +#[test] +fn test_reward_to_invulnerable_with_key_change() { + ExtBuilder::default() + .with_balances(vec![ + // Alice gets 10k extra tokens for her mapping deposit + (AccountId::from(ALICE), 210_000 * UNIT), + (AccountId::from(BOB), 100_000 * UNIT), + (AccountId::from(CHARLIE), 100_000 * UNIT), + (AccountId::from(DAVE), 100_000 * UNIT), + ]) + .with_collators(vec![(AccountId::from(ALICE), 210 * UNIT)]) + .with_para_ids(vec![ + (1001, empty_genesis_data(), vec![]), + (1002, empty_genesis_data(), vec![]), + ]) + .with_config(pallet_configuration::HostConfiguration { + max_collators: 100, + min_orchestrator_collators: 2, + max_orchestrator_collators: 2, + collators_per_container: 2, + full_rotation_period: 24, + }) + .build() + .execute_with(|| { + run_to_block(2); + + run_to_session(2u32); + + // change key, this should be reflected 2 sessions afterward + let alice_new_key = get_aura_id_from_seed(&AccountId::from(DAVE).to_string()); + assert_ok!(Session::set_keys( + origin_of(ALICE.into()), + dancebox_runtime::SessionKeys { + nimbus: alice_new_key, + }, + vec![] + )); + + run_to_session(4u32); + + let account: AccountId = ALICE.into(); + let balance_before = System::account(account.clone()).data.free; + + let summary = run_block(); + assert_eq!(summary.author_id, ALICE.into()); + + let balance_after = System::account(account).data.free; + + let all_rewards = RewardsPortion::get() * summary.inflation; + // rewards are shared between orchestrator and registered paras + let orchestrator_rewards = all_rewards / 3; + assert_eq!( + orchestrator_rewards, + balance_after - balance_before, + "alice should get the correct reward portion" + ); + }); +} + #[test] fn test_migration_config_full_rotation_period() { ExtBuilder::default() diff --git a/test/suites/common/proxy/test-proxy.ts b/test/suites/common/proxy/test-proxy.ts index 22b32e7f5..3f92ee847 100644 --- a/test/suites/common/proxy/test-proxy.ts +++ b/test/suites/common/proxy/test-proxy.ts @@ -1,8 +1,8 @@ import "@polkadot/api-augment"; import { describeSuite, expect, beforeAll } from "@moonwall/cli"; -import { KeyringPair, extractFee } from "@moonwall/util"; +import { KeyringPair } from "@moonwall/util"; import { ApiPromise } from "@polkadot/api"; -import { initializeCustomCreateBlock } from "../../../util/block"; +import { initializeCustomCreateBlock, extractFeeAuthor, filterRewardFromContainer } from "../../../util/block"; describeSuite({ id: "C0103", @@ -84,7 +84,7 @@ describeSuite({ expect(ev1.length).to.be.equal(1); expect(ev1[0].event.data[0].toString()).to.be.eq("Ok"); - const fee = extractFee(events).amount.toBigInt(); + const fee = extractFeeAuthor(events, bob.address).amount.toBigInt(); const balanceAfter = (await polkadotJs.query.system.account(bob.address)).data.free.toBigInt(); // Balance of Bob account increased @@ -106,18 +106,20 @@ describeSuite({ polkadotJs.tx.balances.transfer(charlie.address, 200_000) ); await context.createBlock([await tx.signAsync(charlie)]); - const events = await polkadotJs.query.system.events(); const ev1 = events.filter((a) => { return a.event.method == "ExtrinsicFailed"; }); expect(ev1.length).to.be.equal(1); - const fee = extractFee(events).amount.toBigInt(); + // Charlie receives rewards for authoring container, we should take this into account + const fee = extractFeeAuthor(events, charlie.address).amount.toBigInt(); + const receivedReward = filterRewardFromContainer(events, charlie.address, 2000); + const balanceAfter = (await polkadotJs.query.system.account(charlie.address)).data.free.toBigInt(); // Balance of Charlie account must be the same (minus fee) - expect(balanceBefore - fee).to.equal(balanceAfter); + expect(balanceBefore + receivedReward - fee).to.equal(balanceAfter); }, }); @@ -176,7 +178,7 @@ describeSuite({ expect(ev1.length).to.be.equal(1); expect(ev1[0].event.data[0].toString()).to.not.be.eq("Ok"); - const fee = extractFee(events).amount.toBigInt(); + const fee = extractFeeAuthor(events, dave.address).amount.toBigInt(); const balanceAfter = (await polkadotJs.query.system.account(dave.address)).data.free.toBigInt(); // Balance of Dave account must be the same (minus fee) diff --git a/test/suites/dev-tanssi/fees/test_fee_balance_transfer.ts b/test/suites/dev-tanssi/fees/test_fee_balance_transfer.ts index fd7b3273a..ab66bb970 100644 --- a/test/suites/dev-tanssi/fees/test_fee_balance_transfer.ts +++ b/test/suites/dev-tanssi/fees/test_fee_balance_transfer.ts @@ -1,8 +1,9 @@ import "@tanssi/api-augment"; import { describeSuite, expect, beforeAll } from "@moonwall/cli"; -import { KeyringPair, extractFee, filterAndApply } from "@moonwall/util"; +import { KeyringPair, filterAndApply } from "@moonwall/util"; import { ApiPromise } from "@polkadot/api"; import { extractWeight } from "@moonwall/util"; +import { extractFeeAuthor, fetchIssuance, filterRewardFromOrchestrator } from "util/block"; describeSuite({ id: "DT0401", @@ -37,7 +38,8 @@ describeSuite({ await context.createBlock([signedTx]); const events = await polkadotJs.query.system.events(); - const fee = extractFee(events).amount.toBigInt(); + const fee = extractFeeAuthor(events, alice.address).amount.toBigInt(); + const reward = filterRewardFromOrchestrator(events, alice.address); // Get actual weight const info2 = extractInfoForFee(events); @@ -73,7 +75,7 @@ describeSuite({ const balanceAfter = (await polkadotJs.query.system.account(alice.address)).data.free.toBigInt(); // Balance must be old balance minus fee minus transfered value - expect(balanceBefore - fee - 200_000n).to.equal(balanceAfter); + expect(balanceBefore + reward - fee - 200_000n).to.equal(balanceAfter); }, }); @@ -92,8 +94,9 @@ describeSuite({ await context.createBlock([signedTx]); const events = await polkadotJs.query.system.events(); - const fee = extractFee(events).amount.toBigInt(); - // This + const fee = extractFeeAuthor(events, alice.address).amount.toBigInt(); + const reward = filterRewardFromOrchestrator(events, alice.address); + const expectedFee = adjustedExpectedBasePlusWeightFee + BigInt(signedTx.encodedLength); expect(fee).to.equal(expectedFee); @@ -109,7 +112,7 @@ describeSuite({ const balanceAfter = (await polkadotJs.query.system.account(alice.address)).data.free.toBigInt(); // Balance must be old balance minus fee minus transfered value - expect(balanceBefore - fee - 200_000n).to.equal(balanceAfter); + expect(balanceBefore + reward - fee - 200_000n).to.equal(balanceAfter); }, }); @@ -146,7 +149,8 @@ describeSuite({ await context.createBlock([signedTx]); const events = await polkadotJs.query.system.events(); - const fee = extractFee(events).amount.toBigInt(); + const fee = extractFeeAuthor(events, alice.address).amount.toBigInt(); + const reward = filterRewardFromOrchestrator(events, alice.address); const expectedFee = adjustedExpectedBasePlusWeightFee + BigInt(signedTx.encodedLength); expect(fee).to.equal(expectedFee); @@ -161,7 +165,7 @@ describeSuite({ const balanceAfter = (await polkadotJs.query.system.account(alice.address)).data.free.toBigInt(); // Balance must be old balance minus fee minus transfered value - expect(balanceBefore - fee - 200_000n).to.equal(balanceAfter); + expect(balanceBefore + reward - fee - 200_000n).to.equal(balanceAfter); }, }); @@ -177,18 +181,20 @@ describeSuite({ await context.createBlock([signedTx]); const events = await polkadotJs.query.system.events(); - const fee = extractFee(events).amount.toBigInt(); + const fee = extractFeeAuthor(events, alice.address).amount.toBigInt(); + const issuance = fetchIssuance(events).amount.toBigInt(); + const reward = filterRewardFromOrchestrator(events, alice.address); const expectedFee = adjustedExpectedBasePlusWeightFee + BigInt(signedTx.encodedLength); expect(fee).to.equal(expectedFee); const balanceAfter = (await polkadotJs.query.system.account(alice.address)).data.free.toBigInt(); // Balance must be old balance minus fee minus transfered value - expect(balanceBefore - fee - 200_000n).to.equal(balanceAfter); + expect(balanceBefore + reward - fee - 200_000n).to.equal(balanceAfter); const totalSupplyAfter = (await polkadotJs.query.balances.totalIssuance()).toBigInt(); - expect(totalSupplyBefore - totalSupplyAfter).to.equal(fee); + expect(totalSupplyAfter - totalSupplyBefore).to.equal(issuance - fee); }, }); diff --git a/test/suites/dev-tanssi/issuance-rewards/test_invulnerable_rewards.ts b/test/suites/dev-tanssi/issuance-rewards/test_invulnerable_rewards.ts new file mode 100644 index 000000000..ca67de03f --- /dev/null +++ b/test/suites/dev-tanssi/issuance-rewards/test_invulnerable_rewards.ts @@ -0,0 +1,112 @@ +import "@tanssi/api-augment"; +import { describeSuite, expect, beforeAll } from "@moonwall/cli"; +import { ApiPromise } from "@polkadot/api"; +import { KeyringPair } from "@moonwall/util"; +import { fetchIssuance, filterRewardFromOrchestrator, filterRewardFromContainer } from "util/block"; +import { getAuthorFromDigest } from "util/author"; +import { PARACHAIN_BOND } from "util/constants"; + +describeSuite({ + id: "IR0401", + title: "Invulnerable reward test suite", + foundationMethods: "dev", + testCases: ({ it, context }) => { + let polkadotJs: ApiPromise; + let charlie: KeyringPair; + + beforeAll(async () => { + polkadotJs = context.polkadotJs(); + charlie = context.keyring.charlie; + }); + it({ + id: "E01", + title: "Every block created should reward the appropriate amount to orchestrator", + test: async function () { + await context.createBlock(); + const author = await getAuthorFromDigest(polkadotJs); + // Fetch current session + const currentSession = await polkadotJs.query.session.currentIndex(); + const keys = await polkadotJs.query.authorityMapping.authorityIdMapping(currentSession); + const account = keys.toJSON()[author]; + // 70% is distributed across all rewards + // But we have 2 container chains, so it should get 1/3 of this + // Since it is an invulnerable, it receives all payment + const events = await polkadotJs.query.system.events(); + const issuance = await fetchIssuance(events).amount.toBigInt(); + const chainRewards = (issuance * 7n) / 10n; + const expectedOrchestratorReward = chainRewards / 3n; + const reward = await filterRewardFromOrchestrator(events, account); + expect(reward).to.equal(expectedOrchestratorReward); + }, + }); + + it({ + id: "E02", + title: "Parachain bond receives 30% of the inflation and pending rewards plus division dust", + test: async function () { + let expectedAmountParachainBond = 0n; + + const pendingChainRewards = await polkadotJs.query.inflationRewards.chainsToReward(); + if (pendingChainRewards.isSome) { + const rewardPerChain = pendingChainRewards.unwrap().rewardsPerChain.toBigInt(); + const pendingChainsToReward = BigInt(pendingChainRewards.unwrap().paraIds.length); + expectedAmountParachainBond += pendingChainsToReward * rewardPerChain; + } + + const parachainBondBalanceBefore = ( + await polkadotJs.query.system.account(PARACHAIN_BOND) + ).data.free.toBigInt(); + await context.createBlock(); + + const currentChainRewards = await polkadotJs.query.inflationRewards.chainsToReward(); + const events = await polkadotJs.query.system.events(); + const issuance = await fetchIssuance(events).amount.toBigInt(); + let dust = 0n; + if (currentChainRewards.isSome) { + const currentRewardPerChain = currentChainRewards.unwrap().rewardsPerChain.toBigInt(); + dust = (issuance * 7n) / 10n - 3n * currentRewardPerChain; + } + const parachainBondBalanceAfter = ( + await polkadotJs.query.system.account(PARACHAIN_BOND) + ).data.free.toBigInt(); + expectedAmountParachainBond += (issuance * 3n) / 10n + dust; + await context.createBlock(); + + // Not sure where this one comes from, looks like a rounding thing + expect(parachainBondBalanceAfter - parachainBondBalanceBefore).to.equal( + expectedAmountParachainBond + 1n + ); + }, + }); + + it({ + id: "E03", + title: "Charlie receives the reward from container-chain block proposal", + test: async function () { + const balacharlieBalanceBeforenceBefore = ( + await polkadotJs.query.system.account(charlie.address) + ).data.free.toBigInt(); + + await context.createBlock(); + + const currentChainRewards = (await polkadotJs.query.inflationRewards.chainsToReward()).unwrap(); + const events = await polkadotJs.query.system.events(); + const receivedRewardCharlie = filterRewardFromContainer(events, charlie.address, 2000); + + const balacharlieBalanceBeforenceAfter = ( + await polkadotJs.query.system.account(charlie.address) + ).data.free.toBigInt(); + + // Not sure where this one comes from, looks like a rounding thing + expect(balacharlieBalanceBeforenceAfter - balacharlieBalanceBeforenceBefore).to.equal( + currentChainRewards.rewardsPerChain.toBigInt() + ); + + // Not sure where this one comes from, looks like a rounding thing + expect(balacharlieBalanceBeforenceAfter - balacharlieBalanceBeforenceBefore).to.equal( + receivedRewardCharlie + ); + }, + }); + }, +}); diff --git a/test/suites/dev-tanssi/issuance-rewards/test_issuance.ts b/test/suites/dev-tanssi/issuance-rewards/test_issuance.ts new file mode 100644 index 000000000..2ef440fdd --- /dev/null +++ b/test/suites/dev-tanssi/issuance-rewards/test_issuance.ts @@ -0,0 +1,35 @@ +import "@tanssi/api-augment"; +import { describeSuite, expect, beforeAll } from "@moonwall/cli"; +import { ApiPromise } from "@polkadot/api"; +import { fetchIssuance } from "util/block"; + +describeSuite({ + id: "IR0402", + title: "Issuance reward test suite", + foundationMethods: "dev", + testCases: ({ it, context }) => { + let polkadotJs: ApiPromise; + beforeAll(async () => { + polkadotJs = context.polkadotJs(); + }); + it({ + id: "E01", + title: "Issuance is the correct percentage", + test: async function () { + const supplyBefore = (await polkadotJs.query.balances.totalIssuance()).toBigInt(); + await context.createBlock(); + + const events = await polkadotJs.query.system.events(); + + const issuance = await fetchIssuance(events).amount.toBigInt(); + + const supplyAfter = (await polkadotJs.query.balances.totalIssuance()).toBigInt(); + + // in dev mode is 1% + const expectedIssuanceIncrement = supplyBefore / 100n; + expect(issuance).to.equal(expectedIssuanceIncrement); + expect(supplyAfter).to.equal(supplyBefore + expectedIssuanceIncrement); + }, + }); + }, +}); diff --git a/test/suites/dev-tanssi/staking/test_staking_rewards_balanced.ts b/test/suites/dev-tanssi/staking/test_staking_rewards_balanced.ts new file mode 100644 index 000000000..73974a1c0 --- /dev/null +++ b/test/suites/dev-tanssi/staking/test_staking_rewards_balanced.ts @@ -0,0 +1,169 @@ +import "@tanssi/api-augment"; +import { describeSuite, expect, beforeAll } from "@moonwall/cli"; +import { ApiPromise } from "@polkadot/api"; +import { KeyringPair } from "@moonwall/util"; +import { + fetchIssuance, + fetchRewardAuthorOrchestrator, + filterRewardStakingCollator, + filterRewardStakingDelegators, + jumpSessions, +} from "util/block"; +import { DANCE, STAKING_ACCOUNT } from "util/constants"; + +describeSuite({ + id: "SR0401", + title: "Staking candidate reward test suite", + foundationMethods: "dev", + testCases: ({ it, context }) => { + let polkadotJs: ApiPromise; + let alice: KeyringPair; + let bob: KeyringPair; + + beforeAll(async () => { + polkadotJs = context.polkadotJs(); + alice = context.keyring.alice; + bob = context.keyring.bob; + let aliceNonce = (await polkadotJs.rpc.system.accountNextIndex(alice.address)).toNumber(); + let bobNonce = (await polkadotJs.rpc.system.accountNextIndex(bob.address)).toNumber(); + // We need to remove from invulnerables and add to staking + // for that we need to remove Alice and Bob from invulnerables first + // We will make each of them self-delegate the min amount, while + // we will make each of them delegate the other with 50% + // Alice autocompounding, Bob will be manual + + // Additionally, we need to pass to the staking account the minimum balance + const existentialDeposit = polkadotJs.consts.balances.existentialDeposit; + + await context.createBlock([ + await polkadotJs.tx.sudo + .sudo(polkadotJs.tx.invulnerables.removeInvulnerable(alice.address)) + .signAsync(context.keyring.alice, { nonce: aliceNonce++ }), + await polkadotJs.tx.sudo + .sudo(polkadotJs.tx.invulnerables.removeInvulnerable(bob.address)) + .signAsync(context.keyring.alice, { nonce: aliceNonce++ }), + await polkadotJs.tx.pooledStaking + .requestDelegate(alice.address, "AutoCompounding", 10000n * DANCE) + .signAsync(context.keyring.alice, { nonce: aliceNonce++ }), + await polkadotJs.tx.pooledStaking + .requestDelegate(alice.address, "ManualRewards", 10000n * DANCE) + .signAsync(context.keyring.bob, { nonce: bobNonce++ }), + await polkadotJs.tx.pooledStaking + .requestDelegate(bob.address, "AutoCompounding", 10000n * DANCE) + .signAsync(context.keyring.alice, { nonce: aliceNonce++ }), + await polkadotJs.tx.pooledStaking + .requestDelegate(bob.address, "ManualRewards", 10000n * DANCE) + .signAsync(context.keyring.bob, { nonce: bobNonce++ }), + await polkadotJs.tx.balances + .transfer(STAKING_ACCOUNT, existentialDeposit) + .signAsync(context.keyring.bob, { nonce: bobNonce++ }), + ]); + // At least 2 sessions for the change to have effect + await jumpSessions(context, 2); + }); + it({ + id: "E01", + title: "Alice should receive rewards through staking now", + test: async function () { + // 70% is distributed across all rewards + // But we have 2 container chains, so it should get 1/3 of this + // Since it is an invulnerable, it receives all payment + const events = await polkadotJs.query.system.events(); + const issuance = await fetchIssuance(events).amount.toBigInt(); + const chainRewards = (issuance * 7n) / 10n; + const expectedOrchestratorReward = chainRewards / 3n; + const reward = await fetchRewardAuthorOrchestrator(events); + const stakingRewardedCollator = await filterRewardStakingCollator(events, reward.accountId.toString()); + const stakingRewardedDelegators = await filterRewardStakingDelegators( + events, + reward.accountId.toString() + ); + + // How much should the author have gotten? + // For now everything as we did not execute the pending operations + expect(reward.balance.toBigInt()).to.equal(expectedOrchestratorReward); + expect(stakingRewardedCollator.manualRewards).to.equal(reward.balance.toBigInt()); + expect(stakingRewardedCollator.autoCompoundingRewards).to.equal(0n); + expect(stakingRewardedDelegators.manualRewards).to.equal(0n); + expect(stakingRewardedDelegators.autoCompoundingRewards).to.equal(0n); + }, + }); + + it({ + id: "E02", + title: "Alice should receive shared rewards with delegators through staking now", + test: async function () { + // All pending operations where in session 0 + await context.createBlock([ + await polkadotJs.tx.pooledStaking + .executePendingOperations([ + { + delegator: alice.address, + operation: { + JoiningAutoCompounding: { + candidate: alice.address, + at: 0, + }, + }, + }, + { + delegator: bob.address, + operation: { + JoiningManualRewards: { + candidate: alice.address, + at: 0, + }, + }, + }, + ]) + .signAsync(context.keyring.alice), + ]); + + const totalBacked = ( + await polkadotJs.query.pooledStaking.pools(alice.address, "CandidateTotalStake") + ).toBigInt(); + const totalManual = ( + await polkadotJs.query.pooledStaking.pools(alice.address, "ManualRewardsSharesTotalStaked") + ).toBigInt(); + const totalManualShareSupply = ( + await polkadotJs.query.pooledStaking.pools(alice.address, "ManualRewardsSharesSupply") + ).toBigInt(); + + // We create one more block + await context.createBlock(); + const events = await polkadotJs.query.system.events(); + const reward = await fetchRewardAuthorOrchestrator(events); + + // 20% plus 1 from rounding + const collatorPercentage = (20n * reward.balance.toBigInt()) / 100n + 1n; + + // Rounding + const delegatorRewards = reward.balance.toBigInt() - collatorPercentage; + + // First, manual rewards + const delegatorManualRewards = (totalManual * delegatorRewards) / totalBacked; + // Check its + const delegatorManualRewardsPerShare = delegatorManualRewards / totalManualShareSupply; + const realDistributedManualDelegatorRewards = delegatorManualRewardsPerShare * totalManualShareSupply; + + // Second, autocompounding + const delegatorsAutoCompoundRewards = delegatorRewards - realDistributedManualDelegatorRewards; + + const stakingRewardedCollator = await filterRewardStakingCollator(events, reward.accountId.toString()); + const stakingRewardedDelegators = await filterRewardStakingDelegators( + events, + reward.accountId.toString() + ); + expect(stakingRewardedDelegators.manualRewards).to.equal(realDistributedManualDelegatorRewards); + expect(stakingRewardedDelegators.autoCompoundingRewards).to.equal(delegatorsAutoCompoundRewards); + + // TODO: test better what goes into auto and what goes into manual for collator + const delegatorDust = + delegatorRewards - realDistributedManualDelegatorRewards - delegatorsAutoCompoundRewards; + expect(stakingRewardedCollator.manualRewards + stakingRewardedCollator.autoCompoundingRewards).to.equal( + collatorPercentage + delegatorDust + ); + }, + }); + }, +}); diff --git a/test/suites/dev-tanssi/staking/test_staking_rewards_non_balanced.ts b/test/suites/dev-tanssi/staking/test_staking_rewards_non_balanced.ts new file mode 100644 index 000000000..fce10f5c7 --- /dev/null +++ b/test/suites/dev-tanssi/staking/test_staking_rewards_non_balanced.ts @@ -0,0 +1,169 @@ +import "@tanssi/api-augment"; +import { describeSuite, expect, beforeAll } from "@moonwall/cli"; +import { ApiPromise } from "@polkadot/api"; +import { KeyringPair } from "@moonwall/util"; +import { + fetchIssuance, + fetchRewardAuthorOrchestrator, + filterRewardStakingCollator, + filterRewardStakingDelegators, + jumpSessions, +} from "util/block"; +import { DANCE, STAKING_ACCOUNT } from "util/constants"; + +describeSuite({ + id: "SR0401", + title: "Staking candidate reward test suite", + foundationMethods: "dev", + testCases: ({ it, context }) => { + let polkadotJs: ApiPromise; + let alice: KeyringPair; + let bob: KeyringPair; + + beforeAll(async () => { + polkadotJs = context.polkadotJs(); + alice = context.keyring.alice; + bob = context.keyring.bob; + let aliceNonce = (await polkadotJs.rpc.system.accountNextIndex(alice.address)).toNumber(); + let bobNonce = (await polkadotJs.rpc.system.accountNextIndex(bob.address)).toNumber(); + // We need to remove from invulnerables and add to staking + // for that we need to remove Alice and Bob from invulnerables first + // We will make each of them self-delegate the min amount, while + // we will make each of them delegate the other with 50% + // Alice autocompounding, Bob will be manual + + // Additionally, we need to pass to the staking account the minimum balance + const existentialDeposit = polkadotJs.consts.balances.existentialDeposit; + + await context.createBlock([ + await polkadotJs.tx.sudo + .sudo(polkadotJs.tx.invulnerables.removeInvulnerable(alice.address)) + .signAsync(context.keyring.alice, { nonce: aliceNonce++ }), + await polkadotJs.tx.sudo + .sudo(polkadotJs.tx.invulnerables.removeInvulnerable(bob.address)) + .signAsync(context.keyring.alice, { nonce: aliceNonce++ }), + await polkadotJs.tx.pooledStaking + .requestDelegate(alice.address, "AutoCompounding", 18000n * DANCE) + .signAsync(context.keyring.alice, { nonce: aliceNonce++ }), + await polkadotJs.tx.pooledStaking + .requestDelegate(alice.address, "ManualRewards", 2000n * DANCE) + .signAsync(context.keyring.bob, { nonce: bobNonce++ }), + await polkadotJs.tx.pooledStaking + .requestDelegate(bob.address, "AutoCompounding", 18000n * DANCE) + .signAsync(context.keyring.alice, { nonce: aliceNonce++ }), + await polkadotJs.tx.pooledStaking + .requestDelegate(bob.address, "ManualRewards", 2000n * DANCE) + .signAsync(context.keyring.bob, { nonce: bobNonce++ }), + await polkadotJs.tx.balances + .transfer(STAKING_ACCOUNT, existentialDeposit) + .signAsync(context.keyring.bob, { nonce: bobNonce++ }), + ]); + // At least 2 sessions for the change to have effect + await jumpSessions(context, 2); + }); + it({ + id: "E01", + title: "Alice should receive rewards through staking now", + test: async function () { + // 70% is distributed across all rewards + // But we have 2 container chains, so it should get 1/3 of this + // Since it is an invulnerable, it receives all payment + const events = await polkadotJs.query.system.events(); + const issuance = await fetchIssuance(events).amount.toBigInt(); + const chainRewards = (issuance * 7n) / 10n; + const expectedOrchestratorReward = chainRewards / 3n; + const reward = await fetchRewardAuthorOrchestrator(events); + const stakingRewardedCollator = await filterRewardStakingCollator(events, reward.accountId.toString()); + const stakingRewardedDelegators = await filterRewardStakingDelegators( + events, + reward.accountId.toString() + ); + + // How much should the author have gotten? + // For now everything as we did not execute the pending operations + expect(reward.balance.toBigInt()).to.equal(expectedOrchestratorReward); + expect(stakingRewardedCollator.manualRewards).to.equal(reward.balance.toBigInt()); + expect(stakingRewardedCollator.autoCompoundingRewards).to.equal(0n); + expect(stakingRewardedDelegators.manualRewards).to.equal(0n); + expect(stakingRewardedDelegators.autoCompoundingRewards).to.equal(0n); + }, + }); + + it({ + id: "E02", + title: "Alice should receive shared rewards with delegators through staking now", + test: async function () { + // All pending operations where in session 0 + await context.createBlock([ + await polkadotJs.tx.pooledStaking + .executePendingOperations([ + { + delegator: alice.address, + operation: { + JoiningAutoCompounding: { + candidate: alice.address, + at: 0, + }, + }, + }, + { + delegator: bob.address, + operation: { + JoiningManualRewards: { + candidate: alice.address, + at: 0, + }, + }, + }, + ]) + .signAsync(context.keyring.alice), + ]); + + const totalBacked = ( + await polkadotJs.query.pooledStaking.pools(alice.address, "CandidateTotalStake") + ).toBigInt(); + const totalManual = ( + await polkadotJs.query.pooledStaking.pools(alice.address, "ManualRewardsSharesTotalStaked") + ).toBigInt(); + const totalManualShareSupply = ( + await polkadotJs.query.pooledStaking.pools(alice.address, "ManualRewardsSharesSupply") + ).toBigInt(); + + // We create one more block + await context.createBlock(); + const events = await polkadotJs.query.system.events(); + const reward = await fetchRewardAuthorOrchestrator(events); + + // 20% plus 1 from rounding + const collatorPercentage = (20n * reward.balance.toBigInt()) / 100n + 1n; + + // Rounding + const delegatorRewards = reward.balance.toBigInt() - collatorPercentage; + + // First, manual rewards + const delegatorManualRewards = (totalManual * delegatorRewards) / totalBacked; + // Check its + const delegatorManualRewardsPerShare = delegatorManualRewards / totalManualShareSupply; + const realDistributedManualDelegatorRewards = delegatorManualRewardsPerShare * totalManualShareSupply; + + // Second, autocompounding + const delegatorsAutoCompoundRewards = delegatorRewards - realDistributedManualDelegatorRewards; + + const stakingRewardedCollator = await filterRewardStakingCollator(events, reward.accountId.toString()); + const stakingRewardedDelegators = await filterRewardStakingDelegators( + events, + reward.accountId.toString() + ); + expect(stakingRewardedDelegators.manualRewards).to.equal(realDistributedManualDelegatorRewards); + expect(stakingRewardedDelegators.autoCompoundingRewards).to.equal(delegatorsAutoCompoundRewards); + + // TODO: test better what goes into auto and what goes into manual for collator + const delegatorDust = + delegatorRewards - realDistributedManualDelegatorRewards - delegatorsAutoCompoundRewards; + expect(stakingRewardedCollator.manualRewards + stakingRewardedCollator.autoCompoundingRewards).to.equal( + collatorPercentage + delegatorDust + ); + }, + }); + }, +}); diff --git a/test/util/block.ts b/test/util/block.ts index b0bd247d8..ab26d448e 100644 --- a/test/util/block.ts +++ b/test/util/block.ts @@ -1,5 +1,8 @@ import { DevModeContext, expect } from "@moonwall/cli"; +import { filterAndApply } from "@moonwall/util"; + import { ApiPromise } from "@polkadot/api"; +import { AccountId32, EventRecord } from "@polkadot/types/interfaces"; export async function jumpSessions(context: DevModeContext, count: number): Promise { const session = (await context.polkadotJs().query.session.currentIndex()).addn(count.valueOf()).toNumber(); @@ -57,6 +60,130 @@ export async function waitToSession(context, paraApi: ApiPromise, session: numbe } } +export function extractFeeAuthor(events: EventRecord[] = [], feePayer: string) { + const filtered = filterAndApply( + events, + "balances", + ["Withdraw"], + ({ event }: EventRecord) => event.data as unknown as { who: AccountId32; amount: u128 } + ); + const extractFeeFromAuthor = filtered.filter(({ who }) => who.toString() === feePayer); + return extractFeeFromAuthor[0]; +} + +export function fetchRewardAuthorOrchestrator(events: EventRecord[] = []) { + const filtered = filterAndApply( + events, + "inflationRewards", + ["RewardedOrchestrator"], + ({ event }: EventRecord) => event.data as unknown as { accountId: AccountId32; balance: u128 } + ); + + return filtered[0]; +} + +export function filterRewardStakingCollator(events: EventRecord[] = [], author: string) { + const stakignRewardEvents = fetchRewardStakingCollators(events); + for (const index in stakignRewardEvents) { + if (stakignRewardEvents[index].collator.toString() === author) { + return { + manualRewards: stakignRewardEvents[index].manualClaimRewards.toBigInt(), + autoCompoundingRewards: stakignRewardEvents[index].autoCompoundingRewards.toBigInt(), + }; + } + } + + return { + manualRewards: 0n, + autoCompoundingRewards: 0n, + }; +} + +export function filterRewardStakingDelegators(events: EventRecord[] = [], author: string) { + const stakignRewardEvents = fetchRewardStakingDelegators(events); + for (const index in stakignRewardEvents) { + if (stakignRewardEvents[index].collator.toString() === author) { + return { + manualRewards: stakignRewardEvents[index].manualClaimRewards.toBigInt(), + autoCompoundingRewards: stakignRewardEvents[index].autoCompoundingRewards.toBigInt(), + }; + } + } + + return { + manualRewards: 0n, + autoCompoundingRewards: 0n, + }; +} + +export function fetchRewardStakingDelegators(events: EventRecord[] = []) { + const filtered = filterAndApply( + events, + "pooledStaking", + ["RewardedDelegators"], + ({ event }: EventRecord) => + event.data as unknown as { collator: AccountId32; autoCompoundingRewards: u128; manualClaimRewards: u128 } + ); + + return filtered; +} + +export function fetchRewardStakingCollators(events: EventRecord[] = []) { + const filtered = filterAndApply( + events, + "pooledStaking", + ["RewardedCollator"], + ({ event }: EventRecord) => + event.data as unknown as { collator: AccountId32; autoCompoundingRewards: u128; manualClaimRewards: u128 } + ); + + return filtered; +} + +export function fetchRewardAuthorContainers(events: EventRecord[] = []) { + const filtered = filterAndApply( + events, + "inflationRewards", + ["RewardedContainer"], + ({ event }: EventRecord) => event.data as unknown as { accountId: AccountId32; paraId: ParaId; balance: u128 } + ); + + return filtered; +} + +export function fetchIssuance(events: EventRecord[] = []) { + const filtered = filterAndApply( + events, + "balances", + ["Issued"], + ({ event }: EventRecord) => event.data as unknown as { amount: u128 } + ); + + return filtered[0]; +} + +export function filterRewardFromOrchestrator(events: EventRecord[] = [], author: string) { + const reward = fetchRewardAuthorOrchestrator(events); + if (reward.accountId.toString() === author) { + return reward.balance.toBigInt(); + } else { + return 0n; + } +} + +export function filterRewardFromContainer(events: EventRecord[] = [], feePayer: string, paraId: ParaId) { + const rewardEvents = fetchRewardAuthorContainers(events); + for (const index in rewardEvents) { + if ( + rewardEvents[index].accountId.toString() === feePayer && + rewardEvents[index].paraId.toString() === paraId.toString() + ) { + return rewardEvents[index].balance.toBigInt(); + } + } + return 0n; +} + /// Same as tx.signAndSend(account), except that it waits for the transaction to be included in a block: /// /// ``` diff --git a/test/util/constants.ts b/test/util/constants.ts new file mode 100644 index 000000000..91df6c1bf --- /dev/null +++ b/test/util/constants.ts @@ -0,0 +1,3 @@ +export const PARACHAIN_BOND = "5EYCAe5cJkHcthonN7KrsVp11XYHMqtrFPimDd3Af755ET2D"; +export const DANCE = 1_000_000_000_000n; +export const STAKING_ACCOUNT = "5EYCAe5cHvXp3GAe94dYPGjLqQdn7cnYuENAn66SntQkNTAG"; diff --git a/typescript-api/src/dancebox/interfaces/augment-api-events.ts b/typescript-api/src/dancebox/interfaces/augment-api-events.ts index 0a0447546..94ea7110d 100644 --- a/typescript-api/src/dancebox/interfaces/augment-api-events.ts +++ b/typescript-api/src/dancebox/interfaces/augment-api-events.ts @@ -189,6 +189,22 @@ declare module "@polkadot/api-base/types/events" { /** Generic event */ [key: string]: AugmentedEvent; }; + inflationRewards: { + /** Rewarding container author */ + RewardedContainer: AugmentedEvent< + ApiType, + [accountId: AccountId32, paraId: u32, balance: u128], + { accountId: AccountId32; paraId: u32; balance: u128 } + >; + /** Rewarding orchestrator author */ + RewardedOrchestrator: AugmentedEvent< + ApiType, + [accountId: AccountId32, balance: u128], + { accountId: AccountId32; balance: u128 } + >; + /** Generic event */ + [key: string]: AugmentedEvent; + }; invulnerables: { /** * An account was unable to be added to the Invulnerables because they did not have keys registered. Other diff --git a/typescript-api/src/dancebox/interfaces/augment-api-query.ts b/typescript-api/src/dancebox/interfaces/augment-api-query.ts index d1f4abdee..01ed0de14 100644 --- a/typescript-api/src/dancebox/interfaces/augment-api-query.ts +++ b/typescript-api/src/dancebox/interfaces/augment-api-query.ts @@ -33,6 +33,7 @@ import type { PalletBalancesIdAmount, PalletBalancesReserveData, PalletConfigurationHostConfiguration, + PalletInflationRewardsChainsToRewardValue, PalletPooledStakingCandidateEligibleCandidate, PalletPooledStakingPendingOperationKey, PalletPooledStakingPoolsKey, @@ -268,6 +269,17 @@ declare module "@polkadot/api-base/types/storage" { /** Generic query */ [key: string]: QueryableStorageEntry; }; + inflationRewards: { + /** Container chains to reward per block */ + chainsToReward: AugmentedQuery< + ApiType, + () => Observable>, + [] + > & + QueryableStorageEntry; + /** Generic query */ + [key: string]: QueryableStorageEntry; + }; invulnerables: { /** The invulnerable, permissioned collators. This list must be sorted. */ invulnerables: AugmentedQuery Observable>, []> & diff --git a/typescript-api/src/dancebox/interfaces/lookup.ts b/typescript-api/src/dancebox/interfaces/lookup.ts index ed58dd3e2..e80dd63ee 100644 --- a/typescript-api/src/dancebox/interfaces/lookup.ts +++ b/typescript-api/src/dancebox/interfaces/lookup.ts @@ -536,7 +536,21 @@ export default { PalletPooledStakingTargetPool: { _enum: ["AutoCompounding", "ManualRewards"], }, - /** Lookup56: cumulus_pallet_xcmp_queue::pallet::Event */ + /** Lookup56: pallet_inflation_rewards::pallet::Event */ + PalletInflationRewardsEvent: { + _enum: { + RewardedOrchestrator: { + accountId: "AccountId32", + balance: "u128", + }, + RewardedContainer: { + accountId: "AccountId32", + paraId: "u32", + balance: "u128", + }, + }, + }, + /** Lookup57: cumulus_pallet_xcmp_queue::pallet::Event */ CumulusPalletXcmpQueueEvent: { _enum: { Success: { @@ -571,7 +585,7 @@ export default { }, }, }, - /** Lookup57: staging_xcm::v3::traits::Error */ + /** Lookup58: staging_xcm::v3::traits::Error */ StagingXcmV3TraitsError: { _enum: { Overflow: "Null", @@ -616,7 +630,7 @@ export default { ExceedsStackLimit: "Null", }, }, - /** Lookup58: cumulus_pallet_xcm::pallet::Event */ + /** Lookup59: cumulus_pallet_xcm::pallet::Event */ CumulusPalletXcmEvent: { _enum: { InvalidFormat: "[u8;32]", @@ -624,7 +638,7 @@ export default { ExecutedDownward: "([u8;32],StagingXcmV3TraitsOutcome)", }, }, - /** Lookup59: staging_xcm::v3::traits::Outcome */ + /** Lookup60: staging_xcm::v3::traits::Outcome */ StagingXcmV3TraitsOutcome: { _enum: { Complete: "SpWeightsWeightV2Weight", @@ -632,7 +646,7 @@ export default { Error: "StagingXcmV3TraitsError", }, }, - /** Lookup60: cumulus_pallet_dmp_queue::pallet::Event */ + /** Lookup61: cumulus_pallet_dmp_queue::pallet::Event */ CumulusPalletDmpQueueEvent: { _enum: { InvalidFormat: { @@ -667,7 +681,7 @@ export default { }, }, }, - /** Lookup61: pallet_xcm::pallet::Event */ + /** Lookup62: pallet_xcm::pallet::Event */ PalletXcmEvent: { _enum: { Attempted: { @@ -787,12 +801,12 @@ export default { }, }, }, - /** Lookup62: staging_xcm::v3::multilocation::MultiLocation */ + /** Lookup63: staging_xcm::v3::multilocation::MultiLocation */ StagingXcmV3MultiLocation: { parents: "u8", interior: "StagingXcmV3Junctions", }, - /** Lookup63: staging_xcm::v3::junctions::Junctions */ + /** Lookup64: staging_xcm::v3::junctions::Junctions */ StagingXcmV3Junctions: { _enum: { Here: "Null", @@ -806,7 +820,7 @@ export default { X8: "(StagingXcmV3Junction,StagingXcmV3Junction,StagingXcmV3Junction,StagingXcmV3Junction,StagingXcmV3Junction,StagingXcmV3Junction,StagingXcmV3Junction,StagingXcmV3Junction)", }, }, - /** Lookup64: staging_xcm::v3::junction::Junction */ + /** Lookup65: staging_xcm::v3::junction::Junction */ StagingXcmV3Junction: { _enum: { Parachain: "Compact", @@ -836,7 +850,7 @@ export default { GlobalConsensus: "StagingXcmV3JunctionNetworkId", }, }, - /** Lookup67: staging_xcm::v3::junction::NetworkId */ + /** Lookup68: staging_xcm::v3::junction::NetworkId */ StagingXcmV3JunctionNetworkId: { _enum: { ByGenesis: "[u8;32]", @@ -856,7 +870,7 @@ export default { BitcoinCash: "Null", }, }, - /** Lookup70: staging_xcm::v3::junction::BodyId */ + /** Lookup71: staging_xcm::v3::junction::BodyId */ StagingXcmV3JunctionBodyId: { _enum: { Unit: "Null", @@ -871,7 +885,7 @@ export default { Treasury: "Null", }, }, - /** Lookup71: staging_xcm::v3::junction::BodyPart */ + /** Lookup72: staging_xcm::v3::junction::BodyPart */ StagingXcmV3JunctionBodyPart: { _enum: { Voice: "Null", @@ -892,9 +906,9 @@ export default { }, }, }, - /** Lookup72: staging_xcm::v3::Xcm */ + /** Lookup73: staging_xcm::v3::Xcm */ StagingXcmV3Xcm: "Vec", - /** Lookup74: staging_xcm::v3::Instruction */ + /** Lookup75: staging_xcm::v3::Instruction */ StagingXcmV3Instruction: { _enum: { WithdrawAsset: "StagingXcmV3MultiassetMultiAssets", @@ -1034,28 +1048,28 @@ export default { }, }, }, - /** Lookup75: staging_xcm::v3::multiasset::MultiAssets */ + /** Lookup76: staging_xcm::v3::multiasset::MultiAssets */ StagingXcmV3MultiassetMultiAssets: "Vec", - /** Lookup77: staging_xcm::v3::multiasset::MultiAsset */ + /** Lookup78: staging_xcm::v3::multiasset::MultiAsset */ StagingXcmV3MultiAsset: { id: "StagingXcmV3MultiassetAssetId", fun: "StagingXcmV3MultiassetFungibility", }, - /** Lookup78: staging_xcm::v3::multiasset::AssetId */ + /** Lookup79: staging_xcm::v3::multiasset::AssetId */ StagingXcmV3MultiassetAssetId: { _enum: { Concrete: "StagingXcmV3MultiLocation", Abstract: "[u8;32]", }, }, - /** Lookup79: staging_xcm::v3::multiasset::Fungibility */ + /** Lookup80: staging_xcm::v3::multiasset::Fungibility */ StagingXcmV3MultiassetFungibility: { _enum: { Fungible: "Compact", NonFungible: "StagingXcmV3MultiassetAssetInstance", }, }, - /** Lookup80: staging_xcm::v3::multiasset::AssetInstance */ + /** Lookup81: staging_xcm::v3::multiasset::AssetInstance */ StagingXcmV3MultiassetAssetInstance: { _enum: { Undefined: "Null", @@ -1066,7 +1080,7 @@ export default { Array32: "[u8;32]", }, }, - /** Lookup83: staging_xcm::v3::Response */ + /** Lookup84: staging_xcm::v3::Response */ StagingXcmV3Response: { _enum: { Null: "Null", @@ -1077,7 +1091,7 @@ export default { DispatchResult: "StagingXcmV3MaybeErrorCode", }, }, - /** Lookup87: staging_xcm::v3::PalletInfo */ + /** Lookup88: staging_xcm::v3::PalletInfo */ StagingXcmV3PalletInfo: { index: "Compact", name: "Bytes", @@ -1086,7 +1100,7 @@ export default { minor: "Compact", patch: "Compact", }, - /** Lookup90: staging_xcm::v3::MaybeErrorCode */ + /** Lookup91: staging_xcm::v3::MaybeErrorCode */ StagingXcmV3MaybeErrorCode: { _enum: { Success: "Null", @@ -1094,28 +1108,28 @@ export default { TruncatedError: "Bytes", }, }, - /** Lookup93: staging_xcm::v2::OriginKind */ + /** Lookup94: staging_xcm::v2::OriginKind */ StagingXcmV2OriginKind: { _enum: ["Native", "SovereignAccount", "Superuser", "Xcm"], }, - /** Lookup94: staging_xcm::double_encoded::DoubleEncoded */ + /** Lookup95: staging_xcm::double_encoded::DoubleEncoded */ StagingXcmDoubleEncoded: { encoded: "Bytes", }, - /** Lookup95: staging_xcm::v3::QueryResponseInfo */ + /** Lookup96: staging_xcm::v3::QueryResponseInfo */ StagingXcmV3QueryResponseInfo: { destination: "StagingXcmV3MultiLocation", queryId: "Compact", maxWeight: "SpWeightsWeightV2Weight", }, - /** Lookup96: staging_xcm::v3::multiasset::MultiAssetFilter */ + /** Lookup97: staging_xcm::v3::multiasset::MultiAssetFilter */ StagingXcmV3MultiassetMultiAssetFilter: { _enum: { Definite: "StagingXcmV3MultiassetMultiAssets", Wild: "StagingXcmV3MultiassetWildMultiAsset", }, }, - /** Lookup97: staging_xcm::v3::multiasset::WildMultiAsset */ + /** Lookup98: staging_xcm::v3::multiasset::WildMultiAsset */ StagingXcmV3MultiassetWildMultiAsset: { _enum: { All: "Null", @@ -1131,18 +1145,18 @@ export default { }, }, }, - /** Lookup98: staging_xcm::v3::multiasset::WildFungibility */ + /** Lookup99: staging_xcm::v3::multiasset::WildFungibility */ StagingXcmV3MultiassetWildFungibility: { _enum: ["Fungible", "NonFungible"], }, - /** Lookup99: staging_xcm::v3::WeightLimit */ + /** Lookup100: staging_xcm::v3::WeightLimit */ StagingXcmV3WeightLimit: { _enum: { Unlimited: "Null", Limited: "SpWeightsWeightV2Weight", }, }, - /** Lookup100: staging_xcm::VersionedMultiAssets */ + /** Lookup101: staging_xcm::VersionedMultiAssets */ StagingXcmVersionedMultiAssets: { _enum: { __Unused0: "Null", @@ -1151,26 +1165,26 @@ export default { V3: "StagingXcmV3MultiassetMultiAssets", }, }, - /** Lookup101: staging_xcm::v2::multiasset::MultiAssets */ + /** Lookup102: staging_xcm::v2::multiasset::MultiAssets */ StagingXcmV2MultiassetMultiAssets: "Vec", - /** Lookup103: staging_xcm::v2::multiasset::MultiAsset */ + /** Lookup104: staging_xcm::v2::multiasset::MultiAsset */ StagingXcmV2MultiAsset: { id: "StagingXcmV2MultiassetAssetId", fun: "StagingXcmV2MultiassetFungibility", }, - /** Lookup104: staging_xcm::v2::multiasset::AssetId */ + /** Lookup105: staging_xcm::v2::multiasset::AssetId */ StagingXcmV2MultiassetAssetId: { _enum: { Concrete: "StagingXcmV2MultiLocation", Abstract: "Bytes", }, }, - /** Lookup105: staging_xcm::v2::multilocation::MultiLocation */ + /** Lookup106: staging_xcm::v2::multilocation::MultiLocation */ StagingXcmV2MultiLocation: { parents: "u8", interior: "StagingXcmV2MultilocationJunctions", }, - /** Lookup106: staging_xcm::v2::multilocation::Junctions */ + /** Lookup107: staging_xcm::v2::multilocation::Junctions */ StagingXcmV2MultilocationJunctions: { _enum: { Here: "Null", @@ -1184,7 +1198,7 @@ export default { X8: "(StagingXcmV2Junction,StagingXcmV2Junction,StagingXcmV2Junction,StagingXcmV2Junction,StagingXcmV2Junction,StagingXcmV2Junction,StagingXcmV2Junction,StagingXcmV2Junction)", }, }, - /** Lookup107: staging_xcm::v2::junction::Junction */ + /** Lookup108: staging_xcm::v2::junction::Junction */ StagingXcmV2Junction: { _enum: { Parachain: "Compact", @@ -1210,7 +1224,7 @@ export default { }, }, }, - /** Lookup108: staging_xcm::v2::NetworkId */ + /** Lookup109: staging_xcm::v2::NetworkId */ StagingXcmV2NetworkId: { _enum: { Any: "Null", @@ -1219,7 +1233,7 @@ export default { Kusama: "Null", }, }, - /** Lookup110: staging_xcm::v2::BodyId */ + /** Lookup111: staging_xcm::v2::BodyId */ StagingXcmV2BodyId: { _enum: { Unit: "Null", @@ -1234,7 +1248,7 @@ export default { Treasury: "Null", }, }, - /** Lookup111: staging_xcm::v2::BodyPart */ + /** Lookup112: staging_xcm::v2::BodyPart */ StagingXcmV2BodyPart: { _enum: { Voice: "Null", @@ -1255,14 +1269,14 @@ export default { }, }, }, - /** Lookup112: staging_xcm::v2::multiasset::Fungibility */ + /** Lookup113: staging_xcm::v2::multiasset::Fungibility */ StagingXcmV2MultiassetFungibility: { _enum: { Fungible: "Compact", NonFungible: "StagingXcmV2MultiassetAssetInstance", }, }, - /** Lookup113: staging_xcm::v2::multiasset::AssetInstance */ + /** Lookup114: staging_xcm::v2::multiasset::AssetInstance */ StagingXcmV2MultiassetAssetInstance: { _enum: { Undefined: "Null", @@ -1274,7 +1288,7 @@ export default { Blob: "Bytes", }, }, - /** Lookup114: staging_xcm::VersionedMultiLocation */ + /** Lookup115: staging_xcm::VersionedMultiLocation */ StagingXcmVersionedMultiLocation: { _enum: { __Unused0: "Null", @@ -1283,7 +1297,7 @@ export default { V3: "StagingXcmV3MultiLocation", }, }, - /** Lookup115: frame_system::Phase */ + /** Lookup116: frame_system::Phase */ FrameSystemPhase: { _enum: { ApplyExtrinsic: "u32", @@ -1291,12 +1305,12 @@ export default { Initialization: "Null", }, }, - /** Lookup119: frame_system::LastRuntimeUpgradeInfo */ + /** Lookup120: frame_system::LastRuntimeUpgradeInfo */ FrameSystemLastRuntimeUpgradeInfo: { specVersion: "Compact", specName: "Text", }, - /** Lookup121: frame_system::pallet::Call */ + /** Lookup122: frame_system::pallet::Call */ FrameSystemCall: { _enum: { remark: { @@ -1329,41 +1343,41 @@ export default { }, }, }, - /** Lookup125: frame_system::limits::BlockWeights */ + /** Lookup126: frame_system::limits::BlockWeights */ FrameSystemLimitsBlockWeights: { baseBlock: "SpWeightsWeightV2Weight", maxBlock: "SpWeightsWeightV2Weight", perClass: "FrameSupportDispatchPerDispatchClassWeightsPerClass", }, - /** Lookup126: frame_support::dispatch::PerDispatchClass */ + /** Lookup127: frame_support::dispatch::PerDispatchClass */ FrameSupportDispatchPerDispatchClassWeightsPerClass: { normal: "FrameSystemLimitsWeightsPerClass", operational: "FrameSystemLimitsWeightsPerClass", mandatory: "FrameSystemLimitsWeightsPerClass", }, - /** Lookup127: frame_system::limits::WeightsPerClass */ + /** Lookup128: frame_system::limits::WeightsPerClass */ FrameSystemLimitsWeightsPerClass: { baseExtrinsic: "SpWeightsWeightV2Weight", maxExtrinsic: "Option", maxTotal: "Option", reserved: "Option", }, - /** Lookup129: frame_system::limits::BlockLength */ + /** Lookup130: frame_system::limits::BlockLength */ FrameSystemLimitsBlockLength: { max: "FrameSupportDispatchPerDispatchClassU32", }, - /** Lookup130: frame_support::dispatch::PerDispatchClass */ + /** Lookup131: frame_support::dispatch::PerDispatchClass */ FrameSupportDispatchPerDispatchClassU32: { normal: "u32", operational: "u32", mandatory: "u32", }, - /** Lookup131: sp_weights::RuntimeDbWeight */ + /** Lookup132: sp_weights::RuntimeDbWeight */ SpWeightsRuntimeDbWeight: { read: "u64", write: "u64", }, - /** Lookup132: sp_version::RuntimeVersion */ + /** Lookup133: sp_version::RuntimeVersion */ SpVersionRuntimeVersion: { specName: "Text", implName: "Text", @@ -1374,7 +1388,7 @@ export default { transactionVersion: "u32", stateVersion: "u8", }, - /** Lookup136: frame_system::pallet::Error */ + /** Lookup137: frame_system::pallet::Error */ FrameSystemError: { _enum: [ "InvalidSpecName", @@ -1385,49 +1399,49 @@ export default { "CallFiltered", ], }, - /** Lookup138: cumulus_pallet_parachain_system::unincluded_segment::Ancestor */ + /** Lookup139: cumulus_pallet_parachain_system::unincluded_segment::Ancestor */ CumulusPalletParachainSystemUnincludedSegmentAncestor: { usedBandwidth: "CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth", paraHeadHash: "Option", consumedGoAheadSignal: "Option", }, - /** Lookup139: cumulus_pallet_parachain_system::unincluded_segment::UsedBandwidth */ + /** Lookup140: cumulus_pallet_parachain_system::unincluded_segment::UsedBandwidth */ CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth: { umpMsgCount: "u32", umpTotalBytes: "u32", hrmpOutgoing: "BTreeMap", }, - /** Lookup141: cumulus_pallet_parachain_system::unincluded_segment::HrmpChannelUpdate */ + /** Lookup142: cumulus_pallet_parachain_system::unincluded_segment::HrmpChannelUpdate */ CumulusPalletParachainSystemUnincludedSegmentHrmpChannelUpdate: { msgCount: "u32", totalBytes: "u32", }, - /** Lookup146: polkadot_primitives::v5::UpgradeGoAhead */ + /** Lookup147: polkadot_primitives::v5::UpgradeGoAhead */ PolkadotPrimitivesV5UpgradeGoAhead: { _enum: ["Abort", "GoAhead"], }, - /** Lookup147: cumulus_pallet_parachain_system::unincluded_segment::SegmentTracker */ + /** Lookup148: cumulus_pallet_parachain_system::unincluded_segment::SegmentTracker */ CumulusPalletParachainSystemUnincludedSegmentSegmentTracker: { usedBandwidth: "CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth", hrmpWatermark: "Option", consumedGoAheadSignal: "Option", }, - /** Lookup148: polkadot_primitives::v5::PersistedValidationData */ + /** Lookup149: polkadot_primitives::v5::PersistedValidationData */ PolkadotPrimitivesV5PersistedValidationData: { parentHead: "Bytes", relayParentNumber: "u32", relayParentStorageRoot: "H256", maxPovSize: "u32", }, - /** Lookup151: polkadot_primitives::v5::UpgradeRestriction */ + /** Lookup152: polkadot_primitives::v5::UpgradeRestriction */ PolkadotPrimitivesV5UpgradeRestriction: { _enum: ["Present"], }, - /** Lookup152: sp_trie::storage_proof::StorageProof */ + /** Lookup153: sp_trie::storage_proof::StorageProof */ SpTrieStorageProof: { trieNodes: "BTreeSet", }, - /** Lookup154: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot */ + /** Lookup155: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot */ CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: { dmqMqcHead: "H256", relayDispatchQueueRemainingCapacity: @@ -1435,12 +1449,12 @@ export default { ingressChannels: "Vec<(u32,PolkadotPrimitivesV5AbridgedHrmpChannel)>", egressChannels: "Vec<(u32,PolkadotPrimitivesV5AbridgedHrmpChannel)>", }, - /** Lookup155: cumulus_pallet_parachain_system::relay_state_snapshot::RelayDispatchQueueRemainingCapacity */ + /** Lookup156: cumulus_pallet_parachain_system::relay_state_snapshot::RelayDispatchQueueRemainingCapacity */ CumulusPalletParachainSystemRelayStateSnapshotRelayDispatchQueueRemainingCapacity: { remainingCount: "u32", remainingSize: "u32", }, - /** Lookup158: polkadot_primitives::v5::AbridgedHrmpChannel */ + /** Lookup159: polkadot_primitives::v5::AbridgedHrmpChannel */ PolkadotPrimitivesV5AbridgedHrmpChannel: { maxCapacity: "u32", maxTotalSize: "u32", @@ -1449,7 +1463,7 @@ export default { totalSize: "u32", mqcHead: "Option", }, - /** Lookup159: polkadot_primitives::v5::AbridgedHostConfiguration */ + /** Lookup160: polkadot_primitives::v5::AbridgedHostConfiguration */ PolkadotPrimitivesV5AbridgedHostConfiguration: { maxCodeSize: "u32", maxHeadDataSize: "u32", @@ -1462,22 +1476,22 @@ export default { validationUpgradeDelay: "u32", asyncBackingParams: "PolkadotPrimitivesVstagingAsyncBackingParams", }, - /** Lookup160: polkadot_primitives::vstaging::AsyncBackingParams */ + /** Lookup161: polkadot_primitives::vstaging::AsyncBackingParams */ PolkadotPrimitivesVstagingAsyncBackingParams: { maxCandidateDepth: "u32", allowedAncestryLen: "u32", }, - /** Lookup166: polkadot_core_primitives::OutboundHrmpMessage */ + /** Lookup167: polkadot_core_primitives::OutboundHrmpMessage */ PolkadotCorePrimitivesOutboundHrmpMessage: { recipient: "u32", data: "Bytes", }, - /** Lookup167: cumulus_pallet_parachain_system::CodeUpgradeAuthorization */ + /** Lookup168: cumulus_pallet_parachain_system::CodeUpgradeAuthorization */ CumulusPalletParachainSystemCodeUpgradeAuthorization: { codeHash: "H256", checkVersion: "bool", }, - /** Lookup168: cumulus_pallet_parachain_system::pallet::Call */ + /** Lookup169: cumulus_pallet_parachain_system::pallet::Call */ CumulusPalletParachainSystemCall: { _enum: { set_validation_data: { @@ -1495,24 +1509,24 @@ export default { }, }, }, - /** Lookup169: cumulus_primitives_parachain_inherent::ParachainInherentData */ + /** Lookup170: cumulus_primitives_parachain_inherent::ParachainInherentData */ CumulusPrimitivesParachainInherentParachainInherentData: { validationData: "PolkadotPrimitivesV5PersistedValidationData", relayChainState: "SpTrieStorageProof", downwardMessages: "Vec", horizontalMessages: "BTreeMap>", }, - /** Lookup171: polkadot_core_primitives::InboundDownwardMessage */ + /** Lookup172: polkadot_core_primitives::InboundDownwardMessage */ PolkadotCorePrimitivesInboundDownwardMessage: { sentAt: "u32", msg: "Bytes", }, - /** Lookup174: polkadot_core_primitives::InboundHrmpMessage */ + /** Lookup175: polkadot_core_primitives::InboundHrmpMessage */ PolkadotCorePrimitivesInboundHrmpMessage: { sentAt: "u32", data: "Bytes", }, - /** Lookup177: cumulus_pallet_parachain_system::pallet::Error */ + /** Lookup178: cumulus_pallet_parachain_system::pallet::Error */ CumulusPalletParachainSystemError: { _enum: [ "OverlappingUpgrades", @@ -1525,7 +1539,7 @@ export default { "Unauthorized", ], }, - /** Lookup178: pallet_timestamp::pallet::Call */ + /** Lookup179: pallet_timestamp::pallet::Call */ PalletTimestampCall: { _enum: { set: { @@ -1533,9 +1547,9 @@ export default { }, }, }, - /** Lookup179: parachain_info::pallet::Call */ + /** Lookup180: parachain_info::pallet::Call */ ParachainInfoCall: "Null", - /** Lookup180: pallet_sudo::pallet::Call */ + /** Lookup181: pallet_sudo::pallet::Call */ PalletSudoCall: { _enum: { sudo: { @@ -1557,7 +1571,7 @@ export default { }, }, }, - /** Lookup182: pallet_utility::pallet::Call */ + /** Lookup183: pallet_utility::pallet::Call */ PalletUtilityCall: { _enum: { batch: { @@ -1583,7 +1597,7 @@ export default { }, }, }, - /** Lookup184: dancebox_runtime::OriginCaller */ + /** Lookup185: dancebox_runtime::OriginCaller */ DanceboxRuntimeOriginCaller: { _enum: { system: "FrameSupportDispatchRawOrigin", @@ -1642,7 +1656,7 @@ export default { PolkadotXcm: "PalletXcmOrigin", }, }, - /** Lookup185: frame_support::dispatch::RawOrigin */ + /** Lookup186: frame_support::dispatch::RawOrigin */ FrameSupportDispatchRawOrigin: { _enum: { Root: "Null", @@ -1650,23 +1664,23 @@ export default { None: "Null", }, }, - /** Lookup186: cumulus_pallet_xcm::pallet::Origin */ + /** Lookup187: cumulus_pallet_xcm::pallet::Origin */ CumulusPalletXcmOrigin: { _enum: { Relay: "Null", SiblingParachain: "u32", }, }, - /** Lookup187: pallet_xcm::pallet::Origin */ + /** Lookup188: pallet_xcm::pallet::Origin */ PalletXcmOrigin: { _enum: { Xcm: "StagingXcmV3MultiLocation", Response: "StagingXcmV3MultiLocation", }, }, - /** Lookup188: sp_core::Void */ + /** Lookup189: sp_core::Void */ SpCoreVoid: "Null", - /** Lookup189: pallet_proxy::pallet::Call */ + /** Lookup190: pallet_proxy::pallet::Call */ PalletProxyCall: { _enum: { proxy: { @@ -1717,11 +1731,11 @@ export default { }, }, }, - /** Lookup193: pallet_maintenance_mode::pallet::Call */ + /** Lookup194: pallet_maintenance_mode::pallet::Call */ PalletMaintenanceModeCall: { _enum: ["enter_maintenance_mode", "resume_normal_operation"], }, - /** Lookup194: pallet_balances::pallet::Call */ + /** Lookup195: pallet_balances::pallet::Call */ PalletBalancesCall: { _enum: { transfer_allow_death: { @@ -1763,7 +1777,7 @@ export default { }, }, }, - /** Lookup195: pallet_registrar::pallet::Call */ + /** Lookup196: pallet_registrar::pallet::Call */ PalletRegistrarCall: { _enum: { register: { @@ -1785,7 +1799,7 @@ export default { }, }, }, - /** Lookup196: tp_container_chain_genesis_data::ContainerChainGenesisData */ + /** Lookup197: tp_container_chain_genesis_data::ContainerChainGenesisData */ TpContainerChainGenesisDataContainerChainGenesisData: { storage: "Vec", name: "Bytes", @@ -1794,23 +1808,23 @@ export default { extensions: "Bytes", properties: "TpContainerChainGenesisDataProperties", }, - /** Lookup198: tp_container_chain_genesis_data::ContainerChainGenesisDataItem */ + /** Lookup199: tp_container_chain_genesis_data::ContainerChainGenesisDataItem */ TpContainerChainGenesisDataContainerChainGenesisDataItem: { key: "Bytes", value: "Bytes", }, - /** Lookup200: tp_container_chain_genesis_data::Properties */ + /** Lookup201: tp_container_chain_genesis_data::Properties */ TpContainerChainGenesisDataProperties: { tokenMetadata: "TpContainerChainGenesisDataTokenMetadata", isEthereum: "bool", }, - /** Lookup201: tp_container_chain_genesis_data::TokenMetadata */ + /** Lookup202: tp_container_chain_genesis_data::TokenMetadata */ TpContainerChainGenesisDataTokenMetadata: { tokenSymbol: "Bytes", ss58Format: "u32", tokenDecimals: "u32", }, - /** Lookup206: pallet_configuration::pallet::Call */ + /** Lookup207: pallet_configuration::pallet::Call */ PalletConfigurationCall: { _enum: { set_max_collators: { @@ -1890,9 +1904,9 @@ export default { }, }, }, - /** Lookup207: pallet_collator_assignment::pallet::Call */ + /** Lookup208: pallet_collator_assignment::pallet::Call */ PalletCollatorAssignmentCall: "Null", - /** Lookup208: pallet_author_noting::pallet::Call */ + /** Lookup209: pallet_author_noting::pallet::Call */ PalletAuthorNotingCall: { _enum: { set_latest_author_data: { @@ -1908,13 +1922,13 @@ export default { }, }, }, - /** Lookup209: tp_author_noting_inherent::OwnParachainInherentData */ + /** Lookup210: tp_author_noting_inherent::OwnParachainInherentData */ TpAuthorNotingInherentOwnParachainInherentData: { relayStorageProof: "SpTrieStorageProof", }, - /** Lookup210: pallet_authority_assignment::pallet::Call */ + /** Lookup211: pallet_authority_assignment::pallet::Call */ PalletAuthorityAssignmentCall: "Null", - /** Lookup211: pallet_invulnerables::pallet::Call */ + /** Lookup212: pallet_invulnerables::pallet::Call */ PalletInvulnerablesCall: { _enum: { set_invulnerables: { @@ -1931,7 +1945,7 @@ export default { }, }, }, - /** Lookup212: pallet_session::pallet::Call */ + /** Lookup213: pallet_session::pallet::Call */ PalletSessionCall: { _enum: { set_keys: { @@ -1944,19 +1958,19 @@ export default { purge_keys: "Null", }, }, - /** Lookup213: dancebox_runtime::SessionKeys */ + /** Lookup214: dancebox_runtime::SessionKeys */ DanceboxRuntimeSessionKeys: { nimbus: "NimbusPrimitivesNimbusCryptoPublic", }, - /** Lookup214: nimbus_primitives::nimbus_crypto::Public */ + /** Lookup215: nimbus_primitives::nimbus_crypto::Public */ NimbusPrimitivesNimbusCryptoPublic: "SpCoreSr25519Public", - /** Lookup215: sp_core::sr25519::Public */ + /** Lookup216: sp_core::sr25519::Public */ SpCoreSr25519Public: "[u8;32]", - /** Lookup216: pallet_author_inherent::pallet::Call */ + /** Lookup217: pallet_author_inherent::pallet::Call */ PalletAuthorInherentCall: { _enum: ["kick_off_authorship_validation"], }, - /** Lookup217: pallet_pooled_staking::pallet::Call */ + /** Lookup218: pallet_pooled_staking::pallet::Call */ PalletPooledStakingCall: { _enum: { rebalance_hold: { @@ -1990,16 +2004,16 @@ export default { }, }, }, - /** Lookup218: pallet_pooled_staking::pallet::AllTargetPool */ + /** Lookup219: pallet_pooled_staking::pallet::AllTargetPool */ PalletPooledStakingAllTargetPool: { _enum: ["Joining", "AutoCompounding", "ManualRewards", "Leaving"], }, - /** Lookup220: pallet_pooled_staking::pallet::PendingOperationQuery */ + /** Lookup221: pallet_pooled_staking::pallet::PendingOperationQuery */ PalletPooledStakingPendingOperationQuery: { delegator: "AccountId32", operation: "PalletPooledStakingPendingOperationKey", }, - /** Lookup221: pallet_pooled_staking::pallet::PendingOperationKey */ + /** Lookup222: pallet_pooled_staking::pallet::PendingOperationKey */ PalletPooledStakingPendingOperationKey: { _enum: { JoiningAutoCompounding: { @@ -2016,14 +2030,14 @@ export default { }, }, }, - /** Lookup222: pallet_pooled_staking::pallet::SharesOrStake */ + /** Lookup223: pallet_pooled_staking::pallet::SharesOrStake */ PalletPooledStakingSharesOrStake: { _enum: { Shares: "u128", Stake: "u128", }, }, - /** Lookup225: cumulus_pallet_xcmp_queue::pallet::Call */ + /** Lookup226: cumulus_pallet_xcmp_queue::pallet::Call */ CumulusPalletXcmpQueueCall: { _enum: { service_overweight: { @@ -2070,7 +2084,7 @@ export default { }, }, }, - /** Lookup226: cumulus_pallet_dmp_queue::pallet::Call */ + /** Lookup227: cumulus_pallet_dmp_queue::pallet::Call */ CumulusPalletDmpQueueCall: { _enum: { service_overweight: { @@ -2079,7 +2093,7 @@ export default { }, }, }, - /** Lookup227: pallet_xcm::pallet::Call */ + /** Lookup228: pallet_xcm::pallet::Call */ PalletXcmCall: { _enum: { send: { @@ -2134,7 +2148,7 @@ export default { }, }, }, - /** Lookup228: staging_xcm::VersionedXcm */ + /** Lookup229: staging_xcm::VersionedXcm */ StagingXcmVersionedXcm: { _enum: { __Unused0: "Null", @@ -2143,9 +2157,9 @@ export default { V3: "StagingXcmV3Xcm", }, }, - /** Lookup229: staging_xcm::v2::Xcm */ + /** Lookup230: staging_xcm::v2::Xcm */ StagingXcmV2Xcm: "Vec", - /** Lookup231: staging_xcm::v2::Instruction */ + /** Lookup232: staging_xcm::v2::Instruction */ StagingXcmV2Instruction: { _enum: { WithdrawAsset: "StagingXcmV2MultiassetMultiAssets", @@ -2241,7 +2255,7 @@ export default { UnsubscribeVersion: "Null", }, }, - /** Lookup232: staging_xcm::v2::Response */ + /** Lookup233: staging_xcm::v2::Response */ StagingXcmV2Response: { _enum: { Null: "Null", @@ -2250,7 +2264,7 @@ export default { Version: "u32", }, }, - /** Lookup235: staging_xcm::v2::traits::Error */ + /** Lookup236: staging_xcm::v2::traits::Error */ StagingXcmV2TraitsError: { _enum: { Overflow: "Null", @@ -2281,14 +2295,14 @@ export default { WeightNotComputable: "Null", }, }, - /** Lookup236: staging_xcm::v2::multiasset::MultiAssetFilter */ + /** Lookup237: staging_xcm::v2::multiasset::MultiAssetFilter */ StagingXcmV2MultiassetMultiAssetFilter: { _enum: { Definite: "StagingXcmV2MultiassetMultiAssets", Wild: "StagingXcmV2MultiassetWildMultiAsset", }, }, - /** Lookup237: staging_xcm::v2::multiasset::WildMultiAsset */ + /** Lookup238: staging_xcm::v2::multiasset::WildMultiAsset */ StagingXcmV2MultiassetWildMultiAsset: { _enum: { All: "Null", @@ -2298,18 +2312,18 @@ export default { }, }, }, - /** Lookup238: staging_xcm::v2::multiasset::WildFungibility */ + /** Lookup239: staging_xcm::v2::multiasset::WildFungibility */ StagingXcmV2MultiassetWildFungibility: { _enum: ["Fungible", "NonFungible"], }, - /** Lookup239: staging_xcm::v2::WeightLimit */ + /** Lookup240: staging_xcm::v2::WeightLimit */ StagingXcmV2WeightLimit: { _enum: { Unlimited: "Null", Limited: "Compact", }, }, - /** Lookup248: pallet_root_testing::pallet::Call */ + /** Lookup249: pallet_root_testing::pallet::Call */ PalletRootTestingCall: { _enum: { fill_block: { @@ -2317,27 +2331,27 @@ export default { }, }, }, - /** Lookup250: pallet_sudo::pallet::Error */ + /** Lookup251: pallet_sudo::pallet::Error */ PalletSudoError: { _enum: ["RequireSudo"], }, - /** Lookup251: pallet_utility::pallet::Error */ + /** Lookup252: pallet_utility::pallet::Error */ PalletUtilityError: { _enum: ["TooManyCalls"], }, - /** Lookup254: pallet_proxy::ProxyDefinition */ + /** Lookup255: pallet_proxy::ProxyDefinition */ PalletProxyProxyDefinition: { delegate: "AccountId32", proxyType: "DanceboxRuntimeProxyType", delay: "u32", }, - /** Lookup258: pallet_proxy::Announcement */ + /** Lookup259: pallet_proxy::Announcement */ PalletProxyAnnouncement: { real: "AccountId32", callHash: "H256", height: "u32", }, - /** Lookup260: pallet_proxy::pallet::Error */ + /** Lookup261: pallet_proxy::pallet::Error */ PalletProxyError: { _enum: [ "TooMany", @@ -2350,39 +2364,39 @@ export default { "NoSelfProxy", ], }, - /** Lookup261: pallet_migrations::pallet::Error */ + /** Lookup262: pallet_migrations::pallet::Error */ PalletMigrationsError: { _enum: ["PreimageMissing", "WrongUpperBound", "PreimageIsTooBig", "PreimageAlreadyExists"], }, - /** Lookup262: pallet_maintenance_mode::pallet::Error */ + /** Lookup263: pallet_maintenance_mode::pallet::Error */ PalletMaintenanceModeError: { _enum: ["AlreadyInMaintenanceMode", "NotInMaintenanceMode"], }, - /** Lookup264: pallet_balances::types::BalanceLock */ + /** Lookup265: pallet_balances::types::BalanceLock */ PalletBalancesBalanceLock: { id: "[u8;8]", amount: "u128", reasons: "PalletBalancesReasons", }, - /** Lookup265: pallet_balances::types::Reasons */ + /** Lookup266: pallet_balances::types::Reasons */ PalletBalancesReasons: { _enum: ["Fee", "Misc", "All"], }, - /** Lookup268: pallet_balances::types::ReserveData */ + /** Lookup269: pallet_balances::types::ReserveData */ PalletBalancesReserveData: { id: "[u8;8]", amount: "u128", }, - /** Lookup272: dancebox_runtime::HoldReason */ + /** Lookup273: dancebox_runtime::HoldReason */ DanceboxRuntimeHoldReason: { _enum: ["PooledStake"], }, - /** Lookup275: pallet_balances::types::IdAmount */ + /** Lookup276: pallet_balances::types::IdAmount */ PalletBalancesIdAmount: { id: "[u8;8]", amount: "u128", }, - /** Lookup277: pallet_balances::pallet::Error */ + /** Lookup278: pallet_balances::pallet::Error */ PalletBalancesError: { _enum: [ "VestingBalance", @@ -2397,16 +2411,16 @@ export default { "TooManyFreezes", ], }, - /** Lookup279: pallet_transaction_payment::Releases */ + /** Lookup280: pallet_transaction_payment::Releases */ PalletTransactionPaymentReleases: { _enum: ["V1Ancient", "V2"], }, - /** Lookup284: pallet_registrar::pallet::DepositInfo */ + /** Lookup285: pallet_registrar::pallet::DepositInfo */ PalletRegistrarDepositInfo: { creator: "AccountId32", deposit: "u128", }, - /** Lookup285: pallet_registrar::pallet::Error */ + /** Lookup286: pallet_registrar::pallet::Error */ PalletRegistrarError: { _enum: [ "ParaIdAlreadyRegistered", @@ -2418,7 +2432,7 @@ export default { "NotSufficientDeposit", ], }, - /** Lookup286: pallet_configuration::HostConfiguration */ + /** Lookup287: pallet_configuration::HostConfiguration */ PalletConfigurationHostConfiguration: { maxCollators: "u32", minOrchestratorCollators: "u32", @@ -2426,21 +2440,21 @@ export default { collatorsPerContainer: "u32", fullRotationPeriod: "u32", }, - /** Lookup289: pallet_configuration::pallet::Error */ + /** Lookup290: pallet_configuration::pallet::Error */ PalletConfigurationError: { _enum: ["InvalidNewValue"], }, - /** Lookup290: tp_collator_assignment::AssignedCollators */ + /** Lookup291: tp_collator_assignment::AssignedCollators */ TpCollatorAssignmentAssignedCollatorsAccountId32: { orchestratorChain: "Vec", containerChains: "BTreeMap>", }, - /** Lookup295: pallet_author_noting::pallet::ContainerChainBlockInfo */ + /** Lookup296: pallet_author_noting::pallet::ContainerChainBlockInfo */ PalletAuthorNotingContainerChainBlockInfo: { blockNumber: "u32", author: "AccountId32", }, - /** Lookup296: pallet_author_noting::pallet::Error */ + /** Lookup297: pallet_author_noting::pallet::Error */ PalletAuthorNotingError: { _enum: [ "FailedReading", @@ -2452,31 +2466,31 @@ export default { "NonAuraDigest", ], }, - /** Lookup297: tp_collator_assignment::AssignedCollators */ + /** Lookup298: tp_collator_assignment::AssignedCollators */ TpCollatorAssignmentAssignedCollatorsPublic: { orchestratorChain: "Vec", containerChains: "BTreeMap>", }, - /** Lookup303: pallet_invulnerables::pallet::Error */ + /** Lookup304: pallet_invulnerables::pallet::Error */ PalletInvulnerablesError: { _enum: ["TooManyInvulnerables", "AlreadyInvulnerable", "NotInvulnerable"], }, - /** Lookup308: sp_core::crypto::KeyTypeId */ + /** Lookup309: sp_core::crypto::KeyTypeId */ SpCoreCryptoKeyTypeId: "[u8;4]", - /** Lookup309: pallet_session::pallet::Error */ + /** Lookup310: pallet_session::pallet::Error */ PalletSessionError: { _enum: ["InvalidProof", "NoAssociatedValidatorId", "DuplicatedKey", "NoKeys", "NoAccount"], }, - /** Lookup313: pallet_author_inherent::pallet::Error */ + /** Lookup314: pallet_author_inherent::pallet::Error */ PalletAuthorInherentError: { _enum: ["AuthorAlreadySet", "NoAccountId", "CannotBeAuthor"], }, - /** Lookup315: pallet_pooled_staking::candidate::EligibleCandidate */ + /** Lookup316: pallet_pooled_staking::candidate::EligibleCandidate */ PalletPooledStakingCandidateEligibleCandidate: { candidate: "AccountId32", stake: "u128", }, - /** Lookup318: pallet_pooled_staking::pallet::PoolsKey */ + /** Lookup319: pallet_pooled_staking::pallet::PoolsKey */ PalletPooledStakingPoolsKey: { _enum: { CandidateTotalStake: "Null", @@ -2518,7 +2532,7 @@ export default { }, }, }, - /** Lookup320: pallet_pooled_staking::pallet::Error */ + /** Lookup321: pallet_pooled_staking::pallet::Error */ PalletPooledStakingError: { _enum: { InvalidPalletSetting: "Null", @@ -2537,21 +2551,26 @@ export default { SwapResultsInZeroShares: "Null", }, }, - /** Lookup322: cumulus_pallet_xcmp_queue::InboundChannelDetails */ + /** Lookup322: pallet_inflation_rewards::pallet::ChainsToRewardValue */ + PalletInflationRewardsChainsToRewardValue: { + paraIds: "Vec", + rewardsPerChain: "u128", + }, + /** Lookup324: cumulus_pallet_xcmp_queue::InboundChannelDetails */ CumulusPalletXcmpQueueInboundChannelDetails: { sender: "u32", state: "CumulusPalletXcmpQueueInboundState", messageMetadata: "Vec<(u32,PolkadotParachainPrimitivesPrimitivesXcmpMessageFormat)>", }, - /** Lookup323: cumulus_pallet_xcmp_queue::InboundState */ + /** Lookup325: cumulus_pallet_xcmp_queue::InboundState */ CumulusPalletXcmpQueueInboundState: { _enum: ["Ok", "Suspended"], }, - /** Lookup326: polkadot_parachain_primitives::primitives::XcmpMessageFormat */ + /** Lookup328: polkadot_parachain_primitives::primitives::XcmpMessageFormat */ PolkadotParachainPrimitivesPrimitivesXcmpMessageFormat: { _enum: ["ConcatenatedVersionedXcm", "ConcatenatedEncodedBlob", "Signals"], }, - /** Lookup329: cumulus_pallet_xcmp_queue::OutboundChannelDetails */ + /** Lookup331: cumulus_pallet_xcmp_queue::OutboundChannelDetails */ CumulusPalletXcmpQueueOutboundChannelDetails: { recipient: "u32", state: "CumulusPalletXcmpQueueOutboundState", @@ -2559,11 +2578,11 @@ export default { firstIndex: "u16", lastIndex: "u16", }, - /** Lookup330: cumulus_pallet_xcmp_queue::OutboundState */ + /** Lookup332: cumulus_pallet_xcmp_queue::OutboundState */ CumulusPalletXcmpQueueOutboundState: { _enum: ["Ok", "Suspended"], }, - /** Lookup332: cumulus_pallet_xcmp_queue::QueueConfigData */ + /** Lookup334: cumulus_pallet_xcmp_queue::QueueConfigData */ CumulusPalletXcmpQueueQueueConfigData: { suspendThreshold: "u32", dropThreshold: "u32", @@ -2572,27 +2591,27 @@ export default { weightRestrictDecay: "SpWeightsWeightV2Weight", xcmpMaxIndividualWeight: "SpWeightsWeightV2Weight", }, - /** Lookup334: cumulus_pallet_xcmp_queue::pallet::Error */ + /** Lookup336: cumulus_pallet_xcmp_queue::pallet::Error */ CumulusPalletXcmpQueueError: { _enum: ["FailedToSend", "BadXcmOrigin", "BadXcm", "BadOverweightIndex", "WeightOverLimit"], }, - /** Lookup335: cumulus_pallet_xcm::pallet::Error */ + /** Lookup337: cumulus_pallet_xcm::pallet::Error */ CumulusPalletXcmError: "Null", - /** Lookup336: cumulus_pallet_dmp_queue::ConfigData */ + /** Lookup338: cumulus_pallet_dmp_queue::ConfigData */ CumulusPalletDmpQueueConfigData: { maxIndividual: "SpWeightsWeightV2Weight", }, - /** Lookup337: cumulus_pallet_dmp_queue::PageIndexData */ + /** Lookup339: cumulus_pallet_dmp_queue::PageIndexData */ CumulusPalletDmpQueuePageIndexData: { beginUsed: "u32", endUsed: "u32", overweightCount: "u64", }, - /** Lookup340: cumulus_pallet_dmp_queue::pallet::Error */ + /** Lookup342: cumulus_pallet_dmp_queue::pallet::Error */ CumulusPalletDmpQueueError: { _enum: ["Unknown", "OverLimit"], }, - /** Lookup341: pallet_xcm::pallet::QueryStatus */ + /** Lookup343: pallet_xcm::pallet::QueryStatus */ PalletXcmQueryStatus: { _enum: { Pending: { @@ -2611,7 +2630,7 @@ export default { }, }, }, - /** Lookup345: staging_xcm::VersionedResponse */ + /** Lookup347: staging_xcm::VersionedResponse */ StagingXcmVersionedResponse: { _enum: { __Unused0: "Null", @@ -2620,7 +2639,7 @@ export default { V3: "StagingXcmV3Response", }, }, - /** Lookup351: pallet_xcm::pallet::VersionMigrationStage */ + /** Lookup353: pallet_xcm::pallet::VersionMigrationStage */ PalletXcmVersionMigrationStage: { _enum: { MigrateSupportedVersion: "Null", @@ -2629,7 +2648,7 @@ export default { MigrateAndNotifyOldTargets: "Null", }, }, - /** Lookup353: staging_xcm::VersionedAssetId */ + /** Lookup355: staging_xcm::VersionedAssetId */ StagingXcmVersionedAssetId: { _enum: { __Unused0: "Null", @@ -2638,14 +2657,14 @@ export default { V3: "StagingXcmV3MultiassetAssetId", }, }, - /** Lookup354: pallet_xcm::pallet::RemoteLockedFungibleRecord */ + /** Lookup356: pallet_xcm::pallet::RemoteLockedFungibleRecord */ PalletXcmRemoteLockedFungibleRecord: { amount: "u128", owner: "StagingXcmVersionedMultiLocation", locker: "StagingXcmVersionedMultiLocation", consumers: "Vec<(Null,u128)>", }, - /** Lookup361: pallet_xcm::pallet::Error */ + /** Lookup363: pallet_xcm::pallet::Error */ PalletXcmError: { _enum: [ "Unreachable", @@ -2670,7 +2689,7 @@ export default { "InUse", ], }, - /** Lookup363: sp_runtime::MultiSignature */ + /** Lookup365: sp_runtime::MultiSignature */ SpRuntimeMultiSignature: { _enum: { Ed25519: "SpCoreEd25519Signature", @@ -2678,26 +2697,26 @@ export default { Ecdsa: "SpCoreEcdsaSignature", }, }, - /** Lookup364: sp_core::ed25519::Signature */ + /** Lookup366: sp_core::ed25519::Signature */ SpCoreEd25519Signature: "[u8;64]", - /** Lookup366: sp_core::sr25519::Signature */ + /** Lookup368: sp_core::sr25519::Signature */ SpCoreSr25519Signature: "[u8;64]", - /** Lookup367: sp_core::ecdsa::Signature */ + /** Lookup369: sp_core::ecdsa::Signature */ SpCoreEcdsaSignature: "[u8;65]", - /** Lookup370: frame_system::extensions::check_non_zero_sender::CheckNonZeroSender */ + /** Lookup372: frame_system::extensions::check_non_zero_sender::CheckNonZeroSender */ FrameSystemExtensionsCheckNonZeroSender: "Null", - /** Lookup371: frame_system::extensions::check_spec_version::CheckSpecVersion */ + /** Lookup373: frame_system::extensions::check_spec_version::CheckSpecVersion */ FrameSystemExtensionsCheckSpecVersion: "Null", - /** Lookup372: frame_system::extensions::check_tx_version::CheckTxVersion */ + /** Lookup374: frame_system::extensions::check_tx_version::CheckTxVersion */ FrameSystemExtensionsCheckTxVersion: "Null", - /** Lookup373: frame_system::extensions::check_genesis::CheckGenesis */ + /** Lookup375: frame_system::extensions::check_genesis::CheckGenesis */ FrameSystemExtensionsCheckGenesis: "Null", - /** Lookup376: frame_system::extensions::check_nonce::CheckNonce */ + /** Lookup378: frame_system::extensions::check_nonce::CheckNonce */ FrameSystemExtensionsCheckNonce: "Compact", - /** Lookup377: frame_system::extensions::check_weight::CheckWeight */ + /** Lookup379: frame_system::extensions::check_weight::CheckWeight */ FrameSystemExtensionsCheckWeight: "Null", - /** Lookup378: pallet_transaction_payment::ChargeTransactionPayment */ + /** Lookup380: pallet_transaction_payment::ChargeTransactionPayment */ PalletTransactionPaymentChargeTransactionPayment: "Compact", - /** Lookup379: dancebox_runtime::Runtime */ + /** Lookup381: dancebox_runtime::Runtime */ DanceboxRuntimeRuntime: "Null", }; diff --git a/typescript-api/src/dancebox/interfaces/registry.ts b/typescript-api/src/dancebox/interfaces/registry.ts index 51fc1a9f6..2a867a2f8 100644 --- a/typescript-api/src/dancebox/interfaces/registry.ts +++ b/typescript-api/src/dancebox/interfaces/registry.ts @@ -83,6 +83,8 @@ import type { PalletConfigurationCall, PalletConfigurationError, PalletConfigurationHostConfiguration, + PalletInflationRewardsChainsToRewardValue, + PalletInflationRewardsEvent, PalletInvulnerablesCall, PalletInvulnerablesError, PalletInvulnerablesEvent, @@ -297,6 +299,8 @@ declare module "@polkadot/types/types/registry" { PalletConfigurationCall: PalletConfigurationCall; PalletConfigurationError: PalletConfigurationError; PalletConfigurationHostConfiguration: PalletConfigurationHostConfiguration; + PalletInflationRewardsChainsToRewardValue: PalletInflationRewardsChainsToRewardValue; + PalletInflationRewardsEvent: PalletInflationRewardsEvent; PalletInvulnerablesCall: PalletInvulnerablesCall; PalletInvulnerablesError: PalletInvulnerablesError; PalletInvulnerablesEvent: PalletInvulnerablesEvent; diff --git a/typescript-api/src/dancebox/interfaces/types-lookup.ts b/typescript-api/src/dancebox/interfaces/types-lookup.ts index 6bdb78493..6bd731eec 100644 --- a/typescript-api/src/dancebox/interfaces/types-lookup.ts +++ b/typescript-api/src/dancebox/interfaces/types-lookup.ts @@ -770,7 +770,23 @@ declare module "@polkadot/types/lookup" { readonly type: "AutoCompounding" | "ManualRewards"; } - /** @name CumulusPalletXcmpQueueEvent (56) */ + /** @name PalletInflationRewardsEvent (56) */ + interface PalletInflationRewardsEvent extends Enum { + readonly isRewardedOrchestrator: boolean; + readonly asRewardedOrchestrator: { + readonly accountId: AccountId32; + readonly balance: u128; + } & Struct; + readonly isRewardedContainer: boolean; + readonly asRewardedContainer: { + readonly accountId: AccountId32; + readonly paraId: u32; + readonly balance: u128; + } & Struct; + readonly type: "RewardedOrchestrator" | "RewardedContainer"; + } + + /** @name CumulusPalletXcmpQueueEvent (57) */ interface CumulusPalletXcmpQueueEvent extends Enum { readonly isSuccess: boolean; readonly asSuccess: { @@ -819,7 +835,7 @@ declare module "@polkadot/types/lookup" { | "OverweightServiced"; } - /** @name StagingXcmV3TraitsError (57) */ + /** @name StagingXcmV3TraitsError (58) */ interface StagingXcmV3TraitsError extends Enum { readonly isOverflow: boolean; readonly isUnimplemented: boolean; @@ -906,7 +922,7 @@ declare module "@polkadot/types/lookup" { | "ExceedsStackLimit"; } - /** @name CumulusPalletXcmEvent (58) */ + /** @name CumulusPalletXcmEvent (59) */ interface CumulusPalletXcmEvent extends Enum { readonly isInvalidFormat: boolean; readonly asInvalidFormat: U8aFixed; @@ -917,7 +933,7 @@ declare module "@polkadot/types/lookup" { readonly type: "InvalidFormat" | "UnsupportedVersion" | "ExecutedDownward"; } - /** @name StagingXcmV3TraitsOutcome (59) */ + /** @name StagingXcmV3TraitsOutcome (60) */ interface StagingXcmV3TraitsOutcome extends Enum { readonly isComplete: boolean; readonly asComplete: SpWeightsWeightV2Weight; @@ -928,7 +944,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Complete" | "Incomplete" | "Error"; } - /** @name CumulusPalletDmpQueueEvent (60) */ + /** @name CumulusPalletDmpQueueEvent (61) */ interface CumulusPalletDmpQueueEvent extends Enum { readonly isInvalidFormat: boolean; readonly asInvalidFormat: { @@ -977,7 +993,7 @@ declare module "@polkadot/types/lookup" { | "MaxMessagesExhausted"; } - /** @name PalletXcmEvent (61) */ + /** @name PalletXcmEvent (62) */ interface PalletXcmEvent extends Enum { readonly isAttempted: boolean; readonly asAttempted: { @@ -1137,13 +1153,13 @@ declare module "@polkadot/types/lookup" { | "AssetsClaimed"; } - /** @name StagingXcmV3MultiLocation (62) */ + /** @name StagingXcmV3MultiLocation (63) */ interface StagingXcmV3MultiLocation extends Struct { readonly parents: u8; readonly interior: StagingXcmV3Junctions; } - /** @name StagingXcmV3Junctions (63) */ + /** @name StagingXcmV3Junctions (64) */ interface StagingXcmV3Junctions extends Enum { readonly isHere: boolean; readonly isX1: boolean; @@ -1203,7 +1219,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Here" | "X1" | "X2" | "X3" | "X4" | "X5" | "X6" | "X7" | "X8"; } - /** @name StagingXcmV3Junction (64) */ + /** @name StagingXcmV3Junction (65) */ interface StagingXcmV3Junction extends Enum { readonly isParachain: boolean; readonly asParachain: Compact; @@ -1252,7 +1268,7 @@ declare module "@polkadot/types/lookup" { | "GlobalConsensus"; } - /** @name StagingXcmV3JunctionNetworkId (67) */ + /** @name StagingXcmV3JunctionNetworkId (68) */ interface StagingXcmV3JunctionNetworkId extends Enum { readonly isByGenesis: boolean; readonly asByGenesis: U8aFixed; @@ -1285,7 +1301,7 @@ declare module "@polkadot/types/lookup" { | "BitcoinCash"; } - /** @name StagingXcmV3JunctionBodyId (70) */ + /** @name StagingXcmV3JunctionBodyId (71) */ interface StagingXcmV3JunctionBodyId extends Enum { readonly isUnit: boolean; readonly isMoniker: boolean; @@ -1312,7 +1328,7 @@ declare module "@polkadot/types/lookup" { | "Treasury"; } - /** @name StagingXcmV3JunctionBodyPart (71) */ + /** @name StagingXcmV3JunctionBodyPart (72) */ interface StagingXcmV3JunctionBodyPart extends Enum { readonly isVoice: boolean; readonly isMembers: boolean; @@ -1337,10 +1353,10 @@ declare module "@polkadot/types/lookup" { readonly type: "Voice" | "Members" | "Fraction" | "AtLeastProportion" | "MoreThanProportion"; } - /** @name StagingXcmV3Xcm (72) */ + /** @name StagingXcmV3Xcm (73) */ interface StagingXcmV3Xcm extends Vec {} - /** @name StagingXcmV3Instruction (74) */ + /** @name StagingXcmV3Instruction (75) */ interface StagingXcmV3Instruction extends Enum { readonly isWithdrawAsset: boolean; readonly asWithdrawAsset: StagingXcmV3MultiassetMultiAssets; @@ -1570,16 +1586,16 @@ declare module "@polkadot/types/lookup" { | "UnpaidExecution"; } - /** @name StagingXcmV3MultiassetMultiAssets (75) */ + /** @name StagingXcmV3MultiassetMultiAssets (76) */ interface StagingXcmV3MultiassetMultiAssets extends Vec {} - /** @name StagingXcmV3MultiAsset (77) */ + /** @name StagingXcmV3MultiAsset (78) */ interface StagingXcmV3MultiAsset extends Struct { readonly id: StagingXcmV3MultiassetAssetId; readonly fun: StagingXcmV3MultiassetFungibility; } - /** @name StagingXcmV3MultiassetAssetId (78) */ + /** @name StagingXcmV3MultiassetAssetId (79) */ interface StagingXcmV3MultiassetAssetId extends Enum { readonly isConcrete: boolean; readonly asConcrete: StagingXcmV3MultiLocation; @@ -1588,7 +1604,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Concrete" | "Abstract"; } - /** @name StagingXcmV3MultiassetFungibility (79) */ + /** @name StagingXcmV3MultiassetFungibility (80) */ interface StagingXcmV3MultiassetFungibility extends Enum { readonly isFungible: boolean; readonly asFungible: Compact; @@ -1597,7 +1613,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Fungible" | "NonFungible"; } - /** @name StagingXcmV3MultiassetAssetInstance (80) */ + /** @name StagingXcmV3MultiassetAssetInstance (81) */ interface StagingXcmV3MultiassetAssetInstance extends Enum { readonly isUndefined: boolean; readonly isIndex: boolean; @@ -1613,7 +1629,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Undefined" | "Index" | "Array4" | "Array8" | "Array16" | "Array32"; } - /** @name StagingXcmV3Response (83) */ + /** @name StagingXcmV3Response (84) */ interface StagingXcmV3Response extends Enum { readonly isNull: boolean; readonly isAssets: boolean; @@ -1629,7 +1645,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Null" | "Assets" | "ExecutionResult" | "Version" | "PalletsInfo" | "DispatchResult"; } - /** @name StagingXcmV3PalletInfo (87) */ + /** @name StagingXcmV3PalletInfo (88) */ interface StagingXcmV3PalletInfo extends Struct { readonly index: Compact; readonly name: Bytes; @@ -1639,7 +1655,7 @@ declare module "@polkadot/types/lookup" { readonly patch: Compact; } - /** @name StagingXcmV3MaybeErrorCode (90) */ + /** @name StagingXcmV3MaybeErrorCode (91) */ interface StagingXcmV3MaybeErrorCode extends Enum { readonly isSuccess: boolean; readonly isError: boolean; @@ -1649,7 +1665,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Success" | "Error" | "TruncatedError"; } - /** @name StagingXcmV2OriginKind (93) */ + /** @name StagingXcmV2OriginKind (94) */ interface StagingXcmV2OriginKind extends Enum { readonly isNative: boolean; readonly isSovereignAccount: boolean; @@ -1658,19 +1674,19 @@ declare module "@polkadot/types/lookup" { readonly type: "Native" | "SovereignAccount" | "Superuser" | "Xcm"; } - /** @name StagingXcmDoubleEncoded (94) */ + /** @name StagingXcmDoubleEncoded (95) */ interface StagingXcmDoubleEncoded extends Struct { readonly encoded: Bytes; } - /** @name StagingXcmV3QueryResponseInfo (95) */ + /** @name StagingXcmV3QueryResponseInfo (96) */ interface StagingXcmV3QueryResponseInfo extends Struct { readonly destination: StagingXcmV3MultiLocation; readonly queryId: Compact; readonly maxWeight: SpWeightsWeightV2Weight; } - /** @name StagingXcmV3MultiassetMultiAssetFilter (96) */ + /** @name StagingXcmV3MultiassetMultiAssetFilter (97) */ interface StagingXcmV3MultiassetMultiAssetFilter extends Enum { readonly isDefinite: boolean; readonly asDefinite: StagingXcmV3MultiassetMultiAssets; @@ -1679,7 +1695,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Definite" | "Wild"; } - /** @name StagingXcmV3MultiassetWildMultiAsset (97) */ + /** @name StagingXcmV3MultiassetWildMultiAsset (98) */ interface StagingXcmV3MultiassetWildMultiAsset extends Enum { readonly isAll: boolean; readonly isAllOf: boolean; @@ -1698,14 +1714,14 @@ declare module "@polkadot/types/lookup" { readonly type: "All" | "AllOf" | "AllCounted" | "AllOfCounted"; } - /** @name StagingXcmV3MultiassetWildFungibility (98) */ + /** @name StagingXcmV3MultiassetWildFungibility (99) */ interface StagingXcmV3MultiassetWildFungibility extends Enum { readonly isFungible: boolean; readonly isNonFungible: boolean; readonly type: "Fungible" | "NonFungible"; } - /** @name StagingXcmV3WeightLimit (99) */ + /** @name StagingXcmV3WeightLimit (100) */ interface StagingXcmV3WeightLimit extends Enum { readonly isUnlimited: boolean; readonly isLimited: boolean; @@ -1713,7 +1729,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Unlimited" | "Limited"; } - /** @name StagingXcmVersionedMultiAssets (100) */ + /** @name StagingXcmVersionedMultiAssets (101) */ interface StagingXcmVersionedMultiAssets extends Enum { readonly isV2: boolean; readonly asV2: StagingXcmV2MultiassetMultiAssets; @@ -1722,16 +1738,16 @@ declare module "@polkadot/types/lookup" { readonly type: "V2" | "V3"; } - /** @name StagingXcmV2MultiassetMultiAssets (101) */ + /** @name StagingXcmV2MultiassetMultiAssets (102) */ interface StagingXcmV2MultiassetMultiAssets extends Vec {} - /** @name StagingXcmV2MultiAsset (103) */ + /** @name StagingXcmV2MultiAsset (104) */ interface StagingXcmV2MultiAsset extends Struct { readonly id: StagingXcmV2MultiassetAssetId; readonly fun: StagingXcmV2MultiassetFungibility; } - /** @name StagingXcmV2MultiassetAssetId (104) */ + /** @name StagingXcmV2MultiassetAssetId (105) */ interface StagingXcmV2MultiassetAssetId extends Enum { readonly isConcrete: boolean; readonly asConcrete: StagingXcmV2MultiLocation; @@ -1740,13 +1756,13 @@ declare module "@polkadot/types/lookup" { readonly type: "Concrete" | "Abstract"; } - /** @name StagingXcmV2MultiLocation (105) */ + /** @name StagingXcmV2MultiLocation (106) */ interface StagingXcmV2MultiLocation extends Struct { readonly parents: u8; readonly interior: StagingXcmV2MultilocationJunctions; } - /** @name StagingXcmV2MultilocationJunctions (106) */ + /** @name StagingXcmV2MultilocationJunctions (107) */ interface StagingXcmV2MultilocationJunctions extends Enum { readonly isHere: boolean; readonly isX1: boolean; @@ -1806,7 +1822,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Here" | "X1" | "X2" | "X3" | "X4" | "X5" | "X6" | "X7" | "X8"; } - /** @name StagingXcmV2Junction (107) */ + /** @name StagingXcmV2Junction (108) */ interface StagingXcmV2Junction extends Enum { readonly isParachain: boolean; readonly asParachain: Compact; @@ -1849,7 +1865,7 @@ declare module "@polkadot/types/lookup" { | "Plurality"; } - /** @name StagingXcmV2NetworkId (108) */ + /** @name StagingXcmV2NetworkId (109) */ interface StagingXcmV2NetworkId extends Enum { readonly isAny: boolean; readonly isNamed: boolean; @@ -1859,7 +1875,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Any" | "Named" | "Polkadot" | "Kusama"; } - /** @name StagingXcmV2BodyId (110) */ + /** @name StagingXcmV2BodyId (111) */ interface StagingXcmV2BodyId extends Enum { readonly isUnit: boolean; readonly isNamed: boolean; @@ -1886,7 +1902,7 @@ declare module "@polkadot/types/lookup" { | "Treasury"; } - /** @name StagingXcmV2BodyPart (111) */ + /** @name StagingXcmV2BodyPart (112) */ interface StagingXcmV2BodyPart extends Enum { readonly isVoice: boolean; readonly isMembers: boolean; @@ -1911,7 +1927,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Voice" | "Members" | "Fraction" | "AtLeastProportion" | "MoreThanProportion"; } - /** @name StagingXcmV2MultiassetFungibility (112) */ + /** @name StagingXcmV2MultiassetFungibility (113) */ interface StagingXcmV2MultiassetFungibility extends Enum { readonly isFungible: boolean; readonly asFungible: Compact; @@ -1920,7 +1936,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Fungible" | "NonFungible"; } - /** @name StagingXcmV2MultiassetAssetInstance (113) */ + /** @name StagingXcmV2MultiassetAssetInstance (114) */ interface StagingXcmV2MultiassetAssetInstance extends Enum { readonly isUndefined: boolean; readonly isIndex: boolean; @@ -1938,7 +1954,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Undefined" | "Index" | "Array4" | "Array8" | "Array16" | "Array32" | "Blob"; } - /** @name StagingXcmVersionedMultiLocation (114) */ + /** @name StagingXcmVersionedMultiLocation (115) */ interface StagingXcmVersionedMultiLocation extends Enum { readonly isV2: boolean; readonly asV2: StagingXcmV2MultiLocation; @@ -1947,7 +1963,7 @@ declare module "@polkadot/types/lookup" { readonly type: "V2" | "V3"; } - /** @name FrameSystemPhase (115) */ + /** @name FrameSystemPhase (116) */ interface FrameSystemPhase extends Enum { readonly isApplyExtrinsic: boolean; readonly asApplyExtrinsic: u32; @@ -1956,13 +1972,13 @@ declare module "@polkadot/types/lookup" { readonly type: "ApplyExtrinsic" | "Finalization" | "Initialization"; } - /** @name FrameSystemLastRuntimeUpgradeInfo (119) */ + /** @name FrameSystemLastRuntimeUpgradeInfo (120) */ interface FrameSystemLastRuntimeUpgradeInfo extends Struct { readonly specVersion: Compact; readonly specName: Text; } - /** @name FrameSystemCall (121) */ + /** @name FrameSystemCall (122) */ interface FrameSystemCall extends Enum { readonly isRemark: boolean; readonly asRemark: { @@ -2008,21 +2024,21 @@ declare module "@polkadot/types/lookup" { | "RemarkWithEvent"; } - /** @name FrameSystemLimitsBlockWeights (125) */ + /** @name FrameSystemLimitsBlockWeights (126) */ interface FrameSystemLimitsBlockWeights extends Struct { readonly baseBlock: SpWeightsWeightV2Weight; readonly maxBlock: SpWeightsWeightV2Weight; readonly perClass: FrameSupportDispatchPerDispatchClassWeightsPerClass; } - /** @name FrameSupportDispatchPerDispatchClassWeightsPerClass (126) */ + /** @name FrameSupportDispatchPerDispatchClassWeightsPerClass (127) */ interface FrameSupportDispatchPerDispatchClassWeightsPerClass extends Struct { readonly normal: FrameSystemLimitsWeightsPerClass; readonly operational: FrameSystemLimitsWeightsPerClass; readonly mandatory: FrameSystemLimitsWeightsPerClass; } - /** @name FrameSystemLimitsWeightsPerClass (127) */ + /** @name FrameSystemLimitsWeightsPerClass (128) */ interface FrameSystemLimitsWeightsPerClass extends Struct { readonly baseExtrinsic: SpWeightsWeightV2Weight; readonly maxExtrinsic: Option; @@ -2030,25 +2046,25 @@ declare module "@polkadot/types/lookup" { readonly reserved: Option; } - /** @name FrameSystemLimitsBlockLength (129) */ + /** @name FrameSystemLimitsBlockLength (130) */ interface FrameSystemLimitsBlockLength extends Struct { readonly max: FrameSupportDispatchPerDispatchClassU32; } - /** @name FrameSupportDispatchPerDispatchClassU32 (130) */ + /** @name FrameSupportDispatchPerDispatchClassU32 (131) */ interface FrameSupportDispatchPerDispatchClassU32 extends Struct { readonly normal: u32; readonly operational: u32; readonly mandatory: u32; } - /** @name SpWeightsRuntimeDbWeight (131) */ + /** @name SpWeightsRuntimeDbWeight (132) */ interface SpWeightsRuntimeDbWeight extends Struct { readonly read: u64; readonly write: u64; } - /** @name SpVersionRuntimeVersion (132) */ + /** @name SpVersionRuntimeVersion (133) */ interface SpVersionRuntimeVersion extends Struct { readonly specName: Text; readonly implName: Text; @@ -2060,7 +2076,7 @@ declare module "@polkadot/types/lookup" { readonly stateVersion: u8; } - /** @name FrameSystemError (136) */ + /** @name FrameSystemError (137) */ interface FrameSystemError extends Enum { readonly isInvalidSpecName: boolean; readonly isSpecVersionNeedsToIncrease: boolean; @@ -2077,41 +2093,41 @@ declare module "@polkadot/types/lookup" { | "CallFiltered"; } - /** @name CumulusPalletParachainSystemUnincludedSegmentAncestor (138) */ + /** @name CumulusPalletParachainSystemUnincludedSegmentAncestor (139) */ interface CumulusPalletParachainSystemUnincludedSegmentAncestor extends Struct { readonly usedBandwidth: CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth; readonly paraHeadHash: Option; readonly consumedGoAheadSignal: Option; } - /** @name CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth (139) */ + /** @name CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth (140) */ interface CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth extends Struct { readonly umpMsgCount: u32; readonly umpTotalBytes: u32; readonly hrmpOutgoing: BTreeMap; } - /** @name CumulusPalletParachainSystemUnincludedSegmentHrmpChannelUpdate (141) */ + /** @name CumulusPalletParachainSystemUnincludedSegmentHrmpChannelUpdate (142) */ interface CumulusPalletParachainSystemUnincludedSegmentHrmpChannelUpdate extends Struct { readonly msgCount: u32; readonly totalBytes: u32; } - /** @name PolkadotPrimitivesV5UpgradeGoAhead (146) */ + /** @name PolkadotPrimitivesV5UpgradeGoAhead (147) */ interface PolkadotPrimitivesV5UpgradeGoAhead extends Enum { readonly isAbort: boolean; readonly isGoAhead: boolean; readonly type: "Abort" | "GoAhead"; } - /** @name CumulusPalletParachainSystemUnincludedSegmentSegmentTracker (147) */ + /** @name CumulusPalletParachainSystemUnincludedSegmentSegmentTracker (148) */ interface CumulusPalletParachainSystemUnincludedSegmentSegmentTracker extends Struct { readonly usedBandwidth: CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth; readonly hrmpWatermark: Option; readonly consumedGoAheadSignal: Option; } - /** @name PolkadotPrimitivesV5PersistedValidationData (148) */ + /** @name PolkadotPrimitivesV5PersistedValidationData (149) */ interface PolkadotPrimitivesV5PersistedValidationData extends Struct { readonly parentHead: Bytes; readonly relayParentNumber: u32; @@ -2119,18 +2135,18 @@ declare module "@polkadot/types/lookup" { readonly maxPovSize: u32; } - /** @name PolkadotPrimitivesV5UpgradeRestriction (151) */ + /** @name PolkadotPrimitivesV5UpgradeRestriction (152) */ interface PolkadotPrimitivesV5UpgradeRestriction extends Enum { readonly isPresent: boolean; readonly type: "Present"; } - /** @name SpTrieStorageProof (152) */ + /** @name SpTrieStorageProof (153) */ interface SpTrieStorageProof extends Struct { readonly trieNodes: BTreeSet; } - /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (154) */ + /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (155) */ interface CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot extends Struct { readonly dmqMqcHead: H256; readonly relayDispatchQueueRemainingCapacity: CumulusPalletParachainSystemRelayStateSnapshotRelayDispatchQueueRemainingCapacity; @@ -2138,13 +2154,13 @@ declare module "@polkadot/types/lookup" { readonly egressChannels: Vec>; } - /** @name CumulusPalletParachainSystemRelayStateSnapshotRelayDispatchQueueRemainingCapacity (155) */ + /** @name CumulusPalletParachainSystemRelayStateSnapshotRelayDispatchQueueRemainingCapacity (156) */ interface CumulusPalletParachainSystemRelayStateSnapshotRelayDispatchQueueRemainingCapacity extends Struct { readonly remainingCount: u32; readonly remainingSize: u32; } - /** @name PolkadotPrimitivesV5AbridgedHrmpChannel (158) */ + /** @name PolkadotPrimitivesV5AbridgedHrmpChannel (159) */ interface PolkadotPrimitivesV5AbridgedHrmpChannel extends Struct { readonly maxCapacity: u32; readonly maxTotalSize: u32; @@ -2154,7 +2170,7 @@ declare module "@polkadot/types/lookup" { readonly mqcHead: Option; } - /** @name PolkadotPrimitivesV5AbridgedHostConfiguration (159) */ + /** @name PolkadotPrimitivesV5AbridgedHostConfiguration (160) */ interface PolkadotPrimitivesV5AbridgedHostConfiguration extends Struct { readonly maxCodeSize: u32; readonly maxHeadDataSize: u32; @@ -2168,25 +2184,25 @@ declare module "@polkadot/types/lookup" { readonly asyncBackingParams: PolkadotPrimitivesVstagingAsyncBackingParams; } - /** @name PolkadotPrimitivesVstagingAsyncBackingParams (160) */ + /** @name PolkadotPrimitivesVstagingAsyncBackingParams (161) */ interface PolkadotPrimitivesVstagingAsyncBackingParams extends Struct { readonly maxCandidateDepth: u32; readonly allowedAncestryLen: u32; } - /** @name PolkadotCorePrimitivesOutboundHrmpMessage (166) */ + /** @name PolkadotCorePrimitivesOutboundHrmpMessage (167) */ interface PolkadotCorePrimitivesOutboundHrmpMessage extends Struct { readonly recipient: u32; readonly data: Bytes; } - /** @name CumulusPalletParachainSystemCodeUpgradeAuthorization (167) */ + /** @name CumulusPalletParachainSystemCodeUpgradeAuthorization (168) */ interface CumulusPalletParachainSystemCodeUpgradeAuthorization extends Struct { readonly codeHash: H256; readonly checkVersion: bool; } - /** @name CumulusPalletParachainSystemCall (168) */ + /** @name CumulusPalletParachainSystemCall (169) */ interface CumulusPalletParachainSystemCall extends Enum { readonly isSetValidationData: boolean; readonly asSetValidationData: { @@ -2208,7 +2224,7 @@ declare module "@polkadot/types/lookup" { readonly type: "SetValidationData" | "SudoSendUpwardMessage" | "AuthorizeUpgrade" | "EnactAuthorizedUpgrade"; } - /** @name CumulusPrimitivesParachainInherentParachainInherentData (169) */ + /** @name CumulusPrimitivesParachainInherentParachainInherentData (170) */ interface CumulusPrimitivesParachainInherentParachainInherentData extends Struct { readonly validationData: PolkadotPrimitivesV5PersistedValidationData; readonly relayChainState: SpTrieStorageProof; @@ -2216,19 +2232,19 @@ declare module "@polkadot/types/lookup" { readonly horizontalMessages: BTreeMap>; } - /** @name PolkadotCorePrimitivesInboundDownwardMessage (171) */ + /** @name PolkadotCorePrimitivesInboundDownwardMessage (172) */ interface PolkadotCorePrimitivesInboundDownwardMessage extends Struct { readonly sentAt: u32; readonly msg: Bytes; } - /** @name PolkadotCorePrimitivesInboundHrmpMessage (174) */ + /** @name PolkadotCorePrimitivesInboundHrmpMessage (175) */ interface PolkadotCorePrimitivesInboundHrmpMessage extends Struct { readonly sentAt: u32; readonly data: Bytes; } - /** @name CumulusPalletParachainSystemError (177) */ + /** @name CumulusPalletParachainSystemError (178) */ interface CumulusPalletParachainSystemError extends Enum { readonly isOverlappingUpgrades: boolean; readonly isProhibitedByPolkadot: boolean; @@ -2249,7 +2265,7 @@ declare module "@polkadot/types/lookup" { | "Unauthorized"; } - /** @name PalletTimestampCall (178) */ + /** @name PalletTimestampCall (179) */ interface PalletTimestampCall extends Enum { readonly isSet: boolean; readonly asSet: { @@ -2258,10 +2274,10 @@ declare module "@polkadot/types/lookup" { readonly type: "Set"; } - /** @name ParachainInfoCall (179) */ + /** @name ParachainInfoCall (180) */ type ParachainInfoCall = Null; - /** @name PalletSudoCall (180) */ + /** @name PalletSudoCall (181) */ interface PalletSudoCall extends Enum { readonly isSudo: boolean; readonly asSudo: { @@ -2284,7 +2300,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Sudo" | "SudoUncheckedWeight" | "SetKey" | "SudoAs"; } - /** @name PalletUtilityCall (182) */ + /** @name PalletUtilityCall (183) */ interface PalletUtilityCall extends Enum { readonly isBatch: boolean; readonly asBatch: { @@ -2316,7 +2332,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Batch" | "AsDerivative" | "BatchAll" | "DispatchAs" | "ForceBatch" | "WithWeight"; } - /** @name DanceboxRuntimeOriginCaller (184) */ + /** @name DanceboxRuntimeOriginCaller (185) */ interface DanceboxRuntimeOriginCaller extends Enum { readonly isSystem: boolean; readonly asSystem: FrameSupportDispatchRawOrigin; @@ -2328,7 +2344,7 @@ declare module "@polkadot/types/lookup" { readonly type: "System" | "Void" | "CumulusXcm" | "PolkadotXcm"; } - /** @name FrameSupportDispatchRawOrigin (185) */ + /** @name FrameSupportDispatchRawOrigin (186) */ interface FrameSupportDispatchRawOrigin extends Enum { readonly isRoot: boolean; readonly isSigned: boolean; @@ -2337,7 +2353,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Root" | "Signed" | "None"; } - /** @name CumulusPalletXcmOrigin (186) */ + /** @name CumulusPalletXcmOrigin (187) */ interface CumulusPalletXcmOrigin extends Enum { readonly isRelay: boolean; readonly isSiblingParachain: boolean; @@ -2345,7 +2361,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Relay" | "SiblingParachain"; } - /** @name PalletXcmOrigin (187) */ + /** @name PalletXcmOrigin (188) */ interface PalletXcmOrigin extends Enum { readonly isXcm: boolean; readonly asXcm: StagingXcmV3MultiLocation; @@ -2354,10 +2370,10 @@ declare module "@polkadot/types/lookup" { readonly type: "Xcm" | "Response"; } - /** @name SpCoreVoid (188) */ + /** @name SpCoreVoid (189) */ type SpCoreVoid = Null; - /** @name PalletProxyCall (189) */ + /** @name PalletProxyCall (190) */ interface PalletProxyCall extends Enum { readonly isProxy: boolean; readonly asProxy: { @@ -2427,14 +2443,14 @@ declare module "@polkadot/types/lookup" { | "ProxyAnnounced"; } - /** @name PalletMaintenanceModeCall (193) */ + /** @name PalletMaintenanceModeCall (194) */ interface PalletMaintenanceModeCall extends Enum { readonly isEnterMaintenanceMode: boolean; readonly isResumeNormalOperation: boolean; readonly type: "EnterMaintenanceMode" | "ResumeNormalOperation"; } - /** @name PalletBalancesCall (194) */ + /** @name PalletBalancesCall (195) */ interface PalletBalancesCall extends Enum { readonly isTransferAllowDeath: boolean; readonly asTransferAllowDeath: { @@ -2494,7 +2510,7 @@ declare module "@polkadot/types/lookup" { | "ForceSetBalance"; } - /** @name PalletRegistrarCall (195) */ + /** @name PalletRegistrarCall (196) */ interface PalletRegistrarCall extends Enum { readonly isRegister: boolean; readonly asRegister: { @@ -2521,7 +2537,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Register" | "Deregister" | "MarkValidForCollating" | "SetBootNodes" | "PauseContainerChain"; } - /** @name TpContainerChainGenesisDataContainerChainGenesisData (196) */ + /** @name TpContainerChainGenesisDataContainerChainGenesisData (197) */ interface TpContainerChainGenesisDataContainerChainGenesisData extends Struct { readonly storage: Vec; readonly name: Bytes; @@ -2531,26 +2547,26 @@ declare module "@polkadot/types/lookup" { readonly properties: TpContainerChainGenesisDataProperties; } - /** @name TpContainerChainGenesisDataContainerChainGenesisDataItem (198) */ + /** @name TpContainerChainGenesisDataContainerChainGenesisDataItem (199) */ interface TpContainerChainGenesisDataContainerChainGenesisDataItem extends Struct { readonly key: Bytes; readonly value: Bytes; } - /** @name TpContainerChainGenesisDataProperties (200) */ + /** @name TpContainerChainGenesisDataProperties (201) */ interface TpContainerChainGenesisDataProperties extends Struct { readonly tokenMetadata: TpContainerChainGenesisDataTokenMetadata; readonly isEthereum: bool; } - /** @name TpContainerChainGenesisDataTokenMetadata (201) */ + /** @name TpContainerChainGenesisDataTokenMetadata (202) */ interface TpContainerChainGenesisDataTokenMetadata extends Struct { readonly tokenSymbol: Bytes; readonly ss58Format: u32; readonly tokenDecimals: u32; } - /** @name PalletConfigurationCall (206) */ + /** @name PalletConfigurationCall (207) */ interface PalletConfigurationCall extends Enum { readonly isSetMaxCollators: boolean; readonly asSetMaxCollators: { @@ -2585,10 +2601,10 @@ declare module "@polkadot/types/lookup" { | "SetBypassConsistencyCheck"; } - /** @name PalletCollatorAssignmentCall (207) */ + /** @name PalletCollatorAssignmentCall (208) */ type PalletCollatorAssignmentCall = Null; - /** @name PalletAuthorNotingCall (208) */ + /** @name PalletAuthorNotingCall (209) */ interface PalletAuthorNotingCall extends Enum { readonly isSetLatestAuthorData: boolean; readonly asSetLatestAuthorData: { @@ -2607,15 +2623,15 @@ declare module "@polkadot/types/lookup" { readonly type: "SetLatestAuthorData" | "SetAuthor" | "KillAuthorData"; } - /** @name TpAuthorNotingInherentOwnParachainInherentData (209) */ + /** @name TpAuthorNotingInherentOwnParachainInherentData (210) */ interface TpAuthorNotingInherentOwnParachainInherentData extends Struct { readonly relayStorageProof: SpTrieStorageProof; } - /** @name PalletAuthorityAssignmentCall (210) */ + /** @name PalletAuthorityAssignmentCall (211) */ type PalletAuthorityAssignmentCall = Null; - /** @name PalletInvulnerablesCall (211) */ + /** @name PalletInvulnerablesCall (212) */ interface PalletInvulnerablesCall extends Enum { readonly isSetInvulnerables: boolean; readonly asSetInvulnerables: { @@ -2632,7 +2648,7 @@ declare module "@polkadot/types/lookup" { readonly type: "SetInvulnerables" | "AddInvulnerable" | "RemoveInvulnerable"; } - /** @name PalletSessionCall (212) */ + /** @name PalletSessionCall (213) */ interface PalletSessionCall extends Enum { readonly isSetKeys: boolean; readonly asSetKeys: { @@ -2643,24 +2659,24 @@ declare module "@polkadot/types/lookup" { readonly type: "SetKeys" | "PurgeKeys"; } - /** @name DanceboxRuntimeSessionKeys (213) */ + /** @name DanceboxRuntimeSessionKeys (214) */ interface DanceboxRuntimeSessionKeys extends Struct { readonly nimbus: NimbusPrimitivesNimbusCryptoPublic; } - /** @name NimbusPrimitivesNimbusCryptoPublic (214) */ + /** @name NimbusPrimitivesNimbusCryptoPublic (215) */ interface NimbusPrimitivesNimbusCryptoPublic extends SpCoreSr25519Public {} - /** @name SpCoreSr25519Public (215) */ + /** @name SpCoreSr25519Public (216) */ interface SpCoreSr25519Public extends U8aFixed {} - /** @name PalletAuthorInherentCall (216) */ + /** @name PalletAuthorInherentCall (217) */ interface PalletAuthorInherentCall extends Enum { readonly isKickOffAuthorshipValidation: boolean; readonly type: "KickOffAuthorshipValidation"; } - /** @name PalletPooledStakingCall (217) */ + /** @name PalletPooledStakingCall (218) */ interface PalletPooledStakingCall extends Enum { readonly isRebalanceHold: boolean; readonly asRebalanceHold: { @@ -2708,7 +2724,7 @@ declare module "@polkadot/types/lookup" { | "SwapPool"; } - /** @name PalletPooledStakingAllTargetPool (218) */ + /** @name PalletPooledStakingAllTargetPool (219) */ interface PalletPooledStakingAllTargetPool extends Enum { readonly isJoining: boolean; readonly isAutoCompounding: boolean; @@ -2717,13 +2733,13 @@ declare module "@polkadot/types/lookup" { readonly type: "Joining" | "AutoCompounding" | "ManualRewards" | "Leaving"; } - /** @name PalletPooledStakingPendingOperationQuery (220) */ + /** @name PalletPooledStakingPendingOperationQuery (221) */ interface PalletPooledStakingPendingOperationQuery extends Struct { readonly delegator: AccountId32; readonly operation: PalletPooledStakingPendingOperationKey; } - /** @name PalletPooledStakingPendingOperationKey (221) */ + /** @name PalletPooledStakingPendingOperationKey (222) */ interface PalletPooledStakingPendingOperationKey extends Enum { readonly isJoiningAutoCompounding: boolean; readonly asJoiningAutoCompounding: { @@ -2743,7 +2759,7 @@ declare module "@polkadot/types/lookup" { readonly type: "JoiningAutoCompounding" | "JoiningManualRewards" | "Leaving"; } - /** @name PalletPooledStakingSharesOrStake (222) */ + /** @name PalletPooledStakingSharesOrStake (223) */ interface PalletPooledStakingSharesOrStake extends Enum { readonly isShares: boolean; readonly asShares: u128; @@ -2752,7 +2768,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Shares" | "Stake"; } - /** @name CumulusPalletXcmpQueueCall (225) */ + /** @name CumulusPalletXcmpQueueCall (226) */ interface CumulusPalletXcmpQueueCall extends Enum { readonly isServiceOverweight: boolean; readonly asServiceOverweight: { @@ -2797,7 +2813,7 @@ declare module "@polkadot/types/lookup" { | "UpdateXcmpMaxIndividualWeight"; } - /** @name CumulusPalletDmpQueueCall (226) */ + /** @name CumulusPalletDmpQueueCall (227) */ interface CumulusPalletDmpQueueCall extends Enum { readonly isServiceOverweight: boolean; readonly asServiceOverweight: { @@ -2807,7 +2823,7 @@ declare module "@polkadot/types/lookup" { readonly type: "ServiceOverweight"; } - /** @name PalletXcmCall (227) */ + /** @name PalletXcmCall (228) */ interface PalletXcmCall extends Enum { readonly isSend: boolean; readonly asSend: { @@ -2884,7 +2900,7 @@ declare module "@polkadot/types/lookup" { | "ForceSuspension"; } - /** @name StagingXcmVersionedXcm (228) */ + /** @name StagingXcmVersionedXcm (229) */ interface StagingXcmVersionedXcm extends Enum { readonly isV2: boolean; readonly asV2: StagingXcmV2Xcm; @@ -2893,10 +2909,10 @@ declare module "@polkadot/types/lookup" { readonly type: "V2" | "V3"; } - /** @name StagingXcmV2Xcm (229) */ + /** @name StagingXcmV2Xcm (230) */ interface StagingXcmV2Xcm extends Vec {} - /** @name StagingXcmV2Instruction (231) */ + /** @name StagingXcmV2Instruction (232) */ interface StagingXcmV2Instruction extends Enum { readonly isWithdrawAsset: boolean; readonly asWithdrawAsset: StagingXcmV2MultiassetMultiAssets; @@ -3044,7 +3060,7 @@ declare module "@polkadot/types/lookup" { | "UnsubscribeVersion"; } - /** @name StagingXcmV2Response (232) */ + /** @name StagingXcmV2Response (233) */ interface StagingXcmV2Response extends Enum { readonly isNull: boolean; readonly isAssets: boolean; @@ -3056,7 +3072,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Null" | "Assets" | "ExecutionResult" | "Version"; } - /** @name StagingXcmV2TraitsError (235) */ + /** @name StagingXcmV2TraitsError (236) */ interface StagingXcmV2TraitsError extends Enum { readonly isOverflow: boolean; readonly isUnimplemented: boolean; @@ -3115,7 +3131,7 @@ declare module "@polkadot/types/lookup" { | "WeightNotComputable"; } - /** @name StagingXcmV2MultiassetMultiAssetFilter (236) */ + /** @name StagingXcmV2MultiassetMultiAssetFilter (237) */ interface StagingXcmV2MultiassetMultiAssetFilter extends Enum { readonly isDefinite: boolean; readonly asDefinite: StagingXcmV2MultiassetMultiAssets; @@ -3124,7 +3140,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Definite" | "Wild"; } - /** @name StagingXcmV2MultiassetWildMultiAsset (237) */ + /** @name StagingXcmV2MultiassetWildMultiAsset (238) */ interface StagingXcmV2MultiassetWildMultiAsset extends Enum { readonly isAll: boolean; readonly isAllOf: boolean; @@ -3135,14 +3151,14 @@ declare module "@polkadot/types/lookup" { readonly type: "All" | "AllOf"; } - /** @name StagingXcmV2MultiassetWildFungibility (238) */ + /** @name StagingXcmV2MultiassetWildFungibility (239) */ interface StagingXcmV2MultiassetWildFungibility extends Enum { readonly isFungible: boolean; readonly isNonFungible: boolean; readonly type: "Fungible" | "NonFungible"; } - /** @name StagingXcmV2WeightLimit (239) */ + /** @name StagingXcmV2WeightLimit (240) */ interface StagingXcmV2WeightLimit extends Enum { readonly isUnlimited: boolean; readonly isLimited: boolean; @@ -3150,7 +3166,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Unlimited" | "Limited"; } - /** @name PalletRootTestingCall (248) */ + /** @name PalletRootTestingCall (249) */ interface PalletRootTestingCall extends Enum { readonly isFillBlock: boolean; readonly asFillBlock: { @@ -3159,33 +3175,33 @@ declare module "@polkadot/types/lookup" { readonly type: "FillBlock"; } - /** @name PalletSudoError (250) */ + /** @name PalletSudoError (251) */ interface PalletSudoError extends Enum { readonly isRequireSudo: boolean; readonly type: "RequireSudo"; } - /** @name PalletUtilityError (251) */ + /** @name PalletUtilityError (252) */ interface PalletUtilityError extends Enum { readonly isTooManyCalls: boolean; readonly type: "TooManyCalls"; } - /** @name PalletProxyProxyDefinition (254) */ + /** @name PalletProxyProxyDefinition (255) */ interface PalletProxyProxyDefinition extends Struct { readonly delegate: AccountId32; readonly proxyType: DanceboxRuntimeProxyType; readonly delay: u32; } - /** @name PalletProxyAnnouncement (258) */ + /** @name PalletProxyAnnouncement (259) */ interface PalletProxyAnnouncement extends Struct { readonly real: AccountId32; readonly callHash: H256; readonly height: u32; } - /** @name PalletProxyError (260) */ + /** @name PalletProxyError (261) */ interface PalletProxyError extends Enum { readonly isTooMany: boolean; readonly isNotFound: boolean; @@ -3206,7 +3222,7 @@ declare module "@polkadot/types/lookup" { | "NoSelfProxy"; } - /** @name PalletMigrationsError (261) */ + /** @name PalletMigrationsError (262) */ interface PalletMigrationsError extends Enum { readonly isPreimageMissing: boolean; readonly isWrongUpperBound: boolean; @@ -3215,21 +3231,21 @@ declare module "@polkadot/types/lookup" { readonly type: "PreimageMissing" | "WrongUpperBound" | "PreimageIsTooBig" | "PreimageAlreadyExists"; } - /** @name PalletMaintenanceModeError (262) */ + /** @name PalletMaintenanceModeError (263) */ interface PalletMaintenanceModeError extends Enum { readonly isAlreadyInMaintenanceMode: boolean; readonly isNotInMaintenanceMode: boolean; readonly type: "AlreadyInMaintenanceMode" | "NotInMaintenanceMode"; } - /** @name PalletBalancesBalanceLock (264) */ + /** @name PalletBalancesBalanceLock (265) */ interface PalletBalancesBalanceLock extends Struct { readonly id: U8aFixed; readonly amount: u128; readonly reasons: PalletBalancesReasons; } - /** @name PalletBalancesReasons (265) */ + /** @name PalletBalancesReasons (266) */ interface PalletBalancesReasons extends Enum { readonly isFee: boolean; readonly isMisc: boolean; @@ -3237,25 +3253,25 @@ declare module "@polkadot/types/lookup" { readonly type: "Fee" | "Misc" | "All"; } - /** @name PalletBalancesReserveData (268) */ + /** @name PalletBalancesReserveData (269) */ interface PalletBalancesReserveData extends Struct { readonly id: U8aFixed; readonly amount: u128; } - /** @name DanceboxRuntimeHoldReason (272) */ + /** @name DanceboxRuntimeHoldReason (273) */ interface DanceboxRuntimeHoldReason extends Enum { readonly isPooledStake: boolean; readonly type: "PooledStake"; } - /** @name PalletBalancesIdAmount (275) */ + /** @name PalletBalancesIdAmount (276) */ interface PalletBalancesIdAmount extends Struct { readonly id: U8aFixed; readonly amount: u128; } - /** @name PalletBalancesError (277) */ + /** @name PalletBalancesError (278) */ interface PalletBalancesError extends Enum { readonly isVestingBalance: boolean; readonly isLiquidityRestrictions: boolean; @@ -3280,20 +3296,20 @@ declare module "@polkadot/types/lookup" { | "TooManyFreezes"; } - /** @name PalletTransactionPaymentReleases (279) */ + /** @name PalletTransactionPaymentReleases (280) */ interface PalletTransactionPaymentReleases extends Enum { readonly isV1Ancient: boolean; readonly isV2: boolean; readonly type: "V1Ancient" | "V2"; } - /** @name PalletRegistrarDepositInfo (284) */ + /** @name PalletRegistrarDepositInfo (285) */ interface PalletRegistrarDepositInfo extends Struct { readonly creator: AccountId32; readonly deposit: u128; } - /** @name PalletRegistrarError (285) */ + /** @name PalletRegistrarError (286) */ interface PalletRegistrarError extends Enum { readonly isParaIdAlreadyRegistered: boolean; readonly isParaIdAlreadyPaused: boolean; @@ -3312,7 +3328,7 @@ declare module "@polkadot/types/lookup" { | "NotSufficientDeposit"; } - /** @name PalletConfigurationHostConfiguration (286) */ + /** @name PalletConfigurationHostConfiguration (287) */ interface PalletConfigurationHostConfiguration extends Struct { readonly maxCollators: u32; readonly minOrchestratorCollators: u32; @@ -3321,25 +3337,25 @@ declare module "@polkadot/types/lookup" { readonly fullRotationPeriod: u32; } - /** @name PalletConfigurationError (289) */ + /** @name PalletConfigurationError (290) */ interface PalletConfigurationError extends Enum { readonly isInvalidNewValue: boolean; readonly type: "InvalidNewValue"; } - /** @name TpCollatorAssignmentAssignedCollatorsAccountId32 (290) */ + /** @name TpCollatorAssignmentAssignedCollatorsAccountId32 (291) */ interface TpCollatorAssignmentAssignedCollatorsAccountId32 extends Struct { readonly orchestratorChain: Vec; readonly containerChains: BTreeMap>; } - /** @name PalletAuthorNotingContainerChainBlockInfo (295) */ + /** @name PalletAuthorNotingContainerChainBlockInfo (296) */ interface PalletAuthorNotingContainerChainBlockInfo extends Struct { readonly blockNumber: u32; readonly author: AccountId32; } - /** @name PalletAuthorNotingError (296) */ + /** @name PalletAuthorNotingError (297) */ interface PalletAuthorNotingError extends Enum { readonly isFailedReading: boolean; readonly isFailedDecodingHeader: boolean; @@ -3358,13 +3374,13 @@ declare module "@polkadot/types/lookup" { | "NonAuraDigest"; } - /** @name TpCollatorAssignmentAssignedCollatorsPublic (297) */ + /** @name TpCollatorAssignmentAssignedCollatorsPublic (298) */ interface TpCollatorAssignmentAssignedCollatorsPublic extends Struct { readonly orchestratorChain: Vec; readonly containerChains: BTreeMap>; } - /** @name PalletInvulnerablesError (303) */ + /** @name PalletInvulnerablesError (304) */ interface PalletInvulnerablesError extends Enum { readonly isTooManyInvulnerables: boolean; readonly isAlreadyInvulnerable: boolean; @@ -3372,10 +3388,10 @@ declare module "@polkadot/types/lookup" { readonly type: "TooManyInvulnerables" | "AlreadyInvulnerable" | "NotInvulnerable"; } - /** @name SpCoreCryptoKeyTypeId (308) */ + /** @name SpCoreCryptoKeyTypeId (309) */ interface SpCoreCryptoKeyTypeId extends U8aFixed {} - /** @name PalletSessionError (309) */ + /** @name PalletSessionError (310) */ interface PalletSessionError extends Enum { readonly isInvalidProof: boolean; readonly isNoAssociatedValidatorId: boolean; @@ -3385,7 +3401,7 @@ declare module "@polkadot/types/lookup" { readonly type: "InvalidProof" | "NoAssociatedValidatorId" | "DuplicatedKey" | "NoKeys" | "NoAccount"; } - /** @name PalletAuthorInherentError (313) */ + /** @name PalletAuthorInherentError (314) */ interface PalletAuthorInherentError extends Enum { readonly isAuthorAlreadySet: boolean; readonly isNoAccountId: boolean; @@ -3393,13 +3409,13 @@ declare module "@polkadot/types/lookup" { readonly type: "AuthorAlreadySet" | "NoAccountId" | "CannotBeAuthor"; } - /** @name PalletPooledStakingCandidateEligibleCandidate (315) */ + /** @name PalletPooledStakingCandidateEligibleCandidate (316) */ interface PalletPooledStakingCandidateEligibleCandidate extends Struct { readonly candidate: AccountId32; readonly stake: u128; } - /** @name PalletPooledStakingPoolsKey (318) */ + /** @name PalletPooledStakingPoolsKey (319) */ interface PalletPooledStakingPoolsKey extends Enum { readonly isCandidateTotalStake: boolean; readonly isJoiningShares: boolean; @@ -3469,7 +3485,7 @@ declare module "@polkadot/types/lookup" { | "LeavingSharesHeldStake"; } - /** @name PalletPooledStakingError (320) */ + /** @name PalletPooledStakingError (321) */ interface PalletPooledStakingError extends Enum { readonly isInvalidPalletSetting: boolean; readonly isDisabledFeature: boolean; @@ -3503,21 +3519,27 @@ declare module "@polkadot/types/lookup" { | "SwapResultsInZeroShares"; } - /** @name CumulusPalletXcmpQueueInboundChannelDetails (322) */ + /** @name PalletInflationRewardsChainsToRewardValue (322) */ + interface PalletInflationRewardsChainsToRewardValue extends Struct { + readonly paraIds: Vec; + readonly rewardsPerChain: u128; + } + + /** @name CumulusPalletXcmpQueueInboundChannelDetails (324) */ interface CumulusPalletXcmpQueueInboundChannelDetails extends Struct { readonly sender: u32; readonly state: CumulusPalletXcmpQueueInboundState; readonly messageMetadata: Vec>; } - /** @name CumulusPalletXcmpQueueInboundState (323) */ + /** @name CumulusPalletXcmpQueueInboundState (325) */ interface CumulusPalletXcmpQueueInboundState extends Enum { readonly isOk: boolean; readonly isSuspended: boolean; readonly type: "Ok" | "Suspended"; } - /** @name PolkadotParachainPrimitivesPrimitivesXcmpMessageFormat (326) */ + /** @name PolkadotParachainPrimitivesPrimitivesXcmpMessageFormat (328) */ interface PolkadotParachainPrimitivesPrimitivesXcmpMessageFormat extends Enum { readonly isConcatenatedVersionedXcm: boolean; readonly isConcatenatedEncodedBlob: boolean; @@ -3525,7 +3547,7 @@ declare module "@polkadot/types/lookup" { readonly type: "ConcatenatedVersionedXcm" | "ConcatenatedEncodedBlob" | "Signals"; } - /** @name CumulusPalletXcmpQueueOutboundChannelDetails (329) */ + /** @name CumulusPalletXcmpQueueOutboundChannelDetails (331) */ interface CumulusPalletXcmpQueueOutboundChannelDetails extends Struct { readonly recipient: u32; readonly state: CumulusPalletXcmpQueueOutboundState; @@ -3534,14 +3556,14 @@ declare module "@polkadot/types/lookup" { readonly lastIndex: u16; } - /** @name CumulusPalletXcmpQueueOutboundState (330) */ + /** @name CumulusPalletXcmpQueueOutboundState (332) */ interface CumulusPalletXcmpQueueOutboundState extends Enum { readonly isOk: boolean; readonly isSuspended: boolean; readonly type: "Ok" | "Suspended"; } - /** @name CumulusPalletXcmpQueueQueueConfigData (332) */ + /** @name CumulusPalletXcmpQueueQueueConfigData (334) */ interface CumulusPalletXcmpQueueQueueConfigData extends Struct { readonly suspendThreshold: u32; readonly dropThreshold: u32; @@ -3551,7 +3573,7 @@ declare module "@polkadot/types/lookup" { readonly xcmpMaxIndividualWeight: SpWeightsWeightV2Weight; } - /** @name CumulusPalletXcmpQueueError (334) */ + /** @name CumulusPalletXcmpQueueError (336) */ interface CumulusPalletXcmpQueueError extends Enum { readonly isFailedToSend: boolean; readonly isBadXcmOrigin: boolean; @@ -3561,29 +3583,29 @@ declare module "@polkadot/types/lookup" { readonly type: "FailedToSend" | "BadXcmOrigin" | "BadXcm" | "BadOverweightIndex" | "WeightOverLimit"; } - /** @name CumulusPalletXcmError (335) */ + /** @name CumulusPalletXcmError (337) */ type CumulusPalletXcmError = Null; - /** @name CumulusPalletDmpQueueConfigData (336) */ + /** @name CumulusPalletDmpQueueConfigData (338) */ interface CumulusPalletDmpQueueConfigData extends Struct { readonly maxIndividual: SpWeightsWeightV2Weight; } - /** @name CumulusPalletDmpQueuePageIndexData (337) */ + /** @name CumulusPalletDmpQueuePageIndexData (339) */ interface CumulusPalletDmpQueuePageIndexData extends Struct { readonly beginUsed: u32; readonly endUsed: u32; readonly overweightCount: u64; } - /** @name CumulusPalletDmpQueueError (340) */ + /** @name CumulusPalletDmpQueueError (342) */ interface CumulusPalletDmpQueueError extends Enum { readonly isUnknown: boolean; readonly isOverLimit: boolean; readonly type: "Unknown" | "OverLimit"; } - /** @name PalletXcmQueryStatus (341) */ + /** @name PalletXcmQueryStatus (343) */ interface PalletXcmQueryStatus extends Enum { readonly isPending: boolean; readonly asPending: { @@ -3605,7 +3627,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Pending" | "VersionNotifier" | "Ready"; } - /** @name StagingXcmVersionedResponse (345) */ + /** @name StagingXcmVersionedResponse (347) */ interface StagingXcmVersionedResponse extends Enum { readonly isV2: boolean; readonly asV2: StagingXcmV2Response; @@ -3614,7 +3636,7 @@ declare module "@polkadot/types/lookup" { readonly type: "V2" | "V3"; } - /** @name PalletXcmVersionMigrationStage (351) */ + /** @name PalletXcmVersionMigrationStage (353) */ interface PalletXcmVersionMigrationStage extends Enum { readonly isMigrateSupportedVersion: boolean; readonly isMigrateVersionNotifiers: boolean; @@ -3628,14 +3650,14 @@ declare module "@polkadot/types/lookup" { | "MigrateAndNotifyOldTargets"; } - /** @name StagingXcmVersionedAssetId (353) */ + /** @name StagingXcmVersionedAssetId (355) */ interface StagingXcmVersionedAssetId extends Enum { readonly isV3: boolean; readonly asV3: StagingXcmV3MultiassetAssetId; readonly type: "V3"; } - /** @name PalletXcmRemoteLockedFungibleRecord (354) */ + /** @name PalletXcmRemoteLockedFungibleRecord (356) */ interface PalletXcmRemoteLockedFungibleRecord extends Struct { readonly amount: u128; readonly owner: StagingXcmVersionedMultiLocation; @@ -3643,7 +3665,7 @@ declare module "@polkadot/types/lookup" { readonly consumers: Vec>; } - /** @name PalletXcmError (361) */ + /** @name PalletXcmError (363) */ interface PalletXcmError extends Enum { readonly isUnreachable: boolean; readonly isSendFailure: boolean; @@ -3688,7 +3710,7 @@ declare module "@polkadot/types/lookup" { | "InUse"; } - /** @name SpRuntimeMultiSignature (363) */ + /** @name SpRuntimeMultiSignature (365) */ interface SpRuntimeMultiSignature extends Enum { readonly isEd25519: boolean; readonly asEd25519: SpCoreEd25519Signature; @@ -3699,36 +3721,36 @@ declare module "@polkadot/types/lookup" { readonly type: "Ed25519" | "Sr25519" | "Ecdsa"; } - /** @name SpCoreEd25519Signature (364) */ + /** @name SpCoreEd25519Signature (366) */ interface SpCoreEd25519Signature extends U8aFixed {} - /** @name SpCoreSr25519Signature (366) */ + /** @name SpCoreSr25519Signature (368) */ interface SpCoreSr25519Signature extends U8aFixed {} - /** @name SpCoreEcdsaSignature (367) */ + /** @name SpCoreEcdsaSignature (369) */ interface SpCoreEcdsaSignature extends U8aFixed {} - /** @name FrameSystemExtensionsCheckNonZeroSender (370) */ + /** @name FrameSystemExtensionsCheckNonZeroSender (372) */ type FrameSystemExtensionsCheckNonZeroSender = Null; - /** @name FrameSystemExtensionsCheckSpecVersion (371) */ + /** @name FrameSystemExtensionsCheckSpecVersion (373) */ type FrameSystemExtensionsCheckSpecVersion = Null; - /** @name FrameSystemExtensionsCheckTxVersion (372) */ + /** @name FrameSystemExtensionsCheckTxVersion (374) */ type FrameSystemExtensionsCheckTxVersion = Null; - /** @name FrameSystemExtensionsCheckGenesis (373) */ + /** @name FrameSystemExtensionsCheckGenesis (375) */ type FrameSystemExtensionsCheckGenesis = Null; - /** @name FrameSystemExtensionsCheckNonce (376) */ + /** @name FrameSystemExtensionsCheckNonce (378) */ interface FrameSystemExtensionsCheckNonce extends Compact {} - /** @name FrameSystemExtensionsCheckWeight (377) */ + /** @name FrameSystemExtensionsCheckWeight (379) */ type FrameSystemExtensionsCheckWeight = Null; - /** @name PalletTransactionPaymentChargeTransactionPayment (378) */ + /** @name PalletTransactionPaymentChargeTransactionPayment (380) */ interface PalletTransactionPaymentChargeTransactionPayment extends Compact {} - /** @name DanceboxRuntimeRuntime (379) */ + /** @name DanceboxRuntimeRuntime (381) */ type DanceboxRuntimeRuntime = Null; } // declare module