diff --git a/pallets/liquidity-mining/src/lib.rs b/pallets/liquidity-mining/src/lib.rs index 943895a7cb..6ea307c2fc 100644 --- a/pallets/liquidity-mining/src/lib.rs +++ b/pallets/liquidity-mining/src/lib.rs @@ -22,7 +22,7 @@ use frame_support::{ pallet_prelude::*, sp_runtime::{ - traits::{SaturatedConversion, Saturating, Zero}, + traits::{AccountIdConversion, SaturatedConversion, Saturating, Zero}, FixedPointNumber, FixedU128, }, sp_std::{ @@ -31,7 +31,8 @@ use frame_support::{ convert::TryFrom, vec::Vec, }, - traits::{BalanceStatus, EnsureOrigin}, + traits::EnsureOrigin, + transactional, PalletId, }; use frame_system::pallet_prelude::*; use node_primitives::{CurrencyId, CurrencyIdExt, LeasePeriod, ParaId, TokenInfo, TokenSymbol}; @@ -49,8 +50,10 @@ const DEPOSIT_ID: LockIdentifier = *b"deposit "; pub struct PoolInfo { /// Id of the liquidity-pool pool_id: PoolId, - /// The creator of the liquidity-pool - creator: AccountIdOf, + /// The keeper of the liquidity-pool + keeper: AccountIdOf, + /// The man who charges the rewards to the pool + investor: Option>, /// The trading-pair supported by the liquidity-pool trading_pair: (CurrencyId, CurrencyId), /// The length of time the liquidity-pool releases rewards @@ -104,11 +107,11 @@ impl PoolInfo { self } - /// Trying to change the state from `PoolState::Approved` to `PoolState::Ongoing` + /// Trying to change the state from `PoolState::Charged` to `PoolState::Ongoing` /// /// __NOTE__: Only called in the `Hook` pub(crate) fn try_startup(mut self, n: BlockNumberFor) -> Self { - if self.state == PoolState::Approved { + if self.state == PoolState::Charged { if n >= self.after_block_to_start && self.deposit >= self.min_deposit_to_start { self.block_startup = Some(n); self.state = PoolState::Ongoing; @@ -179,15 +182,11 @@ impl PoolInfo { } for (rtoken, amount) in to_rewards.iter() { - let remain = T::MultiCurrency::repatriate_reserved( - *rtoken, - &self.creator, - &user, - *amount, - BalanceStatus::Free, - )?; + T::MultiCurrency::ensure_can_withdraw(*rtoken, &self.keeper, *amount)?; + } - ensure!(remain == Zero::zero(), Error::::Unexpected); + for (rtoken, amount) in to_rewards.iter() { + T::MultiCurrency::transfer(*rtoken, &self.keeper, &user, *amount)?; } Pallet::::deposit_event(Event::UserClaimed( @@ -211,8 +210,8 @@ pub enum PoolType { #[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Debug)] pub enum PoolState { - UnderAudit, - Approved, + UnCharged, + Charged, Ongoing, Retired, Dead, @@ -333,7 +332,7 @@ pub mod pallet { pub trait Config: frame_system::Config { type Event: From> + IsType<::Event>; - /// Origin for anyone able to create/approve/kill the liquidity-pool. + /// Origin for anyone able to create/kill/force_retire the liquidity-pool. type ControlOrigin: EnsureOrigin; type MultiCurrency: MultiCurrency, CurrencyId = CurrencyId> @@ -360,9 +359,13 @@ pub mod pallet { #[pallet::constant] type MinimumDuration: Get>; - /// The number of liquidity-pool approved should be less than the value + /// The number of liquidity-pool charged should be less than the value #[pallet::constant] - type MaximumApproved: Get; + type MaximumCharged: Get; + + /// ModuleID for creating sub account + #[pallet::constant] + type PalletId: Get; } #[pallet::error] @@ -373,14 +376,13 @@ pub mod pallet { InvalidDepositLimit, InvalidPoolId, InvalidPoolState, - InvalidPoolOwner, - InvalidPooltype, + InvalidPoolType, /// Find duplicate reward when creating the liquidity-pool DuplicateReward, /// When the amount deposited in a liquidity-pool exceeds the `MaximumDepositInPool` ExceedMaximumDeposit, - /// When the number of pool-approved exceeds the `MaximumApproved` - ExceedMaximumApproved, + /// When the number of pool-charged exceeds the `MaximumCharged` + ExceedMaximumCharged, /// Not enough balance to deposit NotEnoughToDeposit, /// Not enough balance of reward to unreserve @@ -393,6 +395,8 @@ pub mod pallet { TooLowDepositInPoolToRedeem, /// The interval between two claims is short TooShortBetweenTwoClaim, + /// The pool has been charged + PoolChargedAlready, /// __NOTE__: ERROR HAPPEN Unexpected, } @@ -402,12 +406,12 @@ pub mod pallet { pub enum Event { /// The liquidity-pool has been created /// - /// [pool_id, pool_type, trading_pair, creator] + /// [pool_id, pool_type, trading_pair, keeper] PoolCreated(PoolId, PoolType, (CurrencyId, CurrencyId), AccountIdOf), - /// The liquidity-pool has been approved + /// The liquidity-pool has been charged /// - /// [pool_id, pool_type, trading_pair] - PoolApproved(PoolId, PoolType, (CurrencyId, CurrencyId)), + /// [pool_id, pool_type, trading_pair, investor] + PoolCharged(PoolId, PoolType, (CurrencyId, CurrencyId), AccountIdOf), /// The liquidity-pool has been started up /// /// [pool_id, pool_type, trading_pair] @@ -445,8 +449,8 @@ pub mod pallet { pub(crate) type NextOrderId = StorageValue<_, PoolId, ValueQuery>; #[pallet::storage] - #[pallet::getter(fn approved_pids)] - pub(crate) type ApprovedPoolIds = StorageValue<_, BTreeSet, ValueQuery>; + #[pallet::getter(fn charged_pids)] + pub(crate) type ChargedPoolIds = StorageValue<_, BTreeSet, ValueQuery>; #[pallet::storage] #[pallet::getter(fn pool)] @@ -560,44 +564,46 @@ pub mod pallet { } #[pallet::weight(1_000)] - pub fn approve_pool(origin: OriginFor, pid: PoolId) -> DispatchResultWithPostInfo { - let _ = T::ControlOrigin::ensure_origin(origin)?; + pub fn charge(origin: OriginFor, pid: PoolId) -> DispatchResultWithPostInfo { + let investor = ensure_signed(origin)?; - let num = Self::approved_pids().len() as u32; - ensure!(num < T::MaximumApproved::get(), Error::::ExceedMaximumApproved); + let num = Self::charged_pids().len() as u32; + ensure!(num < T::MaximumCharged::get(), Error::::ExceedMaximumCharged); let pool: PoolInfo = Self::pool(pid).ok_or(Error::::InvalidPoolId)?; - ensure!(pool.state == PoolState::UnderAudit, Error::::InvalidPoolState); + ensure!(pool.state == PoolState::UnCharged, Error::::InvalidPoolState); + ensure!(pool.investor.is_none(), Error::::PoolChargedAlready); + + for (token, reward) in pool.rewards.iter() { + T::MultiCurrency::ensure_can_withdraw(*token, &investor, reward.total)?; + } - ApprovedPoolIds::::mutate(|pids| pids.insert(pid)); + for (token, reward) in pool.rewards.iter() { + T::MultiCurrency::transfer(*token, &investor, &pool.keeper, reward.total)?; + } + + ChargedPoolIds::::mutate(|pids| pids.insert(pid)); let r#type = pool.r#type; let trading_pair = pool.trading_pair; - let pool_approved = PoolInfo { state: PoolState::Approved, ..pool }; - TotalPoolInfos::::insert(pid, pool_approved); + let pool_charged = + PoolInfo { state: PoolState::Charged, investor: Some(investor.clone()), ..pool }; + TotalPoolInfos::::insert(pid, pool_charged); - Self::deposit_event(Event::PoolApproved(pid, r#type, trading_pair)); + Self::deposit_event(Event::PoolCharged(pid, r#type, trading_pair, investor)); Ok(().into()) } #[pallet::weight(1_000)] pub fn kill_pool(origin: OriginFor, pid: PoolId) -> DispatchResultWithPostInfo { - let signed = ensure_signed(origin)?; + let _ = T::ControlOrigin::ensure_origin(origin)?; let pool: PoolInfo = Self::pool(pid).ok_or(Error::::InvalidPoolId)?; - ensure!(signed == pool.creator, Error::::InvalidPoolOwner); - - ensure!(pool.state == PoolState::UnderAudit, Error::::InvalidPoolState); - - for (token, reward) in pool.rewards.iter() { - let total = reward.total; - let remain = T::MultiCurrency::unreserve(*token, &signed, total); - ensure!(remain == Zero::zero(), Error::::FailOnUnReserve); - } + ensure!(pool.state == PoolState::UnCharged, Error::::InvalidPoolState); let pool_killed = PoolInfo { state: PoolState::Dead, ..pool }; TotalPoolInfos::::remove(pid); @@ -618,7 +624,7 @@ pub mod pallet { let pool: PoolInfo = Self::pool(pid).ok_or(Error::::InvalidPoolId)?.try_retire(); ensure!( - pool.state == PoolState::Approved || pool.state == PoolState::Ongoing, + pool.state == PoolState::Charged || pool.state == PoolState::Ongoing, Error::::InvalidPoolState ); @@ -649,7 +655,8 @@ pub mod pallet { /// /// The conditions to deposit: /// - User should deposit enough(greater than `T::MinimumDeposit`) token to liquidity-pool; - /// - The liquidity-pool should be in special state: `Approved`, `Ongoing`; + /// - The liquidity-pool should be in special state: `Charged`, `Ongoing`; + #[transactional] #[pallet::weight(1_000)] pub fn deposit( origin: OriginFor, @@ -662,7 +669,7 @@ pub mod pallet { Self::pool(pid).ok_or(Error::::InvalidPoolId)?.try_retire().try_update(); ensure!( - pool.state == PoolState::Approved || pool.state == PoolState::Ongoing, + pool.state == PoolState::Charged || pool.state == PoolState::Ongoing, Error::::InvalidPoolState ); @@ -746,7 +753,7 @@ pub mod pallet { /// The extrinsic will: /// - Try to retire the liquidity-pool which has reached the end of life. /// - Try to settle the rewards when the liquidity-pool in `Ongoing`. - /// - Try to unreserve the remaining rewards to the pool creator when the deposit in the + /// - Try to unreserve the remaining rewards to the pool investor when the deposit in the /// liquidity-pool is clear. /// - Try to delete the liquidity-pool in which the deposit becomes zero. /// - Try to delete the deposit-data in which the deposit becomes zero. @@ -754,6 +761,7 @@ pub mod pallet { /// The condition to redeem: /// - User should have some deposit in the liquidity-pool; /// - The liquidity-pool should be in special state: `Ongoing`, `Retired`; + #[transactional] #[pallet::weight(1_000)] pub fn redeem(origin: OriginFor, pid: PoolId) -> DispatchResultWithPostInfo { let user = ensure_signed(origin)?; @@ -816,12 +824,10 @@ pub mod pallet { pool.deposit = left_in_pool; 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 - reward.claimed; - ensure!( - T::MultiCurrency::unreserve(*rtoken, &pool.creator, remain) == Zero::zero(), - Error::::Unexpected - ); + T::MultiCurrency::transfer(*rtoken, &pool.keeper, &investor, remain)?; } pool.state = PoolState::Dead; @@ -848,6 +854,7 @@ pub mod pallet { /// Help someone to redeem the deposit whose deposited in a liquidity-pool. /// /// NOTE: The liquidity-pool should be in retired state. + #[transactional] #[pallet::weight(1_000)] pub fn volunteer_to_redeem( _origin: OriginFor, @@ -882,6 +889,7 @@ pub mod pallet { /// The conditions to claim: /// - User should have enough token deposited in the liquidity-pool; /// - The liquidity-pool should be in special states: `Ongoing`; + #[transactional] #[pallet::weight(1_000)] pub fn claim(origin: OriginFor, pid: PoolId) -> DispatchResultWithPostInfo { let user = ensure_signed(origin)?; @@ -915,7 +923,7 @@ pub mod pallet { min_deposit_to_start: BalanceOf, after_block_to_start: BlockNumberFor, ) -> DispatchResult { - let creator = ensure_signed(origin)?; + let _ = T::ControlOrigin::ensure_origin(origin)?; // Check the trading-pair ensure!(trading_pair.0 != trading_pair.1, Error::::InvalidTradingPair); @@ -945,16 +953,13 @@ pub mod pallet { rewards.insert(token, reward); } - // Reserve rewards - for (token, reward) in rewards.iter() { - T::MultiCurrency::reserve(*token, &creator, reward.total)?; - } - // Construct the PoolInfo let pool_id = Self::next_pool_id(); + let keeper: AccountIdOf = T::PalletId::get().into_sub_account(pool_id); let mining_pool = PoolInfo { pool_id, - creator: creator.clone(), + keeper: keeper.clone(), + investor: None, trading_pair, duration, r#type, @@ -966,14 +971,14 @@ pub mod pallet { rewards, update_b: Zero::zero(), - state: PoolState::UnderAudit, + state: PoolState::UnCharged, block_startup: None, block_retired: None, }; TotalPoolInfos::::insert(pool_id, mining_pool); - Self::deposit_event(Event::PoolCreated(pool_id, r#type, trading_pair, creator)); + Self::deposit_event(Event::PoolCreated(pool_id, r#type, trading_pair, keeper)); Ok(().into()) } @@ -1020,12 +1025,12 @@ pub mod pallet { impl Hooks> for Pallet { fn on_finalize(n: BlockNumberFor) { // Check whether pool-activated is meet the startup condition - for pid in Self::approved_pids() { + for pid in Self::charged_pids() { if let Some(mut pool) = Self::pool(pid) { pool = pool.try_startup(n); if pool.state == PoolState::Ongoing { - ApprovedPoolIds::::mutate(|pids| pids.remove(&pid)); + ChargedPoolIds::::mutate(|pids| pids.remove(&pid)); TotalPoolInfos::::insert(pid, pool); } } diff --git a/pallets/liquidity-mining/src/mock.rs b/pallets/liquidity-mining/src/mock.rs index 77b44a1b45..813371b98b 100644 --- a/pallets/liquidity-mining/src/mock.rs +++ b/pallets/liquidity-mining/src/mock.rs @@ -24,6 +24,7 @@ use frame_support::{ traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify}, BuildStorage, MultiSignature, }, + PalletId, }; use node_primitives::{Amount, Balance, CurrencyId, TokenSymbol}; use sp_core::H256; @@ -165,6 +166,7 @@ parameter_types! { pub const MinimumRewardPerBlock: Balance = 1_000; pub const MinimumDuration: BlockNumber = MINUTES; pub const MaximumApproved: u32 = 4; + pub const LiquidityMiningPalletId: PalletId = PalletId(*b"mining##"); } impl lm::Config for T { @@ -176,15 +178,16 @@ impl lm::Config for T { type MinimumDepositOfUser = MinimumDeposit; type MinimumRewardPerBlock = MinimumRewardPerBlock; type MinimumDuration = MinimumDuration; - type MaximumApproved = MaximumApproved; + type MaximumCharged = MaximumApproved; + type PalletId = LiquidityMiningPalletId; } pub(crate) fn new_test_ext() -> TestExternalities { GenesisConfig { tokens: orml_tokens::GenesisConfig:: { balances: vec![ - (CREATOR, REWARD_1, REWARD_AMOUNT), - (CREATOR, REWARD_2, REWARD_AMOUNT), + (INVESTOR, REWARD_1, REWARD_AMOUNT), + (INVESTOR, REWARD_2, REWARD_AMOUNT), (USER_1, FARMING_DEPOSIT_1, DEPOSIT_AMOUNT), (USER_1, FARMING_DEPOSIT_2, DEPOSIT_AMOUNT), (USER_2, FARMING_DEPOSIT_1, DEPOSIT_AMOUNT), @@ -223,10 +226,11 @@ pub(crate) const REWARD_1: CurrencyId = CurrencyId::Native(TokenSymbol::BNC); pub(crate) const REWARD_2: CurrencyId = CurrencyId::Token(TokenSymbol::KSM); pub(crate) const REWARD_AMOUNT: Balance = UNIT; -pub(crate) const CREATOR: AccountId = AccountId::new([0u8; 32]); +pub(crate) const INVESTOR: AccountId = AccountId::new([0u8; 32]); pub(crate) const USER_1: AccountId = AccountId::new([1u8; 32]); pub(crate) const USER_2: AccountId = AccountId::new([2u8; 32]); pub(crate) const TC_MEMBER_1: AccountId = AccountId::new([3u8; 32]); pub(crate) const TC_MEMBER_2: AccountId = AccountId::new([4u8; 32]); pub(crate) const TC_MEMBER_3: AccountId = AccountId::new([5u8; 32]); pub(crate) const RICHER: AccountId = AccountId::new([6u8; 32]); +pub(crate) const BEGGAR: AccountId = AccountId::new([7u8; 32]); diff --git a/pallets/liquidity-mining/src/tests.rs b/pallets/liquidity-mining/src/tests.rs index 96276e0fc7..011c5822e1 100644 --- a/pallets/liquidity-mining/src/tests.rs +++ b/pallets/liquidity-mining/src/tests.rs @@ -41,7 +41,7 @@ fn run_to_block(n: BlockNumber) { fn create_farming_pool_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_farming_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 2001, 13, 20, @@ -55,17 +55,14 @@ fn create_farming_pool_should_work() { let pool = LM::pool(0).unwrap(); assert_eq!(pool.r#type, PoolType::Farming); - - let per_block = REWARD_AMOUNT / DAYS as Balance; - let reserved = per_block * DAYS as Balance; - let free = REWARD_AMOUNT - reserved; - - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).free, free); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).reserved, reserved); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).free, free); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).reserved, reserved); + assert!(pool.investor.is_none()); + + 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); }); } @@ -73,7 +70,7 @@ fn create_farming_pool_should_work() { fn create_mining_pool_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -85,17 +82,14 @@ fn create_mining_pool_should_work() { let pool = LM::pool(0).unwrap(); assert_eq!(pool.r#type, PoolType::Mining); - - let per_block = REWARD_AMOUNT / DAYS as Balance; - let reserved = per_block * DAYS as Balance; - let free = REWARD_AMOUNT - reserved; - - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).free, free); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).reserved, reserved); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).free, free); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).reserved, reserved); + assert!(pool.investor.is_none()); + + 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); }); } @@ -104,7 +98,7 @@ fn create_mining_pool_with_wrong_currency_should_fail() { new_test_ext().execute_with(|| { assert_noop!( LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), ( CurrencyId::VSBond(RelayChainTokenSymbol::get(), 2001, 13, 20), CurrencyId::VSToken(RelayChainTokenSymbol::get()), @@ -120,7 +114,7 @@ fn create_mining_pool_with_wrong_currency_should_fail() { assert_noop!( LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), ( CurrencyId::LPToken(TokenSymbol::KSM, 1u8, TokenSymbol::DOT, 2u8), CurrencyId::VSToken(RelayChainTokenSymbol::get()), @@ -142,7 +136,7 @@ fn increase_pid_when_create_pool_should_work() { const NUM: PoolId = 8; for pid in 0..NUM { assert_ok!(LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT / NUM), vec![(REWARD_2, REWARD_AMOUNT / NUM)], @@ -187,6 +181,20 @@ fn create_pool_with_wrong_origin_should_fail() { ), DispatchError::BadOrigin, ); + + assert_noop!( + LM::create_pool( + Some(INVESTOR).into(), + (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), + (REWARD_1, REWARD_AMOUNT), + vec![(REWARD_2, REWARD_AMOUNT)], + PoolType::Farming, + DAYS, + 1_000 * UNIT, + 0 + ), + DispatchError::BadOrigin, + ); }); } @@ -195,7 +203,7 @@ fn create_pool_with_duplicate_trading_pair_should_fail() { new_test_ext().execute_with(|| { assert_noop!( LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_1), (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -214,7 +222,7 @@ fn create_pool_with_too_small_duration_should_fail() { new_test_ext().execute_with(|| { assert_noop!( LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -233,7 +241,7 @@ fn create_pool_with_wrong_condition_should_fail() { new_test_ext().execute_with(|| { assert_noop!( LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -247,7 +255,7 @@ fn create_pool_with_wrong_condition_should_fail() { assert_noop!( LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -266,7 +274,7 @@ fn create_pool_with_too_small_per_block_should_fail() { new_test_ext().execute_with(|| { assert_noop!( LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -284,7 +292,7 @@ fn create_pool_with_too_small_per_block_should_fail() { fn create_pool_with_duplicate_reward_should_fail() { new_test_ext().execute_with(|| { let result = LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT), vec![(REWARD_1, REWARD_AMOUNT)], @@ -298,10 +306,10 @@ fn create_pool_with_duplicate_reward_should_fail() { } #[test] -fn approve_pool_should_work() { +fn charge_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -312,23 +320,42 @@ fn approve_pool_should_work() { )); let pool = LM::pool(0).unwrap(); - assert_eq!(pool.state, PoolState::UnderAudit); + assert_eq!(pool.state, PoolState::UnCharged); + assert!(pool.investor.is_none()); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); let pool = LM::pool(0).unwrap(); - assert_eq!(pool.state, PoolState::Approved); + assert_eq!(pool.state, PoolState::Charged); + + assert!(LM::charged_pids().contains(&0)); - assert!(LM::approved_pids().contains(&0)); + let per_block = REWARD_AMOUNT / DAYS as Balance; + let kept = per_block * DAYS as Balance; + let left = REWARD_AMOUNT - kept; + + assert_eq!(Tokens::accounts(INVESTOR, REWARD_1).free, left); + 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, left); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).frozen, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).reserved, 0); + + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_1).free, kept); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_1).frozen, 0); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_1).reserved, 0); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_2).free, kept); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_2).frozen, 0); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_2).reserved, 0); }); } #[test] -fn approve_pool_with_wrong_origin_should_fail() { +fn charge_with_wrong_origin_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -338,17 +365,20 @@ fn approve_pool_with_wrong_origin_should_fail() { 0 )); - assert_noop!(LM::approve_pool(Some(TC_MEMBER_1).into(), 0), DispatchError::BadOrigin); - assert_noop!(LM::approve_pool(Origin::root(), 0), DispatchError::BadOrigin); - assert_noop!(LM::approve_pool(Origin::none(), 0), DispatchError::BadOrigin); + assert_noop!( + LM::charge(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0), + DispatchError::BadOrigin + ); + assert_noop!(LM::charge(Origin::root(), 0), DispatchError::BadOrigin); + assert_noop!(LM::charge(Origin::none(), 0), DispatchError::BadOrigin); }); } #[test] -fn approve_pool_with_wrong_state_should_fail() { +fn charge_with_wrong_state_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -358,21 +388,17 @@ fn approve_pool_with_wrong_state_should_fail() { 0 )); - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); - - assert_noop!( - LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0), - Error::::InvalidPoolState - ); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); + assert_noop!(LM::charge(Some(INVESTOR).into(), 0), Error::::InvalidPoolState); }); } #[test] -fn approve_pool_exceed_maximum_should_fail() { +fn charge_exceed_maximum_should_fail() { new_test_ext().execute_with(|| { for i in 0..MaximumApproved::get() as u128 { assert_ok!(LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT / (MaximumApproved::get() + 1) as u128), vec![(REWARD_2, REWARD_AMOUNT / (MaximumApproved::get() + 1) as u128)], @@ -382,16 +408,13 @@ fn approve_pool_exceed_maximum_should_fail() { 0 )); - assert_ok!(LM::approve_pool( - pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), - i - )); + assert_ok!(LM::charge(Some(INVESTOR).into(), i)); - assert!(LM::approved_pids().contains(&i)); + assert!(LM::charged_pids().contains(&i)); } assert_ok!(LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT / (MaximumApproved::get() + 1) as u128), vec![(REWARD_2, REWARD_AMOUNT / (MaximumApproved::get() + 1) as u128)], @@ -402,22 +425,19 @@ fn approve_pool_exceed_maximum_should_fail() { )); assert_noop!( - LM::approve_pool( - pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), - MaximumApproved::get() as u128, - ), - Error::::ExceedMaximumApproved + LM::charge(Some(INVESTOR).into(), MaximumApproved::get() as u128,), + Error::::ExceedMaximumCharged ); - assert!(!LM::approved_pids().contains(&(MaximumApproved::get() as u128))); + assert!(!LM::charged_pids().contains(&(MaximumApproved::get() as u128))); }); } #[test] -fn kill_pool_should_work() { +fn charge_without_enough_balance_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -428,29 +448,34 @@ fn kill_pool_should_work() { )); let pool = LM::pool(0).unwrap(); - assert_eq!(pool.state, PoolState::UnderAudit); + assert_eq!(pool.state, PoolState::UnCharged); + assert!(pool.investor.is_none()); - let per_block = REWARD_AMOUNT / DAYS as Balance; - let reserved = per_block * DAYS as Balance; - let free = REWARD_AMOUNT - reserved; + // It is unable to call Collective::execute(..) which is private; + assert_noop!(LM::charge(Some(BEGGAR).into(), 0), orml_tokens::Error::::BalanceTooLow); + }); +} - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).free, free); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).reserved, reserved); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).free, free); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).reserved, reserved); +#[test] +fn kill_pool_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(LM::create_pool( + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), + (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), + (REWARD_1, REWARD_AMOUNT), + vec![(REWARD_2, REWARD_AMOUNT)], + PoolType::Farming, + DAYS, + 1_000 * UNIT, + 0 + )); + + let pool = LM::pool(0).unwrap(); + assert_eq!(pool.state, PoolState::UnCharged); - assert_ok!(LM::kill_pool(Some(CREATOR).into(), 0)); + assert_ok!(LM::kill_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); assert!(!TotalPoolInfos::::contains_key(0)); - - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).free, REWARD_AMOUNT); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).reserved, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).free, REWARD_AMOUNT); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).reserved, 0); }); } @@ -458,7 +483,7 @@ fn kill_pool_should_work() { fn kill_pool_with_wrong_origin_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -468,7 +493,7 @@ fn kill_pool_with_wrong_origin_should_fail() { 0 )); - assert_noop!(LM::kill_pool(Some(USER_1).into(), 0), Error::::InvalidPoolOwner); + assert_noop!(LM::kill_pool(Some(USER_1).into(), 0), DispatchError::BadOrigin); assert_noop!(LM::kill_pool(Origin::root(), 0), DispatchError::BadOrigin); assert_noop!(LM::kill_pool(Origin::none(), 0), DispatchError::BadOrigin); }); @@ -478,7 +503,7 @@ fn kill_pool_with_wrong_origin_should_fail() { fn kill_pool_with_wrong_state_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), (FARMING_DEPOSIT_1, FARMING_DEPOSIT_2), (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -488,17 +513,20 @@ fn kill_pool_with_wrong_state_should_fail() { 0 )); - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); - assert_noop!(LM::kill_pool(Some(CREATOR).into(), 0), Error::::InvalidPoolState); + assert_noop!( + LM::kill_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0), + Error::::InvalidPoolState + ); }); } #[test] -fn deposit_to_mining_pool_approved_should_work() { +fn deposit_to_mining_pool_charged_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -508,7 +536,7 @@ fn deposit_to_mining_pool_approved_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); let deposit = 1_000_000 as Balance; assert_ok!(LM::deposit(Some(USER_1).into(), 0, deposit)); @@ -527,10 +555,10 @@ fn deposit_to_mining_pool_approved_should_work() { } #[test] -fn deposit_to_farming_pool_approved_should_work() { +fn deposit_to_farming_pool_charged_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_farming_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 2001, 13, 20, @@ -542,7 +570,7 @@ fn deposit_to_farming_pool_approved_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); let deposit = 1_000_000 as Balance; assert_ok!(LM::deposit(Some(USER_1).into(), 0, deposit)); @@ -569,7 +597,7 @@ fn startup_pool_meet_conditions_should_auto_work() { System::set_block_number(100); assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -579,7 +607,7 @@ fn startup_pool_meet_conditions_should_auto_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, DEPOSIT_AMOUNT)); @@ -588,7 +616,7 @@ fn startup_pool_meet_conditions_should_auto_work() { let pool = LM::pool(0).unwrap(); assert_eq!(pool.state, PoolState::Ongoing); - assert!(!LM::approved_pids().contains(&0)); + assert!(!LM::charged_pids().contains(&0)); }); } @@ -598,7 +626,7 @@ fn deposit_to_pool_ongoing_should_work() { System::set_block_number(100); assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -608,7 +636,7 @@ fn deposit_to_pool_ongoing_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, DEPOSIT_AMOUNT)); @@ -634,7 +662,7 @@ fn deposit_to_pool_ongoing_with_init_deposit_should_work() { System::set_block_number(100); assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -644,7 +672,7 @@ fn deposit_to_pool_ongoing_with_init_deposit_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, 1_000_000)); assert_ok!(LM::deposit(Some(USER_2).into(), 0, 1_000_000)); @@ -685,7 +713,7 @@ fn double_deposit_to_pool_ongoing_in_diff_block_should_work() { System::set_block_number(100); assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -695,7 +723,7 @@ fn double_deposit_to_pool_ongoing_in_diff_block_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, 1_000_000)); @@ -739,7 +767,7 @@ fn double_deposit_to_pool_ongoing_in_same_block_should_work() { System::set_block_number(100); assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -749,7 +777,7 @@ fn double_deposit_to_pool_ongoing_in_same_block_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, 1_000_000)); @@ -785,7 +813,7 @@ fn deposit_with_wrong_pid_should_fail() { assert_noop!(LM::deposit(Some(USER_1).into(), 0, 1_000_000), Error::::InvalidPoolId); assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -795,7 +823,7 @@ fn deposit_with_wrong_pid_should_fail() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_noop!(LM::deposit(Some(USER_1).into(), 1, 1_000_000), Error::::InvalidPoolId); }); @@ -807,7 +835,7 @@ fn deposit_with_wrong_state_should_fail() { System::set_block_number(100); assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -819,7 +847,7 @@ fn deposit_with_wrong_state_should_fail() { assert_noop!(LM::deposit(Some(USER_1).into(), 0, 1_000_000), Error::::InvalidPoolState); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, 1_000_000)); run_to_block(100 + DAYS); @@ -835,7 +863,7 @@ fn deposit_too_little_should_fail() { assert_noop!(LM::deposit(Some(USER_1).into(), 0, 1_000_000), Error::::InvalidPoolId); assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -845,7 +873,7 @@ fn deposit_too_little_should_fail() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_noop!( LM::deposit(Some(USER_1).into(), 0, MinimumDeposit::get() - 1), @@ -860,7 +888,7 @@ fn deposit_with_wrong_origin_should_fail() { assert_noop!(LM::deposit(Some(USER_1).into(), 0, 1_000_000), Error::::InvalidPoolId); assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -870,7 +898,7 @@ fn deposit_with_wrong_origin_should_fail() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_noop!(LM::deposit(Origin::root(), 0, 1_000_000), DispatchError::BadOrigin); assert_noop!(LM::deposit(Origin::none(), 0, 1_000_000), DispatchError::BadOrigin); @@ -883,7 +911,7 @@ fn deposit_exceed_the_limit_should_fail() { assert_noop!(LM::deposit(Some(USER_1).into(), 0, 1_000_000), Error::::InvalidPoolId); assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -893,7 +921,7 @@ fn deposit_exceed_the_limit_should_fail() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, 1_000_000)); assert_noop!( @@ -907,7 +935,7 @@ fn deposit_exceed_the_limit_should_fail() { fn redeem_from_pool_ongoing_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -917,7 +945,7 @@ fn redeem_from_pool_ongoing_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); assert_ok!(LM::deposit(Some(USER_2).into(), 0, UNIT)); @@ -970,7 +998,7 @@ fn redeem_from_pool_ongoing_should_work() { fn redeem_from_pool_retired_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -980,7 +1008,7 @@ fn redeem_from_pool_retired_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); assert_ok!(LM::deposit(Some(USER_2).into(), 0, UNIT)); @@ -1028,12 +1056,12 @@ fn redeem_from_pool_retired_should_work() { assert!(LM::pool(0).is_none()); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).free, REWARD_AMOUNT - 2 * rewarded); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).reserved, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).free, REWARD_AMOUNT - 2 * rewarded); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).reserved, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_1).free, REWARD_AMOUNT - 2 * rewarded); + 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 - 2 * rewarded); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).frozen, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).reserved, 0); }); } @@ -1041,7 +1069,7 @@ fn redeem_from_pool_retired_should_work() { fn double_redeem_from_pool_in_diff_state_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1051,7 +1079,7 @@ fn double_redeem_from_pool_in_diff_state_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); assert_ok!(LM::deposit(Some(USER_2).into(), 0, UNIT)); @@ -1121,17 +1149,17 @@ fn double_redeem_from_pool_in_diff_state_should_work() { assert!(LM::pool(0).is_none()); assert_eq!( - Tokens::accounts(CREATOR, REWARD_1).free, + Tokens::accounts(INVESTOR, REWARD_1).free, REWARD_AMOUNT - (2 * old_rewarded + new_rewarded) ); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).reserved, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_1).frozen, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_1).reserved, 0); assert_eq!( - Tokens::accounts(CREATOR, REWARD_2).free, + Tokens::accounts(INVESTOR, REWARD_2).free, REWARD_AMOUNT - (2 * old_rewarded + new_rewarded) ); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).reserved, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).frozen, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).reserved, 0); }); } @@ -1147,7 +1175,7 @@ fn redeem_with_wrong_origin_should_fail() { fn redeem_with_wrong_pid_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1157,7 +1185,7 @@ fn redeem_with_wrong_pid_should_fail() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); @@ -1171,7 +1199,7 @@ fn redeem_with_wrong_pid_should_fail() { fn redeem_with_wrong_state_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1183,7 +1211,7 @@ fn redeem_with_wrong_state_should_fail() { assert_noop!(LM::redeem(Some(USER_1).into(), 0), Error::::InvalidPoolState); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); assert_noop!(LM::redeem(Some(USER_1).into(), 0), Error::::InvalidPoolState); @@ -1194,7 +1222,7 @@ fn redeem_with_wrong_state_should_fail() { fn redeem_without_deposit_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1206,7 +1234,7 @@ fn redeem_without_deposit_should_fail() { assert_noop!(LM::redeem(Some(USER_1).into(), 0), Error::::InvalidPoolState); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); assert_ok!(LM::deposit(Some(USER_2).into(), 0, UNIT)); @@ -1221,7 +1249,7 @@ fn redeem_without_deposit_should_fail() { fn redeem_all_deposit_from_pool_ongoing_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1233,7 +1261,7 @@ fn redeem_all_deposit_from_pool_ongoing_should_fail() { assert_noop!(LM::redeem(Some(USER_1).into(), 0), Error::::InvalidPoolState); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); run_to_block(100); @@ -1250,7 +1278,7 @@ fn volunteer_to_redeem_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1260,7 +1288,7 @@ fn volunteer_to_redeem_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); assert_ok!(LM::deposit(Some(USER_2).into(), 0, UNIT)); @@ -1306,7 +1334,7 @@ fn volunteer_to_redeem_should_work() { fn volunteer_to_redeem_with_wrong_pid_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1316,7 +1344,7 @@ fn volunteer_to_redeem_with_wrong_pid_should_fail() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); @@ -1330,7 +1358,7 @@ fn volunteer_to_redeem_with_wrong_pid_should_fail() { fn volunteer_to_redeem_with_wrong_state_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1345,7 +1373,7 @@ fn volunteer_to_redeem_with_wrong_state_should_fail() { ); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_noop!( LM::volunteer_to_redeem(Origin::none(), 0, None), @@ -1367,7 +1395,7 @@ fn volunteer_to_redeem_with_wrong_state_should_fail() { fn claim_from_pool_ongoing_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1377,7 +1405,7 @@ fn claim_from_pool_ongoing_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); assert_ok!(LM::deposit(Some(USER_2).into(), 0, UNIT)); @@ -1387,8 +1415,7 @@ fn claim_from_pool_ongoing_should_work() { assert_ok!(LM::claim(Some(USER_1).into(), 0)); let per_block = REWARD_AMOUNT / DAYS as Balance; - let reserved = per_block * DAYS as Balance; - let free = REWARD_AMOUNT - reserved; + let kept = per_block * DAYS as Balance; let pbpd = FixedU128::from((per_block, 2 * UNIT)); let rewarded: Balance = (pbpd * (100 * UNIT).into()).into_inner() / FixedU128::accuracy(); @@ -1400,12 +1427,14 @@ fn claim_from_pool_ongoing_should_work() { assert_eq!(Tokens::accounts(USER_1, REWARD_2).frozen, 0); assert_eq!(Tokens::accounts(USER_1, REWARD_2).reserved, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).free, free); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).reserved, reserved - rewarded); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).free, free); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).reserved, reserved - rewarded); + let pool: PoolInfo = LM::pool(0).unwrap(); + + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_1).free, kept - rewarded); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_1).frozen, 0); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_1).reserved, 0); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_2).free, kept - rewarded); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_2).frozen, 0); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_2).reserved, 0); let pool: PoolInfo = LM::pool(0).unwrap(); assert_eq!(pool.rewards.get(&REWARD_1).unwrap().claimed, rewarded); @@ -1417,7 +1446,7 @@ fn claim_from_pool_ongoing_should_work() { fn claim_from_pool_retired_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1427,7 +1456,7 @@ fn claim_from_pool_retired_should_fail() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); @@ -1442,7 +1471,7 @@ fn claim_from_pool_retired_should_fail() { fn claim_with_wrong_pid_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1452,7 +1481,7 @@ fn claim_with_wrong_pid_should_fail() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); assert_ok!(LM::deposit(Some(USER_2).into(), 0, UNIT)); @@ -1467,7 +1496,7 @@ fn claim_with_wrong_pid_should_fail() { fn claim_with_wrong_origin_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1477,7 +1506,7 @@ fn claim_with_wrong_origin_should_fail() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); assert_ok!(LM::deposit(Some(USER_2).into(), 0, UNIT)); @@ -1493,7 +1522,7 @@ fn claim_with_wrong_origin_should_fail() { fn claim_with_wrong_state_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1506,7 +1535,7 @@ fn claim_with_wrong_state_should_fail() { assert_noop!(LM::claim(Some(USER_2).into(), 0), Error::::InvalidPoolState); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); assert_ok!(LM::deposit(Some(USER_2).into(), 0, UNIT)); @@ -1522,7 +1551,7 @@ fn claim_with_wrong_state_should_fail() { fn claim_without_deposit_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1532,7 +1561,7 @@ fn claim_without_deposit_should_fail() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); @@ -1547,7 +1576,7 @@ fn claim_without_deposit_should_fail() { fn double_claim_in_same_block_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1557,7 +1586,7 @@ fn double_claim_in_same_block_should_fail() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); @@ -1569,10 +1598,10 @@ fn double_claim_in_same_block_should_fail() { } #[test] -fn force_retire_pool_approved_should_work() { +fn force_retire_pool_charged_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1582,7 +1611,7 @@ fn force_retire_pool_approved_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); assert_ok!(LM::deposit(Some(USER_2).into(), 0, UNIT)); @@ -1621,12 +1650,12 @@ fn force_retire_pool_approved_should_work() { assert_eq!(Tokens::accounts(USER_2, MINING_DEPOSIT).frozen, 0); assert_eq!(Tokens::accounts(USER_2, MINING_DEPOSIT).reserved, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).free, REWARD_AMOUNT); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).reserved, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).free, REWARD_AMOUNT); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, 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()); assert!(LM::user_deposit_data(0, USER_1).is_none()); @@ -1635,10 +1664,10 @@ fn force_retire_pool_approved_should_work() { } #[test] -fn force_retire_pool_approved_with_no_deposit_should_work() { +fn force_retire_pool_charged_with_no_deposit_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1648,7 +1677,7 @@ fn force_retire_pool_approved_with_no_deposit_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::force_retire_pool( pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), @@ -1665,7 +1694,7 @@ fn force_retire_pool_ongoing_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1675,7 +1704,7 @@ fn force_retire_pool_ongoing_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); @@ -1727,12 +1756,12 @@ fn force_retire_pool_ongoing_should_work() { assert_eq!(Tokens::accounts(USER_2, MINING_DEPOSIT).reserved, 0); let remain = REWARD_AMOUNT - (reward_step_1 + 2 * reward_step_2); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).free, remain); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).reserved, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).free, remain); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).reserved, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_1).free, remain); + 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, remain); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).frozen, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).reserved, 0); assert!(LM::pool(0).is_none()); assert!(LM::user_deposit_data(0, USER_1).is_none()); @@ -1744,7 +1773,7 @@ fn force_retire_pool_ongoing_should_work() { fn force_retire_pool_with_wrong_origin_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1754,11 +1783,11 @@ fn force_retire_pool_with_wrong_origin_should_fail() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_noop!(LM::force_retire_pool(Origin::root(), 0), DispatchError::BadOrigin); assert_noop!(LM::force_retire_pool(Origin::none(), 0), DispatchError::BadOrigin); - assert_noop!(LM::force_retire_pool(Some(CREATOR).into(), 0), DispatchError::BadOrigin); + assert_noop!(LM::force_retire_pool(Some(INVESTOR).into(), 0), DispatchError::BadOrigin); }); } @@ -1766,7 +1795,7 @@ fn force_retire_pool_with_wrong_origin_should_fail() { fn force_retire_pool_with_wrong_pool_state_should_fail() { new_test_ext().execute_with(|| { assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -1781,7 +1810,7 @@ fn force_retire_pool_with_wrong_pool_state_should_fail() { ); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); @@ -1797,7 +1826,7 @@ fn force_retire_pool_with_wrong_pool_state_should_fail() { fn create_eb_farming_pool_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_eb_farming_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 2001, 13, 20, @@ -1812,16 +1841,12 @@ fn create_eb_farming_pool_should_work() { assert_eq!(pool.r#type, PoolType::EBFarming); - let per_block = REWARD_AMOUNT / DAYS as Balance; - let reserved = per_block * DAYS as Balance; - let free = REWARD_AMOUNT - reserved; - - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).free, free); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).reserved, reserved); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).free, free); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).reserved, reserved); + 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); }); } @@ -1829,7 +1854,7 @@ fn create_eb_farming_pool_should_work() { fn deposit_to_eb_farming_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_eb_farming_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 2001, 13, 20, @@ -1841,7 +1866,7 @@ fn deposit_to_eb_farming_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_noop!( LM::deposit(Some(USER_1).into(), 0, MinimumDeposit::get()), @@ -1880,7 +1905,7 @@ fn redeem_from_eb_farming_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_eb_farming_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 2001, 13, 20, @@ -1892,7 +1917,7 @@ fn redeem_from_eb_farming_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(Tokens::reserve(FARMING_DEPOSIT_1, &USER_1, DEPOSIT_AMOUNT)); assert_ok!(Tokens::reserve(FARMING_DEPOSIT_2, &USER_1, DEPOSIT_AMOUNT)); @@ -1948,7 +1973,7 @@ fn claim_from_eb_farming_should_work() { new_test_ext().execute_with(|| { assert_ok!(LM::create_eb_farming_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 2001, 13, 20, @@ -1960,7 +1985,7 @@ fn claim_from_eb_farming_should_work() { )); // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); assert_ok!(Tokens::reserve(FARMING_DEPOSIT_1, &USER_1, DEPOSIT_AMOUNT)); assert_ok!(Tokens::reserve(FARMING_DEPOSIT_2, &USER_1, DEPOSIT_AMOUNT)); @@ -2016,7 +2041,7 @@ fn simple_integration_test() { const PER_BLOCK: Balance = REWARD_AMOUNT / DAYS as Balance; assert_ok!(LM::create_mining_pool( - Some(CREATOR).into(), + pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), MINING_TRADING_PAIR, (REWARD_1, REWARD_AMOUNT), vec![(REWARD_2, REWARD_AMOUNT)], @@ -2025,16 +2050,25 @@ fn simple_integration_test() { 0 )); - let reserved = PER_BLOCK * DAYS as Balance; - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).free, REWARD_AMOUNT - reserved); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).reserved, reserved); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).free, REWARD_AMOUNT - reserved); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).reserved, reserved); - // It is unable to call Collective::execute(..) which is private; - assert_ok!(LM::approve_pool(pallet_collective::RawOrigin::Member(TC_MEMBER_1).into(), 0)); + assert_ok!(LM::charge(Some(INVESTOR).into(), 0)); + + let pool = LM::pool(0).unwrap(); + let kept = PER_BLOCK * DAYS as Balance; + + assert_eq!(Tokens::accounts(INVESTOR, REWARD_1).free, REWARD_AMOUNT - kept); + 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 - kept); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).frozen, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).reserved, 0); + + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_1).free, kept); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_1).frozen, 0); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_1).reserved, 0); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_2).free, kept); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_2).frozen, 0); + assert_eq!(Tokens::accounts(pool.keeper.clone(), REWARD_2).reserved, 0); assert_ok!(LM::deposit(Some(USER_1).into(), 0, UNIT)); @@ -2112,12 +2146,12 @@ fn simple_integration_test() { assert_eq!(Tokens::accounts(USER_2, MINING_DEPOSIT).reserved, 0); let remain = REWARD_AMOUNT - (reward_step_1 + 2 * reward_step_2 + 2 * reward_step_3); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).free, remain); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_1).reserved, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).free, remain); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).frozen, 0); - assert_eq!(Tokens::accounts(CREATOR, REWARD_2).reserved, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_1).free, remain); + 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, remain); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).frozen, 0); + assert_eq!(Tokens::accounts(INVESTOR, REWARD_2).reserved, 0); assert!(LM::pool(0).is_none()); assert!(LM::user_deposit_data(0, USER_1).is_none()); diff --git a/runtime/asgard/Cargo.toml b/runtime/asgard/Cargo.toml index 9a3fbbccee..c444c565ba 100644 --- a/runtime/asgard/Cargo.toml +++ b/runtime/asgard/Cargo.toml @@ -179,6 +179,7 @@ std = [ "bifrost-salp-rpc-runtime-api/std", "bifrost-vsbond-auction/std", "bifrost-vtoken-mint/std", + "bifrost-liquidity-mining/std", "xcm-support/std", "orml-currencies/std", "orml-traits/std", diff --git a/runtime/asgard/src/lib.rs b/runtime/asgard/src/lib.rs index 7e840ae206..dd0204b11f 100644 --- a/runtime/asgard/src/lib.rs +++ b/runtime/asgard/src/lib.rs @@ -1145,6 +1145,7 @@ parameter_types! { pub const MinimumRewardPerBlock: Balance = 1_000; pub const MinimumDuration: BlockNumber = DAYS; pub const MaximumApproved: u32 = 8; + pub const LiquidityMiningPalletId: PalletId = PalletId(*b"mining##"); } impl bifrost_liquidity_mining::Config for Runtime { @@ -1157,7 +1158,8 @@ impl bifrost_liquidity_mining::Config for Runtime { type MinimumDepositOfUser = MinimumDepositOfUser; type MinimumRewardPerBlock = MinimumRewardPerBlock; type MinimumDuration = MinimumDuration; - type MaximumApproved = MaximumApproved; + type MaximumCharged = MaximumApproved; + type PalletId = LiquidityMiningPalletId; } // bifrost runtime end diff --git a/runtime/bifrost/Cargo.toml b/runtime/bifrost/Cargo.toml index 0bb331982d..2b0ed0f3d9 100644 --- a/runtime/bifrost/Cargo.toml +++ b/runtime/bifrost/Cargo.toml @@ -85,6 +85,7 @@ bifrost-runtime-common = { package = "bifrost-runtime-common", path = "../common bifrost-salp = { path = "../../pallets/salp", default-features = false } bifrost-salp-rpc-runtime-api = { path = "../../pallets/salp/rpc/runtime-api", default-features = false } pallet-vesting = { package = "bifrost-vesting", path = "../../pallets/vesting", default-features = false } +bifrost-liquidity-mining = { path = "../../pallets/liquidity-mining", default-features = false } xcm-support = { path = "../../xcm-support", default-features = false } # orml @@ -161,6 +162,7 @@ std = [ "bifrost-flexible-fee-rpc-runtime-api/std", "bifrost-salp/std", "bifrost-salp-rpc-runtime-api/std", + "bifrost-liquidity-mining/std", ] with-tracing = ["frame-executive/with-tracing"] diff --git a/runtime/bifrost/src/lib.rs b/runtime/bifrost/src/lib.rs index 39468c47a5..e1e84aa686 100644 --- a/runtime/bifrost/src/lib.rs +++ b/runtime/bifrost/src/lib.rs @@ -199,6 +199,7 @@ parameter_types! { parameter_types! { pub const TreasuryPalletId: PalletId = PalletId(*b"bf/trsry"); pub const BifrostCrowdloanId: PalletId = PalletId(*b"bf/salp#"); + pub const LiquidityMiningPalletId: PalletId = PalletId(*b"bf/lm###"); } pub fn get_all_pallet_accounts() -> Vec { @@ -1037,6 +1038,29 @@ impl bifrost_salp::Config for Runtime { type TransactType = SalpTransactType; } +parameter_types! { + pub const RelayChainTokenSymbol: TokenSymbol = TokenSymbol::KSM; + pub const MaximumDepositInPool: Balance = 1_000_000_000 * DOLLARS; + pub const MinimumDepositOfUser: Balance = 1_000_000; + pub const MinimumRewardPerBlock: Balance = 1_000; + pub const MinimumDuration: BlockNumber = DAYS; + pub const MaximumCharged: u32 = 32; +} + +impl bifrost_liquidity_mining::Config for Runtime { + type Event = Event; + type ControlOrigin = + pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>; + type MultiCurrency = Currencies; + type RelayChainTokenSymbol = RelayChainTokenSymbol; + type MaximumDepositInPool = MaximumDepositInPool; + type MinimumDepositOfUser = MinimumDepositOfUser; + type MinimumRewardPerBlock = MinimumRewardPerBlock; + type MinimumDuration = MinimumDuration; + type MaximumCharged = MaximumCharged; + type PalletId = LiquidityMiningPalletId; +} + // Bifrost modules end construct_runtime! { @@ -1100,6 +1124,7 @@ construct_runtime! { // Bifrost modules FlexibleFee: bifrost_flexible_fee::{Pallet, Call, Storage, Event} = 100, Salp: bifrost_salp::{Pallet, Call, Storage, Event} = 105, + LiquidityMining: bifrost_liquidity_mining::{Pallet, Call, Storage, Event} = 108, } } diff --git a/runtime/dev/src/lib.rs b/runtime/dev/src/lib.rs index 4447321c1d..e70a0d9a25 100644 --- a/runtime/dev/src/lib.rs +++ b/runtime/dev/src/lib.rs @@ -1115,6 +1115,7 @@ parameter_types! { pub const MinimumRewardPerBlock: Balance = 1_000; pub const MinimumDuration: BlockNumber = DAYS; pub const MaximumApproved: u32 = 8; + pub const LiquidityMiningPalletId: PalletId = PalletId(*b"mining##"); } impl bifrost_liquidity_mining::Config for Runtime { @@ -1127,7 +1128,8 @@ impl bifrost_liquidity_mining::Config for Runtime { type MinimumDepositOfUser = MinimumDepositOfUser; type MinimumRewardPerBlock = MinimumRewardPerBlock; type MinimumDuration = MinimumDuration; - type MaximumApproved = MaximumApproved; + type MaximumCharged = MaximumApproved; + type PalletId = LiquidityMiningPalletId; } // bifrost runtime end