diff --git a/Cargo.lock b/Cargo.lock index aed6afc6ae..08ac5ad095 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2439,7 +2439,6 @@ name = "dapp-staking-v3-runtime-api" version = "0.0.1-alpha" dependencies = [ "astar-primitives", - "pallet-dapp-staking-v3", "sp-api", "sp-std", ] @@ -4973,6 +4972,7 @@ dependencies = [ "pallet-evm", "pallet-evm-precompile-assets-erc20", "pallet-evm-precompile-dispatch", + "pallet-inflation", "pallet-proxy", "pallet-unified-accounts", "pallet-utility", diff --git a/chain-extensions/pallet-assets/Cargo.toml b/chain-extensions/pallet-assets/Cargo.toml index 72c69bb32a..0bd86ecf95 100644 --- a/chain-extensions/pallet-assets/Cargo.toml +++ b/chain-extensions/pallet-assets/Cargo.toml @@ -46,3 +46,5 @@ std = [ "assets-chain-extension-types/std", "pallet-balances/std", ] +try-runtime = ["frame-support/try-runtime"] +runtime-benchmarks = ["pallet-assets/runtime-benchmarks"] diff --git a/chain-extensions/pallet-assets/src/mock.rs b/chain-extensions/pallet-assets/src/mock.rs index 1ba7a0b8ce..61ae25c4dd 100644 --- a/chain-extensions/pallet-assets/src/mock.rs +++ b/chain-extensions/pallet-assets/src/mock.rs @@ -158,6 +158,8 @@ impl pallet_assets::Config for Test { type CallbackHandle = (); type Extra = (); type RemoveItemsLimit = ConstU32<5>; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; diff --git a/pallets/dapp-staking-migration/src/mock.rs b/pallets/dapp-staking-migration/src/mock.rs index 5da78a43e0..5870641184 100644 --- a/pallets/dapp-staking-migration/src/mock.rs +++ b/pallets/dapp-staking-migration/src/mock.rs @@ -181,6 +181,7 @@ impl pallet_dapp_staking_v3::Config for Test { type NativePriceProvider = DummyPriceProvider; type StakingRewardHandler = DummyStakingRewardHandler; type CycleConfiguration = DummyCycleConfiguration; + type Observers = (); type EraRewardSpanLength = ConstU32<8>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<10>; diff --git a/pallets/dapp-staking-v3/rpc/runtime-api/Cargo.toml b/pallets/dapp-staking-v3/rpc/runtime-api/Cargo.toml index 63ef539a0c..244715aa13 100644 --- a/pallets/dapp-staking-v3/rpc/runtime-api/Cargo.toml +++ b/pallets/dapp-staking-v3/rpc/runtime-api/Cargo.toml @@ -15,13 +15,11 @@ sp-api = { workspace = true } sp-std = { workspace = true } astar-primitives = { workspace = true } -pallet-dapp-staking-v3 = { workspace = true } [features] default = ["std"] std = [ "sp-api/std", "sp-std/std", - "pallet-dapp-staking-v3/std", "astar-primitives/std", ] diff --git a/pallets/dapp-staking-v3/rpc/runtime-api/src/lib.rs b/pallets/dapp-staking-v3/rpc/runtime-api/src/lib.rs index d829e2b275..d08c2379ea 100644 --- a/pallets/dapp-staking-v3/rpc/runtime-api/src/lib.rs +++ b/pallets/dapp-staking-v3/rpc/runtime-api/src/lib.rs @@ -18,8 +18,8 @@ #![cfg_attr(not(feature = "std"), no_std)] +use astar_primitives::dapp_staking::{DAppId, EraNumber, PeriodNumber, TierId}; use astar_primitives::BlockNumber; -use pallet_dapp_staking_v3::{DAppId, EraNumber, PeriodNumber, TierId}; pub use sp_std::collections::btree_map::BTreeMap; sp_api::decl_runtime_apis! { diff --git a/pallets/dapp-staking-v3/src/lib.rs b/pallets/dapp-staking-v3/src/lib.rs index d2160aa86d..7525370f4d 100644 --- a/pallets/dapp-staking-v3/src/lib.rs +++ b/pallets/dapp-staking-v3/src/lib.rs @@ -51,7 +51,10 @@ use sp_runtime::{ pub use sp_std::vec::Vec; use astar_primitives::{ - dapp_staking::{CycleConfiguration, SmartContractHandle, StakingRewardHandler}, + dapp_staking::{ + CycleConfiguration, DAppId, EraNumber, Observer as DAppStakingObserver, PeriodNumber, + SmartContractHandle, StakingRewardHandler, TierId, + }, oracle::PriceProvider, Balance, BlockNumber, }; @@ -138,6 +141,9 @@ pub mod pallet { /// Describes era length, subperiods & period length, as well as cycle length. type CycleConfiguration: CycleConfiguration; + /// dApp staking event observers, notified when certain events occur. + type Observers: DAppStakingObserver; + /// Maximum length of a single era reward span length entry. #[pallet::constant] type EraRewardSpanLength: Get; @@ -1490,16 +1496,12 @@ pub mod pallet { .into()) } - // TODO: this call should be removed prior to mainnet launch. - // It's super useful for testing purposes, but even though force is used in this pallet & works well, - // it won't apply to the inflation recalculation logic - which is wrong. - // Probably for this call to make sense, an outside logic should handle both inflation & dApp staking state changes. - + // TODO: make this unavailable in production, to be only used for testing /// Used to force a change of era or subperiod. /// The effect isn't immediate but will happen on the next block. /// /// Used for testing purposes, when we want to force an era change, or a subperiod change. - /// Not intended to be used in production, except in case of unforseen circumstances. + /// Not intended to be used in production, except in case of unforeseen circumstances. /// /// Can only be called by manager origin. #[pallet::call_index(18)] @@ -1519,6 +1521,12 @@ pub mod pallet { state.period_info.next_subperiod_start_era = state.era.saturating_add(1); } } + + // Right now it won't account for the full weight incurred by calling this notification. + // It's not a big problem since this call is not expected to be called ever in production. + // Also, in case of subperiod forcing, the alignment will be broken but since this is only call for testing, + // we don't need to concern ourselves with it. + Self::notify_block_before_new_era(&state); }); Self::deposit_event(Event::::Force { forcing_type }); @@ -1787,6 +1795,12 @@ pub mod pallet { return consumed_weight; } + // Inform observers about the upcoming new era, if it's the case. + if protocol_state.next_era_start == now.saturating_add(1) { + consumed_weight + .saturating_accrue(Self::notify_block_before_new_era(&protocol_state)); + } + // Nothing to do if it's not new era if !protocol_state.is_new_era(now) { return consumed_weight; @@ -1943,6 +1957,12 @@ pub mod pallet { consumed_weight } + /// Used to notify observers about the upcoming new era in the next block. + fn notify_block_before_new_era(protocol_state: &ProtocolState) -> Weight { + let next_era = protocol_state.era.saturating_add(1); + T::Observers::block_before_new_era(next_era) + } + /// Attempt to cleanup some expired entries, if enough remaining weight & applicable entries exist. /// /// Returns consumed weight. diff --git a/pallets/dapp-staking-v3/src/test/mock.rs b/pallets/dapp-staking-v3/src/test/mock.rs index 247605e456..1be4b46eab 100644 --- a/pallets/dapp-staking-v3/src/test/mock.rs +++ b/pallets/dapp-staking-v3/src/test/mock.rs @@ -36,7 +36,11 @@ use sp_runtime::{ }; use sp_std::cell::RefCell; -use astar_primitives::{dapp_staking::SmartContract, testing::Header, Balance, BlockNumber}; +use astar_primitives::{ + dapp_staking::{Observer as DappStakingObserver, SmartContract}, + testing::Header, + Balance, BlockNumber, +}; pub(crate) type AccountId = u64; @@ -117,6 +121,7 @@ impl PriceProvider for DummyPriceProvider { thread_local! { pub(crate) static DOES_PAYOUT_SUCCEED: RefCell = RefCell::new(false); + pub(crate) static BLOCK_BEFORE_NEW_ERA: RefCell = RefCell::new(0); } pub struct DummyStakingRewardHandler; @@ -180,6 +185,14 @@ impl CycleConfiguration for DummyCycleConfiguration { } } +pub struct DummyDappStakingObserver; +impl DappStakingObserver for DummyDappStakingObserver { + fn block_before_new_era(next_era: EraNumber) -> Weight { + BLOCK_BEFORE_NEW_ERA.with(|v| *v.borrow_mut() = next_era); + Weight::from_parts(1, 2) + } +} + impl pallet_dapp_staking::Config for Test { type RuntimeEvent = RuntimeEvent; type RuntimeFreezeReason = RuntimeFreezeReason; @@ -189,6 +202,7 @@ impl pallet_dapp_staking::Config for Test { type NativePriceProvider = DummyPriceProvider; type StakingRewardHandler = DummyStakingRewardHandler; type CycleConfiguration = DummyCycleConfiguration; + type Observers = DummyDappStakingObserver; type EraRewardSpanLength = ConstU32<8>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<10>; diff --git a/pallets/dapp-staking-v3/src/test/testing_utils.rs b/pallets/dapp-staking-v3/src/test/testing_utils.rs index 83972f376b..1d03a8a4d0 100644 --- a/pallets/dapp-staking-v3/src/test/testing_utils.rs +++ b/pallets/dapp-staking-v3/src/test/testing_utils.rs @@ -32,7 +32,10 @@ use frame_support::{ use sp_runtime::{traits::Zero, Perbill}; use std::collections::HashMap; -use astar_primitives::{dapp_staking::CycleConfiguration, Balance, BlockNumber}; +use astar_primitives::{ + dapp_staking::{CycleConfiguration, EraNumber, PeriodNumber}, + Balance, BlockNumber, +}; /// Helper struct used to store the entire pallet state snapshot. /// Used when comparison of before/after states is required. @@ -700,9 +703,14 @@ pub(crate) fn assert_unstake( ); let is_loyal = pre_staker_info.is_loyal() - && !(unstake_subperiod == Subperiod::BuildAndEarn - && post_staker_info.staked_amount(Subperiod::Voting) - < pre_staker_info.staked_amount(Subperiod::Voting)); + && match unstake_subperiod { + Subperiod::Voting => !post_staker_info.staked_amount(Subperiod::Voting).is_zero(), + Subperiod::BuildAndEarn => { + post_staker_info.staked_amount(Subperiod::Voting) + == pre_staker_info.staked_amount(Subperiod::Voting) + } + }; + assert_eq!( post_staker_info.is_loyal(), is_loyal, @@ -779,7 +787,7 @@ pub(crate) fn assert_claim_staker_rewards(account: AccountId) { .earliest_staked_era() .expect("Entry must exist, otherwise 'claim' is invalid."); - // Get the apprropriate era rewards span for the 'first era' + // Get the appropriate era rewards span for the 'first era' let era_span_length: EraNumber = ::EraRewardSpanLength::get(); let era_span_index = first_claim_era - (first_claim_era % era_span_length); let era_rewards_span = pre_snapshot diff --git a/pallets/dapp-staking-v3/src/test/tests.rs b/pallets/dapp-staking-v3/src/test/tests.rs index e3fae0dda9..3e409379a7 100644 --- a/pallets/dapp-staking-v3/src/test/tests.rs +++ b/pallets/dapp-staking-v3/src/test/tests.rs @@ -30,12 +30,12 @@ use frame_support::{ use sp_runtime::traits::Zero; use astar_primitives::{ - dapp_staking::{CycleConfiguration, SmartContractHandle}, + dapp_staking::{CycleConfiguration, EraNumber, SmartContractHandle}, Balance, BlockNumber, }; #[test] -fn maintenace_mode_works() { +fn maintenances_mode_works() { ExtBuilder::build().execute_with(|| { // Check that maintenance mode is disabled by default assert!(!ActiveProtocolState::::get().maintenance); @@ -63,7 +63,7 @@ fn maintenace_mode_works() { } #[test] -fn maintenace_mode_call_filtering_works() { +fn maintenance_mode_call_filtering_works() { ExtBuilder::build().execute_with(|| { // Enable maintenance mode & check post-state assert_ok!(DappStaking::maintenance_mode(RuntimeOrigin::root(), true)); @@ -237,7 +237,7 @@ fn on_initialize_base_state_change_works() { assert_eq!(protocol_state.era, era + 1); } - // Finaly advance over to the next era and ensure we're back to voting period + // Finally advance over to the next era and ensure we're back to voting period advance_to_next_era(); let protocol_state = ActiveProtocolState::::get(); assert_eq!(protocol_state.subperiod(), Subperiod::Voting); @@ -356,7 +356,7 @@ fn set_dapp_reward_beneficiary_fails() { Error::::ContractNotFound ); - // Non-owner cannnot change reward destination + // Non-owner cannot change reward destination assert_register(owner, &smart_contract); assert_noop!( DappStaking::set_dapp_reward_beneficiary( @@ -582,7 +582,7 @@ fn unlock_with_remaining_amount_below_threshold_is_ok() { } #[test] -fn unlock_with_amount_higher_than_avaiable_is_ok() { +fn unlock_with_amount_higher_than_available_is_ok() { ExtBuilder::build().execute_with(|| { // Lock some amount in a few eras let account = 2; @@ -720,7 +720,7 @@ fn unlock_with_exceeding_unlocking_chunks_storage_limits_fails() { #[test] fn withdraw_unbonded_is_ok() { ExtBuilder::build().execute_with(|| { - // Lock & immediatelly unlock some amount + // Lock & immediately unlock some amount let account = 2; let lock_amount = 97; let unlock_amount = 11; @@ -1523,7 +1523,7 @@ fn claim_staker_rewards_fails_due_to_payout_failure() { // Advance into Build&Earn period, and allow one era to pass. advance_to_era(ActiveProtocolState::::get().era + 2); - // Disable successfull reward payout + // Disable successful reward payout DOES_PAYOUT_SUCCEED.with(|v| *v.borrow_mut() = false); assert_noop!( DappStaking::claim_staker_rewards(RuntimeOrigin::signed(account)), @@ -1705,7 +1705,7 @@ fn claim_bonus_reward_fails_due_to_payout_failure() { // Advance to next period so we can claim bonus reward advance_to_next_period(); - // Disable successfull reward payout + // Disable successful reward payout DOES_PAYOUT_SUCCEED.with(|v| *v.borrow_mut() = false); assert_noop!( DappStaking::claim_bonus_reward(RuntimeOrigin::signed(account), smart_contract), @@ -1904,7 +1904,7 @@ fn claim_dapp_reward_fails_due_to_payout_failure() { // Advance 2 eras so we have an entry for reward claiming advance_to_era(ActiveProtocolState::::get().era + 2); - // Disable successfull reward payout + // Disable successful reward payout DOES_PAYOUT_SUCCEED.with(|v| *v.borrow_mut() = false); assert_noop!( DappStaking::claim_dapp_reward( @@ -2438,11 +2438,6 @@ fn advance_for_some_periods_works() { }) } -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////// -/////// More complex & composite scenarios, maybe move them into a separate file - #[test] fn unlock_after_staked_period_ends_is_ok() { ExtBuilder::build().execute_with(|| { @@ -2571,7 +2566,7 @@ fn stake_after_period_ends_with_max_staked_contracts() { } #[test] -fn post_unlock_balance_cannot_be_transfered() { +fn post_unlock_balance_cannot_be_transferred() { ExtBuilder::build().execute_with(|| { let staker = 2; @@ -2628,3 +2623,51 @@ fn post_unlock_balance_cannot_be_transfered() { assert!(Balances::free_balance(&staker).is_zero()); }) } + +#[test] +fn observer_pre_new_era_block_works() { + ExtBuilder::build().execute_with(|| { + fn assert_observer_value(expected: EraNumber) { + BLOCK_BEFORE_NEW_ERA.with(|v| assert_eq!(expected, *v.borrow())); + } + + // 1. Sanity check + assert_observer_value(0); + + // 2. Advance to the block right before the observer value should be set. + // No modifications should happen. + BLOCK_BEFORE_NEW_ERA.with(|v| { + let _lock = v.borrow(); + run_to_block(ActiveProtocolState::::get().next_era_start - 2); + }); + + // 3. Advance to the next block, when observer value is expected to be set to the next era. + run_for_blocks(1); + assert_observer_value(2); + + // 4. Advance again, until the same similar scenario + BLOCK_BEFORE_NEW_ERA.with(|v| { + let _lock = v.borrow(); + run_for_blocks(1); + assert_eq!( + ActiveProtocolState::::get().subperiod(), + Subperiod::BuildAndEarn, + "Sanity check." + ); + + run_to_block(ActiveProtocolState::::get().next_era_start - 2); + assert_eq!(ActiveProtocolState::::get().era, 2, "Sanity check."); + assert_observer_value(2); + }); + + // 5. Again, check that value is set to the expected one. + run_for_blocks(1); + assert_observer_value(3); + + // 6. Force new era, and ensure observer value is set to the next one. + run_for_blocks(1); + assert_eq!(ActiveProtocolState::::get().era, 3, "Sanity check."); + assert_ok!(DappStaking::force(RuntimeOrigin::root(), ForcingType::Era)); + assert_observer_value(4); + }) +} diff --git a/pallets/dapp-staking-v3/src/test/tests_types.rs b/pallets/dapp-staking-v3/src/test/tests_types.rs index 9d9a5d2e75..91d18964c5 100644 --- a/pallets/dapp-staking-v3/src/test/tests_types.rs +++ b/pallets/dapp-staking-v3/src/test/tests_types.rs @@ -382,7 +382,7 @@ fn account_ledger_staked_amount_for_type_works() { build_and_earn_1 ); - // Inocrrect period should simply return 0 + // Incorrect period should simply return 0 assert!(acc_ledger .staked_amount_for_type(Subperiod::Voting, period - 1) .is_zero()); @@ -816,7 +816,7 @@ fn account_ledger_add_stake_amount_too_large_amount_fails() { Err(AccountLedgerError::UnavailableStakeFunds) ); - // Additional check - have some active stake, and then try to overstake + // Additional check - have some active stake, and then try to stake more than available assert!(acc_ledger .add_stake_amount(lock_amount - 2, era_1, period_info_1) .is_ok()); @@ -2113,7 +2113,7 @@ fn singular_staking_info_unstake_during_voting_is_ok() { "Stake era should remain valid." ); - // Fully unstake, attempting to undersaturate, and ensure loyalty flag is still true. + // Fully unstake, attempting to underflow, and ensure loyalty flag has been removed. let era_2 = era_1 + 2; let remaining_stake = staking_info.total_staked_amount(); assert_eq!( @@ -2121,7 +2121,10 @@ fn singular_staking_info_unstake_during_voting_is_ok() { (remaining_stake, Balance::zero()) ); assert!(staking_info.total_staked_amount().is_zero()); - assert!(staking_info.is_loyal()); + assert!( + !staking_info.is_loyal(), + "Loyalty flag should have been removed since it was full unstake." + ); assert_eq!(staking_info.era(), era_2); } @@ -2507,7 +2510,7 @@ fn contract_stake_amount_unstake_is_ok() { ); assert!( contract_stake.staked_future.is_none(), - "future enry should remain 'None'" + "future entry should remain 'None'" ); // 4th scenario - do a full unstake with existing future entry, expect a cleanup diff --git a/pallets/dapp-staking-v3/src/types.rs b/pallets/dapp-staking-v3/src/types.rs index 1b88199a6b..5216a5b799 100644 --- a/pallets/dapp-staking-v3/src/types.rs +++ b/pallets/dapp-staking-v3/src/types.rs @@ -73,7 +73,10 @@ use sp_runtime::{ }; pub use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, vec::Vec}; -use astar_primitives::{Balance, BlockNumber}; +use astar_primitives::{ + dapp_staking::{DAppId, EraNumber, PeriodNumber, TierId}, + Balance, BlockNumber, +}; use crate::pallet::Config; @@ -90,15 +93,6 @@ pub type EraRewardSpanFor = EraRewardSpan<::EraRewardSpanLength> // Convenience type for `DAppInfo` usage. pub type DAppInfoFor = DAppInfo<::AccountId>; -/// Era number type -pub type EraNumber = u32; -/// Period number type -pub type PeriodNumber = u32; -/// Dapp Id type -pub type DAppId = u16; -/// Tier Id type -pub type TierId = u8; - /// Simple enum representing errors possible when using sparse bounded vector. #[derive(Debug, PartialEq, Eq)] pub enum AccountLedgerError { @@ -1051,8 +1045,10 @@ impl SingularStakingInfo { self.staked.era = self.staked.era.max(current_era); self.loyal_staker = self.loyal_staker - && (subperiod == Subperiod::Voting - || subperiod == Subperiod::BuildAndEarn && self.staked.voting == snapshot.voting); + && match subperiod { + Subperiod::Voting => !self.staked.voting.is_zero(), + Subperiod::BuildAndEarn => self.staked.voting == snapshot.voting, + }; // Amount that was unstaked ( diff --git a/pallets/dapp-staking-v3/src/weights.rs b/pallets/dapp-staking-v3/src/weights.rs index e98d798707..8c5c926f3c 100644 --- a/pallets/dapp-staking-v3/src/weights.rs +++ b/pallets/dapp-staking-v3/src/weights.rs @@ -20,9 +20,9 @@ //! Autogenerated weights for pallet_dapp_staking_v3 //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `devserver-01`, CPU: `Intel(R) Xeon(R) E-2236 CPU @ 3.40GHz` +//! HOSTNAME: `gh-runner-01-ovh`, CPU: `Intel(R) Xeon(R) E-2236 CPU @ 3.40GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("shibuya-dev"), DB CACHE: 1024 // Executed Command: @@ -81,8 +81,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_474_000 picoseconds. - Weight::from_parts(8_711_000, 0) + // Minimum execution time: 9_265_000 picoseconds. + Weight::from_parts(9_422_000, 0) } /// Storage: DappStaking IntegratedDApps (r:1 w:1) /// Proof: DappStaking IntegratedDApps (max_values: Some(65535), max_size: Some(121), added: 2101, mode: MaxEncodedLen) @@ -94,8 +94,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3091` - // Minimum execution time: 16_360_000 picoseconds. - Weight::from_parts(16_697_000, 3091) + // Minimum execution time: 17_285_000 picoseconds. + Weight::from_parts(17_628_000, 3091) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -105,8 +105,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `75` // Estimated: `3091` - // Minimum execution time: 12_927_000 picoseconds. - Weight::from_parts(13_229_000, 3091) + // Minimum execution time: 13_521_000 picoseconds. + Weight::from_parts(13_819_000, 3091) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -116,8 +116,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `75` // Estimated: `3091` - // Minimum execution time: 13_610_000 picoseconds. - Weight::from_parts(13_851_000, 3091) + // Minimum execution time: 13_797_000 picoseconds. + Weight::from_parts(14_051_000, 3091) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -129,8 +129,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `75` // Estimated: `3091` - // Minimum execution time: 16_704_000 picoseconds. - Weight::from_parts(16_952_000, 3091) + // Minimum execution time: 17_242_000 picoseconds. + Weight::from_parts(17_628_000, 3091) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -146,8 +146,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `12` // Estimated: `4764` - // Minimum execution time: 31_680_000 picoseconds. - Weight::from_parts(32_075_000, 4764) + // Minimum execution time: 32_138_000 picoseconds. + Weight::from_parts(32_677_000, 4764) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -163,8 +163,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `156` // Estimated: `4764` - // Minimum execution time: 34_576_000 picoseconds. - Weight::from_parts(34_777_000, 4764) + // Minimum execution time: 33_789_000 picoseconds. + Weight::from_parts(34_052_000, 4764) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -181,10 +181,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `187` // Estimated: `4764` - // Minimum execution time: 33_562_000 picoseconds. - Weight::from_parts(34_600_552, 4764) - // Standard Error: 5_079 - .saturating_add(Weight::from_parts(193_345, 0).saturating_mul(x.into())) + // Minimum execution time: 35_048_000 picoseconds. + Weight::from_parts(36_286_241, 4764) + // Standard Error: 6_246 + .saturating_add(Weight::from_parts(176_805, 0).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -200,8 +200,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `182` // Estimated: `4764` - // Minimum execution time: 36_436_000 picoseconds. - Weight::from_parts(37_262_000, 4764) + // Minimum execution time: 30_390_000 picoseconds. + Weight::from_parts(30_712_000, 4764) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -223,8 +223,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `250` // Estimated: `4764` - // Minimum execution time: 43_866_000 picoseconds. - Weight::from_parts(44_468_000, 4764) + // Minimum execution time: 44_866_000 picoseconds. + Weight::from_parts(45_342_000, 4764) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -246,8 +246,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `427` // Estimated: `4764` - // Minimum execution time: 47_368_000 picoseconds. - Weight::from_parts(48_049_000, 4764) + // Minimum execution time: 48_475_000 picoseconds. + Weight::from_parts(49_000_000, 4764) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -266,10 +266,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `560` // Estimated: `4764` - // Minimum execution time: 51_230_000 picoseconds. - Weight::from_parts(48_696_805, 4764) - // Standard Error: 6_139 - .saturating_add(Weight::from_parts(3_374_191, 0).saturating_mul(x.into())) + // Minimum execution time: 51_987_000 picoseconds. + Weight::from_parts(49_569_909, 4764) + // Standard Error: 5_547 + .saturating_add(Weight::from_parts(3_433_220, 0).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -286,10 +286,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `501` // Estimated: `4764` - // Minimum execution time: 45_030_000 picoseconds. - Weight::from_parts(43_179_071, 4764) - // Standard Error: 5_547 - .saturating_add(Weight::from_parts(3_296_864, 0).saturating_mul(x.into())) + // Minimum execution time: 48_592_000 picoseconds. + Weight::from_parts(46_136_422, 4764) + // Standard Error: 4_476 + .saturating_add(Weight::from_parts(3_444_512, 0).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -303,21 +303,21 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `267` // Estimated: `3775` - // Minimum execution time: 42_248_000 picoseconds. - Weight::from_parts(42_687_000, 3775) + // Minimum execution time: 38_973_000 picoseconds. + Weight::from_parts(39_533_000, 3775) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: DappStaking IntegratedDApps (r:1 w:0) /// Proof: DappStaking IntegratedDApps (max_values: Some(65535), max_size: Some(121), added: 2101, mode: MaxEncodedLen) /// Storage: DappStaking DAppTiers (r:1 w:1) - /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(2083), added: 4558, mode: MaxEncodedLen) + /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(1583), added: 4058, mode: MaxEncodedLen) fn claim_dapp_reward() -> Weight { // Proof Size summary in bytes: - // Measured: `3021` - // Estimated: `5548` - // Minimum execution time: 50_968_000 picoseconds. - Weight::from_parts(51_778_000, 5548) + // Measured: `2585` + // Estimated: `5048` + // Minimum execution time: 54_909_000 picoseconds. + Weight::from_parts(55_839_000, 5048) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -337,8 +337,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `389` // Estimated: `4764` - // Minimum execution time: 42_329_000 picoseconds. - Weight::from_parts(42_737_000, 4764) + // Minimum execution time: 42_755_000 picoseconds. + Weight::from_parts(43_230_000, 4764) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -355,10 +355,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `255 + x * (69 ±0)` // Estimated: `4764 + x * (2613 ±0)` - // Minimum execution time: 42_222_000 picoseconds. - Weight::from_parts(38_945_386, 4764) - // Standard Error: 14_325 - .saturating_add(Weight::from_parts(5_044_310, 0).saturating_mul(x.into())) + // Minimum execution time: 39_922_000 picoseconds. + Weight::from_parts(36_255_858, 4764) + // Standard Error: 14_366 + .saturating_add(Weight::from_parts(5_135_083, 0).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -369,8 +369,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_971_000 picoseconds. - Weight::from_parts(10_190_000, 0) + // Minimum execution time: 11_519_000 picoseconds. + Weight::from_parts(11_865_000, 0) } /// Storage: DappStaking CurrentEraInfo (r:1 w:1) /// Proof: DappStaking CurrentEraInfo (max_values: Some(1), max_size: Some(112), added: 607, mode: MaxEncodedLen) @@ -380,8 +380,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `16` // Estimated: `4254` - // Minimum execution time: 17_308_000 picoseconds. - Weight::from_parts(17_774_000, 4254) + // Minimum execution time: 17_823_000 picoseconds. + Weight::from_parts(18_413_000, 4254) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -396,13 +396,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: DappStaking PeriodEnd (r:0 w:1) /// Proof: DappStaking PeriodEnd (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) /// Storage: DappStaking DAppTiers (r:0 w:1) - /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(2083), added: 4558, mode: MaxEncodedLen) + /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(1583), added: 4058, mode: MaxEncodedLen) fn on_initialize_build_and_earn_to_voting() -> Weight { // Proof Size summary in bytes: // Measured: `550` // Estimated: `4254` - // Minimum execution time: 39_768_000 picoseconds. - Weight::from_parts(40_422_000, 4254) + // Minimum execution time: 41_147_000 picoseconds. + Weight::from_parts(42_304_000, 4254) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -411,13 +411,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: DappStaking EraRewards (r:1 w:1) /// Proof: DappStaking EraRewards (max_values: None, max_size: Some(789), added: 3264, mode: MaxEncodedLen) /// Storage: DappStaking DAppTiers (r:0 w:1) - /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(2083), added: 4558, mode: MaxEncodedLen) + /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(1583), added: 4058, mode: MaxEncodedLen) fn on_initialize_build_and_earn_to_build_and_earn() -> Weight { // Proof Size summary in bytes: // Measured: `68` // Estimated: `4254` - // Minimum execution time: 20_976_000 picoseconds. - Weight::from_parts(21_507_000, 4254) + // Minimum execution time: 23_807_000 picoseconds. + Weight::from_parts(24_367_000, 4254) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -430,10 +430,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `152 + x * (32 ±0)` // Estimated: `3061 + x * (2071 ±0)` - // Minimum execution time: 7_374_000 picoseconds. - Weight::from_parts(10_826_637, 3061) - // Standard Error: 3_374 - .saturating_add(Weight::from_parts(2_291_643, 0).saturating_mul(x.into())) + // Minimum execution time: 7_821_000 picoseconds. + Weight::from_parts(12_000_144, 3061) + // Standard Error: 3_553 + .saturating_add(Weight::from_parts(2_396_421, 0).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) .saturating_add(Weight::from_parts(0, 2071).saturating_mul(x.into())) @@ -445,13 +445,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: DappStaking EraRewards (r:1 w:1) /// Proof: DappStaking EraRewards (max_values: None, max_size: Some(789), added: 3264, mode: MaxEncodedLen) /// Storage: DappStaking DAppTiers (r:0 w:1) - /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(2083), added: 4558, mode: MaxEncodedLen) + /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(1583), added: 4058, mode: MaxEncodedLen) fn on_idle_cleanup() -> Weight { // Proof Size summary in bytes: // Measured: `473` // Estimated: `4254` - // Minimum execution time: 14_500_000 picoseconds. - Weight::from_parts(14_969_000, 4254) + // Minimum execution time: 17_154_000 picoseconds. + Weight::from_parts(17_535_000, 4254) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -463,8 +463,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_474_000 picoseconds. - Weight::from_parts(8_711_000, 0) + // Minimum execution time: 9_265_000 picoseconds. + Weight::from_parts(9_422_000, 0) } /// Storage: DappStaking IntegratedDApps (r:1 w:1) /// Proof: DappStaking IntegratedDApps (max_values: Some(65535), max_size: Some(121), added: 2101, mode: MaxEncodedLen) @@ -476,8 +476,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3091` - // Minimum execution time: 16_360_000 picoseconds. - Weight::from_parts(16_697_000, 3091) + // Minimum execution time: 17_285_000 picoseconds. + Weight::from_parts(17_628_000, 3091) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -487,8 +487,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `75` // Estimated: `3091` - // Minimum execution time: 12_927_000 picoseconds. - Weight::from_parts(13_229_000, 3091) + // Minimum execution time: 13_521_000 picoseconds. + Weight::from_parts(13_819_000, 3091) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -498,8 +498,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `75` // Estimated: `3091` - // Minimum execution time: 13_610_000 picoseconds. - Weight::from_parts(13_851_000, 3091) + // Minimum execution time: 13_797_000 picoseconds. + Weight::from_parts(14_051_000, 3091) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -511,8 +511,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `75` // Estimated: `3091` - // Minimum execution time: 16_704_000 picoseconds. - Weight::from_parts(16_952_000, 3091) + // Minimum execution time: 17_242_000 picoseconds. + Weight::from_parts(17_628_000, 3091) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -528,8 +528,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `12` // Estimated: `4764` - // Minimum execution time: 31_680_000 picoseconds. - Weight::from_parts(32_075_000, 4764) + // Minimum execution time: 32_138_000 picoseconds. + Weight::from_parts(32_677_000, 4764) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -545,8 +545,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `156` // Estimated: `4764` - // Minimum execution time: 34_576_000 picoseconds. - Weight::from_parts(34_777_000, 4764) + // Minimum execution time: 33_789_000 picoseconds. + Weight::from_parts(34_052_000, 4764) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -563,10 +563,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `187` // Estimated: `4764` - // Minimum execution time: 33_562_000 picoseconds. - Weight::from_parts(34_600_552, 4764) - // Standard Error: 5_079 - .saturating_add(Weight::from_parts(193_345, 0).saturating_mul(x.into())) + // Minimum execution time: 35_048_000 picoseconds. + Weight::from_parts(36_286_241, 4764) + // Standard Error: 6_246 + .saturating_add(Weight::from_parts(176_805, 0).saturating_mul(x.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -582,8 +582,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `182` // Estimated: `4764` - // Minimum execution time: 36_436_000 picoseconds. - Weight::from_parts(37_262_000, 4764) + // Minimum execution time: 30_390_000 picoseconds. + Weight::from_parts(30_712_000, 4764) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -605,8 +605,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `250` // Estimated: `4764` - // Minimum execution time: 43_866_000 picoseconds. - Weight::from_parts(44_468_000, 4764) + // Minimum execution time: 44_866_000 picoseconds. + Weight::from_parts(45_342_000, 4764) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -628,8 +628,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `427` // Estimated: `4764` - // Minimum execution time: 47_368_000 picoseconds. - Weight::from_parts(48_049_000, 4764) + // Minimum execution time: 48_475_000 picoseconds. + Weight::from_parts(49_000_000, 4764) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -648,10 +648,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `560` // Estimated: `4764` - // Minimum execution time: 51_230_000 picoseconds. - Weight::from_parts(48_696_805, 4764) - // Standard Error: 6_139 - .saturating_add(Weight::from_parts(3_374_191, 0).saturating_mul(x.into())) + // Minimum execution time: 51_987_000 picoseconds. + Weight::from_parts(49_569_909, 4764) + // Standard Error: 5_547 + .saturating_add(Weight::from_parts(3_433_220, 0).saturating_mul(x.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -668,10 +668,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `501` // Estimated: `4764` - // Minimum execution time: 45_030_000 picoseconds. - Weight::from_parts(43_179_071, 4764) - // Standard Error: 5_547 - .saturating_add(Weight::from_parts(3_296_864, 0).saturating_mul(x.into())) + // Minimum execution time: 48_592_000 picoseconds. + Weight::from_parts(46_136_422, 4764) + // Standard Error: 4_476 + .saturating_add(Weight::from_parts(3_444_512, 0).saturating_mul(x.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -685,21 +685,21 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `267` // Estimated: `3775` - // Minimum execution time: 42_248_000 picoseconds. - Weight::from_parts(42_687_000, 3775) + // Minimum execution time: 38_973_000 picoseconds. + Weight::from_parts(39_533_000, 3775) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: DappStaking IntegratedDApps (r:1 w:0) /// Proof: DappStaking IntegratedDApps (max_values: Some(65535), max_size: Some(121), added: 2101, mode: MaxEncodedLen) /// Storage: DappStaking DAppTiers (r:1 w:1) - /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(2083), added: 4558, mode: MaxEncodedLen) + /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(1583), added: 4058, mode: MaxEncodedLen) fn claim_dapp_reward() -> Weight { // Proof Size summary in bytes: - // Measured: `3021` - // Estimated: `5548` - // Minimum execution time: 50_968_000 picoseconds. - Weight::from_parts(51_778_000, 5548) + // Measured: `2585` + // Estimated: `5048` + // Minimum execution time: 54_909_000 picoseconds. + Weight::from_parts(55_839_000, 5048) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -719,8 +719,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `389` // Estimated: `4764` - // Minimum execution time: 42_329_000 picoseconds. - Weight::from_parts(42_737_000, 4764) + // Minimum execution time: 42_755_000 picoseconds. + Weight::from_parts(43_230_000, 4764) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -737,10 +737,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `255 + x * (69 ±0)` // Estimated: `4764 + x * (2613 ±0)` - // Minimum execution time: 42_222_000 picoseconds. - Weight::from_parts(38_945_386, 4764) - // Standard Error: 14_325 - .saturating_add(Weight::from_parts(5_044_310, 0).saturating_mul(x.into())) + // Minimum execution time: 39_922_000 picoseconds. + Weight::from_parts(36_255_858, 4764) + // Standard Error: 14_366 + .saturating_add(Weight::from_parts(5_135_083, 0).saturating_mul(x.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(x.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -751,8 +751,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_971_000 picoseconds. - Weight::from_parts(10_190_000, 0) + // Minimum execution time: 11_519_000 picoseconds. + Weight::from_parts(11_865_000, 0) } /// Storage: DappStaking CurrentEraInfo (r:1 w:1) /// Proof: DappStaking CurrentEraInfo (max_values: Some(1), max_size: Some(112), added: 607, mode: MaxEncodedLen) @@ -762,8 +762,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `16` // Estimated: `4254` - // Minimum execution time: 17_308_000 picoseconds. - Weight::from_parts(17_774_000, 4254) + // Minimum execution time: 17_823_000 picoseconds. + Weight::from_parts(18_413_000, 4254) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -778,13 +778,13 @@ impl WeightInfo for () { /// Storage: DappStaking PeriodEnd (r:0 w:1) /// Proof: DappStaking PeriodEnd (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) /// Storage: DappStaking DAppTiers (r:0 w:1) - /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(2083), added: 4558, mode: MaxEncodedLen) + /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(1583), added: 4058, mode: MaxEncodedLen) fn on_initialize_build_and_earn_to_voting() -> Weight { // Proof Size summary in bytes: // Measured: `550` // Estimated: `4254` - // Minimum execution time: 39_768_000 picoseconds. - Weight::from_parts(40_422_000, 4254) + // Minimum execution time: 41_147_000 picoseconds. + Weight::from_parts(42_304_000, 4254) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -793,13 +793,13 @@ impl WeightInfo for () { /// Storage: DappStaking EraRewards (r:1 w:1) /// Proof: DappStaking EraRewards (max_values: None, max_size: Some(789), added: 3264, mode: MaxEncodedLen) /// Storage: DappStaking DAppTiers (r:0 w:1) - /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(2083), added: 4558, mode: MaxEncodedLen) + /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(1583), added: 4058, mode: MaxEncodedLen) fn on_initialize_build_and_earn_to_build_and_earn() -> Weight { // Proof Size summary in bytes: // Measured: `68` // Estimated: `4254` - // Minimum execution time: 20_976_000 picoseconds. - Weight::from_parts(21_507_000, 4254) + // Minimum execution time: 23_807_000 picoseconds. + Weight::from_parts(24_367_000, 4254) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -812,10 +812,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `152 + x * (32 ±0)` // Estimated: `3061 + x * (2071 ±0)` - // Minimum execution time: 7_374_000 picoseconds. - Weight::from_parts(10_826_637, 3061) - // Standard Error: 3_374 - .saturating_add(Weight::from_parts(2_291_643, 0).saturating_mul(x.into())) + // Minimum execution time: 7_821_000 picoseconds. + Weight::from_parts(12_000_144, 3061) + // Standard Error: 3_553 + .saturating_add(Weight::from_parts(2_396_421, 0).saturating_mul(x.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(x.into()))) .saturating_add(Weight::from_parts(0, 2071).saturating_mul(x.into())) @@ -827,13 +827,13 @@ impl WeightInfo for () { /// Storage: DappStaking EraRewards (r:1 w:1) /// Proof: DappStaking EraRewards (max_values: None, max_size: Some(789), added: 3264, mode: MaxEncodedLen) /// Storage: DappStaking DAppTiers (r:0 w:1) - /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(2083), added: 4558, mode: MaxEncodedLen) + /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(1583), added: 4058, mode: MaxEncodedLen) fn on_idle_cleanup() -> Weight { // Proof Size summary in bytes: // Measured: `473` // Estimated: `4254` - // Minimum execution time: 14_500_000 picoseconds. - Weight::from_parts(14_969_000, 4254) + // Minimum execution time: 17_154_000 picoseconds. + Weight::from_parts(17_535_000, 4254) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } diff --git a/pallets/inflation/src/benchmarking.rs b/pallets/inflation/src/benchmarking.rs index 113c5f32a7..184ae5cc64 100644 --- a/pallets/inflation/src/benchmarking.rs +++ b/pallets/inflation/src/benchmarking.rs @@ -46,7 +46,7 @@ fn initial_config() { let issuance_safety_cap = total_issuance.saturating_add(params.max_inflation_rate * total_issuance); let config = InflationConfiguration { - recalculation_block: 123, + recalculation_era: 123, issuance_safety_cap, collator_reward_per_block: 11111, treasury_reward_per_block: 33333, @@ -98,46 +98,37 @@ mod benchmarks { initial_config::(); #[extrinsic_call] - _(RawOrigin::Root); + _(RawOrigin::Root, 123); let config = ActiveInflationConfig::::get(); assert_last_event::(Event::::ForcedInflationRecalculation { config }.into()); } #[benchmark] - fn hook_with_recalculation() { + fn recalculation() { initial_config::(); - ActiveInflationConfig::::mutate(|config| { - config.recalculation_block = 0; - }); - let init_issuance = T::Currency::total_issuance(); + let init_recalculation_era = ActiveInflationConfig::::get().recalculation_era; + DoRecalculation::::put(init_recalculation_era); - let block = 1; #[block] { - Pallet::::on_initialize(block); - Pallet::::on_finalize(block); + Pallet::::block_before_new_era(init_recalculation_era); + Pallet::::on_finalize(1); } - assert!(ActiveInflationConfig::::get().recalculation_block > 0); - - // The 'sane' assumption is that at least something will be issued for treasury & collators - assert!(T::Currency::total_issuance() > init_issuance); + assert!(ActiveInflationConfig::::get().recalculation_era > init_recalculation_era); } #[benchmark] - fn hook_without_recalculation() { + fn hooks_without_recalculation() { initial_config::(); - ActiveInflationConfig::::mutate(|config| { - config.recalculation_block = 2; - }); let init_config = ActiveInflationConfig::::get(); let init_issuance = T::Currency::total_issuance(); + DoRecalculation::::kill(); - // Has to be at least 2 blocks less than the recalculation block. - let block = 0; + let block = 1; #[block] { Pallet::::on_initialize(block); diff --git a/pallets/inflation/src/lib.rs b/pallets/inflation/src/lib.rs index 8d278e1c00..ef5286136b 100644 --- a/pallets/inflation/src/lib.rs +++ b/pallets/inflation/src/lib.rs @@ -34,7 +34,7 @@ //! E.g. if 'yearly' inflation is set to be 7%, and total issuance is 200 ASTR, then the max inflation for that cycle will be 14 ASTR. //! //! Each cycle consists of one or more `periods`. -//! Periods are integral part of dApp staking protocol, allowing dApps to promotove themselves, attract stakers and earn rewards. +//! Periods are integral part of dApp staking protocol, allowing dApps to promote themselves, attract stakers and earn rewards. //! At the end of each period, all stakes are reset, and dApps need to repeat the process. //! //! Each period consists of two subperiods: `Voting` and `Build&Earn`. @@ -99,7 +99,9 @@ pub use pallet::*; use astar_primitives::{ - dapp_staking::{CycleConfiguration, StakingRewardHandler}, + dapp_staking::{ + CycleConfiguration, EraNumber, Observer as DappStakingObserver, StakingRewardHandler, + }, Balance, BlockNumber, }; use frame_support::{ @@ -187,6 +189,11 @@ pub mod pallet { #[pallet::storage] pub type InflationParams = StorageValue<_, InflationParameters, ValueQuery>; + /// Flag indicating whether on the first possible opportunity, recalculation of the inflation config should be done. + #[pallet::storage] + #[pallet::whitelist_storage] + pub type DoRecalculation = StorageValue<_, EraNumber, OptionQuery>; + #[pallet::genesis_config] #[cfg_attr(feature = "std", derive(Default))] pub struct GenesisConfig { @@ -199,8 +206,8 @@ pub mod pallet { fn build(&self) { assert!(self.params.is_valid()); - let now = frame_system::Pallet::::block_number(); - let config = Pallet::::recalculate_inflation(now); + let starting_era = 1; + let config = Pallet::::recalculate_inflation(starting_era); ActiveInflationConfig::::put(config); InflationParams::::put(self.params); @@ -209,37 +216,32 @@ pub mod pallet { #[pallet::hooks] impl Hooks for Pallet { - fn on_initialize(now: BlockNumber) -> Weight { + fn on_initialize(_now: BlockNumber) -> Weight { Self::payout_block_rewards(); - let recalculation_weight = - if Self::is_recalculation_in_next_block(now, &ActiveInflationConfig::::get()) { - T::WeightInfo::hook_with_recalculation() - } else { - T::WeightInfo::hook_without_recalculation() - }; - // Benchmarks won't account for the whitelisted storage access so this needs to be added manually. // // ActiveInflationConfig - 1 DB read - let whitelisted_weight = ::DbWeight::get().reads(1); - - recalculation_weight.saturating_add(whitelisted_weight) + // DoRecalculation - 1 DB read + ::DbWeight::get().reads(2) } - fn on_finalize(now: BlockNumber) { - // Recalculation is done at the block right before the re-calculation is supposed to happen. + fn on_finalize(_now: BlockNumber) { + // Recalculation is done at the block right before a new cycle starts. // This is to ensure all the rewards are paid out according to the new inflation configuration from next block. // // If this was done in `on_initialize`, collator & treasury would receive incorrect rewards for that one block. // // This should be done as late as possible, to ensure all operations that modify issuance are done. - if Self::is_recalculation_in_next_block(now, &ActiveInflationConfig::::get()) { - let config = Self::recalculate_inflation(now); + if let Some(next_era) = DoRecalculation::::get() { + let config = Self::recalculate_inflation(next_era); ActiveInflationConfig::::put(config.clone()); + DoRecalculation::::kill(); Self::deposit_event(Event::::NewInflationConfiguration { config }); } + + // NOTE: weight of the `on_finalize` logic with recalculation has to be covered by the observer notify call. } fn integrity_test() { @@ -282,10 +284,13 @@ pub mod pallet { /// Purpose of the call is testing & handling unforeseen circumstances. #[pallet::call_index(1)] #[pallet::weight(T::WeightInfo::force_inflation_recalculation())] - pub fn force_inflation_recalculation(origin: OriginFor) -> DispatchResult { + pub fn force_inflation_recalculation( + origin: OriginFor, + next_era: EraNumber, + ) -> DispatchResult { ensure_root(origin)?; - let config = Self::recalculate_inflation(frame_system::Pallet::::block_number()); + let config = Self::recalculate_inflation(next_era); ActiveInflationConfig::::put(config.clone()); @@ -319,16 +324,6 @@ pub mod pallet { } impl Pallet { - /// Used to check if inflation recalculation is supposed to happen on the next block. - /// - /// This will be true even if recalculation is overdue, e.g. it should have happened in the current or older block. - fn is_recalculation_in_next_block( - now: BlockNumber, - config: &InflationConfiguration, - ) -> bool { - config.recalculation_block.saturating_sub(now) <= 1 - } - /// Payout block rewards to the beneficiaries. /// /// Return the total amount issued. @@ -347,7 +342,7 @@ pub mod pallet { /// Recalculates the inflation based on the total issuance & inflation parameters. /// /// Returns the new inflation configuration. - pub(crate) fn recalculate_inflation(now: BlockNumber) -> InflationConfiguration { + pub(crate) fn recalculate_inflation(next_era: EraNumber) -> InflationConfiguration { let params = InflationParams::::get(); let total_issuance = T::Currency::total_issuance(); @@ -391,11 +386,12 @@ pub mod pallet { let bonus_reward_pool_per_period = bonus_emission / periods_per_cycle; // 4. Block at which the inflation must be recalculated. - let recalculation_block = now.saturating_add(T::CycleConfiguration::blocks_per_cycle()); + let recalculation_era = + next_era.saturating_add(T::CycleConfiguration::eras_per_cycle()); // 5. Return calculated values InflationConfiguration { - recalculation_block, + recalculation_era, issuance_safety_cap, collator_reward_per_block, treasury_reward_per_block, @@ -429,6 +425,21 @@ pub mod pallet { } } + impl DappStakingObserver for Pallet { + /// Informs the pallet that the next block will be the first block of a new era. + fn block_before_new_era(new_era: EraNumber) -> Weight { + let config = ActiveInflationConfig::::get(); + if config.recalculation_era <= new_era { + DoRecalculation::::put(new_era); + + // Need to account for write into a single whitelisted storage item. + T::WeightInfo::recalculation().saturating_add(T::DbWeight::get().writes(1)) + } else { + Weight::zero() + } + } + } + impl StakingRewardHandler for Pallet { fn staker_and_dapp_reward_pools(total_value_staked: Balance) -> (Balance, Balance) { let config = ActiveInflationConfig::::get(); @@ -458,7 +469,7 @@ pub mod pallet { // This can fail only if the amount is below existential deposit & the account doesn't exist, // or if the account has no provider references. - // In both cases, the reward is lost but this can be ignored since it's extremelly unlikely + // In both cases, the reward is lost but this can be ignored since it's extremely unlikely // to appear and doesn't bring any real harm. T::Currency::deposit_creating(account, reward); Ok(()) @@ -471,9 +482,9 @@ pub mod pallet { #[derive(Encode, Decode, MaxEncodedLen, Default, Copy, Clone, Debug, PartialEq, Eq, TypeInfo)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub struct InflationConfiguration { - /// Block number at which the inflation must be recalculated, based on the total issuance at that block. + /// Era number at which the inflation configuration must be recalculated, based on the total issuance at that block. #[codec(compact)] - pub recalculation_block: BlockNumber, + pub recalculation_era: EraNumber, /// Maximum amount of issuance we can have during this cycle. #[codec(compact)] pub issuance_safety_cap: Balance, @@ -592,19 +603,20 @@ pub trait PayoutPerBlock { #[cfg(feature = "try-runtime")] use sp_std::vec::Vec; pub struct PalletInflationInitConfig(PhantomData<(T, P)>); -impl> OnRuntimeUpgrade for PalletInflationInitConfig { +impl> OnRuntimeUpgrade + for PalletInflationInitConfig +{ fn on_runtime_upgrade() -> Weight { if Pallet::::on_chain_storage_version() >= STORAGE_VERSION { return T::DbWeight::get().reads(1); } // 1. Get & set inflation parameters - let inflation_params = P::get(); + let (inflation_params, next_era) = P::get(); InflationParams::::put(inflation_params.clone()); // 2. Calculation inflation config, set it & deposit event - let now = frame_system::Pallet::::block_number(); - let config = Pallet::::recalculate_inflation(now); + let config = Pallet::::recalculate_inflation(next_era); ActiveInflationConfig::::put(config.clone()); Pallet::::deposit_event(Event::::NewInflationConfiguration { config }); @@ -614,8 +626,7 @@ impl> OnRuntimeUpgrade for PalletInflatio log::info!("Inflation pallet storage initialized."); - T::WeightInfo::hook_with_recalculation() - .saturating_add(T::DbWeight::get().reads_writes(1, 2)) + T::WeightInfo::recalculation().saturating_add(T::DbWeight::get().reads_writes(1, 2)) } #[cfg(feature = "try-runtime")] @@ -626,3 +637,24 @@ impl> OnRuntimeUpgrade for PalletInflatio Ok(()) } } + +/// To be used just for Shibuya, can be removed after migration has been executed. +pub struct PalletInflationShibuyaMigration(PhantomData<(T, P)>); +impl> OnRuntimeUpgrade + for PalletInflationShibuyaMigration +{ + fn on_runtime_upgrade() -> Weight { + let (recalculation_era, weight) = P::get(); + ActiveInflationConfig::::mutate(|config| { + // Both recalculation_era and recalculation_block are of the same `u32` type so no need to do any translation. + config.recalculation_era = recalculation_era; + }); + + log::info!( + "Inflation pallet recalculation era set to {}.", + recalculation_era + ); + + T::DbWeight::get().reads_writes(1, 1).saturating_add(weight) + } +} diff --git a/pallets/inflation/src/mock.rs b/pallets/inflation/src/mock.rs index 3cac1bca84..37588f12d3 100644 --- a/pallets/inflation/src/mock.rs +++ b/pallets/inflation/src/mock.rs @@ -53,7 +53,7 @@ pub const INIT_PARAMS: InflationParameters = InflationParameters { /// Initial inflation config set by the mock. pub const INIT_CONFIG: InflationConfiguration = InflationConfiguration { - recalculation_block: 100, + recalculation_era: 100, issuance_safety_cap: 1_000_000, collator_reward_per_block: 1000, treasury_reward_per_block: 1500, @@ -196,13 +196,3 @@ impl ExternalityBuilder { ext } } - -/// Advance to the specified block number. -/// Function assumes first block has been initialized. -pub(crate) fn advance_to_block(n: BlockNumber) { - while System::block_number() < n { - Inflation::on_finalize(System::block_number()); - System::set_block_number(System::block_number() + 1); - Inflation::on_initialize(System::block_number()); - } -} diff --git a/pallets/inflation/src/tests.rs b/pallets/inflation/src/tests.rs index db57a25cfb..75f82800e5 100644 --- a/pallets/inflation/src/tests.rs +++ b/pallets/inflation/src/tests.rs @@ -78,7 +78,7 @@ fn force_set_inflation_params_fails() { fn force_set_inflation_config_work() { ExternalityBuilder::build().execute_with(|| { let mut new_config = ActiveInflationConfig::::get(); - new_config.recalculation_block = new_config.recalculation_block + 50; + new_config.recalculation_era = new_config.recalculation_era + 50; // Execute call, ensure it works assert_ok!(Inflation::force_set_inflation_config( @@ -97,7 +97,7 @@ fn force_set_inflation_config_work() { fn force_set_inflation_config_fails() { ExternalityBuilder::build().execute_with(|| { let mut new_config = ActiveInflationConfig::::get(); - new_config.recalculation_block = new_config.recalculation_block + 50; + new_config.recalculation_era = new_config.recalculation_era + 50; // Make sure action is privileged assert_noop!( @@ -113,8 +113,10 @@ fn force_inflation_recalculation_work() { let old_config = ActiveInflationConfig::::get(); // Execute call, ensure it works + let next_era = 100; assert_ok!(Inflation::force_inflation_recalculation( RuntimeOrigin::root(), + next_era, )); let new_config = ActiveInflationConfig::::get(); @@ -133,34 +135,34 @@ fn force_inflation_fails_due_to_unprivileged_origin() { ExternalityBuilder::build().execute_with(|| { // Make sure action is privileged assert_noop!( - Inflation::force_inflation_recalculation(RuntimeOrigin::signed(1)), + Inflation::force_inflation_recalculation(RuntimeOrigin::signed(1), 100), BadOrigin ); }) } #[test] -fn inflation_recalculation_occurs_when_exepcted() { +fn inflation_recalculation_occurs_when_expected() { ExternalityBuilder::build().execute_with(|| { let init_config = ActiveInflationConfig::::get(); + let recalculation_era = init_config.recalculation_era; + + // Make sure `on_finalize` calls before the expected change are storage noops - advance_to_block(init_config.recalculation_block - 3); - assert_storage_noop!(Inflation::on_finalize(init_config.recalculation_block - 3)); - Inflation::on_initialize( - init_config.recalculation_block - 2 - ); - assert_storage_noop!(Inflation::on_finalize(init_config.recalculation_block - 2)); - Inflation::on_initialize( - init_config.recalculation_block - 1 - ); + Inflation::block_before_new_era(recalculation_era - 2); + assert_storage_noop!(Inflation::on_finalize(100)); + + Inflation::block_before_new_era(recalculation_era - 1); + assert_storage_noop!(Inflation::on_finalize(200)); - // One block before recalculation, on_finalize should calculate new inflation config + // One block before recalculation era starts, on_finalize should calculate new inflation config + Inflation::block_before_new_era(recalculation_era); let init_config = ActiveInflationConfig::::get(); let init_total_issuance = Balances::total_issuance(); // Finally trigger inflation recalculation. - Inflation::on_finalize(init_config.recalculation_block - 1); + Inflation::on_finalize(300); let new_config = ActiveInflationConfig::::get(); assert_ne!( @@ -237,7 +239,7 @@ fn inflation_parameters_validity_check_works() { } #[test] -fn inflation_recalucation_works() { +fn inflation_recalculation_works() { ExternalityBuilder::build().execute_with(|| { let total_issuance = Balances::total_issuance(); let params = InflationParams::::get(); @@ -249,8 +251,8 @@ fn inflation_recalucation_works() { // Verify basics are ok assert_eq!( - new_config.recalculation_block, - now + ::CycleConfiguration::blocks_per_cycle() + new_config.recalculation_era, + now + ::CycleConfiguration::eras_per_cycle() ); assert_eq!( new_config.issuance_safety_cap, @@ -430,7 +432,7 @@ fn payout_reward_fails_when_relaxed_cap_is_exceeded() { } #[test] -fn cylcle_configuration_works() { +fn cycle_configuration_works() { ExternalityBuilder::build().execute_with(|| { type CycleConfig = ::CycleConfiguration; @@ -468,6 +470,6 @@ fn test_genesis_build() { // Verify state is as expected assert_eq!(InflationParams::::get(), genesis_config.params); - assert!(ActiveInflationConfig::::get().recalculation_block > 0); + assert!(ActiveInflationConfig::::get().recalculation_era > 0); }) } diff --git a/pallets/inflation/src/weights.rs b/pallets/inflation/src/weights.rs index 08a53283c4..702c0f11bf 100644 --- a/pallets/inflation/src/weights.rs +++ b/pallets/inflation/src/weights.rs @@ -20,9 +20,9 @@ //! Autogenerated weights for pallet_inflation //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-12-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-01-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `devserver-01`, CPU: `Intel(R) Xeon(R) E-2236 CPU @ 3.40GHz` +//! HOSTNAME: `gh-runner-01-ovh`, CPU: `Intel(R) Xeon(R) E-2236 CPU @ 3.40GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("shibuya-dev"), DB CACHE: 1024 // Executed Command: @@ -52,8 +52,8 @@ pub trait WeightInfo { fn force_set_inflation_params() -> Weight; fn force_set_inflation_config() -> Weight; fn force_inflation_recalculation() -> Weight; - fn hook_with_recalculation() -> Weight; - fn hook_without_recalculation() -> Weight; + fn recalculation() -> Weight; + fn hooks_without_recalculation() -> Weight; } /// Weights for pallet_inflation using the Substrate node and recommended hardware. @@ -65,48 +65,45 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_036_000 picoseconds. - Weight::from_parts(9_186_000, 0) + // Minimum execution time: 9_487_000 picoseconds. + Weight::from_parts(9_652_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } fn force_set_inflation_config() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_073_000 picoseconds. - Weight::from_parts(9_411_000, 0) + // Minimum execution time: 9_168_000 picoseconds. + Weight::from_parts(9_436_000, 0) } /// Storage: Inflation InflationParams (r:1 w:0) /// Proof: Inflation InflationParams (max_values: Some(1), max_size: Some(64), added: 559, mode: MaxEncodedLen) fn force_inflation_recalculation() -> Weight { // Proof Size summary in bytes: - // Measured: `58` + // Measured: `40` // Estimated: `1549` - // Minimum execution time: 14_839_000 picoseconds. - Weight::from_parts(15_198_000, 1549) + // Minimum execution time: 13_496_000 picoseconds. + Weight::from_parts(13_762_000, 1549) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: System Account (r:2 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// Storage: Inflation InflationParams (r:1 w:0) /// Proof: Inflation InflationParams (max_values: Some(1), max_size: Some(64), added: 559, mode: MaxEncodedLen) - fn hook_with_recalculation() -> Weight { + fn recalculation() -> Weight { // Proof Size summary in bytes: - // Measured: `232` - // Estimated: `6196` - // Minimum execution time: 31_965_000 picoseconds. - Weight::from_parts(32_498_000, 6196) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `58` + // Estimated: `1549` + // Minimum execution time: 13_811_000 picoseconds. + Weight::from_parts(13_995_000, 1549) + .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: System Account (r:2 w:1) /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - fn hook_without_recalculation() -> Weight { + fn hooks_without_recalculation() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `6196` - // Minimum execution time: 22_235_000 picoseconds. - Weight::from_parts(22_378_000, 6196) + // Minimum execution time: 21_351_000 picoseconds. + Weight::from_parts(21_749_000, 6196) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -120,48 +117,45 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_036_000 picoseconds. - Weight::from_parts(9_186_000, 0) + // Minimum execution time: 9_487_000 picoseconds. + Weight::from_parts(9_652_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } fn force_set_inflation_config() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_073_000 picoseconds. - Weight::from_parts(9_411_000, 0) + // Minimum execution time: 9_168_000 picoseconds. + Weight::from_parts(9_436_000, 0) } /// Storage: Inflation InflationParams (r:1 w:0) /// Proof: Inflation InflationParams (max_values: Some(1), max_size: Some(64), added: 559, mode: MaxEncodedLen) fn force_inflation_recalculation() -> Weight { // Proof Size summary in bytes: - // Measured: `58` + // Measured: `40` // Estimated: `1549` - // Minimum execution time: 14_839_000 picoseconds. - Weight::from_parts(15_198_000, 1549) + // Minimum execution time: 13_496_000 picoseconds. + Weight::from_parts(13_762_000, 1549) .saturating_add(RocksDbWeight::get().reads(1_u64)) } - /// Storage: System Account (r:2 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// Storage: Inflation InflationParams (r:1 w:0) /// Proof: Inflation InflationParams (max_values: Some(1), max_size: Some(64), added: 559, mode: MaxEncodedLen) - fn hook_with_recalculation() -> Weight { + fn recalculation() -> Weight { // Proof Size summary in bytes: - // Measured: `232` - // Estimated: `6196` - // Minimum execution time: 31_965_000 picoseconds. - Weight::from_parts(32_498_000, 6196) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) + // Measured: `58` + // Estimated: `1549` + // Minimum execution time: 13_811_000 picoseconds. + Weight::from_parts(13_995_000, 1549) + .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: System Account (r:2 w:1) /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - fn hook_without_recalculation() -> Weight { + fn hooks_without_recalculation() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `6196` - // Minimum execution time: 22_235_000 picoseconds. - Weight::from_parts(22_378_000, 6196) + // Minimum execution time: 21_351_000 picoseconds. + Weight::from_parts(21_749_000, 6196) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/pallets/static-price-provider/src/lib.rs b/pallets/static-price-provider/src/lib.rs index 7e1c629e11..d71599c815 100644 --- a/pallets/static-price-provider/src/lib.rs +++ b/pallets/static-price-provider/src/lib.rs @@ -120,9 +120,11 @@ impl> OnRuntimeUpgrade for InitActivePrice { fn on_runtime_upgrade() -> Weight { let init_price = P::get().max(FixedU64::from_rational(1, FixedU64::DIV.into())); - log::info!("Setting initial active price to {:?}", init_price); + log::info!("Setting initial active price to {}", init_price); ActivePrice::::put(init_price); - T::DbWeight::get().writes(1) + STORAGE_VERSION.put::>(); + + T::DbWeight::get().writes(2) } } diff --git a/precompiles/dapp-staking-v3/src/test/mock.rs b/precompiles/dapp-staking-v3/src/test/mock.rs index feff4d634f..36359b9457 100644 --- a/precompiles/dapp-staking-v3/src/test/mock.rs +++ b/precompiles/dapp-staking-v3/src/test/mock.rs @@ -38,12 +38,14 @@ use sp_runtime::traits::{BlakeTwo256, ConstU32, IdentityLookup}; extern crate alloc; use astar_primitives::{ - dapp_staking::{CycleConfiguration, SmartContract, StakingRewardHandler}, + dapp_staking::{ + CycleConfiguration, EraNumber, PeriodNumber, SmartContract, StakingRewardHandler, + }, oracle::PriceProvider, testing::Header, AccountId, Balance, BlockNumber, }; -use pallet_dapp_staking_v3::{EraNumber, PeriodNumber, TierThreshold}; +use pallet_dapp_staking_v3::TierThreshold; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -249,6 +251,7 @@ impl pallet_dapp_staking_v3::Config for Test { type NativePriceProvider = DummyPriceProvider; type StakingRewardHandler = DummyStakingRewardHandler; type CycleConfiguration = DummyCycleConfiguration; + type Observers = (); type EraRewardSpanLength = ConstU32<8>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<10>; diff --git a/precompiles/dapp-staking-v3/src/test/tests_v2.rs b/precompiles/dapp-staking-v3/src/test/tests_v2.rs index 8d93b56198..2279b97fbf 100644 --- a/precompiles/dapp-staking-v3/src/test/tests_v2.rs +++ b/precompiles/dapp-staking-v3/src/test/tests_v2.rs @@ -26,7 +26,8 @@ use sp_runtime::traits::Zero; use assert_matches::assert_matches; -use pallet_dapp_staking_v3::{ActiveProtocolState, EraNumber, EraRewards}; +use astar_primitives::dapp_staking::EraNumber; +use pallet_dapp_staking_v3::{ActiveProtocolState, EraRewards}; #[test] fn read_current_era_is_ok() { diff --git a/precompiles/dapp-staking-v3/src/test/tests_v3.rs b/precompiles/dapp-staking-v3/src/test/tests_v3.rs index 5977417b5e..2ab48e45b9 100644 --- a/precompiles/dapp-staking-v3/src/test/tests_v3.rs +++ b/precompiles/dapp-staking-v3/src/test/tests_v3.rs @@ -25,8 +25,11 @@ use sp_core::H160; use assert_matches::assert_matches; -use astar_primitives::{dapp_staking::CycleConfiguration, BlockNumber}; -use pallet_dapp_staking_v3::{ActiveProtocolState, EraNumber}; +use astar_primitives::{ + dapp_staking::{CycleConfiguration, EraNumber}, + BlockNumber, +}; +use pallet_dapp_staking_v3::ActiveProtocolState; #[test] fn protocol_state_is_ok() { diff --git a/primitives/src/dapp_staking.rs b/primitives/src/dapp_staking.rs index baf7ff34b5..ee6eeedfa5 100644 --- a/primitives/src/dapp_staking.rs +++ b/primitives/src/dapp_staking.rs @@ -20,10 +20,19 @@ use super::{Balance, BlockNumber}; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::RuntimeDebug; +use frame_support::{pallet_prelude::Weight, RuntimeDebug}; use sp_core::H160; use sp_std::hash::Hash; +/// Era number type +pub type EraNumber = u32; +/// Period number type +pub type PeriodNumber = u32; +/// Dapp Id type +pub type DAppId = u16; +/// Tier Id type +pub type TierId = u8; + /// Configuration for cycles, periods, subperiods & eras. /// /// * `cycle` - Time unit similar to 'year' in the real world. Consists of one or more periods. At the beginning of each cycle, inflation is recalculated. @@ -35,17 +44,17 @@ pub trait CycleConfiguration { /// How many different periods are there in a cycle (a 'year'). /// /// This value has to be at least 1. - fn periods_per_cycle() -> u32; + fn periods_per_cycle() -> PeriodNumber; /// For how many standard era lengths does the voting subperiod last. /// /// This value has to be at least 1. - fn eras_per_voting_subperiod() -> u32; + fn eras_per_voting_subperiod() -> EraNumber; /// How many standard eras are there in the build&earn subperiod. /// /// This value has to be at least 1. - fn eras_per_build_and_earn_subperiod() -> u32; + fn eras_per_build_and_earn_subperiod() -> EraNumber; /// How many blocks are there per standard era. /// @@ -53,12 +62,12 @@ pub trait CycleConfiguration { fn blocks_per_era() -> BlockNumber; /// For how many standard era lengths does the period last. - fn eras_per_period() -> u32 { + fn eras_per_period() -> EraNumber { Self::eras_per_voting_subperiod().saturating_add(Self::eras_per_build_and_earn_subperiod()) } - /// For how many standard era lengths does the cylce (a 'year') last. - fn eras_per_cycle() -> u32 { + /// For how many standard era lengths does the cycle (a 'year') last. + fn eras_per_cycle() -> EraNumber { Self::eras_per_period().saturating_mul(Self::periods_per_cycle()) } @@ -68,11 +77,26 @@ pub trait CycleConfiguration { } /// For how many standard era lengths do all the build&earn subperiods in a cycle last. - fn build_and_earn_eras_per_cycle() -> u32 { + fn build_and_earn_eras_per_cycle() -> EraNumber { Self::eras_per_build_and_earn_subperiod().saturating_mul(Self::periods_per_cycle()) } } +/// Trait for observers (listeners) of various events related to dApp staking protocol. +pub trait Observer { + /// Called in the block right before the next era starts. + /// + /// Returns the weight consumed by the call. + /// + /// # Arguments + /// * `next_era` - Era number of the next era. + fn block_before_new_era(_next_era: EraNumber) -> Weight { + Weight::zero() + } +} + +impl Observer for () {} + /// Interface for staking reward handler. /// /// Provides reward pool values for stakers - normal & bonus rewards, as well as dApp reward pool. diff --git a/runtime/local/src/lib.rs b/runtime/local/src/lib.rs index cbfcd9800e..ed0c061853 100644 --- a/runtime/local/src/lib.rs +++ b/runtime/local/src/lib.rs @@ -61,7 +61,7 @@ use sp_runtime::{ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; use astar_primitives::{ - dapp_staking::{CycleConfiguration, SmartContract}, + dapp_staking::{CycleConfiguration, DAppId, EraNumber, PeriodNumber, SmartContract, TierId}, evm::{EvmRevertCodeHandler, HashedDefaultMappings}, Address, AssetId, Balance, BlockNumber, Hash, Header, Index, }; @@ -514,6 +514,7 @@ impl pallet_dapp_staking_v3::Config for Runtime { type NativePriceProvider = StaticPriceProvider; type StakingRewardHandler = Inflation; type CycleConfiguration = InflationCycleConfig; + type Observers = Inflation; type EraRewardSpanLength = ConstU32<8>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<100>; @@ -541,15 +542,15 @@ impl pallet_inflation::PayoutPerBlock for InflationPayoutPerB pub struct InflationCycleConfig; impl CycleConfiguration for InflationCycleConfig { - fn periods_per_cycle() -> u32 { + fn periods_per_cycle() -> PeriodNumber { 4 } - fn eras_per_voting_subperiod() -> u32 { + fn eras_per_voting_subperiod() -> EraNumber { 2 } - fn eras_per_build_and_earn_subperiod() -> u32 { + fn eras_per_build_and_earn_subperiod() -> EraNumber { 22 } @@ -962,13 +963,13 @@ pub enum ProxyType { Balances, /// All Runtime calls from Pallet Assets allowed for proxy account Assets, - /// Only Runtime Calls related to goverance for proxy account + /// Only Runtime Calls related to governance for proxy account /// To know exact calls check InstanceFilter implementation for ProxyTypes Governance, /// Only reject_announcement call from pallet proxy allowed for proxy account CancelProxy, /// All runtime calls from pallet DappStaking allowed for proxy account - DappsStaking, + DappStaking, /// Only claim_staker call from pallet DappStaking allowed for proxy account StakerRewardClaim, } @@ -1036,13 +1037,15 @@ impl InstanceFilter for ProxyType { ) } // All runtime calls from pallet DappStaking allowed for proxy account - ProxyType::DappsStaking => { - matches!(c, RuntimeCall::DappsStaking(..)) + ProxyType::DappStaking => { + matches!(c, RuntimeCall::DappStaking(..)) } ProxyType::StakerRewardClaim => { matches!( c, - RuntimeCall::DappsStaking(pallet_dapps_staking::Call::claim_staker { .. }) + RuntimeCall::DappStaking( + pallet_dapp_staking_v3::Call::claim_staker_rewards { .. } + ) ) } } @@ -1054,7 +1057,7 @@ impl InstanceFilter for ProxyType { (ProxyType::Any, _) => true, (_, ProxyType::Any) => false, (ProxyType::NonTransfer, _) => true, - (ProxyType::DappsStaking, ProxyType::StakerRewardClaim) => true, + (ProxyType::DappStaking, ProxyType::StakerRewardClaim) => true, _ => false, } } @@ -1728,15 +1731,15 @@ impl_runtime_apis! { } impl dapp_staking_v3_runtime_api::DappStakingApi for Runtime { - fn periods_per_cycle() -> pallet_dapp_staking_v3::PeriodNumber { + fn periods_per_cycle() -> PeriodNumber { InflationCycleConfig::periods_per_cycle() } - fn eras_per_voting_subperiod() -> pallet_dapp_staking_v3::EraNumber { + fn eras_per_voting_subperiod() -> EraNumber { InflationCycleConfig::eras_per_voting_subperiod() } - fn eras_per_build_and_earn_subperiod() -> pallet_dapp_staking_v3::EraNumber { + fn eras_per_build_and_earn_subperiod() -> EraNumber { InflationCycleConfig::eras_per_build_and_earn_subperiod() } @@ -1744,7 +1747,7 @@ impl_runtime_apis! { InflationCycleConfig::blocks_per_era() } - fn get_dapp_tier_assignment() -> BTreeMap { + fn get_dapp_tier_assignment() -> BTreeMap { DappStaking::get_dapp_tier_assignment() } } diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index d618fc5e74..fb314f4d01 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -68,13 +68,13 @@ use sp_runtime::{ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; use astar_primitives::{ - dapp_staking::{CycleConfiguration, SmartContract}, + dapp_staking::{CycleConfiguration, DAppId, EraNumber, PeriodNumber, SmartContract, TierId}, evm::{EvmRevertCodeHandler, HashedDefaultMappings}, xcm::AssetLocationIdConverter, Address, AssetId, BlockNumber, Hash, Header, Index, }; - pub use astar_primitives::{AccountId, Balance, Signature}; + pub use pallet_dapp_staking_v3::TierThreshold; pub use pallet_inflation::InflationParameters; @@ -447,6 +447,7 @@ impl pallet_dapp_staking_v3::Config for Runtime { type NativePriceProvider = StaticPriceProvider; type StakingRewardHandler = Inflation; type CycleConfiguration = InflationCycleConfig; + type Observers = Inflation; type EraRewardSpanLength = ConstU32<16>; type RewardRetentionInPeriods = ConstU32<2>; // Low enough value so we can get some expired rewards during testing type MaxNumberOfContracts = ConstU32<500>; @@ -474,15 +475,15 @@ impl pallet_inflation::PayoutPerBlock for InflationPayoutPerB pub struct InflationCycleConfig; impl CycleConfiguration for InflationCycleConfig { - fn periods_per_cycle() -> u32 { + fn periods_per_cycle() -> PeriodNumber { 2 } - fn eras_per_voting_subperiod() -> u32 { + fn eras_per_voting_subperiod() -> EraNumber { 8 } - fn eras_per_build_and_earn_subperiod() -> u32 { + fn eras_per_build_and_earn_subperiod() -> EraNumber { 20 } @@ -756,7 +757,7 @@ impl WeightToFeePolynomial for WeightToFee { } } -/// Handles coverting weight consumed by XCM into native currency fee. +/// Handles converting weight consumed by XCM into native currency fee. /// /// Similar to standard `WeightToFee` handler, but force uses the minimum multiplier. pub struct XcmWeightToFee; @@ -1386,8 +1387,57 @@ impl Get for InitActivePriceGet { pub type Migrations = ( pallet_static_price_provider::InitActivePrice, pallet_dapp_staking_v3::migrations::DappStakingV3TierRewardAsTree, + pallet_inflation::PalletInflationShibuyaMigration, ); +pub struct NextEraProvider; +impl Get<(EraNumber, Weight)> for NextEraProvider { + fn get() -> (EraNumber, Weight) { + // Prior to executing the migration, `recalculation_era` is still set to the old `recalculation_block` + let target_block = + pallet_inflation::ActiveInflationConfig::::get().recalculation_era; + + let state = pallet_dapp_staking_v3::ActiveProtocolState::::get(); + + // Best case scenario, the target era is the first era of the next period. + use pallet_dapp_staking_v3::Subperiod; + let mut target_era = match state.subperiod() { + Subperiod::Voting => state.era.saturating_add( + InflationCycleConfig::eras_per_build_and_earn_subperiod().saturating_add(1), + ), + Subperiod::BuildAndEarn => state.next_subperiod_start_era(), + }; + + // Adding the whole period length in blocks to the current block number, and comparing it with the target + // is good enough to find the target era. + let period_length_in_blocks = InflationCycleConfig::blocks_per_cycle() + / InflationCycleConfig::periods_per_cycle().max(1); + let mut block = System::block_number().saturating_add(period_length_in_blocks); + + // Max number of iterations is the number of periods per cycle, it's not possible for more than that to occur. + let mut limit = InflationCycleConfig::periods_per_cycle(); + + use sp_runtime::traits::Saturating; + while block < target_block && limit > 0 { + target_era.saturating_accrue(InflationCycleConfig::eras_per_period()); + block.saturating_accrue(period_length_in_blocks); + + limit.saturating_dec() + } + + #[cfg(feature = "try-runtime")] + if block < target_block { + panic!("Failed to find target era for migration, please check for errors"); + } + + // A bit overestimated weight, but it's fine since we have some calculations to execute in this function which consume some time. + ( + target_era, + ::DbWeight::get().reads(3), + ) + } +} + type EventRecord = frame_system::EventRecord< ::RuntimeEvent, ::Hash, @@ -1932,15 +1982,15 @@ impl_runtime_apis! { } impl dapp_staking_v3_runtime_api::DappStakingApi for Runtime { - fn periods_per_cycle() -> pallet_dapp_staking_v3::PeriodNumber { + fn periods_per_cycle() -> PeriodNumber { InflationCycleConfig::periods_per_cycle() } - fn eras_per_voting_subperiod() -> pallet_dapp_staking_v3::EraNumber { + fn eras_per_voting_subperiod() -> EraNumber { InflationCycleConfig::eras_per_voting_subperiod() } - fn eras_per_build_and_earn_subperiod() -> pallet_dapp_staking_v3::EraNumber { + fn eras_per_build_and_earn_subperiod() -> EraNumber { InflationCycleConfig::eras_per_build_and_earn_subperiod() } @@ -1948,7 +1998,7 @@ impl_runtime_apis! { InflationCycleConfig::blocks_per_era() } - fn get_dapp_tier_assignment() -> BTreeMap { + fn get_dapp_tier_assignment() -> BTreeMap { DappStaking::get_dapp_tier_assignment() } } diff --git a/runtime/shibuya/src/weights/pallet_dapp_staking_v3.rs b/runtime/shibuya/src/weights/pallet_dapp_staking_v3.rs index 0bcfcee538..a922b3e6ca 100644 --- a/runtime/shibuya/src/weights/pallet_dapp_staking_v3.rs +++ b/runtime/shibuya/src/weights/pallet_dapp_staking_v3.rs @@ -55,8 +55,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_474_000 picoseconds. - Weight::from_parts(8_711_000, 0) + // Minimum execution time: 9_265_000 picoseconds. + Weight::from_parts(9_422_000, 0) } /// Storage: DappStaking IntegratedDApps (r:1 w:1) /// Proof: DappStaking IntegratedDApps (max_values: Some(65535), max_size: Some(121), added: 2101, mode: MaxEncodedLen) @@ -68,8 +68,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `3091` - // Minimum execution time: 16_360_000 picoseconds. - Weight::from_parts(16_697_000, 3091) + // Minimum execution time: 17_285_000 picoseconds. + Weight::from_parts(17_628_000, 3091) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -79,8 +79,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `75` // Estimated: `3091` - // Minimum execution time: 12_927_000 picoseconds. - Weight::from_parts(13_229_000, 3091) + // Minimum execution time: 13_521_000 picoseconds. + Weight::from_parts(13_819_000, 3091) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -90,8 +90,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `75` // Estimated: `3091` - // Minimum execution time: 13_610_000 picoseconds. - Weight::from_parts(13_851_000, 3091) + // Minimum execution time: 13_797_000 picoseconds. + Weight::from_parts(14_051_000, 3091) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -103,8 +103,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `75` // Estimated: `3091` - // Minimum execution time: 16_704_000 picoseconds. - Weight::from_parts(16_952_000, 3091) + // Minimum execution time: 17_242_000 picoseconds. + Weight::from_parts(17_628_000, 3091) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -120,8 +120,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `12` // Estimated: `4764` - // Minimum execution time: 31_680_000 picoseconds. - Weight::from_parts(32_075_000, 4764) + // Minimum execution time: 32_138_000 picoseconds. + Weight::from_parts(32_677_000, 4764) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -137,8 +137,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `156` // Estimated: `4764` - // Minimum execution time: 34_576_000 picoseconds. - Weight::from_parts(34_777_000, 4764) + // Minimum execution time: 33_789_000 picoseconds. + Weight::from_parts(34_052_000, 4764) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -155,10 +155,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `187` // Estimated: `4764` - // Minimum execution time: 33_562_000 picoseconds. - Weight::from_parts(34_600_552, 4764) - // Standard Error: 5_079 - .saturating_add(Weight::from_parts(193_345, 0).saturating_mul(x.into())) + // Minimum execution time: 35_048_000 picoseconds. + Weight::from_parts(36_286_241, 4764) + // Standard Error: 6_246 + .saturating_add(Weight::from_parts(176_805, 0).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -174,8 +174,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `182` // Estimated: `4764` - // Minimum execution time: 36_436_000 picoseconds. - Weight::from_parts(37_262_000, 4764) + // Minimum execution time: 30_390_000 picoseconds. + Weight::from_parts(30_712_000, 4764) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -197,8 +197,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `250` // Estimated: `4764` - // Minimum execution time: 43_866_000 picoseconds. - Weight::from_parts(44_468_000, 4764) + // Minimum execution time: 44_866_000 picoseconds. + Weight::from_parts(45_342_000, 4764) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -220,8 +220,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `427` // Estimated: `4764` - // Minimum execution time: 47_368_000 picoseconds. - Weight::from_parts(48_049_000, 4764) + // Minimum execution time: 48_475_000 picoseconds. + Weight::from_parts(49_000_000, 4764) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -240,10 +240,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `560` // Estimated: `4764` - // Minimum execution time: 51_230_000 picoseconds. - Weight::from_parts(48_696_805, 4764) - // Standard Error: 6_139 - .saturating_add(Weight::from_parts(3_374_191, 0).saturating_mul(x.into())) + // Minimum execution time: 51_987_000 picoseconds. + Weight::from_parts(49_569_909, 4764) + // Standard Error: 5_547 + .saturating_add(Weight::from_parts(3_433_220, 0).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -260,10 +260,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `501` // Estimated: `4764` - // Minimum execution time: 45_030_000 picoseconds. - Weight::from_parts(43_179_071, 4764) - // Standard Error: 5_547 - .saturating_add(Weight::from_parts(3_296_864, 0).saturating_mul(x.into())) + // Minimum execution time: 48_592_000 picoseconds. + Weight::from_parts(46_136_422, 4764) + // Standard Error: 4_476 + .saturating_add(Weight::from_parts(3_444_512, 0).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -277,21 +277,21 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `267` // Estimated: `3775` - // Minimum execution time: 42_248_000 picoseconds. - Weight::from_parts(42_687_000, 3775) + // Minimum execution time: 38_973_000 picoseconds. + Weight::from_parts(39_533_000, 3775) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: DappStaking IntegratedDApps (r:1 w:0) /// Proof: DappStaking IntegratedDApps (max_values: Some(65535), max_size: Some(121), added: 2101, mode: MaxEncodedLen) /// Storage: DappStaking DAppTiers (r:1 w:1) - /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(2083), added: 4558, mode: MaxEncodedLen) + /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(1583), added: 4058, mode: MaxEncodedLen) fn claim_dapp_reward() -> Weight { // Proof Size summary in bytes: - // Measured: `3021` - // Estimated: `5548` - // Minimum execution time: 50_968_000 picoseconds. - Weight::from_parts(51_778_000, 5548) + // Measured: `2585` + // Estimated: `5048` + // Minimum execution time: 54_909_000 picoseconds. + Weight::from_parts(55_839_000, 5048) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -311,8 +311,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `389` // Estimated: `4764` - // Minimum execution time: 42_329_000 picoseconds. - Weight::from_parts(42_737_000, 4764) + // Minimum execution time: 42_755_000 picoseconds. + Weight::from_parts(43_230_000, 4764) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -329,10 +329,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `255 + x * (69 ±0)` // Estimated: `4764 + x * (2613 ±0)` - // Minimum execution time: 42_222_000 picoseconds. - Weight::from_parts(38_945_386, 4764) - // Standard Error: 14_325 - .saturating_add(Weight::from_parts(5_044_310, 0).saturating_mul(x.into())) + // Minimum execution time: 39_922_000 picoseconds. + Weight::from_parts(36_255_858, 4764) + // Standard Error: 14_366 + .saturating_add(Weight::from_parts(5_135_083, 0).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -343,8 +343,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_971_000 picoseconds. - Weight::from_parts(10_190_000, 0) + // Minimum execution time: 11_519_000 picoseconds. + Weight::from_parts(11_865_000, 0) } /// Storage: DappStaking CurrentEraInfo (r:1 w:1) /// Proof: DappStaking CurrentEraInfo (max_values: Some(1), max_size: Some(112), added: 607, mode: MaxEncodedLen) @@ -354,8 +354,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `16` // Estimated: `4254` - // Minimum execution time: 17_308_000 picoseconds. - Weight::from_parts(17_774_000, 4254) + // Minimum execution time: 17_823_000 picoseconds. + Weight::from_parts(18_413_000, 4254) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -370,13 +370,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: DappStaking PeriodEnd (r:0 w:1) /// Proof: DappStaking PeriodEnd (max_values: None, max_size: Some(48), added: 2523, mode: MaxEncodedLen) /// Storage: DappStaking DAppTiers (r:0 w:1) - /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(2083), added: 4558, mode: MaxEncodedLen) + /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(1583), added: 4058, mode: MaxEncodedLen) fn on_initialize_build_and_earn_to_voting() -> Weight { // Proof Size summary in bytes: // Measured: `550` // Estimated: `4254` - // Minimum execution time: 39_768_000 picoseconds. - Weight::from_parts(40_422_000, 4254) + // Minimum execution time: 41_147_000 picoseconds. + Weight::from_parts(42_304_000, 4254) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -385,13 +385,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: DappStaking EraRewards (r:1 w:1) /// Proof: DappStaking EraRewards (max_values: None, max_size: Some(789), added: 3264, mode: MaxEncodedLen) /// Storage: DappStaking DAppTiers (r:0 w:1) - /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(2083), added: 4558, mode: MaxEncodedLen) + /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(1583), added: 4058, mode: MaxEncodedLen) fn on_initialize_build_and_earn_to_build_and_earn() -> Weight { // Proof Size summary in bytes: // Measured: `68` // Estimated: `4254` - // Minimum execution time: 20_976_000 picoseconds. - Weight::from_parts(21_507_000, 4254) + // Minimum execution time: 23_807_000 picoseconds. + Weight::from_parts(24_367_000, 4254) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -404,10 +404,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `152 + x * (32 ±0)` // Estimated: `3061 + x * (2071 ±0)` - // Minimum execution time: 7_374_000 picoseconds. - Weight::from_parts(10_826_637, 3061) - // Standard Error: 3_374 - .saturating_add(Weight::from_parts(2_291_643, 0).saturating_mul(x.into())) + // Minimum execution time: 7_821_000 picoseconds. + Weight::from_parts(12_000_144, 3061) + // Standard Error: 3_553 + .saturating_add(Weight::from_parts(2_396_421, 0).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) .saturating_add(Weight::from_parts(0, 2071).saturating_mul(x.into())) @@ -419,13 +419,13 @@ impl WeightInfo for SubstrateWeight { /// Storage: DappStaking EraRewards (r:1 w:1) /// Proof: DappStaking EraRewards (max_values: None, max_size: Some(789), added: 3264, mode: MaxEncodedLen) /// Storage: DappStaking DAppTiers (r:0 w:1) - /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(2083), added: 4558, mode: MaxEncodedLen) + /// Proof: DappStaking DAppTiers (max_values: None, max_size: Some(1583), added: 4058, mode: MaxEncodedLen) fn on_idle_cleanup() -> Weight { // Proof Size summary in bytes: // Measured: `473` // Estimated: `4254` - // Minimum execution time: 14_500_000 picoseconds. - Weight::from_parts(14_969_000, 4254) + // Minimum execution time: 17_154_000 picoseconds. + Weight::from_parts(17_535_000, 4254) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } diff --git a/runtime/shibuya/src/weights/pallet_inflation.rs b/runtime/shibuya/src/weights/pallet_inflation.rs index 98616cb747..1fdb896f5c 100644 --- a/runtime/shibuya/src/weights/pallet_inflation.rs +++ b/runtime/shibuya/src/weights/pallet_inflation.rs @@ -57,48 +57,45 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_036_000 picoseconds. - Weight::from_parts(9_186_000, 0) + // Minimum execution time: 9_487_000 picoseconds. + Weight::from_parts(9_652_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } fn force_set_inflation_config() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_073_000 picoseconds. - Weight::from_parts(9_411_000, 0) + // Minimum execution time: 9_168_000 picoseconds. + Weight::from_parts(9_436_000, 0) } /// Storage: Inflation InflationParams (r:1 w:0) /// Proof: Inflation InflationParams (max_values: Some(1), max_size: Some(64), added: 559, mode: MaxEncodedLen) fn force_inflation_recalculation() -> Weight { // Proof Size summary in bytes: - // Measured: `58` + // Measured: `40` // Estimated: `1549` - // Minimum execution time: 14_839_000 picoseconds. - Weight::from_parts(15_198_000, 1549) + // Minimum execution time: 13_496_000 picoseconds. + Weight::from_parts(13_762_000, 1549) .saturating_add(T::DbWeight::get().reads(1_u64)) } - /// Storage: System Account (r:2 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) /// Storage: Inflation InflationParams (r:1 w:0) /// Proof: Inflation InflationParams (max_values: Some(1), max_size: Some(64), added: 559, mode: MaxEncodedLen) - fn hook_with_recalculation() -> Weight { + fn recalculation() -> Weight { // Proof Size summary in bytes: - // Measured: `232` - // Estimated: `6196` - // Minimum execution time: 31_965_000 picoseconds. - Weight::from_parts(32_498_000, 6196) - .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `58` + // Estimated: `1549` + // Minimum execution time: 13_811_000 picoseconds. + Weight::from_parts(13_995_000, 1549) + .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: System Account (r:2 w:1) /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - fn hook_without_recalculation() -> Weight { + fn hooks_without_recalculation() -> Weight { // Proof Size summary in bytes: // Measured: `174` // Estimated: `6196` - // Minimum execution time: 22_235_000 picoseconds. - Weight::from_parts(22_378_000, 6196) + // Minimum execution time: 21_351_000 picoseconds. + Weight::from_parts(21_749_000, 6196) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } diff --git a/tests/integration/Cargo.toml b/tests/integration/Cargo.toml index 557300a54b..1d1696f550 100644 --- a/tests/integration/Cargo.toml +++ b/tests/integration/Cargo.toml @@ -27,6 +27,7 @@ pallet-contracts = { workspace = true } pallet-contracts-primitives = { workspace = true } pallet-dapp-staking-v3 = { workspace = true } pallet-dapps-staking = { workspace = true } +pallet-inflation = { workspace = true } pallet-proxy = { workspace = true } pallet-utility = { workspace = true } sp-core = { workspace = true } diff --git a/tests/integration/src/dapp_staking_v3.rs b/tests/integration/src/dapp_staking_v3.rs new file mode 100644 index 0000000000..1a79c9ccbc --- /dev/null +++ b/tests/integration/src/dapp_staking_v3.rs @@ -0,0 +1,80 @@ +// 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 . + +#![cfg(test)] + +use crate::setup::*; + +use pallet_dapp_staking_v3::*; + +#[test] +fn dapp_staking_triggers_inflation_recalculation() { + new_test_ext().execute_with(|| { + let init_inflation_config = pallet_inflation::ActiveInflationConfig::::get(); + + let recalculation_era = init_inflation_config.recalculation_era; + + // It's not feasible to run through all the blocks needed to trigger all the eras. + // Instead, we force the era to change on a block by block basis. + while ActiveProtocolState::::get().era < recalculation_era - 1 { + assert_ok!(DappStaking::force(RuntimeOrigin::root(), ForcingType::Era,)); + run_for_blocks(1); + assert_eq!( + init_inflation_config, + pallet_inflation::ActiveInflationConfig::::get(), + "Must not change until recalculation" + ); + } + assert_eq!( + ActiveProtocolState::::get().subperiod(), + Subperiod::BuildAndEarn, + "Sanity check." + ); + + // Again, hacky approach to speed things up. + // This doesn't influence anything in the protocol essentially. + ActiveProtocolState::::mutate(|state| { + state.next_era_start = System::block_number() + 5; + }); + + // Another sanity check, move block by block and ensure protocol works as expected. + let target_block = ActiveProtocolState::::get().next_era_start; + run_to_block(target_block - 2); + assert_eq!( + init_inflation_config, + pallet_inflation::ActiveInflationConfig::::get(), + "Sanity check." + ); + + // So far inflation config remained unchanged. + // Now we expect the trigger which will update it. + run_for_blocks(1); + assert_eq!( + init_inflation_config, + pallet_inflation::ActiveInflationConfig::::get(), + "Still the same, should be updated ONLY after the block has been finalized." + ); + + run_for_blocks(1); + let new_inflation_config = pallet_inflation::ActiveInflationConfig::::get(); + assert_ne!( + init_inflation_config, new_inflation_config, + "Must be updated after the block has been finalized." + ); + }); +} diff --git a/tests/integration/src/lib.rs b/tests/integration/src/lib.rs index 7de23893ae..747cc8ff4a 100644 --- a/tests/integration/src/lib.rs +++ b/tests/integration/src/lib.rs @@ -46,5 +46,8 @@ mod dispatch_precompile_filter_old; #[cfg(feature = "shibuya")] mod unified_accounts; +#[cfg(feature = "shibuya")] +mod dapp_staking_v3; + #[cfg(any(feature = "shibuya"))] mod assets_chain_extensions; diff --git a/tests/integration/src/setup.rs b/tests/integration/src/setup.rs index ba266bfe3e..5ce81c65d2 100644 --- a/tests/integration/src/setup.rs +++ b/tests/integration/src/setup.rs @@ -20,7 +20,7 @@ pub use frame_support::{ assert_noop, assert_ok, - traits::{OnFinalize, OnIdle, OnInitialize}, + traits::{GenesisBuild, OnFinalize, OnIdle, OnInitialize}, weights::Weight, }; pub use pallet_evm::AddressMapping; @@ -28,7 +28,7 @@ pub use sp_core::{H160, H256, U256}; pub use sp_io::hashing::keccak_256; pub use sp_runtime::{AccountId32, MultiAddress}; -pub use astar_primitives::evm::UnifiedAddressMapper; +pub use astar_primitives::{evm::UnifiedAddressMapper, BlockNumber}; #[cfg(feature = "shibuya")] pub use shibuya::*; @@ -191,6 +191,14 @@ impl ExtBuilder { .assimilate_storage(&mut t) .unwrap(); + #[cfg(any(feature = "shibuya"))] + // Needed to trigger initial inflation config setting. + >::assimilate_storage( + &pallet_inflation::GenesisConfig::default(), + &mut t, + ) + .unwrap(); + let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); ext @@ -210,7 +218,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { // Block time: 12 seconds. pub const BLOCK_TIME: u64 = 12_000; -pub fn run_to_block(n: u32) { +pub fn run_to_block(n: BlockNumber) { while System::block_number() < n { let block_number = System::block_number(); TransactionPayment::on_finalize(block_number); @@ -252,6 +260,10 @@ pub fn run_to_block(n: u32) { } } +pub fn run_for_blocks(n: BlockNumber) { + run_to_block(System::block_number() + n) +} + fn last_events(n: usize) -> Vec { frame_system::Pallet::::events() .into_iter()