diff --git a/pallets/liquidity-mining/src/lib.rs b/pallets/liquidity-mining/src/lib.rs index 3c92ea0a4a..6eab2f126e 100644 --- a/pallets/liquidity-mining/src/lib.rs +++ b/pallets/liquidity-mining/src/lib.rs @@ -202,6 +202,18 @@ impl PoolInfo { Ok(().into()) } + + /// Try to return back the remain of reward from keeper to investor + pub(crate) fn try_withdraw_remain(&self) -> DispatchResult { + let investor = self.investor.clone().ok_or(Error::::Unexpected)?; + + for (rtoken, reward) in self.rewards.iter() { + let remain = reward.total.saturating_sub(reward.claimed); + T::MultiCurrency::transfer(*rtoken, &self.keeper, &investor, remain)?; + } + + Ok(().into()) + } } #[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Debug)] @@ -660,15 +672,20 @@ pub mod pallet { let r#type = pool.r#type; let trading_pair = pool.trading_pair; - if pool.deposit == Zero::zero() { - TotalPoolInfos::::remove(pid); - } else { - let pool_retired = PoolInfo { - state: PoolState::Retired, - block_retired: Some(frame_system::Pallet::::block_number()), - ..pool - }; - TotalPoolInfos::::insert(pid, pool_retired); + match pool.state { + PoolState::Charged if pool.deposit == Zero::zero() => { + pool.try_withdraw_remain()?; + TotalPoolInfos::::remove(pid); + }, + PoolState::Charged | PoolState::Ongoing => { + let pool_retired = PoolInfo { + state: PoolState::Retired, + block_retired: Some(frame_system::Pallet::::block_number()), + ..pool + }; + TotalPoolInfos::::insert(pid, pool_retired); + }, + _ => {}, } Self::deposit_event(Event::PoolRetiredForcefully(pid, r#type, trading_pair)); @@ -1009,12 +1026,7 @@ pub mod pallet { }; if pool.state == PoolState::Retired && pool.deposit == Zero::zero() { - let investor = pool.investor.clone().ok_or(Error::::Unexpected)?; - for (rtoken, reward) in pool.rewards.iter() { - let remain = reward.total.saturating_sub(reward.claimed); - T::MultiCurrency::transfer(*rtoken, &pool.keeper, &investor, remain)?; - } - + pool.try_withdraw_remain()?; pool.state = PoolState::Dead; } diff --git a/pallets/liquidity-mining/src/tests.rs b/pallets/liquidity-mining/src/tests.rs index 0d04a4b6dc..c7913e3345 100644 --- a/pallets/liquidity-mining/src/tests.rs +++ b/pallets/liquidity-mining/src/tests.rs @@ -1791,7 +1791,7 @@ fn force_retire_pool_charged_should_work() { } #[test] -fn force_retire_pool_charged_with_no_deposit_should_work() { +fn force_retire_pool_charged_without_deposit_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), @@ -1806,11 +1806,27 @@ fn force_retire_pool_charged_with_no_deposit_should_work() { // It is unable to call Collective::execute(..) which is private; assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); + let keeper = LM::pool(0).unwrap().keeper; + assert_ok!(LM::force_retire_pool( pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0 )); + assert_eq!(Tokens::accounts(keeper.clone(), REWARD_1).free, 0); + assert_eq!(Tokens::accounts(keeper.clone(), REWARD_1).frozen, 0); + assert_eq!(Tokens::accounts(keeper.clone(), REWARD_1).reserved, 0); + assert_eq!(Tokens::accounts(keeper.clone(), REWARD_2).free, 0); + assert_eq!(Tokens::accounts(keeper.clone(), REWARD_2).frozen, 0); + assert_eq!(Tokens::accounts(keeper.clone(), REWARD_2).reserved, 0); + + assert_eq!(Tokens::accounts(INVESTOR, REWARD_1).free, REWARD_AMOUNT); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_1).frozen, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_1).reserved, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).free, REWARD_AMOUNT); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).frozen, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).reserved, 0); + assert!(LM::pool(0).is_none()); }); }