From 3207039766c0fac096a807675dd218f53c4c6c6a Mon Sep 17 00:00:00 2001 From: Dino Pacandi Date: Mon, 9 Oct 2023 16:57:25 +0200 Subject: [PATCH] Additional scenario --- pallets/dapp-staking-v3/src/lib.rs | 8 ++- .../dapp-staking-v3/src/test/testing_utils.rs | 60 ++++++++++--------- pallets/dapp-staking-v3/src/test/tests.rs | 9 ++- pallets/dapp-staking-v3/src/types.rs | 5 ++ 4 files changed, 52 insertions(+), 30 deletions(-) diff --git a/pallets/dapp-staking-v3/src/lib.rs b/pallets/dapp-staking-v3/src/lib.rs index 380878170d..fc348445d9 100644 --- a/pallets/dapp-staking-v3/src/lib.rs +++ b/pallets/dapp-staking-v3/src/lib.rs @@ -857,7 +857,6 @@ pub mod pallet { _ => Error::::InternalUnstakeError, })?; - // TODO: if it's full unstake, entry must be removed! // 2. // Update `StakerInfo` storage with the reduced stake amount on the specified contract. let new_staking_info = match StakerInfo::::get(&account, &smart_contract) { @@ -897,9 +896,14 @@ pub mod pallet { // 5. // Update remaining storage entries Self::update_ledger(&account, ledger); - StakerInfo::::insert(&account, &smart_contract, new_staking_info); ContractStake::::insert(&smart_contract, contract_stake_info); + if new_staking_info.is_empty() { + StakerInfo::::remove(&account, &smart_contract); + } else { + StakerInfo::::insert(&account, &smart_contract, new_staking_info); + } + Self::deposit_event(Event::::Unstake { account, smart_contract, diff --git a/pallets/dapp-staking-v3/src/test/testing_utils.rs b/pallets/dapp-staking-v3/src/test/testing_utils.rs index fc0e74daf2..cd0236581f 100644 --- a/pallets/dapp-staking-v3/src/test/testing_utils.rs +++ b/pallets/dapp-staking-v3/src/test/testing_utils.rs @@ -598,6 +598,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 is_full_unstake = pre_staker_info.total_staked_amount() == amount; // Unstake from smart contract & verify event assert_ok!(DappStaking::unstake( @@ -614,10 +615,6 @@ pub(crate) fn assert_unstake( // Verify post-state let post_snapshot = MemorySnapshot::new(); let post_ledger = post_snapshot.ledger.get(&account).unwrap(); - let post_staker_info = post_snapshot - .staker_info - .get(&(account, *smart_contract)) - .expect("Entry must exist since 'stake' operation was successfull."); let post_contract_stake = post_snapshot .contract_stake .get(&smart_contract) @@ -643,28 +640,39 @@ pub(crate) fn assert_unstake( // 2. verify staker info // ===================== // ===================== - assert_eq!(post_staker_info.period_number(), unstake_period); - assert_eq!( - post_staker_info.total_staked_amount(), - pre_staker_info.total_staked_amount() - amount, - "Total staked amount must decrease by the 'amount'" - ); - assert_eq!( - post_staker_info.staked_amount(unstake_period_type), - pre_staker_info - .staked_amount(unstake_period_type) - .saturating_sub(amount), - "Staked amount must decrease by the 'amount'" - ); + if is_full_unstake { + assert!( + !StakerInfo::::contains_key(&account, smart_contract), + "Entry must be deleted since it was a full unstake." + ); + } else { + let post_staker_info = post_snapshot + .staker_info + .get(&(account, *smart_contract)) + .expect("Entry must exist since 'stake' operation was successfull and it wasn't a full unstake."); + assert_eq!(post_staker_info.period_number(), unstake_period); + assert_eq!( + post_staker_info.total_staked_amount(), + pre_staker_info.total_staked_amount() - amount, + "Total staked amount must decrease by the 'amount'" + ); + assert_eq!( + post_staker_info.staked_amount(unstake_period_type), + pre_staker_info + .staked_amount(unstake_period_type) + .saturating_sub(amount), + "Staked amount must decrease by the 'amount'" + ); - let is_loyal = !(unstake_period_type == PeriodType::BuildAndEarn - && post_staker_info.staked_amount(PeriodType::Voting) - < pre_staker_info.staked_amount(PeriodType::Voting)); - assert_eq!( - post_staker_info.is_loyal(), - is_loyal, - "If 'Voting' stake amount is reduced in B&E period, loyalty flag must be set to false." - ); + let is_loyal = !(unstake_period_type == PeriodType::BuildAndEarn + && post_staker_info.staked_amount(PeriodType::Voting) + < pre_staker_info.staked_amount(PeriodType::Voting)); + assert_eq!( + post_staker_info.is_loyal(), + is_loyal, + "If 'Voting' stake amount is reduced in B&E period, loyalty flag must be set to false." + ); + } // 3. verify contract stake // ========================= @@ -691,8 +699,6 @@ pub(crate) fn assert_unstake( if pre_era_info.total_staked_amount() < amount { assert!(post_era_info.total_staked_amount().is_zero()); } else { - println!("pre_era_info: {:?}", pre_era_info); - println!("post_era_info: {:?}", post_era_info); assert_eq!( post_era_info.total_staked_amount(), pre_era_info.total_staked_amount() - amount, diff --git a/pallets/dapp-staking-v3/src/test/tests.rs b/pallets/dapp-staking-v3/src/test/tests.rs index 83c6ec676a..9e17c57275 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 as pallet_dapp_staking, ActiveProtocolState, DAppId, EraNumber, Error, IntegratedDApps, - Ledger, NextDAppId, PeriodType, + Ledger, NextDAppId, PeriodType, StakerInfo, }; use frame_support::{assert_noop, assert_ok, error::BadOrigin, traits::Get}; @@ -993,6 +993,13 @@ fn unstake_basic_example_is_ok() { advance_to_era(ActiveProtocolState::::get().era + 3); assert_unstake(account, &smart_contract, unstake_amount_3); assert_unstake(account, &smart_contract, unstake_amount_2); + + // 4th scenario - perform a full unstake + advance_to_next_era(); + let full_unstake_amount = StakerInfo::::get(&account, &smart_contract) + .unwrap() + .total_staked_amount(); + assert_unstake(account, &smart_contract, full_unstake_amount); }) } diff --git a/pallets/dapp-staking-v3/src/types.rs b/pallets/dapp-staking-v3/src/types.rs index 231b34b6ce..b8a7a352b5 100644 --- a/pallets/dapp-staking-v3/src/types.rs +++ b/pallets/dapp-staking-v3/src/types.rs @@ -961,6 +961,11 @@ impl SingularStakingInfo { pub fn period_number(&self) -> PeriodNumber { self.period } + + /// `true` if no stake exists, `false` otherwise. + pub fn is_empty(&self) -> bool { + self.vp_staked_amount.is_zero() && self.bep_staked_amount.is_zero() + } } /// Information about how much was staked on a contract during a specific era or period.