From 78ccc69ea9c074bbc73fe126e9c7d29f2e00336d Mon Sep 17 00:00:00 2001 From: Igor Papandinas <26460174+ipapandinas@users.noreply.github.com> Date: Fri, 9 Aug 2024 14:08:59 +0200 Subject: [PATCH 1/6] try-state wip --- pallets/dapp-staking-v3/src/lib.rs | 232 ++++++++++++++++++++++ pallets/dapp-staking-v3/src/test/mock.rs | 18 +- pallets/dapp-staking-v3/src/test/tests.rs | 209 +++++++++---------- pallets/dapp-staking-v3/src/types.rs | 2 +- 4 files changed, 357 insertions(+), 104 deletions(-) diff --git a/pallets/dapp-staking-v3/src/lib.rs b/pallets/dapp-staking-v3/src/lib.rs index 6580e3d083..2109bd6806 100644 --- a/pallets/dapp-staking-v3/src/lib.rs +++ b/pallets/dapp-staking-v3/src/lib.rs @@ -635,6 +635,12 @@ pub mod pallet { assert!(T::CycleConfiguration::eras_per_build_and_earn_subperiod() > 0); assert!(T::CycleConfiguration::blocks_per_era() > 0); } + + #[cfg(feature = "try-runtime")] + fn try_state(_n: BlockNumberFor<T>) -> Result<(), sp_runtime::TryRuntimeError> { + Self::do_try_state()?; + Ok(()) + } } /// A reason for freezing funds. @@ -2248,5 +2254,231 @@ pub mod pallet { Ok(()) } + + /// Ensure the correctness of the state of this pallet. + #[cfg(any(feature = "try-runtime", test))] + pub fn do_try_state() -> Result<(), sp_runtime::TryRuntimeError> { + Self::try_state_protocol()?; + Self::try_state_next_dapp_id()?; + Self::try_state_integrated_dapps()?; + Self::try_state_tiers()?; + Self::try_state_ledger()?; + Self::try_state_contract_stake()?; + Self::try_state_era_rewards()?; + + Ok(()) + } + + /// ### Invariants of active protocol storage items + /// + /// 1. [`PeriodInfo`] number in [`ActiveProtocolState`] must always be greater than or equal to the number of elements in [`PeriodEnd`]. + /// 2. Ensures the `era` number and `next_era_start` block number are valid. + #[cfg(any(feature = "try-runtime", test))] + pub fn try_state_protocol() -> Result<(), sp_runtime::TryRuntimeError> { + let protocol_state = ActiveProtocolState::<T>::get(); + let period_number = protocol_state.period_info.number; + + // Invariant 1 + if PeriodEnd::<T>::iter().count() >= period_number as usize { + return Err("Number of periods in `PeriodEnd` exceeds or is equal to actual `PeriodInfo` number.".into()); + } + + // Invariant 2 + if protocol_state.era == 0 { + return Err("Invalid era number in ActiveProtocolState.".into()); + } + + let current_block: BlockNumber = + frame_system::Pallet::<T>::block_number().saturated_into(); + if current_block > protocol_state.next_era_start { + return Err( + "Next era start block number is in the past in ActiveProtocolState.".into(), + ); + } + + Ok(()) + } + + /// ### Invariants of NextDAppId + /// + /// 1. [`NextDAppId`] must always be equal to the number of dapps in [`IntegratedDApps`]. + /// 2. [`NextDAppId`] must always be equal to the number of contracts in [`ContractStake`]. + #[cfg(any(feature = "try-runtime", test))] + pub fn try_state_next_dapp_id() -> Result<(), sp_runtime::TryRuntimeError> { + let next_dapp_id = NextDAppId::<T>::get(); + + // Invariant 1 + if next_dapp_id < IntegratedDApps::<T>::count() as u16 { + return Err("Number of integrated dapps is greater than NextDAppId.".into()); + } + + // Invariant 2 + if next_dapp_id < ContractStake::<T>::iter().count() as u16 { + return Err("Number of contract stake infos is greater than NextDAppId.".into()); + } + + Ok(()) + } + + /// ### Invariants of IntegratedDApps + /// + /// 1. The number of entries in [`IntegratedDApps`] should not exceed the [`T::MaxNumberOfContracts`] constant. + #[cfg(any(feature = "try-runtime", test))] + pub fn try_state_integrated_dapps() -> Result<(), sp_runtime::TryRuntimeError> { + let integrated_dapps_count = IntegratedDApps::<T>::count(); + let max_number_of_contracts = T::MaxNumberOfContracts::get(); + + if integrated_dapps_count > max_number_of_contracts { + return Err("Number of integrated dapps exceeds the maximum allowed.".into()); + } + + Ok(()) + } + + /// ### Invariants of StaticTierParams and TierConfig + /// + /// 1. The [`T::NumberOfTiers`] constant must always be equal to the number of `slot_distribution`, `reward_portion`, `tier_thresholds`in [`StaticTierParams`]. + /// 2. The [`T::NumberOfTiers`] constant must always be equal to the number of `slots_per_tier`, `reward_portion`, `tier_thresholds`in [`TierConfig`]. + #[cfg(any(feature = "try-runtime", test))] + pub fn try_state_tiers() -> Result<(), sp_runtime::TryRuntimeError> { + let nb_tiers = T::NumberOfTiers::get(); + let tier_params = StaticTierParams::<T>::get(); + let tier_config = TierConfig::<T>::get(); + + // Invariant 1 + if nb_tiers != tier_params.slot_distribution.len() as u32 { + return Err( + "Number of tiers is incorrect in slot_distribution in StaticTierParams.".into(), + ); + } + if nb_tiers != tier_params.reward_portion.len() as u32 { + return Err( + "Number of tiers is incorrect in reward_portion in StaticTierParams.".into(), + ); + } + if nb_tiers != tier_params.tier_thresholds.len() as u32 { + return Err( + "Number of tiers is incorrect in tier_thresholds in StaticTierParams.".into(), + ); + } + + // Invariant 2 + if nb_tiers != tier_config.slots_per_tier.len() as u32 { + return Err( + "Number of tiers is incorrect in slots_per_tier in StaticTierParams.".into(), + ); + } + if nb_tiers != tier_config.reward_portion.len() as u32 { + return Err( + "Number of tiers is incorrect in reward_portion in StaticTierParams.".into(), + ); + } + if nb_tiers != tier_config.tier_thresholds.len() as u32 { + return Err( + "Number of tiers is incorrect in tier_thresholds in StaticTierParams.".into(), + ); + } + + Ok(()) + } + + /// ### Invariants of Ledger + /// + /// 1. Iterating over all [`Ledger`] accounts should yield the correct stake amount accross all contracts in [`ContractStake`]. + /// 2. Iterating over all [`Ledger`] accounts should yield the correct locked and stakes amounts compared to current era in [`CurrentEraInfo`]. + /// 3. The number of unlocking chunks in [`Ledger`] for any account should not exceed the [`T::MaxUnlockingChunks`] constant. + /// 4. Each staking entry in [`Ledger`] should be greater than or equal to the [`T::MinimumStakeAmount`] constant. + /// 5. Each locking entry in [`Ledger`] should be greater than or equal to the [`T::MinimumLockedAmount`] constant. + /// 6. The number of staking entries per account in [`Ledger`] should not exceed the [`T::MaxNumberOfStakedContracts`] constant. + #[cfg(any(feature = "try-runtime", test))] + pub fn try_state_ledger() -> Result<(), sp_runtime::TryRuntimeError> { + let current_era_info = CurrentEraInfo::<T>::get(); + let current_period_number = ActiveProtocolState::<T>::get().period_number(); + + // Yield amounts in [`Ledger`] + let mut ledger_total_stake = 0u128; + let mut ledger_total_locked = 0u128; + let mut ledger_total_unlocking = 0u128; + let mut ledger_total_staked_future = 0u128; + + for (account, ledger) in Ledger::<T>::iter() { + let account_stake: u128 = ledger.staked_amount(current_period_number); + + ledger_total_stake += account_stake; + ledger_total_staked_future += account_stake; + ledger_total_locked += ledger.active_locked_amount(); + ledger_total_unlocking += ledger.unlocking_amount(); + + // Invariant 3 + if ledger.unlocking.len() > T::MaxUnlockingChunks::get() as usize { + return Err("An account exceeds the maximum unlocking chunks.".into()); + } + + // Invariant 4 + if account_stake < T::MinimumStakeAmount::get() { + return Err("An account has a stake amount lower than the minimum allowed.".into()); + } + + // Invariant 5 + if ledger.active_locked_amount() < T::MinimumLockedAmount::get() { + return Err("An account has a locked amount lower than the minimum allowed.".into()); + } + + // Invariant 6 + if ledger.contract_stake_count > T::MaxNumberOfStakedContracts::get() { + return Err("An account exceeds the maximum number of staked contracts.".into()); + } + } + + // // Yield amounts in contracts in [`ContractStake`] + // let mut contracts_total_stake = 0u128; + // let mut contracts_total_staked_future = 0u128; + + // for (_, contract) in ContractStake::<T>::iter() { + // let contract_stake: u128 = contract.staked_amount(current_period_number); + + // contracts_total_stake += contract_stake; + // contracts_total_staked_future += contract_stake; + // } + + // // Invariant 1 + // if contracts_total_stake != current_era_info.current_stake_amount.total() + // || contracts_total_staked_future != current_era_info.next_stake_amount.total() + // { + // return Err("Mismatch between ContractStake totals and CurrentEraInfo.".into()); + // } + + // Invariant 2 + if ledger_total_stake != current_era_info.current_stake_amount.total() + || ledger_total_locked != current_era_info.total_locked + || ledger_total_unlocking != current_era_info.unlocking + || ledger_total_staked_future != current_era_info.next_stake_amount.total() + { + return Err("Mismatch between Ledger totals and CurrentEraInfo.".into()); + } + + Ok(()) + } + + /// ### Invariants of ContractStake + /// + /// 1. Iterating over all SCs in [`ContractStake`] should yield the correct `staked`& `staked_future` amounts compared to `current_stake_amount` & `next_stake_amount` in [`CurrentEraInfo`] + /// 2. Each staking entry in [`ContractStake`] should be greater than or equal to the [`T::MinimumStakeAmount`] constant. + #[cfg(any(feature = "try-runtime", test))] + pub fn try_state_contract_stake() -> Result<(), sp_runtime::TryRuntimeError> { + Ok(()) + } + + /// ### Invariants of EraRewards + /// + /// 1. Era number in [`DAppTiers`] must also be stored in one of the span of [`EraRewards`]. + /// 2. Combining all span lengths it should yield the number of items in [`DAppTiers`] + /// 3. The sum of rewards for each span in [`EraRewards`] must be equal to the number of rewards for the same eras in [`DAppTiers`] + /// 4. The number of eras retained in [`EraRewards`] should not exceed the [`T::RewardRetentionInPeriods`] constant. + /// 5. Each span lenght entry in [`EraRewards`] should be lower than or equal to the [`T::EraRewardSpanLength`] constant. + #[cfg(any(feature = "try-runtime", test))] + pub fn try_state_era_rewards() -> Result<(), sp_runtime::TryRuntimeError> { + Ok(()) + } } } diff --git a/pallets/dapp-staking-v3/src/test/mock.rs b/pallets/dapp-staking-v3/src/test/mock.rs index dfebbdef00..8fc568c955 100644 --- a/pallets/dapp-staking-v3/src/test/mock.rs +++ b/pallets/dapp-staking-v3/src/test/mock.rs @@ -245,9 +245,16 @@ impl pallet_dapp_staking::Config for Test { type BenchmarkHelper = BenchmarkHelper<MockSmartContract, AccountId>; } -pub struct ExtBuilder; +pub struct ExtBuilder {} + +impl Default for ExtBuilder { + fn default() -> Self { + Self {} + } +} + impl ExtBuilder { - pub fn build() -> TestExternalities { + pub fn build(self) -> TestExternalities { // Normal behavior is for reward payout to succeed DOES_PAYOUT_SUCCEED.with(|v| *v.borrow_mut() = true); @@ -372,6 +379,13 @@ impl ExtBuilder { ext } + + pub fn build_and_execute(self, test: impl FnOnce() -> ()) { + self.build().execute_with(|| { + test(); + DappStaking::do_try_state().unwrap(); + }) + } } /// Run to the specified block number. diff --git a/pallets/dapp-staking-v3/src/test/tests.rs b/pallets/dapp-staking-v3/src/test/tests.rs index d8f124683a..91804ad715 100644 --- a/pallets/dapp-staking-v3/src/test/tests.rs +++ b/pallets/dapp-staking-v3/src/test/tests.rs @@ -50,7 +50,7 @@ use std::collections::BTreeMap; #[test] fn maintenances_mode_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Check that maintenance mode is disabled by default assert!(!ActiveProtocolState::<Test>::get().maintenance); @@ -78,7 +78,7 @@ fn maintenances_mode_works() { #[test] fn maintenance_mode_call_filtering_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Enable maintenance mode & check post-state assert_ok!(DappStaking::maintenance_mode(RuntimeOrigin::root(), true)); assert!(ActiveProtocolState::<Test>::get().maintenance); @@ -187,7 +187,7 @@ fn maintenance_mode_call_filtering_works() { #[test] fn on_initialize_is_noop_if_no_era_change() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let protocol_state = ActiveProtocolState::<Test>::get(); let current_block_number = System::block_number(); @@ -206,7 +206,7 @@ fn on_initialize_is_noop_if_no_era_change() { #[test] fn on_initialize_base_state_change_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Sanity check let protocol_state = ActiveProtocolState::<Test>::get(); assert_eq!(protocol_state.era, 1); @@ -266,7 +266,7 @@ fn on_initialize_base_state_change_works() { #[test] fn register_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Basic test assert_register(5, &MockSmartContract::Wasm(1)); @@ -293,7 +293,7 @@ fn register_is_ok() { #[test] fn register_with_incorrect_origin_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Test assumes that Contract registry & Manager origins are different. assert_noop!( DappStaking::register( @@ -318,7 +318,7 @@ fn register_with_incorrect_origin_fails() { #[test] fn register_already_registered_contract_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let smart_contract = MockSmartContract::Wasm(1); assert_register(2, &smart_contract); assert_noop!( @@ -330,7 +330,7 @@ fn register_already_registered_contract_fails() { #[test] fn register_past_max_number_of_contracts_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let limit = <Test as Config>::MaxNumberOfContracts::get(); for id in 1..=limit { assert_register(1, &MockSmartContract::Wasm(id.into())); @@ -349,7 +349,7 @@ fn register_past_max_number_of_contracts_fails() { #[test] fn register_past_sentinel_value_of_id_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // hacky approach, but good enough for test NextDAppId::<Test>::put(DAppId::MAX - 1); @@ -367,7 +367,7 @@ fn register_past_sentinel_value_of_id_fails() { #[test] fn set_dapp_reward_beneficiary_for_contract_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Prepare & register smart contract let owner = 1; let smart_contract = MockSmartContract::Wasm(3); @@ -386,7 +386,7 @@ fn set_dapp_reward_beneficiary_for_contract_is_ok() { #[test] fn set_dapp_reward_beneficiary_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let owner = 1; let smart_contract = MockSmartContract::Wasm(3); @@ -415,7 +415,7 @@ fn set_dapp_reward_beneficiary_fails() { #[test] fn set_dapp_owner_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Prepare & register smart contract let owner = 1; let smart_contract = MockSmartContract::Wasm(3); @@ -433,7 +433,7 @@ fn set_dapp_owner_is_ok() { #[test] fn set_dapp_owner_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let owner = 1; let smart_contract = MockSmartContract::Wasm(3); @@ -458,7 +458,7 @@ fn set_dapp_owner_fails() { #[test] fn unregister_no_stake_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Prepare dApp let owner = 1; let smart_contract = MockSmartContract::Wasm(3); @@ -484,7 +484,7 @@ fn unregister_no_stake_is_ok() { #[test] fn unregister_with_active_stake_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Prepare dApp let owner = 1; let smart_contract = MockSmartContract::Wasm(3); @@ -499,7 +499,7 @@ fn unregister_with_active_stake_is_ok() { #[test] fn unregister_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let owner = 1; let smart_contract = MockSmartContract::Wasm(3); @@ -534,7 +534,7 @@ fn unregister_fails() { #[test] fn lock_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Lock some amount let locker = 2; let free_balance = Balances::total_balance(&locker); @@ -553,7 +553,7 @@ fn lock_is_ok() { #[test] fn lock_with_reserve_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Prepare locker account let locker = 30; let minimum_locked_amount: Balance = <Test as Config>::MinimumLockedAmount::get(); @@ -572,7 +572,7 @@ fn lock_with_reserve_is_ok() { #[test] fn lock_with_incorrect_amount_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Cannot lock "nothing" assert_noop!( DappStaking::lock(RuntimeOrigin::signed(1), Balance::zero()), @@ -600,7 +600,7 @@ fn lock_with_incorrect_amount_fails() { #[test] fn lock_with_blacklisted_account_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { Balances::make_free_balance_be(&BLACKLISTED_ACCOUNT, 100000); assert_noop!( @@ -612,7 +612,7 @@ fn lock_with_blacklisted_account_fails() { #[test] fn unbond_and_unstake_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Lock some amount let account = 2; let lock_amount = 101; @@ -635,7 +635,7 @@ fn unbond_and_unstake_is_ok() { #[test] fn unlock_basic_example_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Lock some amount let account = 2; let lock_amount = 101; @@ -657,7 +657,7 @@ fn unlock_basic_example_is_ok() { #[test] fn unlock_with_remaining_amount_below_threshold_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Lock some amount in a few eras let account = 2; let lock_amount = 101; @@ -678,7 +678,7 @@ fn unlock_with_remaining_amount_below_threshold_is_ok() { #[test] fn unlock_with_amount_higher_than_available_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Lock some amount in a few eras let account = 2; let lock_amount = 101; @@ -704,7 +704,7 @@ fn unlock_with_amount_higher_than_available_is_ok() { #[test] fn unlock_advanced_examples_are_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Lock some amount let account = 2; let lock_amount = 101; @@ -734,7 +734,7 @@ fn unlock_advanced_examples_are_ok() { #[test] fn unlock_everything_with_active_stake_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let account = 2; let lock_amount = 101; assert_lock(account, lock_amount); @@ -759,7 +759,7 @@ fn unlock_everything_with_active_stake_fails() { #[test] fn unlock_with_zero_amount_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let account = 2; let lock_amount = 101; assert_lock(account, lock_amount); @@ -786,7 +786,7 @@ fn unlock_with_zero_amount_fails() { #[test] fn unlock_with_exceeding_unlocking_chunks_storage_limits_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Lock some amount in a few eras let account = 2; let lock_amount = 103; @@ -814,7 +814,7 @@ fn unlock_with_exceeding_unlocking_chunks_storage_limits_fails() { #[test] fn withdraw_unbonded_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Lock & immediately unlock some amount let account = 2; let lock_amount = 97; @@ -837,7 +837,7 @@ fn withdraw_unbonded_is_ok() { #[test] fn claim_unlocked_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let unlocking_blocks = DappStaking::unlocking_period(); // Lock some amount in a few eras @@ -877,7 +877,7 @@ fn claim_unlocked_is_ok() { #[test] fn claim_unlocked_no_eligible_chunks_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Sanity check let account = 2; assert_noop!( @@ -899,7 +899,7 @@ fn claim_unlocked_no_eligible_chunks_fails() { #[test] fn relock_unlocking_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Lock some amount let account = 2; let lock_amount = 91; @@ -925,7 +925,7 @@ fn relock_unlocking_is_ok() { #[test] fn relock_unlocking_no_chunks_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_noop!( DappStaking::relock_unlocking(RuntimeOrigin::signed(1)), Error::<Test>::NoUnlockingChunks, @@ -935,7 +935,7 @@ fn relock_unlocking_no_chunks_fails() { #[test] fn relock_unlocking_insufficient_lock_amount_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let minimum_locked_amount: Balance = <Test as Config>::MinimumLockedAmount::get(); // lock amount should be above the threshold @@ -979,7 +979,7 @@ fn relock_unlocking_insufficient_lock_amount_fails() { #[test] fn stake_basic_example_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract & lock some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -998,7 +998,7 @@ fn stake_basic_example_is_ok() { #[test] fn stake_after_expiry_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1032,7 +1032,7 @@ fn stake_after_expiry_is_ok() { #[test] fn stake_with_zero_amount_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract & lock some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -1048,7 +1048,7 @@ fn stake_with_zero_amount_fails() { #[test] fn stake_on_invalid_dapp_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let account = 2; assert_lock(account, 300); @@ -1071,7 +1071,7 @@ fn stake_on_invalid_dapp_fails() { #[test] fn stake_in_final_era_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract & lock some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); let account = 2; @@ -1094,7 +1094,7 @@ fn stake_in_final_era_fails() { #[test] fn stake_fails_if_unclaimed_staker_rewards_from_past_remain() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract & lock some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); let account = 2; @@ -1122,7 +1122,7 @@ fn stake_fails_if_unclaimed_staker_rewards_from_past_remain() { #[test] fn stake_fails_if_claimable_bonus_rewards_from_past_remain() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); let account = 2; @@ -1147,7 +1147,7 @@ fn stake_fails_if_claimable_bonus_rewards_from_past_remain() { #[test] fn stake_fails_if_not_enough_stakeable_funds_available() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contracts & lock some amount let smart_contract_1 = MockSmartContract::Wasm(1); let smart_contract_2 = MockSmartContract::Wasm(2); @@ -1178,7 +1178,7 @@ fn stake_fails_if_not_enough_stakeable_funds_available() { #[test] fn stake_fails_due_to_too_small_staking_amount() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract & lock some amount let smart_contract_1 = MockSmartContract::Wasm(1); let smart_contract_2 = MockSmartContract::Wasm(2); @@ -1217,7 +1217,7 @@ fn stake_fails_due_to_too_small_staking_amount() { #[test] fn stake_fails_due_to_too_many_staked_contracts() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let max_number_of_contracts: u32 = <Test as Config>::MaxNumberOfStakedContracts::get(); // Lock amount by staker @@ -1265,7 +1265,7 @@ fn stake_fails_due_to_too_many_staked_contracts() { #[test] fn unstake_basic_example_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract & lock some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1287,7 +1287,7 @@ fn unstake_basic_example_is_ok() { #[test] fn unstake_with_leftover_amount_below_minimum_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract & lock some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1307,7 +1307,7 @@ fn unstake_with_leftover_amount_below_minimum_works() { #[test] fn unstake_with_zero_amount_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract & lock some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -1324,7 +1324,7 @@ fn unstake_with_zero_amount_fails() { #[test] fn unstake_on_invalid_dapp_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let account = 2; assert_lock(account, 300); @@ -1348,7 +1348,7 @@ fn unstake_on_invalid_dapp_fails() { #[test] fn unstake_with_exceeding_amount_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contracts & lock some amount let smart_contract_1 = MockSmartContract::Wasm(1); let smart_contract_2 = MockSmartContract::Wasm(2); @@ -1385,7 +1385,7 @@ fn unstake_with_exceeding_amount_fails() { #[test] fn unstake_from_non_staked_contract_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contracts & lock some amount let smart_contract_1 = MockSmartContract::Wasm(1); let smart_contract_2 = MockSmartContract::Wasm(2); @@ -1408,7 +1408,7 @@ fn unstake_from_non_staked_contract_fails() { #[test] fn unstake_with_unclaimed_rewards_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::Wasm(1); assert_register(1, &smart_contract); @@ -1432,7 +1432,7 @@ fn unstake_with_unclaimed_rewards_fails() { #[test] fn unstake_from_past_period_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract & lock some amount let smart_contract = MockSmartContract::Wasm(1); assert_register(1, &smart_contract); @@ -1453,7 +1453,7 @@ fn unstake_from_past_period_fails() { #[test] fn claim_staker_rewards_basic_example_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1488,7 +1488,7 @@ fn claim_staker_rewards_basic_example_is_ok() { #[test] fn claim_staker_rewards_double_call_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1515,7 +1515,7 @@ fn claim_staker_rewards_double_call_fails() { #[test] fn claim_staker_rewards_no_claimable_rewards_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1555,7 +1555,7 @@ fn claim_staker_rewards_no_claimable_rewards_fails() { #[test] fn claim_staker_rewards_era_after_expiry_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1589,7 +1589,7 @@ fn claim_staker_rewards_era_after_expiry_works() { #[test] fn claim_staker_rewards_after_expiry_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1622,7 +1622,7 @@ fn claim_staker_rewards_after_expiry_fails() { #[test] fn claim_staker_rewards_fails_due_to_payout_failure() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -1650,7 +1650,7 @@ fn claim_staker_rewards_fails_due_to_payout_failure() { #[test] fn claim_bonus_reward_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1685,7 +1685,7 @@ fn claim_bonus_reward_works() { #[test] fn claim_bonus_reward_double_call_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1710,7 +1710,7 @@ fn claim_bonus_reward_double_call_fails() { #[test] fn claim_bonus_reward_when_nothing_to_claim_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1738,7 +1738,7 @@ fn claim_bonus_reward_when_nothing_to_claim_fails() { #[test] fn claim_bonus_reward_with_only_build_and_earn_stake_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1768,7 +1768,7 @@ fn claim_bonus_reward_with_only_build_and_earn_stake_fails() { #[test] fn claim_bonus_reward_after_expiry_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1804,7 +1804,7 @@ fn claim_bonus_reward_after_expiry_fails() { #[test] fn claim_bonus_reward_fails_due_to_payout_failure() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -1832,7 +1832,7 @@ fn claim_bonus_reward_fails_due_to_payout_failure() { #[test] fn claim_dapp_reward_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -1867,7 +1867,7 @@ fn claim_dapp_reward_works() { #[test] fn claim_dapp_reward_from_non_existing_contract_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_noop!( DappStaking::claim_dapp_reward(RuntimeOrigin::signed(1), smart_contract, 1), @@ -1878,7 +1878,7 @@ fn claim_dapp_reward_from_non_existing_contract_fails() { #[test] fn claim_dapp_reward_from_invalid_era_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -1909,7 +1909,7 @@ fn claim_dapp_reward_from_invalid_era_fails() { #[test] fn claim_dapp_reward_if_dapp_not_in_any_tier_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract_1 = MockSmartContract::Wasm(3); let smart_contract_2 = MockSmartContract::Wasm(5); @@ -1940,7 +1940,7 @@ fn claim_dapp_reward_if_dapp_not_in_any_tier_fails() { #[test] fn claim_dapp_reward_twice_for_same_era_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -1973,7 +1973,7 @@ fn claim_dapp_reward_twice_for_same_era_fails() { #[test] fn claim_dapp_reward_for_expired_era_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -2003,7 +2003,7 @@ fn claim_dapp_reward_for_expired_era_fails() { #[test] fn claim_dapp_reward_fails_due_to_payout_failure() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -2039,7 +2039,7 @@ fn claim_dapp_reward_fails_due_to_payout_failure() { #[test] fn unstake_from_unregistered_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -2057,7 +2057,7 @@ fn unstake_from_unregistered_is_ok() { #[test] fn unstake_from_unregistered_fails_for_active_contract() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -2076,7 +2076,7 @@ fn unstake_from_unregistered_fails_for_active_contract() { #[test] fn unstake_from_unregistered_fails_for_not_staked_contract() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -2091,7 +2091,7 @@ fn unstake_from_unregistered_fails_for_not_staked_contract() { #[test] fn unstake_from_unregistered_fails_for_past_period() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -2114,7 +2114,7 @@ fn unstake_from_unregistered_fails_for_past_period() { #[test] fn cleanup_expired_entries_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contracts let contracts: Vec<_> = (1..=5).map(|id| MockSmartContract::Wasm(id)).collect(); contracts.iter().for_each(|smart_contract| { @@ -2176,7 +2176,7 @@ fn cleanup_expired_entries_is_ok() { #[test] fn cleanup_expired_entries_fails_with_no_entries() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contracts let (contract_1, contract_2) = (MockSmartContract::Wasm(1), MockSmartContract::Wasm(2)); assert_register(1, &contract_1); @@ -2205,7 +2205,7 @@ fn cleanup_expired_entries_fails_with_no_entries() { #[test] fn force_era_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // 1. Force new era in the voting subperiod let init_state = ActiveProtocolState::<Test>::get(); assert!( @@ -2283,7 +2283,7 @@ fn force_era_works() { #[test] fn force_subperiod_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // 1. Force new subperiod in the voting subperiod let init_state = ActiveProtocolState::<Test>::get(); assert!( @@ -2365,7 +2365,7 @@ fn force_subperiod_works() { #[test] fn force_with_incorrect_origin_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { assert_noop!( DappStaking::force(RuntimeOrigin::signed(1), ForcingType::Era), BadOrigin @@ -2375,7 +2375,7 @@ fn force_with_incorrect_origin_fails() { #[test] fn force_with_safeguard_on_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { Safeguard::<Test>::put(true); assert_noop!( DappStaking::force(RuntimeOrigin::root(), ForcingType::Era), @@ -2386,7 +2386,7 @@ fn force_with_safeguard_on_fails() { #[test] fn tier_config_recalculation_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let init_price = NATIVE_PRICE.with(|v| v.borrow().clone()); let init_tier_config = TierConfig::<Test>::get(); @@ -2470,7 +2470,7 @@ fn tier_config_recalculation_works() { #[test] fn get_dapp_tier_assignment_and_rewards_basic_example_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Tier config is specially adapted for this test. TierConfig::<Test>::mutate(|config| { config.slots_per_tier = BoundedVec::try_from(vec![2, 5, 13, 20]).unwrap(); @@ -2610,7 +2610,7 @@ fn get_dapp_tier_assignment_and_rewards_basic_example_works() { #[test] fn get_dapp_tier_assignment_and_rewards_zero_slots_per_tier_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // This test will rely on the configuration inside the mock file. // If that changes, this test might have to be updated as well. @@ -2647,14 +2647,14 @@ fn get_dapp_tier_assignment_and_rewards_zero_slots_per_tier_works() { #[test] fn advance_for_some_periods_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { advance_to_period(10); }) } #[test] fn unlock_after_staked_period_ends_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -2676,7 +2676,7 @@ fn unlock_after_staked_period_ends_is_ok() { #[test] fn unstake_from_a_contract_staked_in_past_period_fails() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract & lock some amount let smart_contract_1 = MockSmartContract::Wasm(1); let smart_contract_2 = MockSmartContract::Wasm(2); @@ -2714,7 +2714,7 @@ fn unstake_from_a_contract_staked_in_past_period_fails() { #[test] fn stake_and_unstake_after_reward_claim_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -2747,7 +2747,7 @@ fn stake_and_unstake_after_reward_claim_is_ok() { #[test] fn stake_and_unstake_correctly_updates_staked_amounts() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -2872,7 +2872,7 @@ fn stake_and_unstake_correctly_updates_staked_amounts() { #[test] fn stake_after_period_ends_with_max_staked_contracts() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let max_number_of_contracts: u32 = <Test as Config>::MaxNumberOfStakedContracts::get(); // Lock amount by staker @@ -2906,7 +2906,7 @@ fn stake_after_period_ends_with_max_staked_contracts() { #[test] fn post_unlock_balance_cannot_be_transferred() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let staker = 2; // Lock some of the free balance @@ -2965,7 +2965,7 @@ fn post_unlock_balance_cannot_be_transferred() { #[test] fn observer_pre_new_era_block_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { fn assert_observer_value(expected: EraNumber) { BLOCK_BEFORE_NEW_ERA.with(|v| assert_eq!(expected, *v.borrow())); } @@ -3013,7 +3013,7 @@ fn observer_pre_new_era_block_works() { #[test] fn unregister_after_max_number_of_contracts_allows_register_again() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let max_number_of_contracts = <Test as Config>::MaxNumberOfContracts::get(); let developer = 2; @@ -3099,7 +3099,7 @@ fn safeguard_configurable_by_genesis_config() { #[test] fn base_number_of_slots_is_respected() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // 0. Get expected number of slots for the base price let total_issuance = <Test as Config>::Currency::total_issuance(); let base_native_price = <Test as Config>::BaseNativeCurrencyPrice::get(); @@ -3203,7 +3203,7 @@ fn base_number_of_slots_is_respected() { #[test] fn ranking_will_calc_reward_correctly() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Tier config is specially adapted for this test. TierConfig::<Test>::mutate(|config| { config.slots_per_tier = BoundedVec::try_from(vec![2, 3, 2, 20]).unwrap(); @@ -3268,7 +3268,7 @@ fn ranking_will_calc_reward_correctly() { #[test] fn claim_dapp_reward_with_rank() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { let total_issuance = <Test as Config>::Currency::total_issuance(); // Register smart contract, lock&stake some amount @@ -3315,7 +3315,7 @@ fn claim_dapp_reward_with_rank() { #[test] fn unstake_correctly_reduces_future_contract_stake() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // 0. Register smart contract, lock&stake some amount with staker 1 during the voting subperiod let smart_contract = MockSmartContract::wasm(1 as AccountId); assert_register(1, &smart_contract); @@ -3359,7 +3359,7 @@ fn unstake_correctly_reduces_future_contract_stake() { #[test] fn lock_correctly_considers_unlocking_amount() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Lock the entire amount & immediately start the unlocking process let (staker, unlock_amount) = (1, 13); let total_balance = Balances::total_balance(&staker); @@ -3375,7 +3375,7 @@ fn lock_correctly_considers_unlocking_amount() { #[test] fn fix_account_scenarios_work() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // 1. Lock some amount correctly, unstake it, try to fix it, and ensure the call fails let (account_1, lock_1) = (1, 100); assert_lock(account_1, lock_1); @@ -3447,7 +3447,7 @@ fn fix_account_scenarios_work() { #[test] fn claim_staker_rewards_for_basic_example_is_ok() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -3493,7 +3493,7 @@ fn claim_staker_rewards_for_basic_example_is_ok() { #[test] fn claim_bonus_reward_for_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build_and_execute(|| { // Register smart contract, lock&stake some amount let dev_account = 1; let smart_contract = MockSmartContract::wasm(1 as AccountId); @@ -3537,3 +3537,10 @@ fn claim_bonus_reward_for_works() { ); }) } + +#[test] +fn try_state_works() { + ExtBuilder::default().build_and_execute(|| { + assert_ok!(DappStaking::try_state_protocol()); + }) +} diff --git a/pallets/dapp-staking-v3/src/types.rs b/pallets/dapp-staking-v3/src/types.rs index c8cd9d9c98..5f40fe1277 100644 --- a/pallets/dapp-staking-v3/src/types.rs +++ b/pallets/dapp-staking-v3/src/types.rs @@ -57,7 +57,7 @@ //! //! ## Tier Information //! -//! * `TierThreshold` - an enum describing tier entry thresholds (as TVL amounts or as percentages of the total issuance). +//! * `TierThreshold` - an enum describing tier entry thresholds as percentages of the total issuance. //! * `TierParameters` - contains static information about tiers, like init thresholds, reward & slot distribution. //! * `TiersConfiguration` - contains dynamic information about tiers, derived from `TierParameters` and onchain data. //! * `DAppTier` - a compact struct describing a dApp's tier. From 740b3a9c1819160d74bdb4b1170af74d0f597d7e Mon Sep 17 00:00:00 2001 From: Igor Papandinas <26460174+ipapandinas@users.noreply.github.com> Date: Fri, 9 Aug 2024 17:57:26 +0200 Subject: [PATCH 2/6] try-state implemented - test needed --- pallets/dapp-staking-v3/src/lib.rs | 120 ++++++++++++++++++++++----- pallets/dapp-staking-v3/src/types.rs | 2 +- 2 files changed, 102 insertions(+), 20 deletions(-) diff --git a/pallets/dapp-staking-v3/src/lib.rs b/pallets/dapp-staking-v3/src/lib.rs index 2109bd6806..d90cd202a4 100644 --- a/pallets/dapp-staking-v3/src/lib.rs +++ b/pallets/dapp-staking-v3/src/lib.rs @@ -2401,7 +2401,7 @@ pub mod pallet { let mut ledger_total_unlocking = 0u128; let mut ledger_total_staked_future = 0u128; - for (account, ledger) in Ledger::<T>::iter() { + for (_, ledger) in Ledger::<T>::iter() { let account_stake: u128 = ledger.staked_amount(current_period_number); ledger_total_stake += account_stake; @@ -2416,12 +2416,16 @@ pub mod pallet { // Invariant 4 if account_stake < T::MinimumStakeAmount::get() { - return Err("An account has a stake amount lower than the minimum allowed.".into()); + return Err( + "An account has a stake amount lower than the minimum allowed.".into(), + ); } // Invariant 5 if ledger.active_locked_amount() < T::MinimumLockedAmount::get() { - return Err("An account has a locked amount lower than the minimum allowed.".into()); + return Err( + "An account has a locked amount lower than the minimum allowed.".into(), + ); } // Invariant 6 @@ -2430,23 +2434,23 @@ pub mod pallet { } } - // // Yield amounts in contracts in [`ContractStake`] - // let mut contracts_total_stake = 0u128; - // let mut contracts_total_staked_future = 0u128; + // Yield amounts in contracts in [`ContractStake`] + let mut contracts_total_stake = 0u128; + let mut contracts_total_staked_future = 0u128; - // for (_, contract) in ContractStake::<T>::iter() { - // let contract_stake: u128 = contract.staked_amount(current_period_number); + for (_, contract) in ContractStake::<T>::iter() { + let contract_stake: u128 = contract.total_staked_amount(current_period_number); - // contracts_total_stake += contract_stake; - // contracts_total_staked_future += contract_stake; - // } + contracts_total_stake += contract_stake; + contracts_total_staked_future += contract_stake; + } - // // Invariant 1 - // if contracts_total_stake != current_era_info.current_stake_amount.total() - // || contracts_total_staked_future != current_era_info.next_stake_amount.total() - // { - // return Err("Mismatch between ContractStake totals and CurrentEraInfo.".into()); - // } + // Invariant 1 + if contracts_total_stake != current_era_info.current_stake_amount.total() + || contracts_total_staked_future != current_era_info.next_stake_amount.total() + { + return Err("Mismatch between ContractStake totals and CurrentEraInfo.".into()); + } // Invariant 2 if ledger_total_stake != current_era_info.current_stake_amount.total() @@ -2462,10 +2466,37 @@ pub mod pallet { /// ### Invariants of ContractStake /// - /// 1. Iterating over all SCs in [`ContractStake`] should yield the correct `staked`& `staked_future` amounts compared to `current_stake_amount` & `next_stake_amount` in [`CurrentEraInfo`] + /// 1. Iterating over all contracts in [`ContractStake`] should yield the correct staked amounts compared to current era in [`CurrentEraInfo`] /// 2. Each staking entry in [`ContractStake`] should be greater than or equal to the [`T::MinimumStakeAmount`] constant. #[cfg(any(feature = "try-runtime", test))] pub fn try_state_contract_stake() -> Result<(), sp_runtime::TryRuntimeError> { + let current_era_info = CurrentEraInfo::<T>::get(); + let current_period_number = ActiveProtocolState::<T>::get().period_number(); + + let mut total_staked = 0u128; + let mut total_staked_future = 0u128; + + for (_, contract) in ContractStake::<T>::iter() { + let contract_stake: u128 = contract.total_staked_amount(current_period_number); + + total_staked += contract_stake; + total_staked_future += contract_stake; + + // Invariant 2 + if contract_stake < T::MinimumStakeAmount::get() { + return Err( + "A contract has a staked amount lower than the minimum allowed.".into(), + ); + } + } + + // Invariant 1 + if total_staked != current_era_info.current_stake_amount.total() + || total_staked_future != current_era_info.next_stake_amount.total() + { + return Err("Mismatch between ContractStake totals and CurrentEraInfo.".into()); + } + Ok(()) } @@ -2473,11 +2504,62 @@ pub mod pallet { /// /// 1. Era number in [`DAppTiers`] must also be stored in one of the span of [`EraRewards`]. /// 2. Combining all span lengths it should yield the number of items in [`DAppTiers`] - /// 3. The sum of rewards for each span in [`EraRewards`] must be equal to the number of rewards for the same eras in [`DAppTiers`] + /// 3. The sum of rewards for each span in [`EraRewards`] must be equal to the number of rewards for the same eras in [`DAppTiers`] /// 4. The number of eras retained in [`EraRewards`] should not exceed the [`T::RewardRetentionInPeriods`] constant. /// 5. Each span lenght entry in [`EraRewards`] should be lower than or equal to the [`T::EraRewardSpanLength`] constant. #[cfg(any(feature = "try-runtime", test))] pub fn try_state_era_rewards() -> Result<(), sp_runtime::TryRuntimeError> { + let era_rewards = EraRewards::<T>::iter().collect::<Vec<_>>(); + let dapp_tiers_count = DAppTiers::<T>::iter().count(); + + let mut total_spans_length = 0; + let mut total_rewards_dapp_pool = 0u128; + + for (_, span) in &era_rewards { + total_spans_length += span.len(); + + // Invariant 1 + for era in span.first_era()..=span.last_era() { + if !DAppTiers::<T>::contains_key(era) { + return Err( + "DAppTiers does not contain a required era from EraRewards.".into() + ); + } + } + + for reward in &span.span { + total_rewards_dapp_pool += reward.dapp_reward_pool; + } + + // Invariant 5 + if span.len() > T::EraRewardSpanLength::get() as usize { + return Err( + "Span length for a era exceeds the maximum allowed span length.".into(), + ); + } + } + + // Invariant 2 + if total_spans_length != dapp_tiers_count { + return Err( + "Total span lengths do not match the number of items in DAppTiers.".into(), + ); + } + + // Invariant 3 + let total_dapp_tiers_rewards_dapp_pool: u128 = DAppTiers::<T>::iter() + .map(|(_, r)| r.rewards.iter().copied().sum::<Balance>()) + .sum(); + + if total_rewards_dapp_pool != total_dapp_tiers_rewards_dapp_pool { + return Err("Mismatch between total rewards in EraRewards and DAppTiers.".into()); + } + + // Invariant 4 + if era_rewards.len() > T::RewardRetentionInPeriods::get() as usize { + return Err("Number of eras in EraRewards exceeds the retention period.".into()); + } + Ok(()) } } diff --git a/pallets/dapp-staking-v3/src/types.rs b/pallets/dapp-staking-v3/src/types.rs index 5f40fe1277..fbc10acfde 100644 --- a/pallets/dapp-staking-v3/src/types.rs +++ b/pallets/dapp-staking-v3/src/types.rs @@ -1371,7 +1371,7 @@ pub enum EraRewardSpanError { #[scale_info(skip_type_params(SL))] pub struct EraRewardSpan<SL: Get<u32>> { /// Span of EraRewardInfo entries. - span: BoundedVec<EraReward, SL>, + pub span: BoundedVec<EraReward, SL>, /// The first era in the span. #[codec(compact)] first_era: EraNumber, From f8aadbbcbaf31e4b3e2a7a6444097d7f4d0c0b6c Mon Sep 17 00:00:00 2001 From: Igor Papandinas <26460174+ipapandinas@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:11:22 +0200 Subject: [PATCH 3/6] try-state tested --- pallets/dapp-staking-v3/src/lib.rs | 161 +++++++++------------- pallets/dapp-staking-v3/src/test/tests.rs | 7 - 2 files changed, 63 insertions(+), 105 deletions(-) diff --git a/pallets/dapp-staking-v3/src/lib.rs b/pallets/dapp-staking-v3/src/lib.rs index d90cd202a4..05b99b07e0 100644 --- a/pallets/dapp-staking-v3/src/lib.rs +++ b/pallets/dapp-staking-v3/src/lib.rs @@ -2271,15 +2271,14 @@ pub mod pallet { /// ### Invariants of active protocol storage items /// - /// 1. [`PeriodInfo`] number in [`ActiveProtocolState`] must always be greater than or equal to the number of elements in [`PeriodEnd`]. + /// 1. [`PeriodInfo`] number in [`ActiveProtocolState`] must always be greater than the number of elements in [`PeriodEnd`]. /// 2. Ensures the `era` number and `next_era_start` block number are valid. #[cfg(any(feature = "try-runtime", test))] pub fn try_state_protocol() -> Result<(), sp_runtime::TryRuntimeError> { let protocol_state = ActiveProtocolState::<T>::get(); - let period_number = protocol_state.period_info.number; // Invariant 1 - if PeriodEnd::<T>::iter().count() >= period_number as usize { + if PeriodEnd::<T>::iter().count() >= protocol_state.period_info.number as usize { return Err("Number of periods in `PeriodEnd` exceeds or is equal to actual `PeriodInfo` number.".into()); } @@ -2301,8 +2300,8 @@ pub mod pallet { /// ### Invariants of NextDAppId /// - /// 1. [`NextDAppId`] must always be equal to the number of dapps in [`IntegratedDApps`]. - /// 2. [`NextDAppId`] must always be equal to the number of contracts in [`ContractStake`]. + /// 1. [`NextDAppId`] must always be greater than or equal to the number of dapps in [`IntegratedDApps`]. + /// 2. [`NextDAppId`] must always be greater than or equal to the number of contracts in [`ContractStake`]. #[cfg(any(feature = "try-runtime", test))] pub fn try_state_next_dapp_id() -> Result<(), sp_runtime::TryRuntimeError> { let next_dapp_id = NextDAppId::<T>::get(); @@ -2337,8 +2336,8 @@ pub mod pallet { /// ### Invariants of StaticTierParams and TierConfig /// - /// 1. The [`T::NumberOfTiers`] constant must always be equal to the number of `slot_distribution`, `reward_portion`, `tier_thresholds`in [`StaticTierParams`]. - /// 2. The [`T::NumberOfTiers`] constant must always be equal to the number of `slots_per_tier`, `reward_portion`, `tier_thresholds`in [`TierConfig`]. + /// 1. The [`T::NumberOfTiers`] constant must always be equal to the number of `slot_distribution`, `reward_portion`, `tier_thresholds` in [`StaticTierParams`]. + /// 2. The [`T::NumberOfTiers`] constant must always be equal to the number of `slots_per_tier`, `reward_portion`, `tier_thresholds` in [`TierConfig`]. #[cfg(any(feature = "try-runtime", test))] pub fn try_state_tiers() -> Result<(), sp_runtime::TryRuntimeError> { let nb_tiers = T::NumberOfTiers::get(); @@ -2384,81 +2383,74 @@ pub mod pallet { /// ### Invariants of Ledger /// - /// 1. Iterating over all [`Ledger`] accounts should yield the correct stake amount accross all contracts in [`ContractStake`]. - /// 2. Iterating over all [`Ledger`] accounts should yield the correct locked and stakes amounts compared to current era in [`CurrentEraInfo`]. - /// 3. The number of unlocking chunks in [`Ledger`] for any account should not exceed the [`T::MaxUnlockingChunks`] constant. - /// 4. Each staking entry in [`Ledger`] should be greater than or equal to the [`T::MinimumStakeAmount`] constant. - /// 5. Each locking entry in [`Ledger`] should be greater than or equal to the [`T::MinimumLockedAmount`] constant. - /// 6. The number of staking entries per account in [`Ledger`] should not exceed the [`T::MaxNumberOfStakedContracts`] constant. + /// 1. Iterating over all [`Ledger`] accounts should yield the correct locked and stakes amounts compared to current era in [`CurrentEraInfo`]. + /// 2. The number of unlocking chunks in [`Ledger`] for any account should not exceed the [`T::MaxUnlockingChunks`] constant. + /// 3. Each staking entry in [`Ledger`] should be greater than or equal to the [`T::MinimumStakeAmount`] constant. + /// 4. Each locking entry in [`Ledger`] should be greater than or equal to the [`T::MinimumLockedAmount`] constant. + /// 5. The number of staking entries per account in [`Ledger`] should not exceed the [`T::MaxNumberOfStakedContracts`] constant. #[cfg(any(feature = "try-runtime", test))] pub fn try_state_ledger() -> Result<(), sp_runtime::TryRuntimeError> { - let current_era_info = CurrentEraInfo::<T>::get(); let current_period_number = ActiveProtocolState::<T>::get().period_number(); + let current_era_info = CurrentEraInfo::<T>::get(); + let current_era_total_stake = current_era_info.total_staked_amount_next_era(); // Yield amounts in [`Ledger`] - let mut ledger_total_stake = 0u128; - let mut ledger_total_locked = 0u128; - let mut ledger_total_unlocking = 0u128; - let mut ledger_total_staked_future = 0u128; + let mut ledger_total_stake = Balance::zero(); + let mut ledger_total_locked = Balance::zero(); + let mut ledger_total_unlocking = Balance::zero(); for (_, ledger) in Ledger::<T>::iter() { - let account_stake: u128 = ledger.staked_amount(current_period_number); + let account_stake = ledger.staked_amount(current_period_number); ledger_total_stake += account_stake; - ledger_total_staked_future += account_stake; ledger_total_locked += ledger.active_locked_amount(); ledger_total_unlocking += ledger.unlocking_amount(); - // Invariant 3 + // Invariant 2 if ledger.unlocking.len() > T::MaxUnlockingChunks::get() as usize { return Err("An account exceeds the maximum unlocking chunks.".into()); } - // Invariant 4 - if account_stake < T::MinimumStakeAmount::get() { + // Invariant 3 + if account_stake > Balance::zero() && account_stake < T::MinimumStakeAmount::get() { return Err( "An account has a stake amount lower than the minimum allowed.".into(), ); } - // Invariant 5 - if ledger.active_locked_amount() < T::MinimumLockedAmount::get() { + // Invariant 4 + if ledger.active_locked_amount() > Balance::zero() + && ledger.active_locked_amount() < T::MinimumLockedAmount::get() + { return Err( "An account has a locked amount lower than the minimum allowed.".into(), ); } - // Invariant 6 + // Invariant 5 if ledger.contract_stake_count > T::MaxNumberOfStakedContracts::get() { return Err("An account exceeds the maximum number of staked contracts.".into()); } } - // Yield amounts in contracts in [`ContractStake`] - let mut contracts_total_stake = 0u128; - let mut contracts_total_staked_future = 0u128; - - for (_, contract) in ContractStake::<T>::iter() { - let contract_stake: u128 = contract.total_staked_amount(current_period_number); - - contracts_total_stake += contract_stake; - contracts_total_staked_future += contract_stake; + // Invariant 1 + if ledger_total_stake != current_era_total_stake { + return Err( + "Mismatch between Ledger total staked amounts and CurrentEraInfo total.".into(), + ); } - // Invariant 1 - if contracts_total_stake != current_era_info.current_stake_amount.total() - || contracts_total_staked_future != current_era_info.next_stake_amount.total() - { - return Err("Mismatch between ContractStake totals and CurrentEraInfo.".into()); + if ledger_total_locked != current_era_info.total_locked { + return Err( + "Mismatch between Ledger total locked amounts and CurrentEraInfo total.".into(), + ); } - // Invariant 2 - if ledger_total_stake != current_era_info.current_stake_amount.total() - || ledger_total_locked != current_era_info.total_locked - || ledger_total_unlocking != current_era_info.unlocking - || ledger_total_staked_future != current_era_info.next_stake_amount.total() - { - return Err("Mismatch between Ledger totals and CurrentEraInfo.".into()); + if ledger_total_unlocking != current_era_info.unlocking { + return Err( + "Mismatch between Ledger total unlocked amounts and CurrentEraInfo total." + .into(), + ); } Ok(()) @@ -2466,24 +2458,25 @@ pub mod pallet { /// ### Invariants of ContractStake /// - /// 1. Iterating over all contracts in [`ContractStake`] should yield the correct staked amounts compared to current era in [`CurrentEraInfo`] + /// 1. Iterating over all contracts in [`ContractStake`] should yield the correct staked amounts compared to current era in [`CurrentEraInfo`] /// 2. Each staking entry in [`ContractStake`] should be greater than or equal to the [`T::MinimumStakeAmount`] constant. #[cfg(any(feature = "try-runtime", test))] pub fn try_state_contract_stake() -> Result<(), sp_runtime::TryRuntimeError> { - let current_era_info = CurrentEraInfo::<T>::get(); let current_period_number = ActiveProtocolState::<T>::get().period_number(); + let current_era_info = CurrentEraInfo::<T>::get(); + let current_era_total_stake = current_era_info.total_staked_amount_next_era(); + let ok = current_era_info.total_staked_amount(); - let mut total_staked = 0u128; - let mut total_staked_future = 0u128; + let mut total_staked = Balance::zero(); for (_, contract) in ContractStake::<T>::iter() { - let contract_stake: u128 = contract.total_staked_amount(current_period_number); + let contract_stake = contract.total_staked_amount(current_period_number); total_staked += contract_stake; - total_staked_future += contract_stake; // Invariant 2 - if contract_stake < T::MinimumStakeAmount::get() { + if contract_stake > Balance::zero() && contract_stake < T::MinimumStakeAmount::get() + { return Err( "A contract has a staked amount lower than the minimum allowed.".into(), ); @@ -2491,9 +2484,7 @@ pub mod pallet { } // Invariant 1 - if total_staked != current_era_info.current_stake_amount.total() - || total_staked_future != current_era_info.next_stake_amount.total() - { + if total_staked != current_era_total_stake { return Err("Mismatch between ContractStake totals and CurrentEraInfo.".into()); } @@ -2503,35 +2494,30 @@ pub mod pallet { /// ### Invariants of EraRewards /// /// 1. Era number in [`DAppTiers`] must also be stored in one of the span of [`EraRewards`]. - /// 2. Combining all span lengths it should yield the number of items in [`DAppTiers`] - /// 3. The sum of rewards for each span in [`EraRewards`] must be equal to the number of rewards for the same eras in [`DAppTiers`] - /// 4. The number of eras retained in [`EraRewards`] should not exceed the [`T::RewardRetentionInPeriods`] constant. - /// 5. Each span lenght entry in [`EraRewards`] should be lower than or equal to the [`T::EraRewardSpanLength`] constant. + /// 2. Each span lenght entry in [`EraRewards`] should be lower than or equal to the [`T::EraRewardSpanLength`] constant. #[cfg(any(feature = "try-runtime", test))] pub fn try_state_era_rewards() -> Result<(), sp_runtime::TryRuntimeError> { let era_rewards = EraRewards::<T>::iter().collect::<Vec<_>>(); - let dapp_tiers_count = DAppTiers::<T>::iter().count(); - - let mut total_spans_length = 0; - let mut total_rewards_dapp_pool = 0u128; - - for (_, span) in &era_rewards { - total_spans_length += span.len(); + let dapp_tiers = DAppTiers::<T>::iter().collect::<Vec<_>>(); - // Invariant 1 - for era in span.first_era()..=span.last_era() { - if !DAppTiers::<T>::contains_key(era) { - return Err( - "DAppTiers does not contain a required era from EraRewards.".into() - ); + // Invariant 1 + for (era, _) in &dapp_tiers { + let mut found = false; + for (_, span) in &era_rewards { + if *era >= span.first_era() && *era <= span.last_era() { + found = true; + break; } } - for reward in &span.span { - total_rewards_dapp_pool += reward.dapp_reward_pool; + // Invariant 1 + if !found { + return Err("Era in DAppTiers is not found in any span in EraRewards.".into()); } + } - // Invariant 5 + for (_, span) in &era_rewards { + // Invariant 3 if span.len() > T::EraRewardSpanLength::get() as usize { return Err( "Span length for a era exceeds the maximum allowed span length.".into(), @@ -2539,27 +2525,6 @@ pub mod pallet { } } - // Invariant 2 - if total_spans_length != dapp_tiers_count { - return Err( - "Total span lengths do not match the number of items in DAppTiers.".into(), - ); - } - - // Invariant 3 - let total_dapp_tiers_rewards_dapp_pool: u128 = DAppTiers::<T>::iter() - .map(|(_, r)| r.rewards.iter().copied().sum::<Balance>()) - .sum(); - - if total_rewards_dapp_pool != total_dapp_tiers_rewards_dapp_pool { - return Err("Mismatch between total rewards in EraRewards and DAppTiers.".into()); - } - - // Invariant 4 - if era_rewards.len() > T::RewardRetentionInPeriods::get() as usize { - return Err("Number of eras in EraRewards exceeds the retention period.".into()); - } - Ok(()) } } diff --git a/pallets/dapp-staking-v3/src/test/tests.rs b/pallets/dapp-staking-v3/src/test/tests.rs index 91804ad715..28e8636335 100644 --- a/pallets/dapp-staking-v3/src/test/tests.rs +++ b/pallets/dapp-staking-v3/src/test/tests.rs @@ -3537,10 +3537,3 @@ fn claim_bonus_reward_for_works() { ); }) } - -#[test] -fn try_state_works() { - ExtBuilder::default().build_and_execute(|| { - assert_ok!(DappStaking::try_state_protocol()); - }) -} From f04e1d7168925af05c391a77325e6ba961e47776 Mon Sep 17 00:00:00 2001 From: Igor Papandinas <26460174+ipapandinas@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:28:09 +0200 Subject: [PATCH 4/6] fix clippy --- pallets/dapp-staking-v3/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/pallets/dapp-staking-v3/src/lib.rs b/pallets/dapp-staking-v3/src/lib.rs index 05b99b07e0..c07d7eadfe 100644 --- a/pallets/dapp-staking-v3/src/lib.rs +++ b/pallets/dapp-staking-v3/src/lib.rs @@ -2465,7 +2465,6 @@ pub mod pallet { let current_period_number = ActiveProtocolState::<T>::get().period_number(); let current_era_info = CurrentEraInfo::<T>::get(); let current_era_total_stake = current_era_info.total_staked_amount_next_era(); - let ok = current_era_info.total_staked_amount(); let mut total_staked = Balance::zero(); From 87e4044b417f3e0134282e66f0d95adfac7a3a21 Mon Sep 17 00:00:00 2001 From: Igor Papandinas <26460174+ipapandinas@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:59:12 +0200 Subject: [PATCH 5/6] fix CI --- pallets/dapp-staking-v3/src/benchmarking/mod.rs | 2 +- pallets/dapp-staking-v3/src/test/tests.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pallets/dapp-staking-v3/src/benchmarking/mod.rs b/pallets/dapp-staking-v3/src/benchmarking/mod.rs index bf0adfa0ee..0399a8d46a 100644 --- a/pallets/dapp-staking-v3/src/benchmarking/mod.rs +++ b/pallets/dapp-staking-v3/src/benchmarking/mod.rs @@ -1083,6 +1083,6 @@ mod tests { use sp_io::TestExternalities; pub fn new_test_ext() -> TestExternalities { - mock::ExtBuilder::build() + mock::ExtBuilder::default().build() } } diff --git a/pallets/dapp-staking-v3/src/test/tests.rs b/pallets/dapp-staking-v3/src/test/tests.rs index 28e8636335..a97ce38962 100644 --- a/pallets/dapp-staking-v3/src/test/tests.rs +++ b/pallets/dapp-staking-v3/src/test/tests.rs @@ -483,6 +483,8 @@ fn unregister_no_stake_is_ok() { } #[test] +#[ignore] +/// TODO - Reestablish this test once this bug is fixed: <https://github.com/AstarNetwork/Astar/issues/1333> fn unregister_with_active_stake_is_ok() { ExtBuilder::default().build_and_execute(|| { // Prepare dApp @@ -1322,7 +1324,9 @@ fn unstake_with_zero_amount_fails() { }) } +/// TODO - Reestablish this test once this bug is fixed: <https://github.com/AstarNetwork/Astar/issues/1333> #[test] +#[ignore] fn unstake_on_invalid_dapp_fails() { ExtBuilder::default().build_and_execute(|| { let account = 2; From b1f57b2eb5ef92315413bdc6762486e8cf1f3885 Mon Sep 17 00:00:00 2001 From: Igor Papandinas <26460174+ipapandinas@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:32:39 +0200 Subject: [PATCH 6/6] remove invariant check --- pallets/dapp-staking-v3/src/lib.rs | 16 ++-------------- pallets/dapp-staking-v3/src/test/tests.rs | 4 ---- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/pallets/dapp-staking-v3/src/lib.rs b/pallets/dapp-staking-v3/src/lib.rs index c07d7eadfe..63f061602b 100644 --- a/pallets/dapp-staking-v3/src/lib.rs +++ b/pallets/dapp-staking-v3/src/lib.rs @@ -2458,22 +2458,15 @@ pub mod pallet { /// ### Invariants of ContractStake /// - /// 1. Iterating over all contracts in [`ContractStake`] should yield the correct staked amounts compared to current era in [`CurrentEraInfo`] - /// 2. Each staking entry in [`ContractStake`] should be greater than or equal to the [`T::MinimumStakeAmount`] constant. + /// 1. Each staking entry in [`ContractStake`] should be greater than or equal to the [`T::MinimumStakeAmount`] constant. #[cfg(any(feature = "try-runtime", test))] pub fn try_state_contract_stake() -> Result<(), sp_runtime::TryRuntimeError> { let current_period_number = ActiveProtocolState::<T>::get().period_number(); - let current_era_info = CurrentEraInfo::<T>::get(); - let current_era_total_stake = current_era_info.total_staked_amount_next_era(); - - let mut total_staked = Balance::zero(); for (_, contract) in ContractStake::<T>::iter() { let contract_stake = contract.total_staked_amount(current_period_number); - total_staked += contract_stake; - - // Invariant 2 + // Invariant 1 if contract_stake > Balance::zero() && contract_stake < T::MinimumStakeAmount::get() { return Err( @@ -2482,11 +2475,6 @@ pub mod pallet { } } - // Invariant 1 - if total_staked != current_era_total_stake { - return Err("Mismatch between ContractStake totals and CurrentEraInfo.".into()); - } - Ok(()) } diff --git a/pallets/dapp-staking-v3/src/test/tests.rs b/pallets/dapp-staking-v3/src/test/tests.rs index a97ce38962..28e8636335 100644 --- a/pallets/dapp-staking-v3/src/test/tests.rs +++ b/pallets/dapp-staking-v3/src/test/tests.rs @@ -483,8 +483,6 @@ fn unregister_no_stake_is_ok() { } #[test] -#[ignore] -/// TODO - Reestablish this test once this bug is fixed: <https://github.com/AstarNetwork/Astar/issues/1333> fn unregister_with_active_stake_is_ok() { ExtBuilder::default().build_and_execute(|| { // Prepare dApp @@ -1324,9 +1322,7 @@ fn unstake_with_zero_amount_fails() { }) } -/// TODO - Reestablish this test once this bug is fixed: <https://github.com/AstarNetwork/Astar/issues/1333> #[test] -#[ignore] fn unstake_on_invalid_dapp_fails() { ExtBuilder::default().build_and_execute(|| { let account = 2;