diff --git a/Cargo.lock b/Cargo.lock index 88fc8ff7e..316ec2e47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14118,6 +14118,7 @@ dependencies = [ "scale-info", "smallvec 1.11.0", "sp-api", + "sp-arithmetic", "sp-block-builder", "sp-consensus-aura", "sp-core", diff --git a/pallets/dapp-staking-migration/src/mock.rs b/pallets/dapp-staking-migration/src/mock.rs index e7169c153..6132a73d5 100644 --- a/pallets/dapp-staking-migration/src/mock.rs +++ b/pallets/dapp-staking-migration/src/mock.rs @@ -33,7 +33,7 @@ use sp_runtime::{ }; use astar_primitives::{ - dapp_staking::{CycleConfiguration, SmartContract, StakingRewardHandler}, + dapp_staking::{CycleConfiguration, SmartContract, StakingRewardHandler, StandardTierSlots}, oracle::PriceProvider, Balance, BlockNumber, }; @@ -180,6 +180,7 @@ impl pallet_dapp_staking_v3::Config for Test { type CycleConfiguration = DummyCycleConfiguration; type Observers = (); type AccountCheck = (); + type TierSlots = StandardTierSlots; type EraRewardSpanLength = ConstU32<8>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<10>; diff --git a/pallets/dapp-staking-v3/src/benchmarking/utils.rs b/pallets/dapp-staking-v3/src/benchmarking/utils.rs index 5d520d276..7e85e6ff8 100644 --- a/pallets/dapp-staking-v3/src/benchmarking/utils.rs +++ b/pallets/dapp-staking-v3/src/benchmarking/utils.rs @@ -191,11 +191,12 @@ pub(super) fn initial_config() { }; // Init tier config, based on the initial params - let init_tier_config = TiersConfiguration:: { + let init_tier_config = TiersConfiguration:: { number_of_slots: NUMBER_OF_SLOTS.try_into().unwrap(), slots_per_tier: BoundedVec::try_from(vec![10, 20, 30, 40]).unwrap(), reward_portion: tier_params.reward_portion.clone(), tier_thresholds: tier_params.tier_thresholds.clone(), + _phantom: Default::default(), }; assert!(tier_params.is_valid()); diff --git a/pallets/dapp-staking-v3/src/lib.rs b/pallets/dapp-staking-v3/src/lib.rs index ad42055cd..430a98bb5 100644 --- a/pallets/dapp-staking-v3/src/lib.rs +++ b/pallets/dapp-staking-v3/src/lib.rs @@ -39,7 +39,7 @@ use frame_support::{ pallet_prelude::*, traits::{ fungible::{Inspect as FunInspect, MutateFreeze as FunMutateFreeze}, - OnRuntimeUpgrade, StorageVersion, + StorageVersion, }, weights::Weight, }; @@ -53,7 +53,7 @@ pub use sp_std::vec::Vec; use astar_primitives::{ dapp_staking::{ AccountCheck, CycleConfiguration, DAppId, EraNumber, Observer as DAppStakingObserver, - PeriodNumber, SmartContractHandle, StakingRewardHandler, TierId, + PeriodNumber, SmartContractHandle, StakingRewardHandler, TierId, TierSlots as TierSlotFunc, }, oracle::PriceProvider, Balance, BlockNumber, @@ -70,8 +70,6 @@ mod benchmarking; mod types; pub use types::*; -pub mod migrations; - pub mod weights; pub use weights::WeightInfo; @@ -147,6 +145,9 @@ pub mod pallet { /// Used to check whether an account is allowed to participate in dApp staking. type AccountCheck: AccountCheck; + /// Used to calculate total number of tier slots for some price. + type TierSlots: TierSlotFunc; + /// Maximum length of a single era reward span length entry. #[pallet::constant] type EraRewardSpanLength: Get; @@ -446,7 +447,7 @@ pub mod pallet { /// Tier configuration user for current & preceding eras. #[pallet::storage] pub type TierConfig = - StorageValue<_, TiersConfiguration, ValueQuery>; + StorageValue<_, TiersConfiguration, ValueQuery>; /// Information about which tier a dApp belonged to in a specific era. #[pallet::storage] @@ -506,7 +507,7 @@ pub mod pallet { let number_of_slots = self.slots_per_tier.iter().fold(0_u16, |acc, &slots| { acc.checked_add(slots).expect("Overflow") }); - let tier_config = TiersConfiguration:: { + let tier_config = TiersConfiguration:: { number_of_slots, slots_per_tier: BoundedVec::::try_from( self.slots_per_tier.clone(), @@ -514,6 +515,7 @@ pub mod pallet { .expect("Invalid number of slots per tier entries provided."), reward_portion: tier_params.reward_portion.clone(), tier_thresholds: tier_params.tier_thresholds.clone(), + _phantom: Default::default(), }; assert!( tier_params.is_valid(), diff --git a/pallets/dapp-staking-v3/src/migrations.rs b/pallets/dapp-staking-v3/src/migrations.rs deleted file mode 100644 index 47505c70e..000000000 --- a/pallets/dapp-staking-v3/src/migrations.rs +++ /dev/null @@ -1,129 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar 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. - -// Astar 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 Astar. If not, see . - -use super::*; -use sp_arithmetic::fixed_point::FixedU64; - -/// `OnRuntimeUpgrade` logic used to set & configure init dApp staking v3 storage items. -pub struct DAppStakingV3InitConfig(PhantomData<(T, G, P)>); -impl< - T: Config, - G: Get<( - EraNumber, - TierParameters, - TiersConfiguration, - )>, - P: Get, - > OnRuntimeUpgrade for DAppStakingV3InitConfig -{ - fn on_runtime_upgrade() -> Weight { - if Pallet::::on_chain_storage_version() >= STORAGE_VERSION { - return T::DbWeight::get().reads(1); - } - - // 0. Unwrap arguments - let (init_era, tier_params, base_tier_config) = G::get(); - - // 1. Prepare init active protocol state - let now = frame_system::Pallet::::block_number(); - let voting_period_length = Pallet::::blocks_per_voting_period(); - - let period_number = 1; - let protocol_state = ProtocolState { - era: init_era, - next_era_start: now - .saturating_add(voting_period_length.into()) - .saturated_into(), - period_info: PeriodInfo { - number: period_number, - subperiod: Subperiod::Voting, - next_subperiod_start_era: init_era.saturating_add(1), - }, - maintenance: true, - }; - - // 2. Prepare init current era info - need to set correct eras - let init_era_info = EraInfo { - total_locked: 0, - unlocking: 0, - current_stake_amount: StakeAmount { - voting: 0, - build_and_earn: 0, - era: init_era, - period: period_number, - }, - next_stake_amount: StakeAmount { - voting: 0, - build_and_earn: 0, - era: init_era.saturating_add(1), - period: period_number, - }, - }; - - let average_price = P::get(); - let init_tier_config = base_tier_config.calculate_new(average_price, &tier_params); - - // 3. Write necessary items into storage - ActiveProtocolState::::put(protocol_state); - StaticTierParams::::put(tier_params); - TierConfig::::put(init_tier_config); - STORAGE_VERSION.put::>(); - CurrentEraInfo::::put(init_era_info); - - // 4. Emit events to make indexers happy - Pallet::::deposit_event(Event::::NewEra { era: init_era }); - Pallet::::deposit_event(Event::::NewSubperiod { - subperiod: Subperiod::Voting, - number: 1, - }); - - log::info!("dApp Staking v3 storage initialized."); - - T::DbWeight::get().reads_writes(2, 5) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { - assert_eq!(Pallet::::on_chain_storage_version(), STORAGE_VERSION); - let protocol_state = ActiveProtocolState::::get(); - assert!(protocol_state.maintenance); - - let number_of_tiers = T::NumberOfTiers::get(); - - let tier_params = StaticTierParams::::get(); - assert_eq!(tier_params.reward_portion.len(), number_of_tiers as usize); - assert!(tier_params.is_valid()); - - let tier_config = TierConfig::::get(); - assert_eq!(tier_config.reward_portion.len(), number_of_tiers as usize); - assert_eq!(tier_config.slots_per_tier.len(), number_of_tiers as usize); - assert_eq!(tier_config.tier_thresholds.len(), number_of_tiers as usize); - - let current_era_info = CurrentEraInfo::::get(); - assert_eq!( - current_era_info.current_stake_amount.era, - protocol_state.era - ); - assert_eq!( - current_era_info.next_stake_amount.era, - protocol_state.era + 1 - ); - - Ok(()) - } -} diff --git a/pallets/dapp-staking-v3/src/test/mock.rs b/pallets/dapp-staking-v3/src/test/mock.rs index 234aa7d87..a13ee7606 100644 --- a/pallets/dapp-staking-v3/src/test/mock.rs +++ b/pallets/dapp-staking-v3/src/test/mock.rs @@ -37,7 +37,8 @@ use sp_runtime::{ use sp_std::cell::RefCell; use astar_primitives::{ - dapp_staking::{Observer as DappStakingObserver, SmartContract}, + dapp_staking::{Observer as DappStakingObserver, SmartContract, StandardTierSlots}, + testing::Header, Balance, BlockNumber, }; @@ -204,6 +205,7 @@ impl pallet_dapp_staking::Config for Test { type CycleConfiguration = DummyCycleConfiguration; type Observers = DummyDappStakingObserver; type AccountCheck = DummyAccountCheck; + type TierSlots = StandardTierSlots; type EraRewardSpanLength = ConstU32<8>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<10>; @@ -309,11 +311,15 @@ impl ExtBuilder { }; // Init tier config, based on the initial params - let init_tier_config = TiersConfiguration::<::NumberOfTiers> { + let init_tier_config = TiersConfiguration::< + ::NumberOfTiers, + ::TierSlots, + > { number_of_slots: 40, slots_per_tier: BoundedVec::try_from(vec![2, 5, 13, 20]).unwrap(), reward_portion: tier_params.reward_portion.clone(), tier_thresholds: tier_params.tier_thresholds.clone(), + _phantom: Default::default(), }; pallet_dapp_staking::StaticTierParams::::put(tier_params); diff --git a/pallets/dapp-staking-v3/src/test/tests_types.rs b/pallets/dapp-staking-v3/src/test/tests_types.rs index 64da02a23..8eda247f2 100644 --- a/pallets/dapp-staking-v3/src/test/tests_types.rs +++ b/pallets/dapp-staking-v3/src/test/tests_types.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with Astar. If not, see . -use astar_primitives::Balance; +use astar_primitives::{dapp_staking::StandardTierSlots, Balance}; use frame_support::assert_ok; use sp_arithmetic::fixed_point::FixedU64; use sp_runtime::Permill; @@ -2732,11 +2732,12 @@ fn tier_configuration_basic_tests() { assert!(params.is_valid(), "Example params must be valid!"); // Create a configuration with some values - let init_config = TiersConfiguration:: { + let init_config = TiersConfiguration:: { number_of_slots: 100, slots_per_tier: BoundedVec::try_from(vec![10, 20, 30, 40]).unwrap(), reward_portion: params.reward_portion.clone(), tier_thresholds: params.tier_thresholds.clone(), + _phantom: Default::default(), }; assert!(init_config.is_valid(), "Init config must be valid!"); diff --git a/pallets/dapp-staking-v3/src/types.rs b/pallets/dapp-staking-v3/src/types.rs index e85061ff3..bb6149fed 100644 --- a/pallets/dapp-staking-v3/src/types.rs +++ b/pallets/dapp-staking-v3/src/types.rs @@ -75,7 +75,7 @@ use sp_runtime::{ pub use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, vec::Vec}; use astar_primitives::{ - dapp_staking::{DAppId, EraNumber, PeriodNumber, TierId}, + dapp_staking::{DAppId, EraNumber, PeriodNumber, TierId, TierSlots as TierSlotsFunc}, Balance, BlockNumber, }; @@ -1485,8 +1485,8 @@ impl> Default for TierParameters { CloneNoBound, TypeInfo, )] -#[scale_info(skip_type_params(NT))] -pub struct TiersConfiguration> { +#[scale_info(skip_type_params(NT, T))] +pub struct TiersConfiguration, T: TierSlotsFunc> { /// Total number of slots. #[codec(compact)] pub number_of_slots: u16, @@ -1500,15 +1500,19 @@ pub struct TiersConfiguration> { /// Requirements for entry into each tier. /// First entry refers to the first tier, and so on. pub tier_thresholds: BoundedVec, + /// Phantom data to keep track of the tier slots function. + #[codec(skip)] + pub(crate) _phantom: PhantomData, } -impl> Default for TiersConfiguration { +impl, T: TierSlotsFunc> Default for TiersConfiguration { fn default() -> Self { Self { number_of_slots: 0, slots_per_tier: BoundedVec::default(), reward_portion: BoundedVec::default(), tier_thresholds: BoundedVec::default(), + _phantom: Default::default(), } } } @@ -1518,7 +1522,7 @@ impl> Default for TiersConfiguration { // * There's no need to keep thresholds in two separate storage items since the calculation can always be done compared to the // anchor value of 5 cents. This still needs to be checked & investigated, but it's worth a try. -impl> TiersConfiguration { +impl, T: TierSlotsFunc> TiersConfiguration { /// Check if parameters are valid. pub fn is_valid(&self) -> bool { let number_of_tiers: usize = NT::get() as usize; @@ -1533,7 +1537,7 @@ impl> TiersConfiguration { /// Calculate new `TiersConfiguration`, based on the old settings, current native currency price and tier configuration. pub fn calculate_new(&self, native_price: FixedU64, params: &TierParameters) -> Self { // It must always be at least 1 slot. - let new_number_of_slots = Self::calculate_number_of_slots(native_price).max(1); + let new_number_of_slots = T::number_of_slots(native_price).max(1); // Calculate how much each tier gets slots. let new_slots_per_tier: Vec = params @@ -1621,16 +1625,9 @@ impl> TiersConfiguration { slots_per_tier: new_slots_per_tier, reward_portion: params.reward_portion.clone(), tier_thresholds: new_tier_thresholds, + _phantom: Default::default(), } } - - /// Calculate number of slots, based on the provided native token price. - pub fn calculate_number_of_slots(native_price: FixedU64) -> u16 { - // floor(1000 x price + 50), formula proposed in Tokenomics 2.0 document. - let result: u64 = native_price.saturating_mul_int(1000).saturating_add(50); - - result.unique_saturated_into() - } } /// Information about all of the dApps that got into tiers, and tier rewards diff --git a/precompiles/dapp-staking-v3/src/test/mock.rs b/precompiles/dapp-staking-v3/src/test/mock.rs index c4c89c340..b15dfc514 100644 --- a/precompiles/dapp-staking-v3/src/test/mock.rs +++ b/precompiles/dapp-staking-v3/src/test/mock.rs @@ -43,6 +43,7 @@ extern crate alloc; use astar_primitives::{ dapp_staking::{ CycleConfiguration, EraNumber, PeriodNumber, SmartContract, StakingRewardHandler, + StandardTierSlots, }, oracle::PriceProvider, AccountId, Balance, BlockNumber, @@ -253,6 +254,7 @@ impl pallet_dapp_staking_v3::Config for Test { type CycleConfiguration = DummyCycleConfiguration; type Observers = (); type AccountCheck = (); + type TierSlots = StandardTierSlots; type EraRewardSpanLength = ConstU32<8>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<10>; diff --git a/primitives/src/dapp_staking.rs b/primitives/src/dapp_staking.rs index 53efb6ec6..282be8494 100644 --- a/primitives/src/dapp_staking.rs +++ b/primitives/src/dapp_staking.rs @@ -21,7 +21,9 @@ use super::{Balance, BlockNumber}; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use frame_support::pallet_prelude::{RuntimeDebug, Weight}; +use sp_arithmetic::fixed_point::FixedU64; use sp_core::H160; +use sp_runtime::{traits::UniqueSaturatedInto, FixedPointNumber}; use sp_std::hash::Hash; /// Era number type @@ -182,3 +184,18 @@ impl AccountCheck for () { true } } + +/// Trait for calculating the total number of tier slots for the given price. +pub trait TierSlots { + /// Returns the total number of tier slots for the given price. + fn number_of_slots(price: FixedU64) -> u16; +} + +/// Standard tier slots implementation, as proposed in the Tokenomics 2.0 document. +pub struct StandardTierSlots; +impl TierSlots for StandardTierSlots { + fn number_of_slots(price: FixedU64) -> u16 { + let result: u64 = price.saturating_mul_int(1000_u64).saturating_add(50); + result.unique_saturated_into() + } +} diff --git a/runtime/astar/src/lib.rs b/runtime/astar/src/lib.rs index f666aa252..0e8a8a353 100644 --- a/runtime/astar/src/lib.rs +++ b/runtime/astar/src/lib.rs @@ -69,7 +69,7 @@ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; use astar_primitives::{ dapp_staking::{ AccountCheck as DappStakingAccountCheck, CycleConfiguration, DAppId, EraNumber, - PeriodNumber, SmartContract, TierId, + PeriodNumber, SmartContract, StandardTierSlots, TierId, }, evm::EvmRevertCodeHandler, xcm::AssetLocationIdConverter, @@ -396,6 +396,7 @@ impl pallet_dapp_staking_v3::Config for Runtime { type CycleConfiguration = InflationCycleConfig; type Observers = Inflation; type AccountCheck = AccountCheck; + type TierSlots = StandardTierSlots; type EraRewardSpanLength = ConstU32<16>; type RewardRetentionInPeriods = ConstU32<4>; type MaxNumberOfContracts = ConstU32<500>; diff --git a/runtime/local/src/lib.rs b/runtime/local/src/lib.rs index 741cd4383..c5deca814 100644 --- a/runtime/local/src/lib.rs +++ b/runtime/local/src/lib.rs @@ -61,7 +61,10 @@ use sp_runtime::{ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; use astar_primitives::{ - dapp_staking::{CycleConfiguration, DAppId, EraNumber, PeriodNumber, SmartContract, TierId}, + dapp_staking::{ + CycleConfiguration, DAppId, EraNumber, PeriodNumber, SmartContract, StandardTierSlots, + TierId, + }, evm::{EvmRevertCodeHandler, HashedDefaultMappings}, Address, AssetId, Balance, BlockNumber, Hash, Header, Nonce, }; @@ -518,6 +521,7 @@ impl pallet_dapp_staking_v3::Config for Runtime { type CycleConfiguration = InflationCycleConfig; type Observers = Inflation; type AccountCheck = (); + type TierSlots = StandardTierSlots; type EraRewardSpanLength = ConstU32<8>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<100>; diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index d6f5ce057..5218a771e 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -69,7 +69,7 @@ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; use astar_primitives::{ dapp_staking::{ AccountCheck as DappStakingAccountCheck, CycleConfiguration, DAppId, EraNumber, - PeriodNumber, SmartContract, TierId, + PeriodNumber, SmartContract, StandardTierSlots, TierId, }, evm::{EvmRevertCodeHandler, HashedDefaultMappings}, xcm::AssetLocationIdConverter, @@ -427,6 +427,7 @@ impl pallet_dapp_staking_v3::Config for Runtime { type CycleConfiguration = InflationCycleConfig; type Observers = Inflation; type AccountCheck = AccountCheck; + type TierSlots = StandardTierSlots; type EraRewardSpanLength = ConstU32<16>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<500>; diff --git a/runtime/shiden/Cargo.toml b/runtime/shiden/Cargo.toml index 7ea060c12..d335b30e3 100644 --- a/runtime/shiden/Cargo.toml +++ b/runtime/shiden/Cargo.toml @@ -21,6 +21,7 @@ fp-rpc = { workspace = true } fp-self-contained = { workspace = true } sp-api = { workspace = true } +sp-arithmetic = { workspace = true } sp-block-builder = { workspace = true } sp-consensus-aura = { workspace = true } sp-core = { workspace = true } @@ -138,6 +139,7 @@ std = [ "sp-consensus-aura/std", "sp-io/std", "sp-runtime/std", + "sp-arithmetic/std", "pallet-static-price-provider/std", "sp-runtime-interface/std", "sp-version/std", diff --git a/runtime/shiden/src/lib.rs b/runtime/shiden/src/lib.rs index 560afa2eb..d6779e2ab 100644 --- a/runtime/shiden/src/lib.rs +++ b/runtime/shiden/src/lib.rs @@ -52,6 +52,7 @@ use pallet_transaction_payment::{ use parity_scale_codec::{Compact, Decode, Encode, MaxEncodedLen}; use polkadot_runtime_common::BlockHashCount; use sp_api::impl_runtime_apis; +use sp_arithmetic::fixed_point::FixedU64; use sp_core::{ConstBool, OpaqueMetadata, H160, H256, U256}; use sp_inherents::{CheckInherentsResult, InherentData}; use sp_runtime::{ @@ -68,7 +69,7 @@ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; use astar_primitives::{ dapp_staking::{ AccountCheck as DappStakingAccountCheck, CycleConfiguration, DAppId, EraNumber, - PeriodNumber, SmartContract, TierId, + PeriodNumber, SmartContract, TierId, TierSlots as TierSlotsFunc, }, evm::EvmRevertCodeHandler, xcm::AssetLocationIdConverter, @@ -352,6 +353,15 @@ impl DappStakingAccountCheck for AccountCheck { } } +pub struct ShidenTierSlots; +impl TierSlotsFunc for ShidenTierSlots { + fn number_of_slots(price: FixedU64) -> u16 { + // According to the forum proposal, the original formula's factor is reduced from 1000x to 100x. + let result: u64 = price.saturating_mul_int(100_u64).saturating_add(50); + result.unique_saturated_into() + } +} + parameter_types! { pub const MinimumStakingAmount: Balance = 50 * SDN; } @@ -367,6 +377,7 @@ impl pallet_dapp_staking_v3::Config for Runtime { type CycleConfiguration = InflationCycleConfig; type Observers = Inflation; type AccountCheck = AccountCheck; + type TierSlots = ShidenTierSlots; type EraRewardSpanLength = ConstU32<16>; type RewardRetentionInPeriods = ConstU32<3>; type MaxNumberOfContracts = ConstU32<500>; @@ -1112,14 +1123,8 @@ parameter_types! { /// /// Once done, migrations should be removed from the tuple. pub type Migrations = ( - // Part of shiden-119 - frame_support::migrations::RemovePallet< - DappStakingMigrationName, - ::DbWeight, - >, - // Part of shiden-119 - RecalculationEraFix, - pallet_contracts::Migration, + // Part of shiden-121 (added after v5.33.0 release) + SetNewTierConfig, ); use frame_support::traits::OnRuntimeUpgrade; @@ -1139,6 +1144,38 @@ impl OnRuntimeUpgrade for RecalculationEraFix { } } +pub struct SetNewTierConfig; +impl OnRuntimeUpgrade for SetNewTierConfig { + fn on_runtime_upgrade() -> Weight { + use astar_primitives::oracle::PriceProvider; + use frame_support::BoundedVec; + + // Set new init tier config values according to the forum post + let mut init_tier_config = pallet_dapp_staking_v3::TierConfig::::get(); + init_tier_config.number_of_slots = 55; + init_tier_config.slots_per_tier = + BoundedVec::try_from(vec![2, 11, 16, 24]).unwrap_or_default(); + + #[cfg(feature = "try-runtime")] + { + assert!( + init_tier_config.number_of_slots >= init_tier_config.slots_per_tier.iter().sum::() as u16, + "Safety check, sum of slots per tier must be equal or less than max number of slots (due to possible rounding)" + ); + } + + // Based on the new init config, calculate the new tier config based on the 'average' price + let price = StaticPriceProvider::average_price(); + let tier_params = pallet_dapp_staking_v3::StaticTierParams::::get(); + + let new_tier_config = init_tier_config.calculate_new(price, &tier_params); + + pallet_dapp_staking_v3::TierConfig::::put(new_tier_config); + + ::DbWeight::get().reads_writes(3, 1) + } +} + type EventRecord = frame_system::EventRecord< ::RuntimeEvent, ::Hash,