diff --git a/pallets/dapp-staking-v3/src/benchmarking.rs b/pallets/dapp-staking-v3/src/benchmarking.rs index 5f71f00ee3..ac0ac838c7 100644 --- a/pallets/dapp-staking-v3/src/benchmarking.rs +++ b/pallets/dapp-staking-v3/src/benchmarking.rs @@ -74,9 +74,9 @@ pub(crate) fn advance_to_next_era() { // } // /// Advance blocks until next period type has been reached. -// pub(crate) fn advance_to_next_period_type() { -// let period_type = ActiveProtocolState::::get().period_type(); -// while ActiveProtocolState::::get().period_type() == period_type { +// pub(crate) fn advance_to_next_subperiod() { +// let subperiod = ActiveProtocolState::::get().subperiod(); +// while ActiveProtocolState::::get().subperiod() == subperiod { // run_for_blocks::(One::one()); // } // } @@ -99,7 +99,7 @@ pub fn initial_config() { next_era_start: era_length.saturating_mul(voting_period_length_in_eras.into()) + One::one(), period_info: PeriodInfo { number: 1, - period_type: PeriodType::Voting, + subperiod: Subperiod::Voting, ending_era: 2, }, maintenance: false, @@ -217,6 +217,17 @@ mod benchmarks { } } + #[benchmark] + fn experimental_read() { + // Prepare init config (protocol state, tier params & config, etc.) + initial_config::(); + + #[block] + { + let _ = ExperimentalContractEntries::::get(10); + } + } + impl_benchmark_test_suite!( Pallet, crate::benchmarking::tests::new_test_ext(), diff --git a/pallets/dapp-staking-v3/src/dsv3_weight.rs b/pallets/dapp-staking-v3/src/dsv3_weight.rs index 64948127b5..1dca8a56ce 100644 --- a/pallets/dapp-staking-v3/src/dsv3_weight.rs +++ b/pallets/dapp-staking-v3/src/dsv3_weight.rs @@ -20,7 +20,7 @@ //! Autogenerated weights for pallet_dapp_staking_v3 //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-10-30, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-11-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `Dinos-MBP`, CPU: `` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -50,6 +50,7 @@ use core::marker::PhantomData; /// Weight functions needed for pallet_dapp_staking_v3. pub trait WeightInfo { fn dapp_tier_assignment(x: u32, ) -> Weight; + fn experimental_read() -> Weight; } /// Weights for pallet_dapp_staking_v3 using the Substrate node and recommended hardware. @@ -62,19 +63,29 @@ impl WeightInfo for SubstrateWeight { /// Storage: DappStaking IntegratedDApps (r:101 w:0) /// Proof: DappStaking IntegratedDApps (max_values: None, max_size: Some(121), added: 2596, mode: MaxEncodedLen) /// Storage: DappStaking ContractStake (r:100 w:0) - /// Proof: DappStaking ContractStake (max_values: None, max_size: Some(170), added: 2645, mode: MaxEncodedLen) + /// Proof: DappStaking ContractStake (max_values: None, max_size: Some(130), added: 2605, mode: MaxEncodedLen) /// The range of component `x` is `[0, 100]`. fn dapp_tier_assignment(x: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `823 + x * (164 ±0)` - // Estimated: `3586 + x * (2645 ±0)` - // Minimum execution time: 8_000_000 picoseconds. - Weight::from_parts(12_342_575, 3586) - // Standard Error: 16_840 - .saturating_add(Weight::from_parts(7_051_078, 0).saturating_mul(x.into())) + // Measured: `836 + x * (169 ±0)` + // Estimated: `3586 + x * (2605 ±0)` + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(12_879_631, 3586) + // Standard Error: 18_480 + .saturating_add(Weight::from_parts(7_315_677, 0).saturating_mul(x.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(x.into()))) - .saturating_add(Weight::from_parts(0, 2645).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 2605).saturating_mul(x.into())) + } + /// Storage: DappStaking ExperimentalContractEntries (r:1 w:0) + /// Proof: DappStaking ExperimentalContractEntries (max_values: None, max_size: Some(3483), added: 5958, mode: MaxEncodedLen) + fn experimental_read() -> Weight { + // Proof Size summary in bytes: + // Measured: `224` + // Estimated: `6948` + // Minimum execution time: 5_000_000 picoseconds. + Weight::from_parts(5_000_000, 6948) + .saturating_add(T::DbWeight::get().reads(1_u64)) } } @@ -87,18 +98,28 @@ impl WeightInfo for () { /// Storage: DappStaking IntegratedDApps (r:101 w:0) /// Proof: DappStaking IntegratedDApps (max_values: None, max_size: Some(121), added: 2596, mode: MaxEncodedLen) /// Storage: DappStaking ContractStake (r:100 w:0) - /// Proof: DappStaking ContractStake (max_values: None, max_size: Some(170), added: 2645, mode: MaxEncodedLen) + /// Proof: DappStaking ContractStake (max_values: None, max_size: Some(130), added: 2605, mode: MaxEncodedLen) /// The range of component `x` is `[0, 100]`. fn dapp_tier_assignment(x: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `823 + x * (164 ±0)` - // Estimated: `3586 + x * (2645 ±0)` - // Minimum execution time: 8_000_000 picoseconds. - Weight::from_parts(12_342_575, 3586) - // Standard Error: 16_840 - .saturating_add(Weight::from_parts(7_051_078, 0).saturating_mul(x.into())) + // Measured: `836 + x * (169 ±0)` + // Estimated: `3586 + x * (2605 ±0)` + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(12_879_631, 3586) + // Standard Error: 18_480 + .saturating_add(Weight::from_parts(7_315_677, 0).saturating_mul(x.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(x.into()))) - .saturating_add(Weight::from_parts(0, 2645).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 2605).saturating_mul(x.into())) + } + /// Storage: DappStaking ExperimentalContractEntries (r:1 w:0) + /// Proof: DappStaking ExperimentalContractEntries (max_values: None, max_size: Some(3483), added: 5958, mode: MaxEncodedLen) + fn experimental_read() -> Weight { + // Proof Size summary in bytes: + // Measured: `224` + // Estimated: `6948` + // Minimum execution time: 5_000_000 picoseconds. + Weight::from_parts(5_000_000, 6948) + .saturating_add(RocksDbWeight::get().reads(1_u64)) } } diff --git a/pallets/dapp-staking-v3/src/lib.rs b/pallets/dapp-staking-v3/src/lib.rs index ae62162165..441bbb445f 100644 --- a/pallets/dapp-staking-v3/src/lib.rs +++ b/pallets/dapp-staking-v3/src/lib.rs @@ -178,7 +178,7 @@ pub mod pallet { NewEra { era: EraNumber }, /// New period has started. NewPeriod { - period_type: PeriodType, + subperiod: Subperiod, number: PeriodNumber, }, /// A smart contract has been registered for dApp staking @@ -416,6 +416,11 @@ pub mod pallet { pub type DAppTiers = StorageMap<_, Twox64Concat, EraNumber, DAppTierRewardsFor, OptionQuery>; + // TODO: this is experimental, please don't review + #[pallet::storage] + pub type ExperimentalContractEntries = + StorageMap<_, Twox64Concat, EraNumber, ContractEntriesFor, OptionQuery>; + #[pallet::genesis_config] #[derive(frame_support::DefaultNoBound)] pub struct GenesisConfig { @@ -473,7 +478,7 @@ pub mod pallet { next_era_start: Pallet::::blocks_per_voting_period() + 1_u32.into(), period_info: PeriodInfo { number: 1, - period_type: PeriodType::Voting, + subperiod: Subperiod::Voting, ending_era: 2, }, maintenance: false, @@ -510,8 +515,8 @@ pub mod pallet { let current_era = protocol_state.era; let next_era = current_era.saturating_add(1); - let (maybe_period_event, era_reward) = match protocol_state.period_type() { - PeriodType::Voting => { + let (maybe_period_event, era_reward) = match protocol_state.subperiod() { + Subperiod::Voting => { // For the sake of consistency, we put zero reward into storage let era_reward = EraReward { staker_reward_pool: Balance::zero(), @@ -523,9 +528,9 @@ pub mod pallet { next_era.saturating_add(T::StandardErasPerBuildAndEarnPeriod::get()); let build_and_earn_start_block = now.saturating_add(T::StandardEraLength::get()); - protocol_state.into_next_period_type(ending_era, build_and_earn_start_block); + protocol_state.into_next_subperiod(ending_era, build_and_earn_start_block); - era_info.migrate_to_next_era(Some(protocol_state.period_type())); + era_info.migrate_to_next_era(Some(protocol_state.subperiod())); // Update tier configuration to be used when calculating rewards for the upcoming eras let next_tier_config = NextTierConfig::::take(); @@ -533,13 +538,13 @@ pub mod pallet { ( Some(Event::::NewPeriod { - period_type: protocol_state.period_type(), + subperiod: protocol_state.subperiod(), number: protocol_state.period_number(), }), era_reward, ) } - PeriodType::BuildAndEarn => { + Subperiod::BuildAndEarn => { let (staker_reward_pool, dapp_reward_pool) = T::RewardPoolProvider::normal_reward_pools(); let era_reward = EraReward { @@ -564,7 +569,7 @@ pub mod pallet { &protocol_state.period_number(), PeriodEndInfo { bonus_reward_pool, - total_vp_stake: era_info.staked_amount(PeriodType::Voting), + total_vp_stake: era_info.staked_amount(Subperiod::Voting), final_era: current_era, }, ); @@ -575,9 +580,9 @@ pub mod pallet { let voting_period_length = Self::blocks_per_voting_period(); let next_era_start_block = now.saturating_add(voting_period_length); - protocol_state.into_next_period_type(ending_era, next_era_start_block); + protocol_state.into_next_subperiod(ending_era, next_era_start_block); - era_info.migrate_to_next_era(Some(protocol_state.period_type())); + era_info.migrate_to_next_era(Some(protocol_state.subperiod())); // Re-calculate tier configuration for the upcoming new period let tier_params = StaticTierParams::::get(); @@ -588,7 +593,7 @@ pub mod pallet { ( Some(Event::::NewPeriod { - period_type: protocol_state.period_type(), + subperiod: protocol_state.subperiod(), number: protocol_state.period_number(), }), era_reward, @@ -1045,12 +1050,12 @@ pub mod pallet { None => ( SingularStakingInfo::new( protocol_state.period_number(), - protocol_state.period_type(), + protocol_state.subperiod(), ), true, ), }; - new_staking_info.stake(amount, protocol_state.period_type()); + new_staking_info.stake(amount, protocol_state.subperiod()); ensure!( new_staking_info.total_staked_amount() >= T::MinimumStakeAmount::get(), Error::::InsufficientStakeAmount @@ -1072,7 +1077,7 @@ pub mod pallet { // 4. // Update total staked amount for the next era. CurrentEraInfo::::mutate(|era_info| { - era_info.add_stake_amount(amount, protocol_state.period_type()); + era_info.add_stake_amount(amount, protocol_state.subperiod()); }); // 5. @@ -1139,7 +1144,7 @@ pub mod pallet { amount }; - staking_info.unstake(amount, protocol_state.period_type()); + staking_info.unstake(amount, protocol_state.subperiod()); (staking_info, amount) } None => { @@ -1170,7 +1175,7 @@ pub mod pallet { // 4. // Update total staked amount for the next era. CurrentEraInfo::::mutate(|era_info| { - era_info.unstake_amount(amount, protocol_state.period_type()); + era_info.unstake_amount(amount, protocol_state.subperiod()); }); // 5. @@ -1323,7 +1328,7 @@ pub mod pallet { Error::::InternalClaimBonusError ); - let eligible_amount = staker_info.staked_amount(PeriodType::Voting); + let eligible_amount = staker_info.staked_amount(Subperiod::Voting); let bonus_reward = Perbill::from_rational(eligible_amount, period_end_info.total_vp_stake) * period_end_info.bonus_reward_pool; @@ -1447,7 +1452,7 @@ pub mod pallet { // Update total staked amount for the next era. // This means 'fake' stake total amount has been kept until now, even though contract was unregistered. CurrentEraInfo::::mutate(|era_info| { - era_info.unstake_amount(amount, protocol_state.period_type()); + era_info.unstake_amount(amount, protocol_state.subperiod()); }); // Update remaining storage entries @@ -1517,7 +1522,7 @@ pub mod pallet { match force_type { ForcingType::Era => (), - ForcingType::PeriodType => { + ForcingType::Subperiod => { state.period_info.ending_era = state.era.saturating_add(1); } } @@ -1608,6 +1613,13 @@ pub mod pallet { // Even without async backing though, we should have enough capacity to handle this. // UPDATE: might work with async backing, but right now we could handle up to 150 dApps before exceeding the PoV size. + // UPDATE2: instead of taking the approach of reading an ever increasing amount of entries from storage, we can instead adopt an approach + // of eficiently storing composite information into `BTreeMap`. The approach is essentially the same as the one used below to store rewards. + // Each time `stake` or `unstake` are called, corresponding entries are updated. This way we can keep track of all the contract stake in a single DB entry. + // To make the solution more scalable, we could 'split' stake entries into spans, similar as rewards are handled now. + // + // Experiment with an 'experimental' entry shows PoV size of ~7kB induced for entry that can hold up to 100 entries. + let tier_config = TierConfig::::get(); let mut dapp_stakes = Vec::with_capacity(IntegratedDApps::::count() as usize); @@ -1676,6 +1688,9 @@ pub mod pallet { // 4. // Sort by dApp ID, in ascending order (unstable sort should be faster, and stability is guaranteed due to lack of duplicated Ids). + // TODO & Idea: perhaps use BTreeMap instead? It will "sort" automatically based on dApp Id, and we can efficiently remove entries, + // reducing PoV size step by step. + // It's a trade-off between speed and PoV size. Although both are quite minor, so maybe it doesn't matter that much. dapp_tiers.sort_unstable_by(|first, second| first.dapp_id.cmp(&second.dapp_id)); // 5. Calculate rewards. diff --git a/pallets/dapp-staking-v3/src/test/mock.rs b/pallets/dapp-staking-v3/src/test/mock.rs index 8dc7be2a08..a2fdd20a26 100644 --- a/pallets/dapp-staking-v3/src/test/mock.rs +++ b/pallets/dapp-staking-v3/src/test/mock.rs @@ -204,7 +204,7 @@ impl ExtBuilder { next_era_start: era_length.saturating_mul(voting_period_length_in_eras.into()) + 1, period_info: PeriodInfo { number: 1, - period_type: PeriodType::Voting, + subperiod: Subperiod::Voting, ending_era: 2, }, maintenance: false, @@ -304,9 +304,9 @@ pub(crate) fn advance_to_next_period() { } /// Advance blocks until next period type has been reached. -pub(crate) fn advance_to_into_next_period_type() { - let period_type = ActiveProtocolState::::get().period_type(); - while ActiveProtocolState::::get().period_type() == period_type { +pub(crate) fn advance_to_into_next_subperiod() { + let subperiod = ActiveProtocolState::::get().subperiod(); + while ActiveProtocolState::::get().subperiod() == subperiod { run_for_blocks(1); } } diff --git a/pallets/dapp-staking-v3/src/test/testing_utils.rs b/pallets/dapp-staking-v3/src/test/testing_utils.rs index 499cef4d28..3ac63253ab 100644 --- a/pallets/dapp-staking-v3/src/test/testing_utils.rs +++ b/pallets/dapp-staking-v3/src/test/testing_utils.rs @@ -437,7 +437,7 @@ pub(crate) fn assert_stake( let stake_era = pre_snapshot.active_protocol_state.era + 1; let stake_period = pre_snapshot.active_protocol_state.period_number(); - let stake_period_type = pre_snapshot.active_protocol_state.period_type(); + let stake_subperiod = pre_snapshot.active_protocol_state.subperiod(); // Stake on smart contract & verify event assert_ok!(DappStaking::stake( @@ -496,8 +496,8 @@ pub(crate) fn assert_stake( "Total staked amount must increase by the 'amount'" ); assert_eq!( - post_staker_info.staked_amount(stake_period_type), - pre_staker_info.staked_amount(stake_period_type) + amount, + post_staker_info.staked_amount(stake_subperiod), + pre_staker_info.staked_amount(stake_subperiod) + amount, "Staked amount must increase by the 'amount'" ); assert_eq!(post_staker_info.period_number(), stake_period); @@ -516,14 +516,14 @@ pub(crate) fn assert_stake( ); assert!(amount >= ::MinimumStakeAmount::get()); assert_eq!( - post_staker_info.staked_amount(stake_period_type), + post_staker_info.staked_amount(stake_subperiod), amount, "Staked amount must be equal to exactly the 'amount'" ); assert_eq!(post_staker_info.period_number(), stake_period); assert_eq!( post_staker_info.is_loyal(), - stake_period_type == PeriodType::Voting + stake_subperiod == Subperiod::Voting ); } } @@ -537,8 +537,8 @@ pub(crate) fn assert_stake( "Staked amount must increase by the 'amount'" ); assert_eq!( - post_contract_stake.staked_amount(stake_period, stake_period_type), - pre_contract_stake.staked_amount(stake_period, stake_period_type) + amount, + post_contract_stake.staked_amount(stake_period, stake_subperiod), + pre_contract_stake.staked_amount(stake_period, stake_subperiod) + amount, "Staked amount must increase by the 'amount'" ); @@ -561,8 +561,8 @@ pub(crate) fn assert_stake( pre_era_info.total_staked_amount_next_era() + amount ); assert_eq!( - post_era_info.staked_amount_next_era(stake_period_type), - pre_era_info.staked_amount_next_era(stake_period_type) + amount + post_era_info.staked_amount_next_era(stake_subperiod), + pre_era_info.staked_amount_next_era(stake_subperiod) + amount ); } @@ -586,7 +586,7 @@ pub(crate) fn assert_unstake( let _unstake_era = pre_snapshot.active_protocol_state.era; let unstake_period = pre_snapshot.active_protocol_state.period_number(); - let unstake_period_type = pre_snapshot.active_protocol_state.period_type(); + let unstake_subperiod = pre_snapshot.active_protocol_state.subperiod(); let minimum_stake_amount: Balance = ::MinimumStakeAmount::get(); let is_full_unstake = @@ -655,17 +655,17 @@ pub(crate) fn assert_unstake( "Total staked amount must decrease by the 'amount'" ); assert_eq!( - post_staker_info.staked_amount(unstake_period_type), + post_staker_info.staked_amount(unstake_subperiod), pre_staker_info - .staked_amount(unstake_period_type) + .staked_amount(unstake_subperiod) .saturating_sub(amount), "Staked amount must decrease by the 'amount'" ); let is_loyal = pre_staker_info.is_loyal() - && !(unstake_period_type == PeriodType::BuildAndEarn - && post_staker_info.staked_amount(PeriodType::Voting) - < pre_staker_info.staked_amount(PeriodType::Voting)); + && !(unstake_subperiod == 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, @@ -682,9 +682,9 @@ pub(crate) fn assert_unstake( "Staked amount must decreased by the 'amount'" ); assert_eq!( - post_contract_stake.staked_amount(unstake_period, unstake_period_type), + post_contract_stake.staked_amount(unstake_period, unstake_subperiod), pre_contract_stake - .staked_amount(unstake_period, unstake_period_type) + .staked_amount(unstake_period, unstake_subperiod) .saturating_sub(amount), "Staked amount must decreased by the 'amount'" ); @@ -709,22 +709,22 @@ pub(crate) fn assert_unstake( "Total staked amount for the next era must decrease by 'amount'. No overflow is allowed." ); - if unstake_period_type == PeriodType::BuildAndEarn - && pre_era_info.staked_amount_next_era(PeriodType::BuildAndEarn) < amount + if unstake_subperiod == Subperiod::BuildAndEarn + && pre_era_info.staked_amount_next_era(Subperiod::BuildAndEarn) < amount { - let overflow = amount - pre_era_info.staked_amount_next_era(PeriodType::BuildAndEarn); + let overflow = amount - pre_era_info.staked_amount_next_era(Subperiod::BuildAndEarn); assert!(post_era_info - .staked_amount_next_era(PeriodType::BuildAndEarn) + .staked_amount_next_era(Subperiod::BuildAndEarn) .is_zero()); assert_eq!( - post_era_info.staked_amount_next_era(PeriodType::Voting), - pre_era_info.staked_amount_next_era(PeriodType::Voting) - overflow + post_era_info.staked_amount_next_era(Subperiod::Voting), + pre_era_info.staked_amount_next_era(Subperiod::Voting) - overflow ); } else { assert_eq!( - post_era_info.staked_amount_next_era(unstake_period_type), - pre_era_info.staked_amount_next_era(unstake_period_type) - amount + post_era_info.staked_amount_next_era(unstake_subperiod), + pre_era_info.staked_amount_next_era(unstake_subperiod) - amount ); } } @@ -866,7 +866,7 @@ pub(crate) fn assert_claim_bonus_reward(account: AccountId, smart_contract: &Moc let pre_free_balance = ::Currency::free_balance(&account); let staked_period = pre_staker_info.period_number(); - let stake_amount = pre_staker_info.staked_amount(PeriodType::Voting); + let stake_amount = pre_staker_info.staked_amount(Subperiod::Voting); let period_end_info = pre_snapshot .period_end diff --git a/pallets/dapp-staking-v3/src/test/tests.rs b/pallets/dapp-staking-v3/src/test/tests.rs index 4b23f8c784..acc842314e 100644 --- a/pallets/dapp-staking-v3/src/test/tests.rs +++ b/pallets/dapp-staking-v3/src/test/tests.rs @@ -20,7 +20,7 @@ use crate::test::mock::*; use crate::test::testing_utils::*; use crate::{ pallet::Config, ActiveProtocolState, DAppId, EraNumber, EraRewards, Error, ForcingType, - IntegratedDApps, Ledger, NextDAppId, PeriodNumber, PeriodType, + IntegratedDApps, Ledger, NextDAppId, PeriodNumber, Subperiod, }; use frame_support::{assert_noop, assert_ok, error::BadOrigin, traits::Get}; @@ -34,8 +34,13 @@ fn print_test() { ExtBuilder::build().execute_with(|| { use crate::dsv3_weight::WeightInfo; println!( - ">>> {:?}", - crate::dsv3_weight::SubstrateWeight::::dapp_tier_assignment(200) + ">>> dApp tier assignment reading & calculation {:?}", + crate::dsv3_weight::SubstrateWeight::::dapp_tier_assignment(100) + ); + + println!( + ">>> Experimental storage entry read {:?}", + crate::dsv3_weight::SubstrateWeight::::experimental_read() ); }) } @@ -156,7 +161,7 @@ fn on_initialize_state_change_works() { let protocol_state = ActiveProtocolState::::get(); assert_eq!(protocol_state.era, 1); assert_eq!(protocol_state.period_number(), 1); - assert_eq!(protocol_state.period_type(), PeriodType::Voting); + assert_eq!(protocol_state.subperiod(), Subperiod::Voting); assert_eq!(System::block_number(), 1); let blocks_per_voting_period = DappStaking::blocks_per_voting_period(); @@ -170,15 +175,15 @@ fn on_initialize_state_change_works() { run_to_block(protocol_state.next_era_start - 1); let protocol_state = ActiveProtocolState::::get(); assert_eq!( - protocol_state.period_type(), - PeriodType::Voting, + protocol_state.subperiod(), + Subperiod::Voting, "Period type should still be the same." ); assert_eq!(protocol_state.era, 1); run_for_blocks(1); let protocol_state = ActiveProtocolState::::get(); - assert_eq!(protocol_state.period_type(), PeriodType::BuildAndEarn); + assert_eq!(protocol_state.subperiod(), Subperiod::BuildAndEarn); assert_eq!(protocol_state.era, 2); assert_eq!(protocol_state.period_number(), 1); @@ -191,7 +196,7 @@ fn on_initialize_state_change_works() { advance_to_next_era(); assert_eq!(System::block_number(), pre_block + blocks_per_era); let protocol_state = ActiveProtocolState::::get(); - assert_eq!(protocol_state.period_type(), PeriodType::BuildAndEarn); + assert_eq!(protocol_state.subperiod(), Subperiod::BuildAndEarn); assert_eq!(protocol_state.period_number(), 1); assert_eq!(protocol_state.era, era + 1); } @@ -199,7 +204,7 @@ fn on_initialize_state_change_works() { // Finaly 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.period_type(), PeriodType::Voting); + assert_eq!(protocol_state.subperiod(), Subperiod::Voting); assert_eq!(protocol_state.era, 2 + eras_per_bep_period); assert_eq!( protocol_state.next_era_start, @@ -864,7 +869,7 @@ fn stake_in_final_era_fails() { // Force Build&Earn period ActiveProtocolState::::mutate(|state| { - state.period_info.period_type = PeriodType::BuildAndEarn; + state.period_info.subperiod = Subperiod::BuildAndEarn; state.period_info.ending_era = state.era + 1; }); @@ -1287,7 +1292,7 @@ fn claim_staker_rewards_after_expiry_fails() { advance_to_period( ActiveProtocolState::::get().period_number() + reward_retention_in_periods, ); - advance_to_into_next_period_type(); + advance_to_into_next_subperiod(); advance_to_era(ActiveProtocolState::::get().period_info.ending_era - 1); assert_claim_staker_rewards(account); @@ -1412,10 +1417,10 @@ fn claim_bonus_reward_with_only_build_and_earn_stake_fails() { assert_lock(account, lock_amount); // Stake in Build&Earn period type, advance to next era and try to claim bonus reward - advance_to_into_next_period_type(); + advance_to_into_next_subperiod(); assert_eq!( - ActiveProtocolState::::get().period_type(), - PeriodType::BuildAndEarn, + ActiveProtocolState::::get().subperiod(), + Subperiod::BuildAndEarn, "Sanity check." ); let stake_amount = 93; diff --git a/pallets/dapp-staking-v3/src/test/tests_types.rs b/pallets/dapp-staking-v3/src/test/tests_types.rs index ee12676228..5f90691794 100644 --- a/pallets/dapp-staking-v3/src/test/tests_types.rs +++ b/pallets/dapp-staking-v3/src/test/tests_types.rs @@ -37,20 +37,20 @@ macro_rules! get_u32_type { } #[test] -fn period_type_sanity_check() { - assert_eq!(PeriodType::Voting.next(), PeriodType::BuildAndEarn); - assert_eq!(PeriodType::BuildAndEarn.next(), PeriodType::Voting); +fn subperiod_sanity_check() { + assert_eq!(Subperiod::Voting.next(), Subperiod::BuildAndEarn); + assert_eq!(Subperiod::BuildAndEarn.next(), Subperiod::Voting); } #[test] fn period_info_basic_checks() { let period_number = 2; let ending_era = 5; - let info = PeriodInfo::new(period_number, PeriodType::Voting, ending_era); + let info = PeriodInfo::new(period_number, Subperiod::Voting, ending_era); // Sanity checks assert_eq!(info.number, period_number); - assert_eq!(info.period_type, PeriodType::Voting); + assert_eq!(info.subperiod, Subperiod::Voting); assert_eq!(info.ending_era, ending_era); // Voting period checks @@ -65,7 +65,7 @@ fn period_info_basic_checks() { } // Build&Earn period checks - let info = PeriodInfo::new(period_number, PeriodType::BuildAndEarn, ending_era); + let info = PeriodInfo::new(period_number, Subperiod::BuildAndEarn, ending_era); assert!(!info.is_next_period(ending_era - 1)); assert!(info.is_next_period(ending_era)); assert!(info.is_next_period(ending_era + 1)); @@ -88,11 +88,11 @@ fn protocol_state_basic_checks() { let period_number = 5; let ending_era = 11; let next_era_start = 31; - protocol_state.period_info = PeriodInfo::new(period_number, PeriodType::Voting, ending_era); + protocol_state.period_info = PeriodInfo::new(period_number, Subperiod::Voting, ending_era); protocol_state.next_era_start = next_era_start; assert_eq!(protocol_state.period_number(), period_number); - assert_eq!(protocol_state.period_type(), PeriodType::Voting); + assert_eq!(protocol_state.subperiod(), Subperiod::Voting); // New era check assert!(!protocol_state.is_new_era(next_era_start - 1)); @@ -102,8 +102,8 @@ fn protocol_state_basic_checks() { // Toggle new period type check - 'Voting' to 'BuildAndEarn' let ending_era_1 = 23; let next_era_start_1 = 41; - protocol_state.into_next_period_type(ending_era_1, next_era_start_1); - assert_eq!(protocol_state.period_type(), PeriodType::BuildAndEarn); + protocol_state.into_next_subperiod(ending_era_1, next_era_start_1); + assert_eq!(protocol_state.subperiod(), Subperiod::BuildAndEarn); assert_eq!( protocol_state.period_number(), period_number, @@ -116,8 +116,8 @@ fn protocol_state_basic_checks() { // Toggle from 'BuildAndEarn' over to 'Voting' let ending_era_2 = 24; let next_era_start_2 = 91; - protocol_state.into_next_period_type(ending_era_2, next_era_start_2); - assert_eq!(protocol_state.period_type(), PeriodType::Voting); + protocol_state.into_next_subperiod(ending_era_2, next_era_start_2); + assert_eq!(protocol_state.subperiod(), Subperiod::Voting); assert_eq!( protocol_state.period_number(), period_number + 1, @@ -328,20 +328,20 @@ fn account_ledger_staked_amount_for_type_works() { // Correct period should return staked amounts assert_eq!( - acc_ledger.staked_amount_for_type(PeriodType::Voting, period), + acc_ledger.staked_amount_for_type(Subperiod::Voting, period), voting_1 ); assert_eq!( - acc_ledger.staked_amount_for_type(PeriodType::BuildAndEarn, period), + acc_ledger.staked_amount_for_type(Subperiod::BuildAndEarn, period), build_and_earn_1 ); // Inocrrect period should simply return 0 assert!(acc_ledger - .staked_amount_for_type(PeriodType::Voting, period - 1) + .staked_amount_for_type(Subperiod::Voting, period - 1) .is_zero()); assert!(acc_ledger - .staked_amount_for_type(PeriodType::BuildAndEarn, period - 1) + .staked_amount_for_type(Subperiod::BuildAndEarn, period - 1) .is_zero()); // 2nd scenario - both entries are set, but 'future' must be relevant one. @@ -355,20 +355,20 @@ fn account_ledger_staked_amount_for_type_works() { // Correct period should return staked amounts assert_eq!( - acc_ledger.staked_amount_for_type(PeriodType::Voting, period), + acc_ledger.staked_amount_for_type(Subperiod::Voting, period), voting_2 ); assert_eq!( - acc_ledger.staked_amount_for_type(PeriodType::BuildAndEarn, period), + acc_ledger.staked_amount_for_type(Subperiod::BuildAndEarn, period), build_and_earn_2 ); // Inocrrect period should simply return 0 assert!(acc_ledger - .staked_amount_for_type(PeriodType::Voting, period - 1) + .staked_amount_for_type(Subperiod::Voting, period - 1) .is_zero()); assert!(acc_ledger - .staked_amount_for_type(PeriodType::BuildAndEarn, period - 1) + .staked_amount_for_type(Subperiod::BuildAndEarn, period - 1) .is_zero()); } @@ -463,7 +463,7 @@ fn account_ledger_add_stake_amount_basic_example_works() { // Sanity check let period_number = 2; assert!(acc_ledger - .add_stake_amount(0, 0, PeriodInfo::new(period_number, PeriodType::Voting, 0)) + .add_stake_amount(0, 0, PeriodInfo::new(period_number, Subperiod::Voting, 0)) .is_ok()); assert!(acc_ledger.staked.is_empty()); assert!(acc_ledger.staked_future.is_none()); @@ -471,7 +471,7 @@ fn account_ledger_add_stake_amount_basic_example_works() { // 1st scenario - stake some amount in Voting period, and ensure values are as expected. let first_era = 1; let period_1 = 1; - let period_info_1 = PeriodInfo::new(period_1, PeriodType::Voting, 100); + let period_info_1 = PeriodInfo::new(period_1, Subperiod::Voting, 100); let lock_amount = 17; let stake_amount = 11; acc_ledger.add_lock_amount(lock_amount); @@ -495,26 +495,26 @@ fn account_ledger_add_stake_amount_basic_example_works() { assert!(acc_ledger.staked_future.unwrap().build_and_earn.is_zero()); assert_eq!(acc_ledger.staked_amount(period_1), stake_amount); assert_eq!( - acc_ledger.staked_amount_for_type(PeriodType::Voting, period_1), + acc_ledger.staked_amount_for_type(Subperiod::Voting, period_1), stake_amount ); assert!(acc_ledger - .staked_amount_for_type(PeriodType::BuildAndEarn, period_1) + .staked_amount_for_type(Subperiod::BuildAndEarn, period_1) .is_zero()); // Second scenario - stake some more, but to the next period type let snapshot = acc_ledger.staked; - let period_info_2 = PeriodInfo::new(period_1, PeriodType::BuildAndEarn, 100); + let period_info_2 = PeriodInfo::new(period_1, Subperiod::BuildAndEarn, 100); assert!(acc_ledger .add_stake_amount(1, first_era, period_info_2) .is_ok()); assert_eq!(acc_ledger.staked_amount(period_1), stake_amount + 1); assert_eq!( - acc_ledger.staked_amount_for_type(PeriodType::Voting, period_1), + acc_ledger.staked_amount_for_type(Subperiod::Voting, period_1), stake_amount ); assert_eq!( - acc_ledger.staked_amount_for_type(PeriodType::BuildAndEarn, period_1), + acc_ledger.staked_amount_for_type(Subperiod::BuildAndEarn, period_1), 1 ); assert_eq!(acc_ledger.staked, snapshot); @@ -528,7 +528,7 @@ fn account_ledger_add_stake_amount_advanced_example_works() { // 1st scenario - stake some amount, and ensure values are as expected. let first_era = 1; let period_1 = 1; - let period_info_1 = PeriodInfo::new(period_1, PeriodType::Voting, 100); + let period_info_1 = PeriodInfo::new(period_1, Subperiod::Voting, 100); let lock_amount = 17; let stake_amount_1 = 11; acc_ledger.add_lock_amount(lock_amount); @@ -550,14 +550,14 @@ fn account_ledger_add_stake_amount_advanced_example_works() { "This entry must remain unchanged." ); assert_eq!( - acc_ledger.staked_amount_for_type(PeriodType::Voting, period_1), + acc_ledger.staked_amount_for_type(Subperiod::Voting, period_1), stake_amount_1 + stake_amount_2 ); assert_eq!( acc_ledger .staked_future .unwrap() - .for_type(PeriodType::Voting), + .for_type(Subperiod::Voting), stake_amount_1 + stake_amount_2 ); assert_eq!(acc_ledger.staked_future.unwrap().era, first_era + 1); @@ -571,7 +571,7 @@ fn account_ledger_add_stake_amount_invalid_era_or_period_fails() { // Prep actions let first_era = 5; let period_1 = 2; - let period_info_1 = PeriodInfo::new(period_1, PeriodType::Voting, 100); + let period_info_1 = PeriodInfo::new(period_1, Subperiod::Voting, 100); let lock_amount = 13; let stake_amount = 7; acc_ledger.add_lock_amount(lock_amount); @@ -590,7 +590,7 @@ fn account_ledger_add_stake_amount_invalid_era_or_period_fails() { acc_ledger.add_stake_amount( 1, first_era, - PeriodInfo::new(period_1 + 1, PeriodType::Voting, 100) + PeriodInfo::new(period_1 + 1, Subperiod::Voting, 100) ), Err(AccountLedgerError::InvalidPeriod) ); @@ -607,7 +607,7 @@ fn account_ledger_add_stake_amount_invalid_era_or_period_fails() { acc_ledger.add_stake_amount( 1, first_era, - PeriodInfo::new(period_1 + 1, PeriodType::Voting, 100) + PeriodInfo::new(period_1 + 1, Subperiod::Voting, 100) ), Err(AccountLedgerError::InvalidPeriod) ); @@ -620,14 +620,14 @@ fn account_ledger_add_stake_amount_too_large_amount_fails() { // Sanity check assert_eq!( - acc_ledger.add_stake_amount(10, 1, PeriodInfo::new(1, PeriodType::Voting, 100)), + acc_ledger.add_stake_amount(10, 1, PeriodInfo::new(1, Subperiod::Voting, 100)), Err(AccountLedgerError::UnavailableStakeFunds) ); // Lock some amount, and try to stake more than that let first_era = 5; let period_1 = 2; - let period_info_1 = PeriodInfo::new(period_1, PeriodType::Voting, 100); + let period_info_1 = PeriodInfo::new(period_1, Subperiod::Voting, 100); let lock_amount = 13; acc_ledger.add_lock_amount(lock_amount); assert_eq!( @@ -654,7 +654,7 @@ fn account_ledger_unstake_amount_basic_scenario_works() { let amount_1 = 19; let era_1 = 2; let period_1 = 1; - let period_info_1 = PeriodInfo::new(period_1, PeriodType::BuildAndEarn, 100); + let period_info_1 = PeriodInfo::new(period_1, Subperiod::BuildAndEarn, 100); acc_ledger.add_lock_amount(amount_1); let mut acc_ledger_2 = acc_ledger.clone(); @@ -701,7 +701,7 @@ fn account_ledger_unstake_amount_advanced_scenario_works() { let amount_1 = 19; let era_1 = 2; let period_1 = 1; - let period_info_1 = PeriodInfo::new(period_1, PeriodType::BuildAndEarn, 100); + let period_info_1 = PeriodInfo::new(period_1, Subperiod::BuildAndEarn, 100); acc_ledger.add_lock_amount(amount_1); // We have two entries at once @@ -719,20 +719,20 @@ fn account_ledger_unstake_amount_advanced_scenario_works() { ); assert_eq!( - acc_ledger.staked.for_type(PeriodType::Voting), + acc_ledger.staked.for_type(Subperiod::Voting), amount_1 - 1 - 3 ); assert_eq!( acc_ledger .staked_future .unwrap() - .for_type(PeriodType::Voting), + .for_type(Subperiod::Voting), amount_1 - 3 ); assert!(acc_ledger .staked_future .unwrap() - .for_type(PeriodType::BuildAndEarn) + .for_type(Subperiod::BuildAndEarn) .is_zero()); // 2nd scenario - perform full unstake @@ -755,7 +755,7 @@ fn account_ledger_unstake_amount_advanced_scenario_works() { acc_ledger .staked_future .unwrap() - .for_type(PeriodType::BuildAndEarn), + .for_type(Subperiod::BuildAndEarn), amount_2 ); } @@ -769,7 +769,7 @@ fn account_ledger_unstake_from_invalid_era_fails() { let amount_1 = 13; let era_1 = 2; let period_1 = 1; - let period_info_1 = PeriodInfo::new(period_1, PeriodType::BuildAndEarn, 100); + let period_info_1 = PeriodInfo::new(period_1, Subperiod::BuildAndEarn, 100); acc_ledger.add_lock_amount(amount_1); assert!(acc_ledger .add_stake_amount(amount_1, era_1, period_info_1) @@ -786,7 +786,7 @@ fn account_ledger_unstake_from_invalid_era_fails() { acc_ledger.unstake_amount( 1, era_1, - PeriodInfo::new(period_1 + 1, PeriodType::Voting, 100) + PeriodInfo::new(period_1 + 1, Subperiod::Voting, 100) ), Err(AccountLedgerError::InvalidPeriod) ); @@ -803,7 +803,7 @@ fn account_ledger_unstake_from_invalid_era_fails() { acc_ledger.unstake_amount( 1, era_1, - PeriodInfo::new(period_1 + 1, PeriodType::Voting, 100) + PeriodInfo::new(period_1 + 1, Subperiod::Voting, 100) ), Err(AccountLedgerError::InvalidPeriod) ); @@ -818,7 +818,7 @@ fn account_ledger_unstake_too_much_fails() { let amount_1 = 23; let era_1 = 2; let period_1 = 1; - let period_info_1 = PeriodInfo::new(period_1, PeriodType::BuildAndEarn, 100); + let period_info_1 = PeriodInfo::new(period_1, Subperiod::BuildAndEarn, 100); acc_ledger.add_lock_amount(amount_1); assert!(acc_ledger .add_stake_amount(amount_1, era_1, period_info_1) @@ -847,7 +847,7 @@ fn account_ledger_unlockable_amount_works() { // Some amount is staked, period matches let stake_period = 5; let stake_amount = 17; - let period_info = PeriodInfo::new(stake_period, PeriodType::Voting, 100); + let period_info = PeriodInfo::new(stake_period, Subperiod::Voting, 100); assert!(acc_ledger .add_stake_amount(stake_amount, lock_era, period_info) .is_ok()); @@ -985,10 +985,10 @@ fn era_info_stake_works() { // Add some voting period stake let vp_stake_amount = 7; - era_info.add_stake_amount(vp_stake_amount, PeriodType::Voting); + era_info.add_stake_amount(vp_stake_amount, Subperiod::Voting); assert_eq!(era_info.total_staked_amount_next_era(), vp_stake_amount); assert_eq!( - era_info.staked_amount_next_era(PeriodType::Voting), + era_info.staked_amount_next_era(Subperiod::Voting), vp_stake_amount ); assert!( @@ -998,13 +998,13 @@ fn era_info_stake_works() { // Add some build&earn period stake let bep_stake_amount = 13; - era_info.add_stake_amount(bep_stake_amount, PeriodType::BuildAndEarn); + era_info.add_stake_amount(bep_stake_amount, Subperiod::BuildAndEarn); assert_eq!( era_info.total_staked_amount_next_era(), vp_stake_amount + bep_stake_amount ); assert_eq!( - era_info.staked_amount_next_era(PeriodType::BuildAndEarn), + era_info.staked_amount_next_era(Subperiod::BuildAndEarn), bep_stake_amount ); assert!( @@ -1032,15 +1032,15 @@ fn era_info_unstake_works() { // 1st scenario - unstake some amount, no overflow let unstake_amount_1 = bep_stake_amount_1; - era_info.unstake_amount(unstake_amount_1, PeriodType::BuildAndEarn); + era_info.unstake_amount(unstake_amount_1, Subperiod::BuildAndEarn); // Current era assert_eq!( era_info.total_staked_amount(), total_staked - unstake_amount_1 ); - assert_eq!(era_info.staked_amount(PeriodType::Voting), vp_stake_amount); - assert!(era_info.staked_amount(PeriodType::BuildAndEarn).is_zero()); + assert_eq!(era_info.staked_amount(Subperiod::Voting), vp_stake_amount); + assert!(era_info.staked_amount(Subperiod::BuildAndEarn).is_zero()); // Next era assert_eq!( @@ -1048,18 +1048,18 @@ fn era_info_unstake_works() { total_staked_next_era - unstake_amount_1 ); assert_eq!( - era_info.staked_amount_next_era(PeriodType::Voting), + era_info.staked_amount_next_era(Subperiod::Voting), vp_stake_amount ); assert_eq!( - era_info.staked_amount_next_era(PeriodType::BuildAndEarn), + era_info.staked_amount_next_era(Subperiod::BuildAndEarn), bep_stake_amount_2 - unstake_amount_1 ); // 2nd scenario - unstake some more, but with overflow let overflow = 2; let unstake_amount_2 = bep_stake_amount_2 - unstake_amount_1 + overflow; - era_info.unstake_amount(unstake_amount_2, PeriodType::BuildAndEarn); + era_info.unstake_amount(unstake_amount_2, Subperiod::BuildAndEarn); // Current era assert_eq!( @@ -1073,11 +1073,11 @@ fn era_info_unstake_works() { vp_stake_amount - overflow ); assert_eq!( - era_info.staked_amount_next_era(PeriodType::Voting), + era_info.staked_amount_next_era(Subperiod::Voting), vp_stake_amount - overflow ); assert!(era_info - .staked_amount_next_era(PeriodType::BuildAndEarn) + .staked_amount_next_era(Subperiod::BuildAndEarn) .is_zero()); } @@ -1087,101 +1087,101 @@ fn stake_amount_works() { // Sanity check assert!(stake_amount.total().is_zero()); - assert!(stake_amount.for_type(PeriodType::Voting).is_zero()); - assert!(stake_amount.for_type(PeriodType::BuildAndEarn).is_zero()); + assert!(stake_amount.for_type(Subperiod::Voting).is_zero()); + assert!(stake_amount.for_type(Subperiod::BuildAndEarn).is_zero()); // Stake some amount in voting period let vp_stake_1 = 11; - stake_amount.add(vp_stake_1, PeriodType::Voting); + stake_amount.add(vp_stake_1, Subperiod::Voting); assert_eq!(stake_amount.total(), vp_stake_1); - assert_eq!(stake_amount.for_type(PeriodType::Voting), vp_stake_1); - assert!(stake_amount.for_type(PeriodType::BuildAndEarn).is_zero()); + assert_eq!(stake_amount.for_type(Subperiod::Voting), vp_stake_1); + assert!(stake_amount.for_type(Subperiod::BuildAndEarn).is_zero()); // Stake some amount in build&earn period let bep_stake_1 = 13; - stake_amount.add(bep_stake_1, PeriodType::BuildAndEarn); + stake_amount.add(bep_stake_1, Subperiod::BuildAndEarn); assert_eq!(stake_amount.total(), vp_stake_1 + bep_stake_1); - assert_eq!(stake_amount.for_type(PeriodType::Voting), vp_stake_1); - assert_eq!(stake_amount.for_type(PeriodType::BuildAndEarn), bep_stake_1); + assert_eq!(stake_amount.for_type(Subperiod::Voting), vp_stake_1); + assert_eq!(stake_amount.for_type(Subperiod::BuildAndEarn), bep_stake_1); // Unstake some amount from voting period let vp_unstake_1 = 5; - stake_amount.subtract(5, PeriodType::Voting); + stake_amount.subtract(5, Subperiod::Voting); assert_eq!( stake_amount.total(), vp_stake_1 + bep_stake_1 - vp_unstake_1 ); assert_eq!( - stake_amount.for_type(PeriodType::Voting), + stake_amount.for_type(Subperiod::Voting), vp_stake_1 - vp_unstake_1 ); - assert_eq!(stake_amount.for_type(PeriodType::BuildAndEarn), bep_stake_1); + assert_eq!(stake_amount.for_type(Subperiod::BuildAndEarn), bep_stake_1); // Unstake some amount from build&earn period let bep_unstake_1 = 2; - stake_amount.subtract(bep_unstake_1, PeriodType::BuildAndEarn); + stake_amount.subtract(bep_unstake_1, Subperiod::BuildAndEarn); assert_eq!( stake_amount.total(), vp_stake_1 + bep_stake_1 - vp_unstake_1 - bep_unstake_1 ); assert_eq!( - stake_amount.for_type(PeriodType::Voting), + stake_amount.for_type(Subperiod::Voting), vp_stake_1 - vp_unstake_1 ); assert_eq!( - stake_amount.for_type(PeriodType::BuildAndEarn), + stake_amount.for_type(Subperiod::BuildAndEarn), bep_stake_1 - bep_unstake_1 ); // Unstake some more from build&earn period, and chip away from the voting period let total_stake = vp_stake_1 + bep_stake_1 - vp_unstake_1 - bep_unstake_1; let bep_unstake_2 = bep_stake_1 - bep_unstake_1 + 1; - stake_amount.subtract(bep_unstake_2, PeriodType::BuildAndEarn); + stake_amount.subtract(bep_unstake_2, Subperiod::BuildAndEarn); assert_eq!(stake_amount.total(), total_stake - bep_unstake_2); assert_eq!( - stake_amount.for_type(PeriodType::Voting), + stake_amount.for_type(Subperiod::Voting), vp_stake_1 - vp_unstake_1 - 1 ); - assert!(stake_amount.for_type(PeriodType::BuildAndEarn).is_zero()); + assert!(stake_amount.for_type(Subperiod::BuildAndEarn).is_zero()); } #[test] fn singular_staking_info_basics_are_ok() { let period_number = 3; - let period_type = PeriodType::Voting; - let mut staking_info = SingularStakingInfo::new(period_number, period_type); + let subperiod = Subperiod::Voting; + let mut staking_info = SingularStakingInfo::new(period_number, subperiod); // Sanity checks assert_eq!(staking_info.period_number(), period_number); assert!(staking_info.is_loyal()); assert!(staking_info.total_staked_amount().is_zero()); - assert!(!SingularStakingInfo::new(period_number, PeriodType::BuildAndEarn).is_loyal()); + assert!(!SingularStakingInfo::new(period_number, Subperiod::BuildAndEarn).is_loyal()); // Add some staked amount during `Voting` period let vote_stake_amount_1 = 11; - staking_info.stake(vote_stake_amount_1, PeriodType::Voting); + staking_info.stake(vote_stake_amount_1, Subperiod::Voting); assert_eq!(staking_info.total_staked_amount(), vote_stake_amount_1); assert_eq!( - staking_info.staked_amount(PeriodType::Voting), + staking_info.staked_amount(Subperiod::Voting), vote_stake_amount_1 ); assert!(staking_info - .staked_amount(PeriodType::BuildAndEarn) + .staked_amount(Subperiod::BuildAndEarn) .is_zero()); // Add some staked amount during `BuildAndEarn` period let bep_stake_amount_1 = 23; - staking_info.stake(bep_stake_amount_1, PeriodType::BuildAndEarn); + staking_info.stake(bep_stake_amount_1, Subperiod::BuildAndEarn); assert_eq!( staking_info.total_staked_amount(), vote_stake_amount_1 + bep_stake_amount_1 ); assert_eq!( - staking_info.staked_amount(PeriodType::Voting), + staking_info.staked_amount(Subperiod::Voting), vote_stake_amount_1 ); assert_eq!( - staking_info.staked_amount(PeriodType::BuildAndEarn), + staking_info.staked_amount(Subperiod::BuildAndEarn), bep_stake_amount_1 ); } @@ -1189,17 +1189,17 @@ fn singular_staking_info_basics_are_ok() { #[test] fn singular_staking_info_unstake_during_voting_is_ok() { let period_number = 3; - let period_type = PeriodType::Voting; - let mut staking_info = SingularStakingInfo::new(period_number, period_type); + let subperiod = Subperiod::Voting; + let mut staking_info = SingularStakingInfo::new(period_number, subperiod); // Prep actions let vote_stake_amount_1 = 11; - staking_info.stake(vote_stake_amount_1, PeriodType::Voting); + staking_info.stake(vote_stake_amount_1, Subperiod::Voting); // Unstake some amount during `Voting` period, loyalty should remain as expected. let unstake_amount_1 = 5; assert_eq!( - staking_info.unstake(unstake_amount_1, PeriodType::Voting), + staking_info.unstake(unstake_amount_1, Subperiod::Voting), (unstake_amount_1, Balance::zero()) ); assert_eq!( @@ -1211,7 +1211,7 @@ fn singular_staking_info_unstake_during_voting_is_ok() { // Fully unstake, attempting to undersaturate, and ensure loyalty flag is still true. let remaining_stake = staking_info.total_staked_amount(); assert_eq!( - staking_info.unstake(remaining_stake + 1, PeriodType::Voting), + staking_info.unstake(remaining_stake + 1, Subperiod::Voting), (remaining_stake, Balance::zero()) ); assert!(staking_info.total_staked_amount().is_zero()); @@ -1221,19 +1221,19 @@ fn singular_staking_info_unstake_during_voting_is_ok() { #[test] fn singular_staking_info_unstake_during_bep_is_ok() { let period_number = 3; - let period_type = PeriodType::Voting; - let mut staking_info = SingularStakingInfo::new(period_number, period_type); + let subperiod = Subperiod::Voting; + let mut staking_info = SingularStakingInfo::new(period_number, subperiod); // Prep actions let vote_stake_amount_1 = 11; - staking_info.stake(vote_stake_amount_1, PeriodType::Voting); + staking_info.stake(vote_stake_amount_1, Subperiod::Voting); let bep_stake_amount_1 = 23; - staking_info.stake(bep_stake_amount_1, PeriodType::BuildAndEarn); + staking_info.stake(bep_stake_amount_1, Subperiod::BuildAndEarn); // 1st scenario - Unstake some of the amount staked during B&E period let unstake_1 = 5; assert_eq!( - staking_info.unstake(5, PeriodType::BuildAndEarn), + staking_info.unstake(5, Subperiod::BuildAndEarn), (Balance::zero(), unstake_1) ); assert_eq!( @@ -1241,11 +1241,11 @@ fn singular_staking_info_unstake_during_bep_is_ok() { vote_stake_amount_1 + bep_stake_amount_1 - unstake_1 ); assert_eq!( - staking_info.staked_amount(PeriodType::Voting), + staking_info.staked_amount(Subperiod::Voting), vote_stake_amount_1 ); assert_eq!( - staking_info.staked_amount(PeriodType::BuildAndEarn), + staking_info.staked_amount(Subperiod::BuildAndEarn), bep_stake_amount_1 - unstake_1 ); assert!(staking_info.is_loyal()); @@ -1253,12 +1253,12 @@ fn singular_staking_info_unstake_during_bep_is_ok() { // 2nd scenario - unstake all of the amount staked during B&E period, and then some more. // The point is to take a chunk from the voting period stake too. let current_total_stake = staking_info.total_staked_amount(); - let current_bep_stake = staking_info.staked_amount(PeriodType::BuildAndEarn); + let current_bep_stake = staking_info.staked_amount(Subperiod::BuildAndEarn); let voting_stake_overflow = 2; let unstake_2 = current_bep_stake + voting_stake_overflow; assert_eq!( - staking_info.unstake(unstake_2, PeriodType::BuildAndEarn), + staking_info.unstake(unstake_2, Subperiod::BuildAndEarn), (voting_stake_overflow, current_bep_stake) ); assert_eq!( @@ -1266,11 +1266,11 @@ fn singular_staking_info_unstake_during_bep_is_ok() { current_total_stake - unstake_2 ); assert_eq!( - staking_info.staked_amount(PeriodType::Voting), + staking_info.staked_amount(Subperiod::Voting), vote_stake_amount_1 - voting_stake_overflow ); assert!(staking_info - .staked_amount(PeriodType::BuildAndEarn) + .staked_amount(Subperiod::BuildAndEarn) .is_zero()); assert!( !staking_info.is_loyal(), @@ -1325,7 +1325,7 @@ fn contract_stake_info_stake_is_ok() { let era_1 = 3; let stake_era_1 = era_1 + 1; let period_1 = 5; - let period_info_1 = PeriodInfo::new(period_1, PeriodType::Voting, 20); + let period_info_1 = PeriodInfo::new(period_1, Subperiod::Voting, 20); let amount_1 = 31; contract_stake.stake(amount_1, period_info_1, era_1); assert!(!contract_stake.is_empty()); @@ -1342,7 +1342,7 @@ fn contract_stake_info_stake_is_ok() { assert_eq!(entry_1_1.total(), amount_1); // 2nd scenario - stake some more to the same era but different period type, and verify state change. - let period_info_1 = PeriodInfo::new(period_1, PeriodType::BuildAndEarn, 20); + let period_info_1 = PeriodInfo::new(period_1, Subperiod::BuildAndEarn, 20); contract_stake.stake(amount_1, period_info_1, era_1); let entry_1_2 = contract_stake.get(stake_era_1, period_1).unwrap(); assert_eq!(entry_1_2.era, stake_era_1); @@ -1368,7 +1368,7 @@ fn contract_stake_info_stake_is_ok() { let era_3 = era_2 + 3; let stake_era_3 = era_3 + 1; let period_2 = period_1 + 1; - let period_info_2 = PeriodInfo::new(period_2, PeriodType::BuildAndEarn, 20); + let period_info_2 = PeriodInfo::new(period_2, Subperiod::BuildAndEarn, 20); let amount_3 = 41; contract_stake.stake(amount_3, period_info_2, era_3); @@ -1409,7 +1409,7 @@ fn contract_stake_info_unstake_is_ok() { // Prep action - create a stake entry let era_1 = 2; let period = 3; - let period_info = PeriodInfo::new(period, PeriodType::Voting, 20); + let period_info = PeriodInfo::new(period, Subperiod::Voting, 20); let stake_amount = 100; contract_stake.stake(stake_amount, period_info, era_1); @@ -1421,12 +1421,12 @@ fn contract_stake_info_unstake_is_ok() { stake_amount - amount_1 ); assert_eq!( - contract_stake.staked_amount(period, PeriodType::Voting), + contract_stake.staked_amount(period, Subperiod::Voting), stake_amount - amount_1 ); // 2nd scenario - unstake in the future era, entries should be aligned to the current era - let period_info = PeriodInfo::new(period, PeriodType::BuildAndEarn, 40); + let period_info = PeriodInfo::new(period, Subperiod::BuildAndEarn, 40); let era_2 = era_1 + 3; let amount_2 = 7; contract_stake.unstake(amount_2, period_info, era_2); @@ -1435,7 +1435,7 @@ fn contract_stake_info_unstake_is_ok() { stake_amount - amount_1 - amount_2 ); assert_eq!( - contract_stake.staked_amount(period, PeriodType::Voting), + contract_stake.staked_amount(period, Subperiod::Voting), stake_amount - amount_1 - amount_2 ); } diff --git a/pallets/dapp-staking-v3/src/types.rs b/pallets/dapp-staking-v3/src/types.rs index f8b0b264f8..d461e06909 100644 --- a/pallets/dapp-staking-v3/src/types.rs +++ b/pallets/dapp-staking-v3/src/types.rs @@ -39,6 +39,10 @@ pub type AccountLedgerFor = AccountLedger, ::M pub type DAppTierRewardsFor = DAppTierRewards, ::NumberOfTiers>; +// TODO: temp experimental type, don't review +pub type ContractEntriesFor = + ExperimentalContractStakeEntries, ::NumberOfTiers>; + // Helper struct for converting `u16` getter into `u32` #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct MaxNumberOfContractsU32(PhantomData); @@ -76,22 +80,21 @@ pub enum AccountLedgerError { AlreadyClaimed, } -// TODO: rename to SubperiodType? It would be less ambigious. -/// Distinct period types in dApp staking protocol. +/// Distinct subperiods in dApp staking protocol. #[derive(Encode, Decode, MaxEncodedLen, Clone, Copy, Debug, PartialEq, Eq, TypeInfo)] -pub enum PeriodType { - /// Period during which the focus is on voting. +pub enum Subperiod { + /// Subperiod during which the focus is on voting. Voting, - /// Period during which dApps and stakers earn rewards. + /// Subperiod during which dApps and stakers earn rewards. BuildAndEarn, } -impl PeriodType { - /// Next period type, after `self`. +impl Subperiod { + /// Next subperiod, after `self`. pub fn next(&self) -> Self { match self { - PeriodType::Voting => PeriodType::BuildAndEarn, - PeriodType::BuildAndEarn => PeriodType::Voting, + Subperiod::Voting => Subperiod::BuildAndEarn, + Subperiod::BuildAndEarn => Subperiod::Voting, } } } @@ -102,27 +105,27 @@ pub struct PeriodInfo { /// Period number. #[codec(compact)] pub number: PeriodNumber, - /// Subperiod type. - pub period_type: PeriodType, - /// Last ear of the sub-period, after this a new sub-period should start. + /// subperiod. + pub subperiod: Subperiod, + /// Last ear of the subperiod, after this a new subperiod should start. #[codec(compact)] pub ending_era: EraNumber, } impl PeriodInfo { /// Create new instance of `PeriodInfo` - pub fn new(number: PeriodNumber, period_type: PeriodType, ending_era: EraNumber) -> Self { + pub fn new(number: PeriodNumber, subperiod: Subperiod, ending_era: EraNumber) -> Self { Self { number, - period_type, + subperiod, ending_era, } } /// `true` if the provided era belongs to the next period, `false` otherwise. - /// It's only possible to provide this information for the `BuildAndEarn` period type. + /// It's only possible to provide this information for the `BuildAndEarn` subperiod. pub fn is_next_period(&self, era: EraNumber) -> bool { - self.period_type == PeriodType::BuildAndEarn && self.ending_era <= era + self.subperiod == Subperiod::BuildAndEarn && self.ending_era <= era } } @@ -145,8 +148,8 @@ pub struct PeriodEndInfo { pub enum ForcingType { /// Force the next era to start. Era, - /// Force the current period type to end, and new one to start. It will also force a new era to start. - PeriodType, + /// Force the current subperiod to end, and new one to start. It will also force a new era to start. + Subperiod, } /// General information & state of the dApp staking protocol. @@ -174,7 +177,7 @@ where next_era_start: BlockNumber::from(1_u32), period_info: PeriodInfo { number: 0, - period_type: PeriodType::Voting, + subperiod: Subperiod::Voting, ending_era: 2, }, maintenance: false, @@ -186,9 +189,9 @@ impl ProtocolState where BlockNumber: AtLeast32BitUnsigned + MaxEncodedLen, { - /// Current sub-period type. - pub fn period_type(&self) -> PeriodType { - self.period_info.period_type + /// Current subperiod. + pub fn subperiod(&self) -> Subperiod { + self.period_info.subperiod } /// Current period number. @@ -207,9 +210,9 @@ where self.next_era_start <= now } - /// Triggers the next period type, updating appropriate parameters. - pub fn into_next_period_type(&mut self, ending_era: EraNumber, next_era_start: BlockNumber) { - let period_number = if self.period_type() == PeriodType::BuildAndEarn { + /// Triggers the next subperiod, updating appropriate parameters. + pub fn into_next_subperiod(&mut self, ending_era: EraNumber, next_era_start: BlockNumber) { + let period_number = if self.subperiod() == Subperiod::BuildAndEarn { self.period_number().saturating_add(1) } else { self.period_number() @@ -217,7 +220,7 @@ where self.period_info = PeriodInfo { number: period_number, - period_type: self.period_type().next(), + subperiod: self.subperiod().next(), ending_era, }; self.next_era_start = next_era_start; @@ -315,6 +318,7 @@ pub struct AccountLedger< // TODO: introduce a variable which keeps track of the latest era for which the rewards have been calculated. // This is needed since in case we break up reward calculation into multiple blocks, we should prohibit staking until // reward calculation has finished. + // >>> Only if we decide to break calculation into multiple steps. } impl Default for AccountLedger @@ -468,15 +472,13 @@ where } } - /// How much is staked for the specified period type, in respect to the specified era. - pub fn staked_amount_for_type(&self, period_type: PeriodType, period: PeriodNumber) -> Balance { + /// How much is staked for the specified subperiod, in respect to the specified era. + pub fn staked_amount_for_type(&self, subperiod: Subperiod, period: PeriodNumber) -> Balance { // First check the 'future' entry, afterwards check the 'first' entry match self.staked_future { - Some(stake_amount) if stake_amount.period == period => { - stake_amount.for_type(period_type) - } + Some(stake_amount) if stake_amount.period == period => stake_amount.for_type(subperiod), _ => match self.staked { - stake_amount if stake_amount.period == period => stake_amount.for_type(period_type), + stake_amount if stake_amount.period == period => stake_amount.for_type(subperiod), _ => Balance::zero(), }, } @@ -540,13 +542,13 @@ where // Update existing entry if it exists, otherwise create it. match self.staked_future.as_mut() { Some(stake_amount) => { - stake_amount.add(amount, current_period_info.period_type); + stake_amount.add(amount, current_period_info.subperiod); } None => { let mut stake_amount = self.staked; stake_amount.era = era + 1; stake_amount.period = current_period_info.number; - stake_amount.add(amount, current_period_info.period_type); + stake_amount.add(amount, current_period_info.subperiod); self.staked_future = Some(stake_amount); } } @@ -576,8 +578,7 @@ where return Err(AccountLedgerError::UnstakeAmountLargerThanStake); } - self.staked - .subtract(amount, current_period_info.period_type); + self.staked.subtract(amount, current_period_info.subperiod); // Convenience cleanup if self.staked.is_empty() { @@ -585,7 +586,7 @@ where } if let Some(mut stake_amount) = self.staked_future { - stake_amount.subtract(amount, current_period_info.period_type); + stake_amount.subtract(amount, current_period_info.subperiod); self.staked_future = if stake_amount.is_empty() { None @@ -792,37 +793,37 @@ impl StakeAmount { self.voting.is_zero() && self.build_and_earn.is_zero() } - /// Total amount staked in both period types. + /// Total amount staked in both subperiods. pub fn total(&self) -> Balance { self.voting.saturating_add(self.build_and_earn) } - /// Amount staked for the specified period type. - pub fn for_type(&self, period_type: PeriodType) -> Balance { - match period_type { - PeriodType::Voting => self.voting, - PeriodType::BuildAndEarn => self.build_and_earn, + /// Amount staked for the specified subperiod. + pub fn for_type(&self, subperiod: Subperiod) -> Balance { + match subperiod { + Subperiod::Voting => self.voting, + Subperiod::BuildAndEarn => self.build_and_earn, } } - /// Stake the specified `amount` for the specified `period_type`. - pub fn add(&mut self, amount: Balance, period_type: PeriodType) { - match period_type { - PeriodType::Voting => self.voting.saturating_accrue(amount), - PeriodType::BuildAndEarn => self.build_and_earn.saturating_accrue(amount), + /// Stake the specified `amount` for the specified `subperiod`. + pub fn add(&mut self, amount: Balance, subperiod: Subperiod) { + match subperiod { + Subperiod::Voting => self.voting.saturating_accrue(amount), + Subperiod::BuildAndEarn => self.build_and_earn.saturating_accrue(amount), } } - /// Unstake the specified `amount` for the specified `period_type`. + /// Unstake the specified `amount` for the specified `subperiod`. /// - /// In case period type is `Voting`, the amount is subtracted from the voting period. + /// In case subperiod is `Voting`, the amount is subtracted from the voting period. /// - /// In case period type is `Build&Earn`, the amount is first subtracted from the + /// In case subperiod is `Build&Earn`, the amount is first subtracted from the /// build&earn amount, and any rollover is subtracted from the voting period. - pub fn subtract(&mut self, amount: Balance, period_type: PeriodType) { - match period_type { - PeriodType::Voting => self.voting.saturating_reduce(amount), - PeriodType::BuildAndEarn => { + pub fn subtract(&mut self, amount: Balance, subperiod: Subperiod) { + match subperiod { + Subperiod::Voting => self.voting.saturating_reduce(amount), + Subperiod::BuildAndEarn => { if self.build_and_earn >= amount { self.build_and_earn.saturating_reduce(amount); } else { @@ -875,15 +876,15 @@ impl EraInfo { self.unlocking.saturating_reduce(amount); } - /// Add the specified `amount` to the appropriate stake amount, based on the `PeriodType`. - pub fn add_stake_amount(&mut self, amount: Balance, period_type: PeriodType) { - self.next_stake_amount.add(amount, period_type); + /// Add the specified `amount` to the appropriate stake amount, based on the `Subperiod`. + pub fn add_stake_amount(&mut self, amount: Balance, subperiod: Subperiod) { + self.next_stake_amount.add(amount, subperiod); } - /// Subtract the specified `amount` from the appropriate stake amount, based on the `PeriodType`. - pub fn unstake_amount(&mut self, amount: Balance, period_type: PeriodType) { - self.current_stake_amount.subtract(amount, period_type); - self.next_stake_amount.subtract(amount, period_type); + /// Subtract the specified `amount` from the appropriate stake amount, based on the `Subperiod`. + pub fn unstake_amount(&mut self, amount: Balance, subperiod: Subperiod) { + self.current_stake_amount.subtract(amount, subperiod); + self.next_stake_amount.subtract(amount, subperiod); } /// Total staked amount in this era. @@ -892,8 +893,8 @@ impl EraInfo { } /// Staked amount of specified `type` in this era. - pub fn staked_amount(&self, period_type: PeriodType) -> Balance { - self.current_stake_amount.for_type(period_type) + pub fn staked_amount(&self, subperiod: Subperiod) -> Balance { + self.current_stake_amount.for_type(subperiod) } /// Total staked amount in the next era. @@ -902,23 +903,23 @@ impl EraInfo { } /// Staked amount of specifeid `type` in the next era. - pub fn staked_amount_next_era(&self, period_type: PeriodType) -> Balance { - self.next_stake_amount.for_type(period_type) + pub fn staked_amount_next_era(&self, subperiod: Subperiod) -> Balance { + self.next_stake_amount.for_type(subperiod) } /// Updates `Self` to reflect the transition to the next era. /// /// ## Args - /// `next_period_type` - `None` if no period type change, `Some(type)` if `type` is starting from the next era. - pub fn migrate_to_next_era(&mut self, next_period_type: Option) { + /// `next_subperiod` - `None` if no subperiod change, `Some(type)` if `type` is starting from the next era. + pub fn migrate_to_next_era(&mut self, next_subperiod: Option) { self.active_era_locked = self.total_locked; - match next_period_type { + match next_subperiod { // If next era marks start of new voting period period, it means we're entering a new period - Some(PeriodType::Voting) => { + Some(Subperiod::Voting) => { self.current_stake_amount = Default::default(); self.next_stake_amount = Default::default(); } - Some(PeriodType::BuildAndEarn) | None => { + Some(Subperiod::BuildAndEarn) | None => { self.current_stake_amount = self.next_stake_amount; } }; @@ -942,19 +943,18 @@ impl SingularStakingInfo { /// ## Args /// /// `period` - period number for which this entry is relevant. - /// `period_type` - period type during which this entry is created. - pub fn new(period: PeriodNumber, period_type: PeriodType) -> Self { + /// `subperiod` - subperiod during which this entry is created. + pub fn new(period: PeriodNumber, subperiod: Subperiod) -> Self { Self { - // TODO: one drawback here is using the struct which has `era` as the field - it's not needed here. Should I add a special struct just for this? staked: StakeAmount::new(Balance::zero(), Balance::zero(), 0, period), // Loyalty staking is only possible if stake is first made during the voting period. - loyal_staker: period_type == PeriodType::Voting, + loyal_staker: subperiod == Subperiod::Voting, } } - /// Stake the specified amount on the contract, for the specified period type. - pub fn stake(&mut self, amount: Balance, period_type: PeriodType) { - self.staked.add(amount, period_type); + /// Stake the specified amount on the contract, for the specified subperiod. + pub fn stake(&mut self, amount: Balance, subperiod: Subperiod) { + self.staked.add(amount, subperiod); } /// Unstakes some of the specified amount from the contract. @@ -963,15 +963,14 @@ impl SingularStakingInfo { /// and `voting period` has passed, this will remove the _loyalty_ flag from the staker. /// /// Returns the amount that was unstaked from the `voting period` stake, and from the `build&earn period` stake. - pub fn unstake(&mut self, amount: Balance, period_type: PeriodType) -> (Balance, Balance) { + pub fn unstake(&mut self, amount: Balance, subperiod: Subperiod) -> (Balance, Balance) { let snapshot = self.staked; - self.staked.subtract(amount, period_type); + self.staked.subtract(amount, subperiod); self.loyal_staker = self.loyal_staker - && (period_type == PeriodType::Voting - || period_type == PeriodType::BuildAndEarn - && self.staked.voting == snapshot.voting); + && (subperiod == Subperiod::Voting + || subperiod == Subperiod::BuildAndEarn && self.staked.voting == snapshot.voting); // Amount that was unstaked ( @@ -982,14 +981,14 @@ impl SingularStakingInfo { ) } - /// Total staked on the contract by the user. Both period type stakes are included. + /// Total staked on the contract by the user. Both subperiod stakes are included. pub fn total_staked_amount(&self) -> Balance { self.staked.total() } /// Returns amount staked in the specified period. - pub fn staked_amount(&self, period_type: PeriodType) -> Balance { - self.staked.for_type(period_type) + pub fn staked_amount(&self, subperiod: Subperiod) -> Balance { + self.staked.for_type(subperiod) } /// If `true` staker has staked during voting period and has never reduced their sta @@ -1083,18 +1082,18 @@ impl ContractStakeAmount { } } - /// Staked amount on the contract, for specified period type, in the active period. - pub fn staked_amount(&self, active_period: PeriodNumber, period_type: PeriodType) -> Balance { + /// Staked amount on the contract, for specified subperiod, in the active period. + pub fn staked_amount(&self, active_period: PeriodNumber, subperiod: Subperiod) -> Balance { match (self.staked, self.staked_future) { (_, Some(staked_future)) if staked_future.period == active_period => { - staked_future.for_type(period_type) + staked_future.for_type(subperiod) } - (staked, _) if staked.period == active_period => staked.for_type(period_type), + (staked, _) if staked.period == active_period => staked.for_type(subperiod), _ => Balance::zero(), } } - /// Stake the specified `amount` on the contract, for the specified `period_type` and `era`. + /// Stake the specified `amount` on the contract, for the specified `subperiod` and `era`. pub fn stake(&mut self, amount: Balance, period_info: PeriodInfo, current_era: EraNumber) { let stake_era = current_era.saturating_add(1); // TODO: maybe keep the check that period/era aren't historical? @@ -1103,7 +1102,7 @@ impl ContractStakeAmount { match self.staked_future.as_mut() { // Future entry matches the era, just updated it and return Some(stake_amount) if stake_amount.era == stake_era => { - stake_amount.add(amount, period_info.period_type); + stake_amount.add(amount, period_info.subperiod); return; } // Future entry has older era, but periods match so overwrite the 'current' entry with it @@ -1121,7 +1120,7 @@ impl ContractStakeAmount { // otherwise just create a dummy new entry _ => Default::default(), }; - new_entry.add(amount, period_info.period_type); + new_entry.add(amount, period_info.subperiod); new_entry.era = stake_era; new_entry.period = period_info.number; @@ -1133,7 +1132,7 @@ impl ContractStakeAmount { } } - /// Unstake the specified `amount` from the contract, for the specified `period_type` and `era`. + /// Unstake the specified `amount` from the contract, for the specified `subperiod` and `era`. pub fn unstake(&mut self, amount: Balance, period_info: PeriodInfo, current_era: EraNumber) { // TODO: tests need to be re-writen for this after the refactoring @@ -1156,9 +1155,9 @@ impl ContractStakeAmount { } // Subtract both amounts - self.staked.subtract(amount, period_info.period_type); + self.staked.subtract(amount, period_info.subperiod); if let Some(stake_amount) = self.staked_future.as_mut() { - stake_amount.subtract(amount, period_info.period_type); + stake_amount.subtract(amount, period_info.subperiod); } // Conevnience cleanup @@ -1657,3 +1656,36 @@ pub trait RewardPoolProvider { /// Get the bonus pool for stakers. fn bonus_reward_pool() -> Balance; } + +// TODO: this is experimental, don't review +#[derive(Encode, Decode, MaxEncodedLen, Copy, Clone, Debug, PartialEq, Eq, TypeInfo)] +pub struct ExperimentalContractStakeEntry { + #[codec(compact)] + pub dapp_id: DAppId, + #[codec(compact)] + pub voting: Balance, + #[codec(compact)] + pub build_and_earn: Balance, +} + +// TODO: this is experimental, don't review +#[derive( + Encode, + Decode, + MaxEncodedLen, + RuntimeDebugNoBound, + PartialEqNoBound, + EqNoBound, + CloneNoBound, + TypeInfo, +)] +#[scale_info(skip_type_params(MD, NT))] +pub struct ExperimentalContractStakeEntries, NT: Get> { + /// DApps and their corresponding tiers (or `None` if they have been claimed in the meantime) + pub dapps: BoundedVec, + /// Rewards for each tier. First entry refers to the first tier, and so on. + pub rewards: BoundedVec, + /// Period during which this struct was created. + #[codec(compact)] + pub period: PeriodNumber, +}