From 4fd2981d6fd0ef70d85e2e13f1c8a94a949d0fcc Mon Sep 17 00:00:00 2001 From: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:50:00 +0200 Subject: [PATCH] Kusama: Make the current inflation formula adjustable. (#364) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR does not alter the inflation of Kusama, but instead make the current parameters of the system fully configurable. ## Parameters The parameters are as follows: ```rust /// Minimum inflation rate used to calculate era payouts. pub static MinInflation: Perquintill = Perquintill::from_rational(25u64, 1000); /// Maximum inflation rate used to calculate era payouts. pub static MaxInflation: Perquintill = Perquintill::from_percent(10); /// Ideal stake ratio used to calculate era payouts. pub static IdealStake: Perquintill = Perquintill::from_percent(75); /// Falloff used to calculate era payouts. pub static Falloff: Perquintill = Perquintill::from_percent(5); /// Whether to use auction slots or not in the calculation of era payouts, then we subtract /// `num_auctioned_slots.min(60) / 200` from `ideal_stake`. /// /// That is, we assume up to 60 parachains that are leased can reduce the ideal stake by a /// maximum of 30%. /// /// With the move to agile-coretime, this parameter does not make much sense and should /// generally be set to false. pub static UseAuctionSlots: bool = true; ``` All of the above are exactly the current values in Kusama, and leave everything unchanged, leading to roughly `1kKSM` minted for validators, and around `90KSM` for treasury. All of the above can be changed via the `Root` track only. Given that it is hard to come to consensus, I highly advise this PR (and a similar PR to Polkadot) to NOT alter any parameter and leave that to the token holders. Just to provide one example, if we set `UseAuctionSlots = false` and leave everything else un-changed, the amount minted per era would be: * `807KSM` for staking * `238KSM` for treasury > This, in my opinion, is the most non-controversial change as the incorporation of auctions in the inflation rate is already meaningless with agile-coretime. ## Consideration for UIs This PR is shipped with a new runtime API that is only added to the Kusama runtime: `Inflation_experimental_inflation_info`. I hope this API is used by the UIs to show the inflation parameters of the network, rather than re-creating the Rust logic in the front-end. --------- Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Oliver Tale-Yazdi Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> Co-authored-by: clangenb <37865735+clangenb@users.noreply.github.com> Co-authored-by: Dónal Murray Co-authored-by: Gonçalo Pestana Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> Co-authored-by: Dónal Murray Co-authored-by: fellowship-merge-bot[bot] <151052383+fellowship-merge-bot[bot]@users.noreply.github.com> --- CHANGELOG.md | 2 + Cargo.lock | 38 ++- Cargo.toml | 4 + relay/common/Cargo.toml | 30 +++ relay/common/src/lib.rs | 115 +++++++++ relay/kusama/Cargo.toml | 7 + relay/kusama/src/lib.rs | 237 ++++++++++++++++-- relay/kusama/src/weights/mod.rs | 1 + relay/kusama/src/weights/pallet_parameters.rs | 51 ++++ 9 files changed, 467 insertions(+), 18 deletions(-) create mode 100644 relay/common/Cargo.toml create mode 100644 relay/common/src/lib.rs create mode 100644 relay/kusama/src/weights/pallet_parameters.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f215d3efa..6d351bea8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,8 +20,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Add the Polkadot Coretime Chain runtime ([polkadot-fellows/runtimes#410](https://github.com/polkadot-fellows/runtimes/pull/410)) - Kusama: Add a "Spokesperson" proxy type only allowed to send remarks ([polkadot-fellows/runtimes#430](https://github.com/polkadot-fellows/runtimes/pull/430)) - Add the Polkadot and Kusama Coretime Chain specs ([polkadot-fellows/runtimes#432](https://github.com/polkadot-fellows/runtimes/pull/432)) +- Kusama: Make the current inflation formula adjustable ([polkadot-fellows/runtimes#364](https://github.com/polkadot-fellows/runtimes/pull/364)) - Port Agile Coretime migration from polkadot-sdk in order to fix leases with gaps handling([polkadot-fellows/runtimes#426](https://github.com/polkadot-fellows/runtimes/pull/426)) + #### From [#322](https://github.com/polkadot-fellows/runtimes/pull/322): - Add `claim_assets` extrinsic to `pallet-xcm` ([SDK v1.9 #3403](https://github.com/paritytech/polkadot-sdk/pull/3403)). diff --git a/Cargo.lock b/Cargo.lock index e18345ee89..207caffac2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8703,6 +8703,25 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-parameters" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58d9a81a93202105a660e6aa3d3f81638bdd109ca0497f3e528529cd52d034db" +dependencies = [ + "docify", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "sp-core 34.0.0", + "sp-runtime 38.0.0", + "sp-std", +] + [[package]] name = "pallet-preimage" version = "36.0.0" @@ -11078,6 +11097,18 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "relay-common" +version = "1.0.0" +dependencies = [ + "pallet-staking-reward-fn", + "parity-scale-codec", + "polkadot-primitives", + "scale-info", + "sp-api", + "sp-runtime 38.0.0", +] + [[package]] name = "reqwest" version = "0.11.27" @@ -14239,9 +14270,9 @@ dependencies = [ [[package]] name = "ss58-registry" -version = "1.44.0" +version = "1.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35935738370302d5e33963665b77541e4b990a3e919ec904c837a56cfc891de1" +checksum = "4743ce898933fbff7bbf414f497c459a782d496269644b3d650a398ae6a487ba" dependencies = [ "Inflector", "num-format", @@ -14325,6 +14356,7 @@ dependencies = [ "pallet-nomination-pools-runtime-api", "pallet-offences", "pallet-offences-benchmarking", + "pallet-parameters", "pallet-preimage", "pallet-proxy", "pallet-ranked-collective", @@ -14349,6 +14381,7 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-parachains", + "relay-common", "scale-info", "separator", "serde_json", @@ -14376,6 +14409,7 @@ dependencies = [ "sp-transaction-pool", "sp-trie 36.0.0", "sp-version", + "ss58-registry", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", diff --git a/Cargo.toml b/Cargo.toml index 280dcd504a..8c6e70033a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -137,6 +137,7 @@ pallet-nomination-pools-benchmarking = { version = "34.0.0", default-features = pallet-nomination-pools-runtime-api = { version = "31.0.0", default-features = false } pallet-offences = { version = "35.0.0", default-features = false } pallet-offences-benchmarking = { version = "36.0.0", default-features = false } +pallet-parameters = { version = "0.7.0", default-features = false } pallet-preimage = { version = "36.0.0", default-features = false } pallet-proxy = { version = "36.0.0", default-features = false } pallet-ranked-collective = { version = "36.0.0", default-features = false } @@ -243,6 +244,8 @@ subxt = { version = "0.35.0", default-features = false } tracing-subscriber = { version = "0.3.18" } zombienet-sdk = { version = "0.2.4" } tuplex = { version = "0.1.0", default-features = false } +relay-common = { path = "relay/common", default-features = false } +ss58-registry = { version = "1.47.0" } [workspace] resolver = "2" @@ -275,6 +278,7 @@ members = [ "integration-tests/emulated/tests/people/people-kusama", "integration-tests/emulated/tests/people/people-polkadot", "integration-tests/zombienet", + "relay/common", "relay/kusama", "relay/kusama/constants", "relay/polkadot", diff --git a/relay/common/Cargo.toml b/relay/common/Cargo.toml new file mode 100644 index 0000000000..1b6ded352a --- /dev/null +++ b/relay/common/Cargo.toml @@ -0,0 +1,30 @@ +[package] +authors.workspace = true +description = "Shared utilities between relay runtimes" +edition.workspace = true +license.workspace = true +name = "relay-common" +repository.workspace = true +version.workspace = true + +[dependencies] +codec = { features = ["derive", "max-encoded-len"], workspace = true } +scale-info = { features = ["derive"], workspace = true } + +sp-api ={ workspace = true } +sp-runtime = { workspace = true } +polkadot-primitives = { workspace = true } +pallet-staking-reward-fn ={ workspace = true } + + +[features] +default = ["std"] +std = [ + "codec/std", + "scale-info/std", + + "sp-api/std", + "sp-runtime/std", + "polkadot-primitives/std", + "pallet-staking-reward-fn/std", +] diff --git a/relay/common/src/lib.rs b/relay/common/src/lib.rs new file mode 100644 index 0000000000..0f0e119f25 --- /dev/null +++ b/relay/common/src/lib.rs @@ -0,0 +1,115 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Shared code between the Kusama nd Polkadot RC Runtimes. +#![cfg_attr(not(feature = "std"), no_std)] + +use polkadot_primitives::Balance; +use sp_runtime::{Perquintill, Saturating}; + +/// Extra runtime APIs for kusama runtime. +pub mod apis { + /// Information about the current inflation rate of the system. + /// + /// Both fields should be treated as best-effort, given that the inflation rate might not be + /// fully predict-able. + #[derive(scale_info::TypeInfo, codec::Encode, codec::Decode)] + pub struct InflationInfo { + /// The rate of inflation estimated per annum. + pub inflation: sp_runtime::Perquintill, + /// Next amount that we anticipate to mint. + /// + /// First item is the amount that goes to stakers, second is the leftover that is usually + /// forwarded to the treasury. + pub next_mint: (polkadot_primitives::Balance, polkadot_primitives::Balance), + } + + sp_api::decl_runtime_apis! { + pub trait Inflation { + /// Return the current estimates of the inflation amount. + /// + /// This is marked as experimental in light of RFC#89. Nonetheless, its usage is highly + /// recommended over trying to read-storage, or re-create the onchain logic. + fn experimental_inflation_prediction_info() -> InflationInfo; + } + } +} + +// ---- TODO: Below is copy pasted from sdk, remove once we pull the version containing +// https://github.com/paritytech/polkadot-sdk/pull/4938 + +#[derive(Debug, Clone)] +/// Parameters passed into [`relay_era_payout`] function. +pub struct EraPayoutParams { + /// Total staked amount. + pub total_staked: Balance, + /// Total stakable amount. + /// + /// Usually, this is equal to the total issuance, except if a large part of the issuance is + /// locked in another sub-system. + pub total_stakable: Balance, + /// Ideal stake ratio, which is reduced by `legacy_auction_proportion` if not `None`. + pub ideal_stake: Perquintill, + /// Maximum inflation rate. + pub max_annual_inflation: Perquintill, + /// Minimum inflation rate. + pub min_annual_inflation: Perquintill, + /// Falloff used to calculate era payouts. + pub falloff: Perquintill, + /// Fraction of the era period used to calculate era payouts. + pub period_fraction: Perquintill, + /// Legacy auction proportion, which, if not `None`, is subtracted from `ideal_stake`. + pub legacy_auction_proportion: Option, +} + +/// A specialized function to compute the inflation of the staking system, tailored for Polkadot +/// Relay Chains, such as Polkadot, Kusama, and Westend. +pub fn relay_era_payout(params: EraPayoutParams) -> (Balance, Balance) { + let EraPayoutParams { + total_staked, + total_stakable, + ideal_stake, + max_annual_inflation, + min_annual_inflation, + falloff, + period_fraction, + legacy_auction_proportion, + } = params; + + let delta_annual_inflation = max_annual_inflation.saturating_sub(min_annual_inflation); + + let ideal_stake = ideal_stake.saturating_sub(legacy_auction_proportion.unwrap_or_default()); + + let stake = Perquintill::from_rational(total_staked, total_stakable); + let adjustment = pallet_staking_reward_fn::compute_inflation(stake, ideal_stake, falloff); + let staking_inflation = + min_annual_inflation.saturating_add(delta_annual_inflation * adjustment); + + let max_payout = period_fraction * max_annual_inflation * total_stakable; + let staking_payout = (period_fraction * staking_inflation) * total_stakable; + let rest = max_payout.saturating_sub(staking_payout); + + let other_issuance = total_stakable.saturating_sub(total_staked); + if total_staked > other_issuance { + let _cap_rest = Perquintill::from_rational(other_issuance, total_staked) * staking_payout; + // We don't do anything with this, but if we wanted to, we could introduce a cap on the + // treasury amount with: `rest = rest.min(cap_rest);` + } + (staking_payout, rest) +} + +// ---- TODO: Above is copy pasted from sdk, remove once we pull the version containing +// https://github.com/paritytech/polkadot-sdk/pull/4938 diff --git a/relay/kusama/Cargo.toml b/relay/kusama/Cargo.toml index 5a600a1d35..0cc6705aab 100644 --- a/relay/kusama/Cargo.toml +++ b/relay/kusama/Cargo.toml @@ -85,6 +85,7 @@ pallet-whitelist = { workspace = true } pallet-xcm = { workspace = true } pallet-xcm-benchmarks = { optional = true, workspace = true } frame-election-provider-support = { workspace = true } +pallet-parameters = { workspace = true } frame-benchmarking = { optional = true, workspace = true } frame-try-runtime = { optional = true, workspace = true } @@ -105,6 +106,7 @@ xcm-builder = { workspace = true } xcm-runtime-apis = { workspace = true } sp-debug-derive = { workspace = true } +relay-common = { workspace = true } [dev-dependencies] sp-keyring = { workspace = true } @@ -113,6 +115,7 @@ separator = { workspace = true } remote-externalities = { workspace = true } tokio = { features = ["macros"], workspace = true } sp-tracing = { workspace = true } +ss58-registry = { workspace = true } [build-dependencies] substrate-wasm-builder = { workspace = true, optional = true } @@ -166,6 +169,7 @@ std = [ "pallet-offences/std", "pallet-preimage/std", "pallet-proxy/std", + "pallet-parameters/std", "pallet-ranked-collective/std", "pallet-recovery/std", "pallet-referenda/std", @@ -186,6 +190,7 @@ std = [ "pallet-xcm/std", "polkadot-primitives/std", "polkadot-runtime-common/std", + "relay-common/std", "runtime-parachains/std", "scale-info/std", "serde_json/std", @@ -241,6 +246,7 @@ runtime-benchmarks = [ "pallet-nomination-pools/runtime-benchmarks", "pallet-offences-benchmarking/runtime-benchmarks", "pallet-offences/runtime-benchmarks", + "pallet-parameters/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-ranked-collective/runtime-benchmarks", @@ -314,6 +320,7 @@ try-runtime = [ "polkadot-runtime-common/try-runtime", "runtime-parachains/try-runtime", "sp-runtime/try-runtime", + "pallet-parameters/try-runtime", ] # Enable metadata hash generation at compile time for the `CheckMetadataHash` extension. diff --git a/relay/kusama/src/lib.rs b/relay/kusama/src/lib.rs index bb31116d06..1be9dc612c 100644 --- a/relay/kusama/src/lib.rs +++ b/relay/kusama/src/lib.rs @@ -20,8 +20,14 @@ // `construct_runtime!` does a lot of recursion and requires us to increase the limit. #![recursion_limit = "512"] +extern crate alloc; + use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::weights::constants::{WEIGHT_PROOF_SIZE_PER_KB, WEIGHT_REF_TIME_PER_MICROS}; +use frame_support::{ + dynamic_params::{dynamic_pallet_params, dynamic_params}, + traits::EnsureOriginWithArg, + weights::constants::{WEIGHT_PROOF_SIZE_PER_KB, WEIGHT_REF_TIME_PER_MICROS}, +}; use kusama_runtime_constants::system_parachain::coretime::TIMESLICE_PERIOD; use pallet_nis::WithMaximumOf; use polkadot_primitives::{ @@ -40,7 +46,9 @@ use polkadot_runtime_common::{ paras_registrar, prod_or_fast, slots, BalanceToU256, BlockHashCount, BlockLength, CurrencyToVote, SlowAdjustingFeeUpdate, U256ToBalance, }; +use relay_common::apis::*; use scale_info::TypeInfo; +use sp_runtime::traits::Saturating; use sp_std::{ cmp::Ordering, collections::{btree_map::BTreeMap, vec_deque::VecDeque}, @@ -623,6 +631,86 @@ impl pallet_bags_list::Config for Runtime { type Score = sp_npos_elections::VoteWeight; } +/// Dynamic params that can be adjusted at runtime. +#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::)] +pub mod dynamic_params { + use super::*; + + /// Parameters used to calculate era payouts, see + /// [`polkadot_runtime_common::impls::EraPayoutParams`]. + #[dynamic_pallet_params] + #[codec(index = 0)] + pub mod inflation { + /// Minimum inflation rate used to calculate era payouts. + #[codec(index = 0)] + pub static MinInflation: Perquintill = Perquintill::from_rational(25u64, 1000); + + /// Maximum inflation rate used to calculate era payouts. + #[codec(index = 1)] + pub static MaxInflation: Perquintill = Perquintill::from_percent(10); + + /// Ideal stake ratio used to calculate era payouts. + #[codec(index = 2)] + pub static IdealStake: Perquintill = Perquintill::from_percent(75); + + /// Falloff used to calculate era payouts. + #[codec(index = 3)] + pub static Falloff: Perquintill = Perquintill::from_percent(5); + + /// Whether to use auction slots or not in the calculation of era payouts. If true, then we + /// subtract `num_auctioned_slots.min(60) / 200` from `ideal_stake`. + /// + /// That is, we assume up to 60 parachains that are leased can reduce the ideal stake by a + /// maximum of 30%. + /// + /// With the move to Agile Coretime, this parameter does not make much sense and should + /// generally be set to false. + #[codec(index = 4)] + pub static UseAuctionSlots: bool = false; + } +} + +#[cfg(feature = "runtime-benchmarks")] +impl Default for RuntimeParameters { + fn default() -> Self { + RuntimeParameters::Inflation(dynamic_params::inflation::Parameters::MinInflation( + dynamic_params::inflation::MinInflation, + Some(Perquintill::from_rational(25u64, 1000u64)), + )) + } +} + +/// Defines what origin can modify which dynamic parameters. +pub struct DynamicParameterOrigin; +impl EnsureOriginWithArg for DynamicParameterOrigin { + type Success = (); + + fn try_origin( + origin: RuntimeOrigin, + key: &RuntimeParametersKey, + ) -> Result { + use crate::RuntimeParametersKey::*; + + match key { + Inflation(_) => frame_system::ensure_root(origin.clone()), + } + .map_err(|_| origin) + } + + #[cfg(feature = "runtime-benchmarks")] + fn try_successful_origin(_key: &RuntimeParametersKey) -> Result { + // Provide the origin for the parameter returned by `Default`: + Ok(RuntimeOrigin::root()) + } +} + +impl pallet_parameters::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeParameters = RuntimeParameters; + type AdminOrigin = DynamicParameterOrigin; + type WeightInfo = weights::pallet_parameters::WeightInfo; +} + pub struct EraPayout; impl pallet_staking::EraPayout for EraPayout { fn era_payout( @@ -630,24 +718,30 @@ impl pallet_staking::EraPayout for EraPayout { _total_issuance: Balance, era_duration_millis: u64, ) -> (Balance, Balance) { - // all para-ids that are currently active. - let auctioned_slots = parachains_paras::Parachains::::get() - .into_iter() - // all active para-ids that do not belong to a system chain is the number - // of parachains that we should take into account for inflation. - .filter(|i| *i >= LOWEST_PUBLIC_ID) - .count() as u64; - - const MAX_ANNUAL_INFLATION: Perquintill = Perquintill::from_percent(10); const MILLISECONDS_PER_YEAR: u64 = 1000 * 3600 * 24 * 36525 / 100; - polkadot_runtime_common::impls::era_payout( + let params = relay_common::EraPayoutParams { total_staked, - Nis::issuance().other, - MAX_ANNUAL_INFLATION, - Perquintill::from_rational(era_duration_millis, MILLISECONDS_PER_YEAR), - auctioned_slots, - ) + total_stakable: Nis::issuance().other, + ideal_stake: dynamic_params::inflation::IdealStake::get(), + max_annual_inflation: dynamic_params::inflation::MaxInflation::get(), + min_annual_inflation: dynamic_params::inflation::MinInflation::get(), + falloff: dynamic_params::inflation::Falloff::get(), + period_fraction: Perquintill::from_rational(era_duration_millis, MILLISECONDS_PER_YEAR), + legacy_auction_proportion: if dynamic_params::inflation::UseAuctionSlots::get() { + let auctioned_slots = parachains_paras::Parachains::::get() + .into_iter() + // All active para-ids that do not belong to a system chain is the number of + // parachains that we should take into account for inflation. + .filter(|i| *i >= LOWEST_PUBLIC_ID) + .count() as u64; + Some(Perquintill::from_rational(auctioned_slots.min(60), 200u64)) + } else { + None + }, + }; + log::debug!(target: "runtime::kusama", "params: {:?}", params); + relay_common::relay_era_payout(params) } } @@ -1568,6 +1662,7 @@ construct_runtime! { FellowshipReferenda: pallet_referenda:: = 23, Origins: pallet_custom_origins = 43, Whitelist: pallet_whitelist = 44, + Parameters: pallet_parameters = 46, // Claims. Usable initially. Claims: claims = 19, @@ -1781,6 +1876,7 @@ mod benches { [pallet_vesting, Vesting] [pallet_whitelist, Whitelist] [pallet_asset_rate, AssetRate] + [pallet_parameters, Parameters] // XCM [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] [pallet_xcm_benchmarks::fungible, pallet_xcm_benchmarks::fungible::Pallet::] @@ -1788,7 +1884,47 @@ mod benches { ); } +impl Runtime { + fn impl_experimental_inflation_info() -> InflationInfo { + use pallet_staking::{ActiveEra, EraPayout, ErasTotalStake}; + let (staked, _start) = ActiveEra::::get() + .map(|ae| (ErasTotalStake::::get(ae.index), ae.start.unwrap_or(0))) + .unwrap_or((0, 0)); + let stake_able_issuance = Nis::issuance().other; + + let ideal_staking_rate = dynamic_params::inflation::IdealStake::get(); + let inflation = if dynamic_params::inflation::UseAuctionSlots::get() { + let auctioned_slots = parachains_paras::Parachains::::get() + .into_iter() + // All active para-ids that do not belong to a system chain is the number of + // parachains that we should take into account for inflation. + .filter(|i| *i >= LOWEST_PUBLIC_ID) + .count() as u64; + ideal_staking_rate + .saturating_sub(Perquintill::from_rational(auctioned_slots.min(60), 200u64)) + } else { + ideal_staking_rate + }; + + // We assume un-delayed 6h eras. + let era_duration = 6 * HOURS; + let next_mint = ::EraPayout::era_payout( + staked, + stake_able_issuance, + era_duration.into(), + ); + + InflationInfo { inflation, next_mint } + } +} + sp_api::impl_runtime_apis! { + impl relay_common::apis::Inflation for Runtime { + fn experimental_inflation_prediction_info() -> InflationInfo { + Runtime::impl_experimental_inflation_info() + } + } + impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { VERSION @@ -2844,6 +2980,75 @@ mod remote_tests { ext.execute_with(|| Runtime::on_runtime_upgrade(UpgradeCheckSelect::PreAndPost)); } + #[tokio::test] + async fn next_inflation() { + use hex_literal::hex; + sp_tracing::try_init_simple(); + let transport: Transport = + var("WS").unwrap_or("wss://rpc.dotters.network/kusama".to_string()).into(); + let mut ext = Builder::::default() + .mode(Mode::Online(OnlineConfig { + transport, + hashed_prefixes: vec![ + // entire nis pallet + hex!("928fa8b8d92aa31f47ed74f188a43f70").to_vec(), + // staking eras total stake + hex!("5f3e4907f716ac89b6347d15ececedcaa141c4fe67c2d11f4a10c6aca7a79a04") + .to_vec(), + ], + hashed_keys: vec![ + // staking active era + hex!("5f3e4907f716ac89b6347d15ececedca487df464e44a534ba6b0cbb32407b587") + .to_vec(), + // balances ti + hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80") + .to_vec(), + // timestamp now + hex!("f0c365c3cf59d671eb72da0e7a4113c49f1f0515f462cdcf84e0f1d6045dfcbb") + .to_vec(), + // para-ids + hex!("cd710b30bd2eab0352ddcc26417aa1940b76934f4cc08dee01012d059e1b83ee") + .to_vec(), + ], + ..Default::default() + })) + .build() + .await + .unwrap(); + ext.execute_with(|| { + use pallet_staking::EraPayout; + let (total_staked, started) = pallet_staking::ActiveEra::::get() + .map(|ae| { + (pallet_staking::ErasTotalStake::::get(ae.index), ae.start.unwrap()) + }) + .unwrap(); + let total_issuance = Nis::issuance().other; + let _real_era_duration_millis = + pallet_timestamp::Now::::get().saturating_sub(started); + // 6h in milliseconds + let average_era_duration_millis = 6 * 60 * 60 * 1000; + let (staking, leftover) = ::EraPayout::era_payout( + total_staked, + total_issuance, + average_era_duration_millis, + ); + use ss58_registry::TokenRegistry; + let token: ss58_registry::Token = TokenRegistry::Ksm.into(); + + log::info!(target: "runtime::kusama", "total-staked = {:?}", token.amount(total_staked)); + log::info!(target: "runtime::kusama", "total-issuance = {:?}", token.amount(total_issuance)); + log::info!(target: "runtime::kusama", "staking-rate = {:?}", Perquintill::from_rational(total_staked, total_issuance)); + log::info!(target: "runtime::kusama", "era-duration = {:?}", average_era_duration_millis); + log::info!(target: "runtime::kusama", "min-inflation = {:?}", dynamic_params::inflation::MinInflation::get()); + log::info!(target: "runtime::kusama", "max-inflation = {:?}", dynamic_params::inflation::MaxInflation::get()); + log::info!(target: "runtime::kusama", "falloff = {:?}", dynamic_params::inflation::Falloff::get()); + log::info!(target: "runtime::kusama", "useAuctionSlots = {:?}", dynamic_params::inflation::UseAuctionSlots::get()); + log::info!(target: "runtime::kusama", "idealStake = {:?}", dynamic_params::inflation::IdealStake::get()); + log::info!(target: "runtime::kusama", "maxStakingRewards = {:?}", pallet_staking::MaxStakedRewards::::get()); + log::info!(target: "runtime::kusama", "💰 Inflation ==> staking = {:?} / leftover = {:?}", token.amount(staking), token.amount(leftover)); + }); + } + #[tokio::test] #[ignore = "this test is meant to be executed manually"] async fn try_fast_unstake_all() { diff --git a/relay/kusama/src/weights/mod.rs b/relay/kusama/src/weights/mod.rs index 21d376bcce..263e2e1c6d 100644 --- a/relay/kusama/src/weights/mod.rs +++ b/relay/kusama/src/weights/mod.rs @@ -31,6 +31,7 @@ pub mod pallet_message_queue; pub mod pallet_multisig; pub mod pallet_nis; pub mod pallet_nomination_pools; +pub mod pallet_parameters; pub mod pallet_preimage; pub mod pallet_proxy; pub mod pallet_ranked_collective; diff --git a/relay/kusama/src/weights/pallet_parameters.rs b/relay/kusama/src/weights/pallet_parameters.rs new file mode 100644 index 0000000000..a393c8de68 --- /dev/null +++ b/relay/kusama/src/weights/pallet_parameters.rs @@ -0,0 +1,51 @@ +// Copyright (C) Parity Technologies and the various Polkadot contributors, see Contributions.md +// for a list of specific contributors. +// SPDX-License-Identifier: Apache-2.0 + +//! Autogenerated weights for `pallet_parameters` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-04-05, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("kusama-dev")`, DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_parameters +// --chain=kusama-dev +// --header=./polkadot/file_header.txt +// --output=./polkadot/runtime/kusama/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_parameters`. +pub struct WeightInfo(PhantomData); +impl pallet_parameters::WeightInfo for WeightInfo { + /// Storage: `Parameters::Parameters` (r:1 w:1) + /// Proof: `Parameters::Parameters` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + fn set_parameter() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `3493` + // Minimum execution time: 6_937_000 picoseconds. + Weight::from_parts(7_242_000, 0) + .saturating_add(Weight::from_parts(0, 3493)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +}