From 9ee0414c18070a73708e5e2b593a91cf1fa882b2 Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 11 Sep 2024 17:53:15 +0200 Subject: [PATCH 01/37] add init implementation for update global farm --- pallets/liquidity-mining/src/lib.rs | 44 ++++++++++++++++ .../src/tests/update_global_farm.rs | 51 +++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/pallets/liquidity-mining/src/lib.rs b/pallets/liquidity-mining/src/lib.rs index 2197c9a5d..099e1705b 100644 --- a/pallets/liquidity-mining/src/lib.rs +++ b/pallets/liquidity-mining/src/lib.rs @@ -568,6 +568,50 @@ impl, I: 'static> Pallet { Ok(()) }) } + /* */ + + /// TODO DOC + fn update_global_farm( + who: T::AccountId, + global_farm_id: GlobalFarmId, + planned_yielding_periods: PeriodOf, + yield_per_period: Perquintill, + min_deposit: Balance, + ) -> Result<(), DispatchError> { + //TODO: same origin as create glboal farm + //TODO: add validation as we have in global farm + //TODO and return error if use specify yield farm that is not in global farm + //TODO: send event but oinly in the omnipool liq + //TODO: add invariant test too + + >::try_mutate(global_farm_id, |maybe_global_farm| { + let global_farm = maybe_global_farm.as_mut().ok_or(Error::::GlobalFarmNotFound)?; + + ensure!(global_farm.state.is_active(), Error::::GlobalFarmNotFound); + + ensure!(who == global_farm.owner, Error::::Forbidden); + + //Sync farms to get right accumulated_rpz and pending rewards + let current_period = Self::get_current_period(global_farm.blocks_per_period)?; + Self::sync_global_farm(global_farm, current_period)?; + + //Calculate the new max reward period + let pot = Self::pot_account_id().ok_or(Error::::ErrorGetAccountId)?; + let total_rewards = T::MultiCurrency::free_balance(global_farm.reward_currency, &pot); + let planned_periods = + TryInto::::try_into(planned_yielding_periods).map_err(|_| ArithmeticError::Overflow)?; + let new_max_reward_period = total_rewards.checked_div(planned_periods).ok_or(Error::::InvalidPlannedYieldingPeriods)?; + + //Update global farm fields + global_farm.planned_yielding_periods = planned_yielding_periods; + global_farm.yield_per_period = yield_per_period; + global_farm.min_deposit = min_deposit; + + global_farm.max_reward_per_period = new_max_reward_period; + + Ok(()) + }) + } /// Terminate existing liquidity mining program. Undistributed rewards are transferred to /// owner(`who`). diff --git a/pallets/liquidity-mining/src/tests/update_global_farm.rs b/pallets/liquidity-mining/src/tests/update_global_farm.rs index d567303a8..508781b4f 100644 --- a/pallets/liquidity-mining/src/tests/update_global_farm.rs +++ b/pallets/liquidity-mining/src/tests/update_global_farm.rs @@ -182,3 +182,54 @@ fn update_global_farm_price_adjustment_should_fail_when_farm_is_already_terminat }); }) } + +#[test] +fn update_global_farm_should_work() { + predefined_test_ext_with_deposits().execute_with(|| { + let _ = with_transaction(|| { + //Arrange + let planned_yielding_periods: BlockNumber = 1_000_000_000_u64; + let yield_per_period = Perquintill::from_percent(20); + let min_deposit = 20_000; + + let global_farm_0 = LiquidityMining::global_farm(GC_FARM).unwrap(); + + set_block_number(100_000); + + //Act + assert_ok!(LiquidityMining::update_global_farm( + GC, + GC_FARM, + planned_yielding_periods, + yield_per_period, + min_deposit, + )); + + //Assert that global farm is updated + assert_eq!( + LiquidityMining::global_farm(GC_FARM).unwrap(), + GlobalFarmData { + updated_at: 1_000, + planned_yielding_periods, + yield_per_period, + min_deposit, + accumulated_rpz: FixedU128::from_inner(491_000_000_000_000_000_000_u128), + pending_rewards: 343195125000000000000, + max_reward_per_period: 344478675000, + ..global_farm_0 + }, + ); + frame_system::Pallet::::assert_has_event(mock::RuntimeEvent::LiquidityMining( + Event::GlobalFarmAccRPZUpdated { + global_farm_id: global_farm_0.id, + accumulated_rpz: FixedU128::from_inner(491_000_000_000_000_000_000_u128), + total_shares_z: global_farm_0.total_shares_z, + }, + )); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); +} + + From 23ff4456ee18c65d6a30864295d556673b755abc Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 11 Sep 2024 18:02:59 +0200 Subject: [PATCH 02/37] add validations for update global farm params --- pallets/liquidity-mining/src/lib.rs | 11 +-- .../src/tests/update_global_farm.rs | 72 +++++++++++++++++++ 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/pallets/liquidity-mining/src/lib.rs b/pallets/liquidity-mining/src/lib.rs index 099e1705b..32fc5e788 100644 --- a/pallets/liquidity-mining/src/lib.rs +++ b/pallets/liquidity-mining/src/lib.rs @@ -570,7 +570,7 @@ impl, I: 'static> Pallet { } /* */ - /// TODO DOC + /// TODO DOC and in readme fn update_global_farm( who: T::AccountId, global_farm_id: GlobalFarmId, @@ -579,16 +579,19 @@ impl, I: 'static> Pallet { min_deposit: Balance, ) -> Result<(), DispatchError> { //TODO: same origin as create glboal farm - //TODO: add validation as we have in global farm - //TODO and return error if use specify yield farm that is not in global farm //TODO: send event but oinly in the omnipool liq //TODO: add invariant test too + ensure!(min_deposit.ge(&MIN_DEPOSIT), Error::::InvalidMinDeposit); + ensure!( + planned_yielding_periods >= T::MinPlannedYieldingPeriods::get(), + Error::::InvalidPlannedYieldingPeriods + ); + ensure!(!yield_per_period.is_zero(), Error::::InvalidYieldPerPeriod); >::try_mutate(global_farm_id, |maybe_global_farm| { let global_farm = maybe_global_farm.as_mut().ok_or(Error::::GlobalFarmNotFound)?; ensure!(global_farm.state.is_active(), Error::::GlobalFarmNotFound); - ensure!(who == global_farm.owner, Error::::Forbidden); //Sync farms to get right accumulated_rpz and pending rewards diff --git a/pallets/liquidity-mining/src/tests/update_global_farm.rs b/pallets/liquidity-mining/src/tests/update_global_farm.rs index 508781b4f..e168f7d36 100644 --- a/pallets/liquidity-mining/src/tests/update_global_farm.rs +++ b/pallets/liquidity-mining/src/tests/update_global_farm.rs @@ -18,6 +18,7 @@ use super::*; use pretty_assertions::assert_eq; use test_ext::*; +use crate::tests::mock::MinPlannedYieldingPeriods; #[test] fn update_global_farm_price_adjustment_should_work() { @@ -232,4 +233,75 @@ fn update_global_farm_should_work() { }); } +#[test] +fn update_global_farm_should_fail_with_invalid_deposit() { + predefined_test_ext_with_deposits().execute_with(|| { + let _ = with_transaction(|| { + //Arrange + let planned_yielding_periods: BlockNumber = 1_000_000_000_u64; + let yield_per_period = Perquintill::from_percent(20); + + set_block_number(100_000); + + //Act + assert_noop!(LiquidityMining::update_global_farm( + GC, + GC_FARM, + planned_yielding_periods, + yield_per_period, + MIN_DEPOSIT - 1, + ), Error::::InvalidMinDeposit); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); +} + +#[test] +fn update_global_farm_should_fail_when_planning_yield_period_is_too_small() { + predefined_test_ext_with_deposits().execute_with(|| { + let _ = with_transaction(|| { + //Arrange + let planned_yielding_periods: BlockNumber = MinPlannedYieldingPeriods::get() - 1; + let yield_per_period = Perquintill::from_percent(20); + + set_block_number(100_000); + + //Act + assert_noop!(LiquidityMining::update_global_farm( + GC, + GC_FARM, + planned_yielding_periods, + yield_per_period, + MIN_DEPOSIT, + ), Error::::InvalidPlannedYieldingPeriods); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); +} + +#[test] +fn update_global_farm_should_fail_when_yield_period_is_zero() { + predefined_test_ext_with_deposits().execute_with(|| { + let _ = with_transaction(|| { + //Arrange + let planned_yielding_periods: BlockNumber = MinPlannedYieldingPeriods::get(); + let zero_yield_per_period = Perquintill::from_percent(0); + + set_block_number(100_000); + + //Act + assert_noop!(LiquidityMining::update_global_farm( + GC, + GC_FARM, + planned_yielding_periods, + zero_yield_per_period, + MIN_DEPOSIT, + ), Error::::InvalidYieldPerPeriod); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); +} From b00cee4b1a7b6e294ab55d98edc0ba8ad890a4ee Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 11 Sep 2024 18:28:14 +0200 Subject: [PATCH 03/37] add upate global farm to omnipool LM --- pallets/liquidity-mining/src/lib.rs | 6 +- pallets/omnipool-liquidity-mining/src/lib.rs | 37 ++++ .../src/tests/mod.rs | 1 + .../src/tests/update_global_farm.rs | 170 ++++++++++++++++++ traits/src/liquidity_mining.rs | 8 + 5 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 pallets/omnipool-liquidity-mining/src/tests/update_global_farm.rs diff --git a/pallets/liquidity-mining/src/lib.rs b/pallets/liquidity-mining/src/lib.rs index 32fc5e788..3572e1d27 100644 --- a/pallets/liquidity-mining/src/lib.rs +++ b/pallets/liquidity-mining/src/lib.rs @@ -572,7 +572,6 @@ impl, I: 'static> Pallet { /// TODO DOC and in readme fn update_global_farm( - who: T::AccountId, global_farm_id: GlobalFarmId, planned_yielding_periods: PeriodOf, yield_per_period: Perquintill, @@ -592,7 +591,6 @@ impl, I: 'static> Pallet { let global_farm = maybe_global_farm.as_mut().ok_or(Error::::GlobalFarmNotFound)?; ensure!(global_farm.state.is_active(), Error::::GlobalFarmNotFound); - ensure!(who == global_farm.owner, Error::::Forbidden); //Sync farms to get right accumulated_rpz and pending rewards let current_period = Self::get_current_period(global_farm.blocks_per_period)?; @@ -1863,6 +1861,10 @@ impl, I: 'static> hydradx_traits::liquidity_mining::Mutate Result<(), Self::Error> { + Self::update_global_farm(global_farm_id, planned_yielding_periods, yield_per_period, min_deposit) + } + fn terminate_global_farm( who: T::AccountId, global_farm_id: u32, diff --git a/pallets/omnipool-liquidity-mining/src/lib.rs b/pallets/omnipool-liquidity-mining/src/lib.rs index 9ed62972d..353954635 100644 --- a/pallets/omnipool-liquidity-mining/src/lib.rs +++ b/pallets/omnipool-liquidity-mining/src/lib.rs @@ -181,6 +181,14 @@ pub mod pallet { lrna_price_adjustment: FixedU128, }, + /// Global farm was updated + GlobalFarmUpdated { + id: GlobalFarmId, + planned_yielding_periods: PeriodOf, + yield_per_period: Perquintill, + min_deposit: Balance, + }, + /// Global farm was terminated. GlobalFarmTerminated { global_farm_id: GlobalFarmId, @@ -878,6 +886,35 @@ pub mod pallet { Ok(()) } + + /// Update global farm parameters. + #[pallet::call_index(12)] + #[pallet::weight(::WeightInfo::create_global_farm())] + pub fn update_global_farm( + origin: OriginFor, + global_farm_id: GlobalFarmId, + planned_yielding_periods: crate::PeriodOf, + yield_per_period: Perquintill, + min_deposit: Balance, + ) -> DispatchResult { + T::CreateOrigin::ensure_origin(origin)?; + + T::LiquidityMiningHandler::update_global_farm( + global_farm_id, + planned_yielding_periods, + yield_per_period, + min_deposit, + )?; + + Self::deposit_event(Event::GlobalFarmUpdated { + id: global_farm_id, + planned_yielding_periods, + yield_per_period, + min_deposit, + }); + + Ok(()) + } } } diff --git a/pallets/omnipool-liquidity-mining/src/tests/mod.rs b/pallets/omnipool-liquidity-mining/src/tests/mod.rs index d180b5d84..0a0249c56 100644 --- a/pallets/omnipool-liquidity-mining/src/tests/mod.rs +++ b/pallets/omnipool-liquidity-mining/src/tests/mod.rs @@ -38,5 +38,6 @@ pub mod resume_yield_farm; pub mod stop_yield_farm; pub mod terminate_global_farm; pub mod terminate_yield_farm; +pub mod update_global_farm; pub mod update_yield_farm; pub mod withdraw_shares; diff --git a/pallets/omnipool-liquidity-mining/src/tests/update_global_farm.rs b/pallets/omnipool-liquidity-mining/src/tests/update_global_farm.rs new file mode 100644 index 000000000..f5ed5f9f2 --- /dev/null +++ b/pallets/omnipool-liquidity-mining/src/tests/update_global_farm.rs @@ -0,0 +1,170 @@ +// Copyright (C) 2020-2023 Intergalactic, Limited (GIB). +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::*; +#[test] +fn update_global_farm_should_work() { + ExtBuilder::default() + .with_endowed_accounts(vec![ + (Omnipool::protocol_account(), DAI, 1000 * ONE), + (Omnipool::protocol_account(), HDX, NATIVE_AMOUNT), + (LP1, KSM, 5000 * ONE), + (LP2, DOT, 2000 * ONE), + (GC, HDX, 100_000_000 * ONE), + (ALICE, KSM, 10_000 * ONE), + (BOB, DOT, 10_000 * ONE), + ]) + .with_registered_asset(KSM) + .with_registered_asset(DOT) + .with_initial_pool(FixedU128::from_float(0.5), FixedU128::from(1)) + .with_token(KSM, FixedU128::from_float(0.65), LP1, 2000 * ONE) + .with_global_farm( + 80_000_000 * ONE, + 2_628_000, + 1, + HDX, + GC, + Perquintill::from_float(0.000_000_15_f64), + 1_000, + FixedU128::one(), + ) + .with_yield_farm(GC, 1, KSM, FixedU128::one(), None) + .build() + .execute_with(|| { + let global_farm_id = 1; + + let planned_yielding_periods: BlockNumber = 1_000_000_000_u64; + let yield_per_period = Perquintill::from_percent(20); + let min_deposit = 20_000; + + //Act + assert_ok!( + OmnipoolMining::update_global_farm( + RuntimeOrigin::root(), + global_farm_id, + planned_yielding_periods, + yield_per_period, + min_deposit, + ), + ); + + //Assert + assert_last_event!(crate::Event::GlobalFarmUpdated { + id: 1, + planned_yielding_periods, + yield_per_period, + min_deposit, + } + .into()); + }); +} + +#[test] +fn update_global_farm_should_fail_when_origin_is_not_allowed() { + ExtBuilder::default() + .with_endowed_accounts(vec![ + (Omnipool::protocol_account(), DAI, 1000 * ONE), + (Omnipool::protocol_account(), HDX, NATIVE_AMOUNT), + (LP1, KSM, 5000 * ONE), + (LP2, DOT, 2000 * ONE), + (GC, HDX, 100_000_000 * ONE), + (ALICE, KSM, 10_000 * ONE), + (BOB, DOT, 10_000 * ONE), + ]) + .with_registered_asset(KSM) + .with_registered_asset(DOT) + .with_initial_pool(FixedU128::from_float(0.5), FixedU128::from(1)) + .with_token(KSM, FixedU128::from_float(0.65), LP1, 2000 * ONE) + .with_global_farm( + 80_000_000 * ONE, + 2_628_000, + 1, + HDX, + GC, + Perquintill::from_float(0.000_000_15_f64), + 1_000, + FixedU128::one(), + ) + .with_yield_farm(GC, 1, KSM, FixedU128::one(), None) + .build() + .execute_with(|| { + let global_farm_id = 1; + + let planned_yielding_periods: BlockNumber = 1_000_000_000_u64; + let yield_per_period = Perquintill::from_percent(20); + let min_deposit = 20_000; + + //Act and assert + assert_noop!( + OmnipoolMining::update_global_farm( + RuntimeOrigin::signed(ALICE), + global_farm_id, + planned_yielding_periods, + yield_per_period, + min_deposit, + ), + BadOrigin + ); + }); +} + +#[test] +fn update_global_farm_should_fail_when_origin_is_none() { + ExtBuilder::default() + .with_endowed_accounts(vec![ + (Omnipool::protocol_account(), DAI, 1000 * ONE), + (Omnipool::protocol_account(), HDX, NATIVE_AMOUNT), + (LP1, KSM, 5000 * ONE), + (LP2, DOT, 2000 * ONE), + (GC, HDX, 100_000_000 * ONE), + (ALICE, KSM, 10_000 * ONE), + (BOB, DOT, 10_000 * ONE), + ]) + .with_registered_asset(KSM) + .with_registered_asset(DOT) + .with_initial_pool(FixedU128::from_float(0.5), FixedU128::from(1)) + .with_token(KSM, FixedU128::from_float(0.65), LP1, 2000 * ONE) + .with_global_farm( + 80_000_000 * ONE, + 2_628_000, + 1, + HDX, + GC, + Perquintill::from_float(0.000_000_15_f64), + 1_000, + FixedU128::one(), + ) + .with_yield_farm(GC, 1, KSM, FixedU128::one(), None) + .build() + .execute_with(|| { + let global_farm_id = 1; + + let planned_yielding_periods: BlockNumber = 1_000_000_000_u64; + let yield_per_period = Perquintill::from_percent(20); + let min_deposit = 20_000; + + //Act and assert + assert_noop!( + OmnipoolMining::update_global_farm( + RuntimeOrigin::none(), + global_farm_id, + planned_yielding_periods, + yield_per_period, + min_deposit, + ), + BadOrigin + ); + }); +} diff --git a/traits/src/liquidity_mining.rs b/traits/src/liquidity_mining.rs index d79a8b809..c22e680ad 100644 --- a/traits/src/liquidity_mining.rs +++ b/traits/src/liquidity_mining.rs @@ -52,6 +52,14 @@ pub trait Mutate { price_adjustment: FixedU128, ) -> Result<(), Self::Error>; + /// Update global farm parameters + fn update_global_farm( + global_farm_id: GlobalFarmId, + planned_yielding_periods: Self::Period, + yield_per_period: Perquintill, + min_deposit: Self::Balance, + ) -> Result<(), Self::Error>; + /// Terminate existing global farm. /// /// Returns: `(reward currency, undistributed rewards, destination account)` From 8167b802d19bff75b544f9b0fb4fc6022fa08330 Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 11 Sep 2024 18:32:17 +0200 Subject: [PATCH 04/37] add doc for omni update_global_farm --- pallets/omnipool-liquidity-mining/src/lib.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pallets/omnipool-liquidity-mining/src/lib.rs b/pallets/omnipool-liquidity-mining/src/lib.rs index 353954635..e7377cd60 100644 --- a/pallets/omnipool-liquidity-mining/src/lib.rs +++ b/pallets/omnipool-liquidity-mining/src/lib.rs @@ -887,7 +887,20 @@ pub mod pallet { Ok(()) } - /// Update global farm parameters. + /// This extrinsic updates global farm's main parameters. + /// + /// The dispatch origin for this call must be `T::CreateOrigin`. + /// !!!WARN: `T::CreateOrigin` has power over funds of `owner`'s account and it should be + /// configured to trusted origin e.g Sudo or Governance. + /// + /// Parameters: + /// - `origin`: account allowed to create new liquidity mining program(root, governance). + /// - `global_farm_id`: id of the global farm to update. + /// - `planned_yielding_periods`: planned number of periods to distribute `total_rewards`. + /// - `yield_per_period`: percentage return on `reward_currency` of all farms. + /// - `min_deposit`: minimum amount of LP shares to be deposited into the liquidity mining by each user. + /// + /// Emits `GlobalFarmUpdated` event when successful. #[pallet::call_index(12)] #[pallet::weight(::WeightInfo::create_global_farm())] pub fn update_global_farm( From f037aa4d36402b5a77e6561b9bd4559c5d353d43 Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 11 Sep 2024 18:34:44 +0200 Subject: [PATCH 05/37] added doc --- pallets/liquidity-mining/src/lib.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pallets/liquidity-mining/src/lib.rs b/pallets/liquidity-mining/src/lib.rs index 3572e1d27..f1f6d33bd 100644 --- a/pallets/liquidity-mining/src/lib.rs +++ b/pallets/liquidity-mining/src/lib.rs @@ -568,17 +568,21 @@ impl, I: 'static> Pallet { Ok(()) }) } - /* */ - /// TODO DOC and in readme + /// Update global farm's main fields. + /// + /// + /// Parameters: + /// - `global_farm_id`: global farm id. + /// - `planned_yielding_periods`: planned number of periods to distribute `total_rewards`. + /// - `yield_per_period`: percentage return on `reward_currency` of all pools. + /// - `min_deposit`: minimum amount of LP shares to be deposited into liquidity mining by each user. fn update_global_farm( global_farm_id: GlobalFarmId, planned_yielding_periods: PeriodOf, yield_per_period: Perquintill, min_deposit: Balance, ) -> Result<(), DispatchError> { - //TODO: same origin as create glboal farm - //TODO: send event but oinly in the omnipool liq //TODO: add invariant test too ensure!(min_deposit.ge(&MIN_DEPOSIT), Error::::InvalidMinDeposit); ensure!( @@ -592,7 +596,7 @@ impl, I: 'static> Pallet { ensure!(global_farm.state.is_active(), Error::::GlobalFarmNotFound); - //Sync farms to get right accumulated_rpz and pending rewards + //Sync global farm to get right accumulated_rpz and pending rewards let current_period = Self::get_current_period(global_farm.blocks_per_period)?; Self::sync_global_farm(global_farm, current_period)?; @@ -607,7 +611,6 @@ impl, I: 'static> Pallet { global_farm.planned_yielding_periods = planned_yielding_periods; global_farm.yield_per_period = yield_per_period; global_farm.min_deposit = min_deposit; - global_farm.max_reward_per_period = new_max_reward_period; Ok(()) From 7943ab26bbf6d3ce998ea5b48e9ab654012b4083 Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 11 Sep 2024 18:40:46 +0200 Subject: [PATCH 06/37] fix compilation error --- pallets/liquidity-mining/src/tests/update_global_farm.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pallets/liquidity-mining/src/tests/update_global_farm.rs b/pallets/liquidity-mining/src/tests/update_global_farm.rs index e168f7d36..f15067c45 100644 --- a/pallets/liquidity-mining/src/tests/update_global_farm.rs +++ b/pallets/liquidity-mining/src/tests/update_global_farm.rs @@ -199,7 +199,6 @@ fn update_global_farm_should_work() { //Act assert_ok!(LiquidityMining::update_global_farm( - GC, GC_FARM, planned_yielding_periods, yield_per_period, @@ -245,7 +244,6 @@ fn update_global_farm_should_fail_with_invalid_deposit() { //Act assert_noop!(LiquidityMining::update_global_farm( - GC, GC_FARM, planned_yielding_periods, yield_per_period, @@ -269,7 +267,6 @@ fn update_global_farm_should_fail_when_planning_yield_period_is_too_small() { //Act assert_noop!(LiquidityMining::update_global_farm( - GC, GC_FARM, planned_yielding_periods, yield_per_period, @@ -293,7 +290,6 @@ fn update_global_farm_should_fail_when_yield_period_is_zero() { //Act assert_noop!(LiquidityMining::update_global_farm( - GC, GC_FARM, planned_yielding_periods, zero_yield_per_period, From 08afc6136f5aebd35cf363a058029707dc6adf28 Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 11 Sep 2024 19:16:31 +0200 Subject: [PATCH 07/37] add todo for invariant test --- .../liquidity-mining/src/tests/invariants.rs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index 7ba945344..e2209aaec 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -886,3 +886,38 @@ fn invariant_4() { .unwrap(); }); } + + +/* +TODO: continue +fn planned_yielding_periods() -> impl Strategy> { + 1_000u64..1_000_000_000u64 +} + +fn percentage() -> impl Strategy { + 1..100u64 +} + +fn min_deposit() -> impl Strategy { + 1000..10000000u128 +} + +proptest! { + #![proptest_config(ProptestConfig::with_cases(1_000))] + #[test] + fn update_global_farm_invariants( + (mut farm, current_period) in get_global_farm_and_current_period(), + planned_yield_period in planned_yielding_periods(), + perc in percentage(), + min_deposit in min_deposit(), + ) { + let yield_per_period = Perquintill::from_percent(perc); + new_test_ext().execute_with(|| { + let _ = with_transaction(|| { + LiquidityMining::update_global_farm(farm.id, planned_yield_period, yield_per_period,min_deposit).unwrap(); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); + } +}*/ \ No newline at end of file From 7883a837daf4e0391cbaa92a64e126581815834b Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 11 Sep 2024 19:47:25 +0200 Subject: [PATCH 08/37] add benchmark for update global farm --- .../omnipool-liquidity-mining/src/benchmarks.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pallets/omnipool-liquidity-mining/src/benchmarks.rs b/pallets/omnipool-liquidity-mining/src/benchmarks.rs index 7e01ed4a7..badbadbf5 100644 --- a/pallets/omnipool-liquidity-mining/src/benchmarks.rs +++ b/pallets/omnipool-liquidity-mining/src/benchmarks.rs @@ -291,6 +291,23 @@ benchmarks! { }: _(RawOrigin::Root, G_FARM_TOTAL_REWARDS, planned_yielding_periods, blocks_per_period, REWARD_CURRENCY.into(), owner, yield_per_period, min_deposit, FixedU128::one()) + update_global_farm { + let owner = create_funded_account::("owner", 0, G_FARM_TOTAL_REWARDS, REWARD_CURRENCY.into()); + let global_farm_id = 1; + let yield_farm_id = 2; + + initialize_omnipool::()?; + + initialize_global_farm::(owner.clone())?; + initialize_yield_farm::(owner.clone(), global_farm_id, BTC.into())?; + + let planned_yielding_periods = BlockNumberFor::::from(100_000_u32); + let yield_per_period = Perquintill::from_percent(20); + let min_deposit = 1_000; + + }: _(RawOrigin::Root, global_farm_id, planned_yielding_periods, yield_per_period, min_deposit) + + terminate_global_farm { let owner = create_funded_account::("owner", 0, G_FARM_TOTAL_REWARDS, REWARD_CURRENCY.into()); let global_farm_id = 1; From 51fbd926514aea9595c9ceff7090efb6abba6f7c Mon Sep 17 00:00:00 2001 From: dmoka Date: Thu, 12 Sep 2024 08:51:16 +0200 Subject: [PATCH 09/37] wip - add full run test --- .../liquidity-mining/src/tests/full_run.rs | 173 +++++++++++++++++- .../xyk-liquidity-mining/src/tests/mock.rs | 26 ++- 2 files changed, 192 insertions(+), 7 deletions(-) diff --git a/pallets/liquidity-mining/src/tests/full_run.rs b/pallets/liquidity-mining/src/tests/full_run.rs index ea8bd67dc..735b9ac8a 100644 --- a/pallets/liquidity-mining/src/tests/full_run.rs +++ b/pallets/liquidity-mining/src/tests/full_run.rs @@ -24,7 +24,7 @@ use test_utils::assert_balance_approx; use rand::Rng; -//This test test full run LM. Global farm is not full but it's running longer than expected. Users +//This test tests full run LM. Global farm is not full but it's running longer than expected. Users //should be able to claim expected amount. //This test case is without loyalty factor. #[test] @@ -285,6 +285,177 @@ fn non_full_farm_distribute_everything_and_update_farms() { }); } +#[test] +fn non_full_farm_distribute_everything_and_update_global_farms_fields() { + new_test_ext().execute_with(|| { + let _ = with_transaction(|| { + const GLOBAL_FARM: GlobalFarmId = 1; + const YIELD_FARM_A: YieldFarmId = 2; + const YIELD_FARM_B: YieldFarmId = 3; + + const ALICE_DEPOSIT: DepositId = 1; + const BOB_DEPOSIT: DepositId = 2; + const CHARLIE_DEPOSIT: DepositId = 3; + + //initialize farms + set_block_number(100); + assert_ok!(LiquidityMining2::create_global_farm( + 200_000 * ONE, + 20, + 10, + BSX, + BSX, + GC, + Perquintill::from_float(0.5), + 1_000, + One::one(), + )); + + assert_ok!(LiquidityMining2::create_yield_farm( + GC, + GLOBAL_FARM, + FixedU128::from(2_u128), + None, + BSX_TKN1_AMM, + vec![BSX, TKN1], + )); + + assert_ok!(LiquidityMining2::create_yield_farm( + GC, + GLOBAL_FARM, + FixedU128::from(1_u128), + None, + BSX_TKN2_AMM, + vec![BSX, TKN2], + )); + + set_block_number(110); + //alice + assert_ok!(LiquidityMining2::deposit_lp_shares( + GLOBAL_FARM, + YIELD_FARM_A, + BSX_TKN1_AMM, + 5_000 * ONE, + |_, _, _| { Ok(5_000 * ONE) } + )); + + set_block_number(120); + //bob + assert_ok!(LiquidityMining2::deposit_lp_shares( + GLOBAL_FARM, + YIELD_FARM_B, + BSX_TKN2_AMM, + 2_500 * ONE, + |_, _, _| { Ok(2_500 * ONE) } + )); + + //charlie + assert_ok!(LiquidityMining2::deposit_lp_shares( + GLOBAL_FARM, + YIELD_FARM_B, + BSX_TKN2_AMM, + 2_500 * ONE, + |_, _, _| { Ok(2_500 * ONE) } + )); + + set_block_number(130); + + //Claim rewards, leading to farms sync + let _ = LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); + + assert_eq!( + Tokens::free_balance(BSX, &LiquidityMining2::farm_account_id(GLOBAL_FARM).unwrap()), + 187500000000000000 + ); + + //We check that not everything has been claimed yet + assert_eq!( + Tokens::free_balance(BSX, &LiquidityMining2::pot_account_id().unwrap()), + 2500000000000000 + ); + + let planned_yielding_periods: BlockNumber = 30_u64; + let yield_per_period = Perquintill::from_percent(1); + let min_deposit = 20_000; + assert_ok!(LiquidityMining2::update_global_farm(GLOBAL_FARM, planned_yielding_periods,yield_per_period,min_deposit)); + + set_block_number(501); + + //Check that alice has things to claim + let (_, _, claimed, unclaimable) = + LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); + assert_eq!(claimed, 2055555555555547); + assert_eq!(unclaimable, 0); + + // Check that BOB has things to claim + let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(BOB, BOB_DEPOSIT, YIELD_FARM_B, false).unwrap(); + assert_eq!(claimed, 1763888888888886); + assert_eq!(unclaimable, 0); + + // Check that Charlie has things to claim + let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(CHARLIE, CHARLIE_DEPOSIT, YIELD_FARM_B, false).unwrap(); + assert_eq!(claimed, 1763888888888886); + assert_eq!(unclaimable, 0); + + assert_eq!( + Tokens::free_balance(BSX, &LiquidityMining2::pot_account_id().unwrap()), + 2 + ); + + assert_eq!(LiquidityMining2::global_farm(GLOBAL_FARM).unwrap().updated_at, 50); + assert_eq!( + LiquidityMining2::yield_farm((BSX_TKN1_AMM, GLOBAL_FARM, YIELD_FARM_A)) + .unwrap() + .updated_at, + 50 + ); + + set_block_number(1000); + let (_, _, claimed, unclaimable) = + LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); + assert_eq!(claimed, 2777777777777766); + assert_eq!(unclaimable, 0); + + let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(BOB, BOB_DEPOSIT, YIELD_FARM_B, false).unwrap(); + assert_eq!(claimed, 694444444444442); + assert_eq!(unclaimable, 0); + + let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(CHARLIE, CHARLIE_DEPOSIT, YIELD_FARM_B, false).unwrap(); + assert_eq!(claimed, 694444444444442); + assert_eq!(unclaimable, 0); + + assert_eq!( + Tokens::free_balance(BSX, &LiquidityMining2::pot_account_id().unwrap()), + 2 + ); + + set_block_number(5000); + let (_, _, claimed, unclaimable) = + LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); + assert_eq!(claimed, 22222222222222133); + assert_eq!(unclaimable, 0); + + let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(BOB, BOB_DEPOSIT, YIELD_FARM_B, false).unwrap(); + assert_eq!(claimed, 5555555555555533); + assert_eq!(unclaimable, 0); + + let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(CHARLIE, CHARLIE_DEPOSIT, YIELD_FARM_B, false).unwrap(); + assert_eq!(claimed, 5555555555555533); + assert_eq!(unclaimable, 0); + + assert_eq!(LiquidityMining2::global_farm(GLOBAL_FARM).unwrap().updated_at, 500); + assert_eq!( + LiquidityMining2::yield_farm((BSX_TKN2_AMM, GLOBAL_FARM, YIELD_FARM_B)) + .unwrap() + .updated_at, + 500 + ); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); +} + //This test tests `update_global_farm` and `update_yield_farm` after farm distributed all the //rewards. #[test] diff --git a/pallets/xyk-liquidity-mining/src/tests/mock.rs b/pallets/xyk-liquidity-mining/src/tests/mock.rs index bc58c68c0..5cb63db8c 100644 --- a/pallets/xyk-liquidity-mining/src/tests/mock.rs +++ b/pallets/xyk-liquidity-mining/src/tests/mock.rs @@ -161,13 +161,13 @@ thread_local! { #[derive(Copy, Clone)] pub struct DymmyGlobalFarm { total_rewards: Balance, - _planned_yielding_periods: PeriodOf, + planned_yielding_periods: PeriodOf, _blocks_per_period: BlockNumber, incentivized_asset: AssetId, reward_currency: AssetId, _owner: AccountId, - _yield_per_period: Perquintill, - _min_deposit: Balance, + yield_per_period: Perquintill, + min_deposit: Balance, price_adjustment: FixedU128, _max_reward_per_period: Balance, } @@ -529,13 +529,13 @@ impl hydradx_traits::liquidity_mining::Mutate f farm_id, DymmyGlobalFarm { total_rewards, - _planned_yielding_periods: planned_yielding_periods, + planned_yielding_periods, _blocks_per_period: blocks_per_period, incentivized_asset, reward_currency, _owner: owner, - _yield_per_period: yield_per_period, - _min_deposit: min_deposit, + yield_per_period, + min_deposit, price_adjustment, _max_reward_per_period: max_reward_per_period, }, @@ -812,6 +812,20 @@ impl hydradx_traits::liquidity_mining::Mutate f //NOTE: Basilisk is not using this fn. Err(sp_runtime::DispatchError::Other("Not implemented")) } + + fn update_global_farm(global_farm_id: GlobalFarmId, planned_yielding_periods: Self::Period, yield_per_period: Perquintill, min_deposit: Self::Balance) -> Result<(), Self::Error> { + GLOBAL_FARMS.with(|v| { + let mut p = v.borrow_mut(); + + let global_farm = p.get_mut(&global_farm_id).unwrap(); + + global_farm.planned_yielding_periods = planned_yielding_periods; + global_farm.yield_per_period = yield_per_period; + global_farm.min_deposit = min_deposit; + + Ok(()) + }) + } } impl hydradx_traits::liquidity_mining::Inspect for DummyLiquidityMining { From f86ce37453e5a803fbb612296907dc24e07cee62 Mon Sep 17 00:00:00 2001 From: dmoka Date: Thu, 12 Sep 2024 12:41:54 +0200 Subject: [PATCH 10/37] fix update faram and full run test --- pallets/liquidity-mining/src/lib.rs | 5 ++- .../liquidity-mining/src/tests/full_run.rs | 42 ++++++------------- .../src/tests/update_global_farm.rs | 2 +- 3 files changed, 16 insertions(+), 33 deletions(-) diff --git a/pallets/liquidity-mining/src/lib.rs b/pallets/liquidity-mining/src/lib.rs index f1f6d33bd..d90a1ee2e 100644 --- a/pallets/liquidity-mining/src/lib.rs +++ b/pallets/liquidity-mining/src/lib.rs @@ -601,11 +601,12 @@ impl, I: 'static> Pallet { Self::sync_global_farm(global_farm, current_period)?; //Calculate the new max reward period - let pot = Self::pot_account_id().ok_or(Error::::ErrorGetAccountId)?; - let total_rewards = T::MultiCurrency::free_balance(global_farm.reward_currency, &pot); + let global_farm_account = Self::farm_account_id(global_farm.id)?; + let total_rewards = T::MultiCurrency::free_balance(global_farm.reward_currency, &global_farm_account); let planned_periods = TryInto::::try_into(planned_yielding_periods).map_err(|_| ArithmeticError::Overflow)?; let new_max_reward_period = total_rewards.checked_div(planned_periods).ok_or(Error::::InvalidPlannedYieldingPeriods)?; + ensure!(!new_max_reward_period.is_zero(), Error::::InvalidPlannedYieldingPeriods); //Update global farm fields global_farm.planned_yielding_periods = planned_yielding_periods; diff --git a/pallets/liquidity-mining/src/tests/full_run.rs b/pallets/liquidity-mining/src/tests/full_run.rs index 735b9ac8a..20ecde59a 100644 --- a/pallets/liquidity-mining/src/tests/full_run.rs +++ b/pallets/liquidity-mining/src/tests/full_run.rs @@ -375,7 +375,7 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { ); let planned_yielding_periods: BlockNumber = 30_u64; - let yield_per_period = Perquintill::from_percent(1); + let yield_per_period = Perquintill::from_float(0.45); let min_deposit = 20_000; assert_ok!(LiquidityMining2::update_global_farm(GLOBAL_FARM, planned_yielding_periods,yield_per_period,min_deposit)); @@ -384,22 +384,22 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { //Check that alice has things to claim let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); - assert_eq!(claimed, 2055555555555547); + assert_eq!(claimed, 124999999999999333); assert_eq!(unclaimable, 0); // Check that BOB has things to claim let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(BOB, BOB_DEPOSIT, YIELD_FARM_B, false).unwrap(); - assert_eq!(claimed, 1763888888888886); + assert_eq!(claimed, 32499999999999833); assert_eq!(unclaimable, 0); // Check that Charlie has things to claim let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(CHARLIE, CHARLIE_DEPOSIT, YIELD_FARM_B, false).unwrap(); - assert_eq!(claimed, 1763888888888886); + assert_eq!(claimed, 32499999999999833); assert_eq!(unclaimable, 0); assert_eq!( Tokens::free_balance(BSX, &LiquidityMining2::pot_account_id().unwrap()), - 2 + 1 ); assert_eq!(LiquidityMining2::global_farm(GLOBAL_FARM).unwrap().updated_at, 50); @@ -410,45 +410,27 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { 50 ); - set_block_number(1000); + //Assert that user has nothing else to claim + set_block_number(600); let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); - assert_eq!(claimed, 2777777777777766); - assert_eq!(unclaimable, 0); - - let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(BOB, BOB_DEPOSIT, YIELD_FARM_B, false).unwrap(); - assert_eq!(claimed, 694444444444442); - assert_eq!(unclaimable, 0); - - let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(CHARLIE, CHARLIE_DEPOSIT, YIELD_FARM_B, false).unwrap(); - assert_eq!(claimed, 694444444444442); - assert_eq!(unclaimable, 0); - - assert_eq!( - Tokens::free_balance(BSX, &LiquidityMining2::pot_account_id().unwrap()), - 2 - ); - - set_block_number(5000); - let (_, _, claimed, unclaimable) = - LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); - assert_eq!(claimed, 22222222222222133); + assert_eq!(claimed, 0); assert_eq!(unclaimable, 0); let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(BOB, BOB_DEPOSIT, YIELD_FARM_B, false).unwrap(); - assert_eq!(claimed, 5555555555555533); + assert_eq!(claimed, 0); assert_eq!(unclaimable, 0); let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(CHARLIE, CHARLIE_DEPOSIT, YIELD_FARM_B, false).unwrap(); - assert_eq!(claimed, 5555555555555533); + assert_eq!(claimed, 0); assert_eq!(unclaimable, 0); - assert_eq!(LiquidityMining2::global_farm(GLOBAL_FARM).unwrap().updated_at, 500); + assert_eq!(LiquidityMining2::global_farm(GLOBAL_FARM).unwrap().updated_at, 60); assert_eq!( LiquidityMining2::yield_farm((BSX_TKN2_AMM, GLOBAL_FARM, YIELD_FARM_B)) .unwrap() .updated_at, - 500 + 60 ); TransactionOutcome::Commit(DispatchResult::Ok(())) diff --git a/pallets/liquidity-mining/src/tests/update_global_farm.rs b/pallets/liquidity-mining/src/tests/update_global_farm.rs index f15067c45..06edda00a 100644 --- a/pallets/liquidity-mining/src/tests/update_global_farm.rs +++ b/pallets/liquidity-mining/src/tests/update_global_farm.rs @@ -215,7 +215,7 @@ fn update_global_farm_should_work() { min_deposit, accumulated_rpz: FixedU128::from_inner(491_000_000_000_000_000_000_u128), pending_rewards: 343195125000000000000, - max_reward_per_period: 344478675000, + max_reward_per_period: 29655521325000, ..global_farm_0 }, ); From 17582c8d4f9f59ac0596da0a9e861cda80ebb801 Mon Sep 17 00:00:00 2001 From: dmoka Date: Thu, 12 Sep 2024 12:52:09 +0200 Subject: [PATCH 11/37] add lp share withdraw --- pallets/liquidity-mining/src/tests/full_run.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pallets/liquidity-mining/src/tests/full_run.rs b/pallets/liquidity-mining/src/tests/full_run.rs index 20ecde59a..48784e78f 100644 --- a/pallets/liquidity-mining/src/tests/full_run.rs +++ b/pallets/liquidity-mining/src/tests/full_run.rs @@ -416,14 +416,29 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); assert_eq!(claimed, 0); assert_eq!(unclaimable, 0); + assert_ok!(LiquidityMining2::withdraw_lp_shares( + ALICE_DEPOSIT, + YIELD_FARM_A, + unclaimable + )); let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(BOB, BOB_DEPOSIT, YIELD_FARM_B, false).unwrap(); assert_eq!(claimed, 0); assert_eq!(unclaimable, 0); + assert_ok!(LiquidityMining2::withdraw_lp_shares( + BOB_DEPOSIT, + YIELD_FARM_B, + unclaimable + )); let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(CHARLIE, CHARLIE_DEPOSIT, YIELD_FARM_B, false).unwrap(); assert_eq!(claimed, 0); assert_eq!(unclaimable, 0); + assert_ok!(LiquidityMining2::withdraw_lp_shares( + CHARLIE_DEPOSIT, + YIELD_FARM_B, + unclaimable + )); assert_eq!(LiquidityMining2::global_farm(GLOBAL_FARM).unwrap().updated_at, 60); assert_eq!( From 063d1e28165292ca4de7d03dd28ace5f2c12c819 Mon Sep 17 00:00:00 2001 From: dmoka Date: Thu, 12 Sep 2024 13:04:03 +0200 Subject: [PATCH 12/37] add redeposit to full farm test --- .../liquidity-mining/src/tests/full_run.rs | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/pallets/liquidity-mining/src/tests/full_run.rs b/pallets/liquidity-mining/src/tests/full_run.rs index 48784e78f..c3ecb8894 100644 --- a/pallets/liquidity-mining/src/tests/full_run.rs +++ b/pallets/liquidity-mining/src/tests/full_run.rs @@ -340,6 +340,7 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { )); set_block_number(120); + //bob assert_ok!(LiquidityMining2::deposit_lp_shares( GLOBAL_FARM, @@ -361,7 +362,21 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { set_block_number(130); //Claim rewards, leading to farms sync - let _ = LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); + let (_,_,_,unclaimeable) = LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); + + //Withdraw and redeposit for ALICE + let (_, withdran_amount,_) = LiquidityMining2::withdraw_lp_shares( + ALICE_DEPOSIT, + YIELD_FARM_A, + unclaimeable + ).unwrap(); + let alice_new_deposit_id = LiquidityMining2::deposit_lp_shares( + GLOBAL_FARM, + YIELD_FARM_A, + BSX_TKN1_AMM, + withdran_amount, + |_, _, _| { Ok(5_000 * ONE) } + ).unwrap(); assert_eq!( Tokens::free_balance(BSX, &LiquidityMining2::farm_account_id(GLOBAL_FARM).unwrap()), @@ -383,7 +398,7 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { //Check that alice has things to claim let (_, _, claimed, unclaimable) = - LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); + LiquidityMining2::claim_rewards(ALICE, alice_new_deposit_id, YIELD_FARM_A, false).unwrap(); assert_eq!(claimed, 124999999999999333); assert_eq!(unclaimable, 0); @@ -413,11 +428,11 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { //Assert that user has nothing else to claim set_block_number(600); let (_, _, claimed, unclaimable) = - LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); + LiquidityMining2::claim_rewards(ALICE, alice_new_deposit_id, YIELD_FARM_A, false).unwrap(); assert_eq!(claimed, 0); assert_eq!(unclaimable, 0); assert_ok!(LiquidityMining2::withdraw_lp_shares( - ALICE_DEPOSIT, + alice_new_deposit_id, YIELD_FARM_A, unclaimable )); From 7ecd04e89ef02a344fcca3c0fe46336f883990e2 Mon Sep 17 00:00:00 2001 From: dmoka Date: Thu, 12 Sep 2024 13:20:53 +0200 Subject: [PATCH 13/37] formatting --- pallets/liquidity-mining/src/lib.rs | 18 ++++++-- .../liquidity-mining/src/tests/full_run.rs | 34 ++++++++------ .../liquidity-mining/src/tests/invariants.rs | 3 +- .../src/tests/update_global_farm.rs | 45 ++++++++++--------- 4 files changed, 60 insertions(+), 40 deletions(-) diff --git a/pallets/liquidity-mining/src/lib.rs b/pallets/liquidity-mining/src/lib.rs index d90a1ee2e..c51f1523e 100644 --- a/pallets/liquidity-mining/src/lib.rs +++ b/pallets/liquidity-mining/src/lib.rs @@ -605,10 +605,15 @@ impl, I: 'static> Pallet { let total_rewards = T::MultiCurrency::free_balance(global_farm.reward_currency, &global_farm_account); let planned_periods = TryInto::::try_into(planned_yielding_periods).map_err(|_| ArithmeticError::Overflow)?; - let new_max_reward_period = total_rewards.checked_div(planned_periods).ok_or(Error::::InvalidPlannedYieldingPeriods)?; - ensure!(!new_max_reward_period.is_zero(), Error::::InvalidPlannedYieldingPeriods); + let new_max_reward_period = total_rewards + .checked_div(planned_periods) + .ok_or(Error::::InvalidPlannedYieldingPeriods)?; + ensure!( + !new_max_reward_period.is_zero(), + Error::::InvalidPlannedYieldingPeriods + ); - //Update global farm fields + //Update global farm fields global_farm.planned_yielding_periods = planned_yielding_periods; global_farm.yield_per_period = yield_per_period; global_farm.min_deposit = min_deposit; @@ -1865,7 +1870,12 @@ impl, I: 'static> hydradx_traits::liquidity_mining::Mutate Result<(), Self::Error> { + fn update_global_farm( + global_farm_id: GlobalFarmId, + planned_yielding_periods: Self::Period, + yield_per_period: Perquintill, + min_deposit: Self::Balance, + ) -> Result<(), Self::Error> { Self::update_global_farm(global_farm_id, planned_yielding_periods, yield_per_period, min_deposit) } diff --git a/pallets/liquidity-mining/src/tests/full_run.rs b/pallets/liquidity-mining/src/tests/full_run.rs index c3ecb8894..652d40ec0 100644 --- a/pallets/liquidity-mining/src/tests/full_run.rs +++ b/pallets/liquidity-mining/src/tests/full_run.rs @@ -362,21 +362,20 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { set_block_number(130); //Claim rewards, leading to farms sync - let (_,_,_,unclaimeable) = LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); + let (_, _, _, unclaimeable) = + LiquidityMining2::claim_rewards(ALICE, ALICE_DEPOSIT, YIELD_FARM_A, false).unwrap(); //Withdraw and redeposit for ALICE - let (_, withdran_amount,_) = LiquidityMining2::withdraw_lp_shares( - ALICE_DEPOSIT, - YIELD_FARM_A, - unclaimeable - ).unwrap(); + let (_, withdran_amount, _) = + LiquidityMining2::withdraw_lp_shares(ALICE_DEPOSIT, YIELD_FARM_A, unclaimeable).unwrap(); let alice_new_deposit_id = LiquidityMining2::deposit_lp_shares( GLOBAL_FARM, YIELD_FARM_A, BSX_TKN1_AMM, withdran_amount, - |_, _, _| { Ok(5_000 * ONE) } - ).unwrap(); + |_, _, _| Ok(5_000 * ONE), + ) + .unwrap(); assert_eq!( Tokens::free_balance(BSX, &LiquidityMining2::farm_account_id(GLOBAL_FARM).unwrap()), @@ -392,7 +391,12 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { let planned_yielding_periods: BlockNumber = 30_u64; let yield_per_period = Perquintill::from_float(0.45); let min_deposit = 20_000; - assert_ok!(LiquidityMining2::update_global_farm(GLOBAL_FARM, planned_yielding_periods,yield_per_period,min_deposit)); + assert_ok!(LiquidityMining2::update_global_farm( + GLOBAL_FARM, + planned_yielding_periods, + yield_per_period, + min_deposit + )); set_block_number(501); @@ -403,12 +407,14 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { assert_eq!(unclaimable, 0); // Check that BOB has things to claim - let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(BOB, BOB_DEPOSIT, YIELD_FARM_B, false).unwrap(); + let (_, _, claimed, unclaimable) = + LiquidityMining2::claim_rewards(BOB, BOB_DEPOSIT, YIELD_FARM_B, false).unwrap(); assert_eq!(claimed, 32499999999999833); assert_eq!(unclaimable, 0); // Check that Charlie has things to claim - let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(CHARLIE, CHARLIE_DEPOSIT, YIELD_FARM_B, false).unwrap(); + let (_, _, claimed, unclaimable) = + LiquidityMining2::claim_rewards(CHARLIE, CHARLIE_DEPOSIT, YIELD_FARM_B, false).unwrap(); assert_eq!(claimed, 32499999999999833); assert_eq!(unclaimable, 0); @@ -437,7 +443,8 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { unclaimable )); - let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(BOB, BOB_DEPOSIT, YIELD_FARM_B, false).unwrap(); + let (_, _, claimed, unclaimable) = + LiquidityMining2::claim_rewards(BOB, BOB_DEPOSIT, YIELD_FARM_B, false).unwrap(); assert_eq!(claimed, 0); assert_eq!(unclaimable, 0); assert_ok!(LiquidityMining2::withdraw_lp_shares( @@ -446,7 +453,8 @@ fn non_full_farm_distribute_everything_and_update_global_farms_fields() { unclaimable )); - let (_, _, claimed, unclaimable) = LiquidityMining2::claim_rewards(CHARLIE, CHARLIE_DEPOSIT, YIELD_FARM_B, false).unwrap(); + let (_, _, claimed, unclaimable) = + LiquidityMining2::claim_rewards(CHARLIE, CHARLIE_DEPOSIT, YIELD_FARM_B, false).unwrap(); assert_eq!(claimed, 0); assert_eq!(unclaimable, 0); assert_ok!(LiquidityMining2::withdraw_lp_shares( diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index e2209aaec..f6ee661f8 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -887,7 +887,6 @@ fn invariant_4() { }); } - /* TODO: continue fn planned_yielding_periods() -> impl Strategy> { @@ -920,4 +919,4 @@ proptest! { }); }); } -}*/ \ No newline at end of file +}*/ diff --git a/pallets/liquidity-mining/src/tests/update_global_farm.rs b/pallets/liquidity-mining/src/tests/update_global_farm.rs index 06edda00a..caa0da2c5 100644 --- a/pallets/liquidity-mining/src/tests/update_global_farm.rs +++ b/pallets/liquidity-mining/src/tests/update_global_farm.rs @@ -16,9 +16,9 @@ // limitations under the License. use super::*; +use crate::tests::mock::MinPlannedYieldingPeriods; use pretty_assertions::assert_eq; use test_ext::*; -use crate::tests::mock::MinPlannedYieldingPeriods; #[test] fn update_global_farm_price_adjustment_should_work() { @@ -215,7 +215,7 @@ fn update_global_farm_should_work() { min_deposit, accumulated_rpz: FixedU128::from_inner(491_000_000_000_000_000_000_u128), pending_rewards: 343195125000000000000, - max_reward_per_period: 29655521325000, + max_reward_per_period: 29655521325000, ..global_farm_0 }, ); @@ -243,12 +243,15 @@ fn update_global_farm_should_fail_with_invalid_deposit() { set_block_number(100_000); //Act - assert_noop!(LiquidityMining::update_global_farm( - GC_FARM, - planned_yielding_periods, - yield_per_period, - MIN_DEPOSIT - 1, - ), Error::::InvalidMinDeposit); + assert_noop!( + LiquidityMining::update_global_farm( + GC_FARM, + planned_yielding_periods, + yield_per_period, + MIN_DEPOSIT - 1, + ), + Error::::InvalidMinDeposit + ); TransactionOutcome::Commit(DispatchResult::Ok(())) }); @@ -266,12 +269,10 @@ fn update_global_farm_should_fail_when_planning_yield_period_is_too_small() { set_block_number(100_000); //Act - assert_noop!(LiquidityMining::update_global_farm( - GC_FARM, - planned_yielding_periods, - yield_per_period, - MIN_DEPOSIT, - ), Error::::InvalidPlannedYieldingPeriods); + assert_noop!( + LiquidityMining::update_global_farm(GC_FARM, planned_yielding_periods, yield_per_period, MIN_DEPOSIT,), + Error::::InvalidPlannedYieldingPeriods + ); TransactionOutcome::Commit(DispatchResult::Ok(())) }); @@ -289,15 +290,17 @@ fn update_global_farm_should_fail_when_yield_period_is_zero() { set_block_number(100_000); //Act - assert_noop!(LiquidityMining::update_global_farm( - GC_FARM, - planned_yielding_periods, - zero_yield_per_period, - MIN_DEPOSIT, - ), Error::::InvalidYieldPerPeriod); + assert_noop!( + LiquidityMining::update_global_farm( + GC_FARM, + planned_yielding_periods, + zero_yield_per_period, + MIN_DEPOSIT, + ), + Error::::InvalidYieldPerPeriod + ); TransactionOutcome::Commit(DispatchResult::Ok(())) }); }); } - From 49fef602cfbe7184ff8828ceefdec63aa3996577 Mon Sep 17 00:00:00 2001 From: dmoka Date: Mon, 16 Sep 2024 15:32:47 +0200 Subject: [PATCH 14/37] add invariant 2-3-4 for update global farm --- .../liquidity-mining/src/tests/invariants.rs | 297 ++++++++++++++++-- 1 file changed, 276 insertions(+), 21 deletions(-) diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index f6ee661f8..e36b12673 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -887,36 +887,291 @@ fn invariant_4() { }); } -/* -TODO: continue fn planned_yielding_periods() -> impl Strategy> { - 1_000u64..1_000_000_000u64 + 1_000u64..5_000_000u64 } fn percentage() -> impl Strategy { - 1..100u64 + 1..40u64 } fn min_deposit() -> impl Strategy { 1000..10000000u128 } -proptest! { - #![proptest_config(ProptestConfig::with_cases(1_000))] - #[test] - fn update_global_farm_invariants( - (mut farm, current_period) in get_global_farm_and_current_period(), - planned_yield_period in planned_yielding_periods(), - perc in percentage(), - min_deposit in min_deposit(), - ) { - let yield_per_period = Perquintill::from_percent(perc); - new_test_ext().execute_with(|| { - let _ = with_transaction(|| { - LiquidityMining::update_global_farm(farm.id, planned_yield_period, yield_per_period,min_deposit).unwrap(); +//Number of blocks added to current block number in each test case run. This number should be +//reasonable smaller than total of runned test to make sure lot of claims is executed and +//multiple claims for same deposit to happen. +fn blocks_offset_range() -> impl Strategy { + 1..10u64 +} - TransactionOutcome::Commit(DispatchResult::Ok(())) - }); +//Index of deposit in `deposit` vec. This idx is used in each test case run and execute claim +//if deposit exits +fn deposit_idx_range() -> impl Strategy { + 0..500_usize +} + + +#[test] +//Update global farm for invariants 1,2,3 +//https://www.notion.so/Liquidity-mining-spec-b30ccfe470a74173b82c3702b1e8fca1#422dea2e23744859baeb704dbdb3caca +// +fn update_global_farm_invariant_1_2_3() { + //Number of sucessfull test cases that must execute for the test as a whole to pass. + let successfull_cases = 1_000; + //Number of blocks added to current block number in each test case run. This number should be + //reasonable smaller than total of runned test to make sure lot of claims is executed and + //multiple claims for same deposit to happen. + let blocks_offset_range = 1..10_u64; + //Index of deposit in `deposit` vec. This idx is used in each test case run and execute claim + //if deposit exits. + + let deposit_idx_range = 0..500_usize; + + invariants_externalities().execute_with(|| { + let mut runner = TestRunner::new(Config { + cases: successfull_cases, + source_file: Some("liquidity-mining/src/tests/invariants.rs"), + test_name: Some("update_global_farm_invariant_1_2_3"), + ..Config::default() }); - } -}*/ + let deposits: RefCell> = RefCell::new(Vec::new()); + let pot = LiquidityMining::pot_account_id().unwrap(); + + runner + .run( + &(arb_deposit(), blocks_offset_range, deposit_idx_range, planned_yielding_periods(), percentage(), min_deposit()), + |(d, blocks_offset, deposit_idx, planned_yielding_period, percent, min_deposit)| { + deposits.borrow_mut().push(d.clone()); + + let yield_per_period = Perquintill::from_percent(percent); + + //Act + let _ = with_transaction(|| { + LiquidityMining::update_global_farm(d.global_farm_id, planned_yielding_period, yield_per_period, min_deposit).unwrap(); + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + + //We deposit and roll block to have claimable rewards + let _ = with_transaction(|| { + assert_ok!(LiquidityMining::deposit_lp_shares( + d.global_farm_id, + d.yield_farm_id, + d.amm_pool_id, + d.shares, + |_, _, _| -> Result { Ok(d.valued_shares) } + )); + set_block_number(mock::System::block_number() + blocks_offset); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + + let _ = with_transaction(|| { + //claim rewards only if deposit exists + if deposit_idx < deposits.borrow().len() { + let d = &deposits.borrow()[deposit_idx]; + let deposit_id = deposit_idx as u128 + 1; + + assert_ok!(LiquidityMining::claim_rewards(ALICE, deposit_id, d.yield_farm_id, true)); + } + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + + //INVARIANT 2 + //Calculate necessary values and assert + let (total_rewards_sum, farm_balances_sum, pot_balance_sum) = G_FARMS.with(|v| { + let mut total_rewards_sum = 0_u128; + let mut farm_balances_sum = 0_u128; + let mut pot_balance_sum = 0_u128; + let mut already_summed_balances: Vec = Vec::new(); + + v.borrow().clone().into_iter().for_each(|gf| { + farm_balances_sum += Tokens::free_balance( + gf.reward_currency, + &LiquidityMining::farm_account_id(gf.id).unwrap(), + ); + + total_rewards_sum += gf.total_rewards; + + if !already_summed_balances.contains(&gf.reward_currency) { + pot_balance_sum += Tokens::total_balance(gf.reward_currency, &pot); + already_summed_balances.push(gf.reward_currency); + } + }); + (total_rewards_sum, farm_balances_sum, pot_balance_sum) + }); + + let last_deposit_id = LiquidityMining::deposit_id(); + let mut claimed_by_users_sum = 0_u128; + for i in 1..=last_deposit_id { + let d = LiquidityMining::deposit(i).unwrap(); + + let claimed_amount = d.yield_farm_entries[0].accumulated_claimed_rewards; + claimed_by_users_sum += claimed_amount; + } + + //WARN: There is no room for rounding errors in this invariant. Any discrepancy + //in this assert means we are loosing tokens somewhere. + assert_eq!( + total_rewards_sum, + farm_balances_sum + pot_balance_sum + claimed_by_users_sum, + ); + + //INVARIANT 3 + //Calculate necessary values and assert + let (total_rewards_sum, farm_balances_sum, pot_balance_sum) = G_FARMS.with(|v| { + let mut total_rewards_sum = 0_u128; + let mut farm_balances_sum = 0_u128; + let mut pot_balance_sum = 0_u128; + let mut already_summed_balances: Vec = Vec::new(); + + v.borrow().clone().into_iter().for_each(|gf| { + farm_balances_sum += Tokens::free_balance( + gf.reward_currency, + &LiquidityMining::farm_account_id(gf.id).unwrap(), + ); + + total_rewards_sum += gf.total_rewards; + + if !already_summed_balances.contains(&gf.reward_currency) { + pot_balance_sum += Tokens::total_balance(gf.reward_currency, &pot); + already_summed_balances.push(gf.reward_currency); + } + }); + (total_rewards_sum, farm_balances_sum, pot_balance_sum) + }); + + let last_deposit_id = LiquidityMining::deposit_id(); + let mut claimed_by_users_sum = 0_u128; + for i in 1..=last_deposit_id { + let d = LiquidityMining::deposit(i).unwrap(); + + let claimed_amount = d.yield_farm_entries[0].accumulated_claimed_rewards; + claimed_by_users_sum += claimed_amount; + } + + //WARN: There is no room for rounding errors in this invariant. Any discrepancy + //in this assert means we are loosing tokens somewhere. + assert_eq!( + total_rewards_sum, + farm_balances_sum + pot_balance_sum + claimed_by_users_sum, + ); + + Ok(()) + }, + ) + .unwrap(); + }); +} + + +#[test] +//Update global farm for invariant 4 https://www.notion.so/Liquidity-mining-spec-b30ccfe470a74173b82c3702b1e8fca1#422dea2e23744859baeb704dbdb3caca +// +fn update_global_farm_invariant_4() { + //Number of sucessfull test cases that must execute for the test as a whole to pass. + let successfull_cases = 1_000; + //Number of blocks added to current block number in each test case run. This number should be + //reasonable smaller than total of runned test to make sure lot of claims is executed and + //multiple claims for same deposit to happen. + let blocks_offset_range = 1..10_u64; + //Index of deposit in `deposit` vec. This idx is used in each test case run and execute claim + //if deposit exits. + + let deposit_idx_range = 0..500_usize; + + invariants_externalities().execute_with(|| { + let mut runner = TestRunner::new(Config { + cases: successfull_cases, + source_file: Some("liquidity-mining/src/tests/invariants.rs"), + test_name: Some("update_global_farm_invariant_4"), + ..Config::default() + }); + let deposits: RefCell> = RefCell::new(Vec::new()); + let paid_until_now: RefCell> = RefCell::new(HashMap::new()); + + runner + .run( + &(arb_deposit(), blocks_offset_range, deposit_idx_range, planned_yielding_periods(), percentage(), min_deposit()), + |(d, blocks_offset, deposit_idx, planned_yielding_period, percent, min_deposit)| { + deposits.borrow_mut().push(d.clone()); + let g_farm_0 = LiquidityMining::global_farm(d.global_farm_id).unwrap(); + + let yield_per_period = Perquintill::from_percent(percent); + + //Act + let _ = with_transaction(|| { + LiquidityMining::update_global_farm(d.global_farm_id, planned_yielding_period, yield_per_period, min_deposit).unwrap(); + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + + //We deposit + let _ = with_transaction(|| { + assert_ok!(LiquidityMining::deposit_lp_shares( + d.global_farm_id, + d.yield_farm_id, + d.amm_pool_id, + d.shares, + |_, _, _| -> Result { Ok(d.valued_shares) } + )); + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + + //INVARIANT 4 (part 1) + let _ = with_transaction(|| { + let g_farm_1 = LiquidityMining::global_farm(g_farm_0.id).unwrap(); + let s_0 = g_farm_1.accumulated_paid_rewards + g_farm_1.pending_rewards; + *paid_until_now.borrow_mut().entry(g_farm_1.id).or_insert(0_u128) += (g_farm_1.accumulated_rpz + - g_farm_0.accumulated_rpz) + .checked_mul_int(g_farm_0.total_shares_z) + .unwrap(); + + //NOTE: global-farm is updated before deposit so in this case we need to + //use Z{now-1} instead of Z{now} which includes deposited shares. + assert_eq_approx!(s_0, *paid_until_now.borrow().get(&d.global_farm_id).unwrap(), 1_000_000, "accumulated_paid_rewards + pending_rewards = sum(rpz{now} - rpz{now-1} * Z{now-1}) for all periods"); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + + //We roll block to have claimable rewards + let _ = with_transaction(|| { + set_block_number(mock::System::block_number() + blocks_offset); + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + + //Invariant 4 (part 2) + let _ = with_transaction(|| { + //claim rewards only if deposit exists + if deposit_idx < deposits.borrow().len() { + let d = &deposits.borrow()[deposit_idx]; + let deposit_id = deposit_idx as u128 + 1; + + let g_farm_0 = LiquidityMining::global_farm(d.global_farm_id).unwrap(); + + assert_ok!(LiquidityMining::claim_rewards(ALICE, deposit_id, d.yield_farm_id, true)); + + let g_farm_1 = LiquidityMining::global_farm(g_farm_0.id).unwrap(); + let s_0 = g_farm_1.accumulated_paid_rewards + g_farm_1.pending_rewards; + *paid_until_now.borrow_mut().entry(g_farm_1.id).or_insert(0_u128) += (g_farm_1.accumulated_rpz + - g_farm_0.accumulated_rpz) + .checked_mul_int(g_farm_1.total_shares_z) + .unwrap(); + + //NOTE: global-farm is updated before claim so RPZ includes all Z so Z{now} + //must be used in this case. + assert_eq_approx!(s_0, *paid_until_now.borrow().get(&d.global_farm_id).unwrap(), 1_000_000, "accumulated_paid_rewards + pending_rewards = sum(rpz{now} - rpz{now-1} * Z{now}) for all periods"); + } + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + + Ok(()) + }, + ) + .unwrap(); + }); +} + + + From 67f3d1a178bbdf8546f1c02d3f06253d4217be3e Mon Sep 17 00:00:00 2001 From: dmoka Date: Tue, 17 Sep 2024 08:25:07 +0200 Subject: [PATCH 15/37] add invariant test for 1st invariant --- pallets/liquidity-mining/src/lib.rs | 1 - .../liquidity-mining/src/tests/invariants.rs | 113 ++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/pallets/liquidity-mining/src/lib.rs b/pallets/liquidity-mining/src/lib.rs index c51f1523e..b9d02e17b 100644 --- a/pallets/liquidity-mining/src/lib.rs +++ b/pallets/liquidity-mining/src/lib.rs @@ -583,7 +583,6 @@ impl, I: 'static> Pallet { yield_per_period: Perquintill, min_deposit: Balance, ) -> Result<(), DispatchError> { - //TODO: add invariant test too ensure!(min_deposit.ge(&MIN_DEPOSIT), Error::::InvalidMinDeposit); ensure!( planned_yielding_periods >= T::MinPlannedYieldingPeriods::get(), diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index e36b12673..1a6a594ce 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -506,6 +506,20 @@ prop_compose! { } } +prop_compose! { + fn arb_deposit2()( + shares in 1_000 * ONE..1_000_000 * ONE, + valued_shares in 10_001..10_000_000 * ONE, + g_idx in 0..3_usize, + y_idx in 0..2_usize, + ) -> Deposit { + let g_farm = G_FARMS.with(|v| v.borrow()[g_idx].clone()); + let y_farm = &g_farm.yield_farms[y_idx]; + + Deposit {global_farm_id: g_farm.id,yield_farm_id: y_farm.0, amm_pool_id: y_farm.1, shares, valued_shares} + } +} + #[test] //https://www.notion.so/Liquidity-mining-spec-b30ccfe470a74173b82c3702b1e8fca1#87868f45e4d04ecb92374c5f795a493d // @@ -898,6 +912,10 @@ fn percentage() -> impl Strategy { fn min_deposit() -> impl Strategy { 1000..10000000u128 } +fn min_deposit2() -> impl Strategy { + 1000..10_000u128 +} + //Number of blocks added to current block number in each test case run. This number should be //reasonable smaller than total of runned test to make sure lot of claims is executed and @@ -1175,3 +1193,98 @@ fn update_global_farm_invariant_4() { + +#[test] +//Update global farm for invariant one +//https://www.notion.so/Liquidity-mining-spec-b30ccfe470a74173b82c3702b1e8fca1#87868f45e4d04ecb92374c5f795a493d + +fn update_global_farm_invariant_first() { + //Number of sucessfull test cases that must execute for the test as a whole to pass. + let successfull_cases = 1_000; + //Number of blocks added to current block number in each test case run. This number should be + //reasonable smaller than total of runned test to make sure lot of claims is executed and + //multiple claims for same deposit to happen. + let blocks_offset_range = 1..10_u64; + //Index of deposit in `deposit` vec. This idx is used in each test case run and execute claim + //if deposit exits. + + let deposit_idx_range = 0..500_usize; + + invariants_externalities().execute_with(|| { + let mut runner = TestRunner::new(Config { + cases: successfull_cases, + source_file: Some("liquidity-mining/src/tests/invariants.rs"), + test_name: Some("update_global_farm_invariant_first"), + ..Config::default() + }); + let deposits: RefCell> = RefCell::new(Vec::new()); + + runner + .run( + &(arb_deposit2(), blocks_offset_range, deposit_idx_range, planned_yielding_periods(), percentage(), min_deposit()), + |(d, blocks_offset, deposit_idx, planned_yielding_period, percent, min_deposit)| { + deposits.borrow_mut().push(d.clone()); + + let yield_per_period = Perquintill::from_percent(percent); + + //Act + let _ = with_transaction(|| { + LiquidityMining::update_global_farm(d.global_farm_id, planned_yielding_period, yield_per_period, 1000).unwrap(); + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + + let _ = with_transaction(|| { + assert_ok!(LiquidityMining::deposit_lp_shares( + d.global_farm_id, + d.yield_farm_id, + d.amm_pool_id, + d.shares, + |_, _, _| -> Result { Ok(d.valued_shares) } + )); + + set_block_number(mock::System::block_number() + blocks_offset); + + //claim rewards only if deposit exists + if deposit_idx < deposits.borrow().len() { + let d = &deposits.borrow()[deposit_idx]; + let deposit_id = deposit_idx as u128 + 1; + + assert_ok!(LiquidityMining::claim_rewards(ALICE, deposit_id, d.yield_farm_id, true)); + } + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + + + //Assert: + G_FARMS.with(|v| { + v.borrow().clone().into_iter().for_each(|gf| { + let g_farm_balance = Tokens::free_balance( + gf.reward_currency, + &LiquidityMining::farm_account_id(gf.id).unwrap(), + ); + let g_farm_1 = LiquidityMining::global_farm(gf.id).unwrap(); + + //1.1 assert + let s_1 = g_farm_balance + g_farm_1.accumulated_paid_rewards + g_farm_1.pending_rewards; + //NOTE: This should be precise. + assert_eq!(gf.total_rewards, s_1); + + //1.2 assert + let s_1: u128 = g_farm_1.max_reward_per_period * g_farm_1.planned_yielding_periods as u128; + //NOTE: Approax becasue of div in max_reward_per_period calculation. + assert_eq_approx!( + gf.total_rewards, + s_1, + 5_000_000, + "total_rewards = max_reward_per_period * planned_yielding_periods" + ); + }) + }); + + Ok(()) + }, + ) + .unwrap(); + }); +} \ No newline at end of file From f2b7b5d25f82ea2523aa1a573e498c5b10dcae7a Mon Sep 17 00:00:00 2001 From: dmoka Date: Tue, 17 Sep 2024 13:56:18 +0200 Subject: [PATCH 16/37] add integration test for updating global farm --- .../src/omnipool_liquidity_mining.rs | 58 +++++++++++++++++++ pallets/liquidity-mining/src/types.rs | 6 +- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/integration-tests/src/omnipool_liquidity_mining.rs b/integration-tests/src/omnipool_liquidity_mining.rs index cd2149ebd..112eeacc8 100644 --- a/integration-tests/src/omnipool_liquidity_mining.rs +++ b/integration-tests/src/omnipool_liquidity_mining.rs @@ -1238,6 +1238,64 @@ fn liquidity_mining_should_work_when_farm_distribute_bonds() { }); } +#[test] +fn update_global_farm_should_work() { + TestNet::reset(); + + Hydra::execute_with(|| { + let global_farm_id = 1; + let yield_farm_id = 2; + + //Arrange + init_omnipool(); + + //NOTE: necessary to get oracle price. + hydradx_run_to_block(100); + set_relaychain_block_number(100); + create_global_farm(None, None); + + set_relaychain_block_number(200); + create_yield_farm(global_farm_id, ETH); + + set_relaychain_block_number(300); + + assert_ok!(hydradx_runtime::Currencies::update_balance( + hydradx_runtime::RuntimeOrigin::root(), + CHARLIE.into(), + ETH, + 10_000 * UNITS as i128, + )); + let position_id = omnipool_add_liquidity(CHARLIE.into(), ETH, 1_000 * UNITS); + + set_relaychain_block_number(400); + + assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::deposit_shares( + RuntimeOrigin::signed(CHARLIE.into()), + global_farm_id, + yield_farm_id, + position_id + )); + + //Act + let planned_yielding_periods: BlockNumber = 1_000_000_000_u32; + let yield_per_period = Perquintill::from_percent(20); + let min_deposit = 20_000; + assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::update_global_farm( + RuntimeOrigin::root(), + global_farm_id, + planned_yielding_periods, + yield_per_period, + min_deposit + )); + + //Assert + let g_farm = warehouse_liquidity_mining::GlobalFarm::::get(global_farm_id).unwrap(); + assert_eq!(g_farm.planned_yielding_periods, planned_yielding_periods); + assert_eq!(g_farm.yield_per_period, yield_per_period); + assert_eq!(g_farm.min_deposit, min_deposit); + }); +} + pub fn expect_reward_claimed_events(e: Vec) { let last_events = test_utils::last_events::(10); diff --git a/pallets/liquidity-mining/src/types.rs b/pallets/liquidity-mining/src/types.rs index e4d11091d..1b646bcb5 100644 --- a/pallets/liquidity-mining/src/types.rs +++ b/pallets/liquidity-mining/src/types.rs @@ -54,13 +54,13 @@ pub struct GlobalFarmData, I: 'static = ()> { pub reward_currency: T::AssetId, pub(super) pending_rewards: Balance, pub(super) accumulated_paid_rewards: Balance, - pub(super) yield_per_period: Perquintill, - pub(super) planned_yielding_periods: PeriodOf, + pub yield_per_period: Perquintill, + pub planned_yielding_periods: PeriodOf, pub(super) blocks_per_period: BlockNumberFor, pub incentivized_asset: T::AssetId, pub(super) max_reward_per_period: Balance, // min. LP shares user must deposit to start yield farming. - pub(super) min_deposit: Balance, + pub min_deposit: Balance, // This include `active` and `stopped` yield farms. pub(super) live_yield_farms_count: u32, // This include `active`, `stopped`, `terminated` - this count is decreased only if yield From 9109b277f641d1f19c58ab422e15a0f79fe530f3 Mon Sep 17 00:00:00 2001 From: martinfridrich Date: Tue, 17 Sep 2024 17:00:53 +0200 Subject: [PATCH 17/37] fix update_global_farm_invariant_first() invariant test --- .../liquidity-mining/src/tests/invariants.rs | 58 ++++++++++++++----- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index 1a6a594ce..af832c3d4 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -916,7 +916,6 @@ fn min_deposit2() -> impl Strategy { 1000..10_000u128 } - //Number of blocks added to current block number in each test case run. This number should be //reasonable smaller than total of runned test to make sure lot of claims is executed and //multiple claims for same deposit to happen. @@ -930,7 +929,6 @@ fn deposit_idx_range() -> impl Strategy { 0..500_usize } - #[test] //Update global farm for invariants 1,2,3 //https://www.notion.so/Liquidity-mining-spec-b30ccfe470a74173b82c3702b1e8fca1#422dea2e23744859baeb704dbdb3caca @@ -959,7 +957,14 @@ fn update_global_farm_invariant_1_2_3() { runner .run( - &(arb_deposit(), blocks_offset_range, deposit_idx_range, planned_yielding_periods(), percentage(), min_deposit()), + &( + arb_deposit(), + blocks_offset_range, + deposit_idx_range, + planned_yielding_periods(), + percentage(), + min_deposit(), + ), |(d, blocks_offset, deposit_idx, planned_yielding_period, percent, min_deposit)| { deposits.borrow_mut().push(d.clone()); @@ -967,7 +972,13 @@ fn update_global_farm_invariant_1_2_3() { //Act let _ = with_transaction(|| { - LiquidityMining::update_global_farm(d.global_farm_id, planned_yielding_period, yield_per_period, min_deposit).unwrap(); + LiquidityMining::update_global_farm( + d.global_farm_id, + planned_yielding_period, + yield_per_period, + min_deposit, + ) + .unwrap(); TransactionOutcome::Commit(DispatchResult::Ok(())) }); @@ -1084,7 +1095,6 @@ fn update_global_farm_invariant_1_2_3() { }); } - #[test] //Update global farm for invariant 4 https://www.notion.so/Liquidity-mining-spec-b30ccfe470a74173b82c3702b1e8fca1#422dea2e23744859baeb704dbdb3caca // @@ -1191,9 +1201,6 @@ fn update_global_farm_invariant_4() { }); } - - - #[test] //Update global farm for invariant one //https://www.notion.so/Liquidity-mining-spec-b30ccfe470a74173b82c3702b1e8fca1#87868f45e4d04ecb92374c5f795a493d @@ -1218,20 +1225,37 @@ fn update_global_farm_invariant_first() { ..Config::default() }); let deposits: RefCell> = RefCell::new(Vec::new()); + //NOTE: farm ids start with 1 so skip 0, farm's id is used as index into array + let distributed_before_update: RefCell<[u128; 4]> = RefCell::new([0, 0, 0, 0]); runner .run( - &(arb_deposit2(), blocks_offset_range, deposit_idx_range, planned_yielding_periods(), percentage(), min_deposit()), - |(d, blocks_offset, deposit_idx, planned_yielding_period, percent, min_deposit)| { + &( + arb_deposit2(), + blocks_offset_range, + deposit_idx_range, + planned_yielding_periods(), + percentage(), + ), + |(d, blocks_offset, deposit_idx, planned_yielding_period, percent)| { deposits.borrow_mut().push(d.clone()); let yield_per_period = Perquintill::from_percent(percent); //Act let _ = with_transaction(|| { - LiquidityMining::update_global_farm(d.global_farm_id, planned_yielding_period, yield_per_period, 1000).unwrap(); + LiquidityMining::update_global_farm( + d.global_farm_id, + planned_yielding_period, + yield_per_period, + 1_000, + ) + .unwrap(); TransactionOutcome::Commit(DispatchResult::Ok(())) }); + let g_farm = LiquidityMining::global_farm(d.global_farm_id).unwrap(); + distributed_before_update.borrow_mut()[d.global_farm_id as usize] = + g_farm.accumulated_paid_rewards + g_farm.pending_rewards; let _ = with_transaction(|| { assert_ok!(LiquidityMining::deposit_lp_shares( @@ -1255,7 +1279,6 @@ fn update_global_farm_invariant_first() { TransactionOutcome::Commit(DispatchResult::Ok(())) }); - //Assert: G_FARMS.with(|v| { v.borrow().clone().into_iter().for_each(|gf| { @@ -1271,13 +1294,16 @@ fn update_global_farm_invariant_first() { assert_eq!(gf.total_rewards, s_1); //1.2 assert - let s_1: u128 = g_farm_1.max_reward_per_period * g_farm_1.planned_yielding_periods as u128; + let s_1: u128 = g_farm_1.max_reward_per_period * g_farm_1.planned_yielding_periods as u128 + + distributed_before_update.borrow()[gf.id as usize]; + //NOTE: Approax becasue of div in max_reward_per_period calculation. + assert!(gf.total_rewards >= s_1, "total_rewards >= distributed + max_reward_per_period * planned_yielding_periods"); assert_eq_approx!( gf.total_rewards, s_1, - 5_000_000, - "total_rewards = max_reward_per_period * planned_yielding_periods" + 10_000_000, + "total_rewards >= distributed + max_reward_per_period * planned_yielding_periods" ); }) }); @@ -1287,4 +1313,4 @@ fn update_global_farm_invariant_first() { ) .unwrap(); }); -} \ No newline at end of file +} From c134f2f24d7bd4e36ba2b050354eea1a69ecea1d Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 10:18:40 +0200 Subject: [PATCH 18/37] make update global farm integratio ntest more complex --- .../src/omnipool_liquidity_mining.rs | 88 ++++++++++++++++--- 1 file changed, 75 insertions(+), 13 deletions(-) diff --git a/integration-tests/src/omnipool_liquidity_mining.rs b/integration-tests/src/omnipool_liquidity_mining.rs index 112eeacc8..d64651ecc 100644 --- a/integration-tests/src/omnipool_liquidity_mining.rs +++ b/integration-tests/src/omnipool_liquidity_mining.rs @@ -1239,15 +1239,19 @@ fn liquidity_mining_should_work_when_farm_distribute_bonds() { } #[test] -fn update_global_farm_should_work() { +fn claim_rewards_should_work_when_farm_is_updated() { TestNet::reset(); Hydra::execute_with(|| { - let global_farm_id = 1; - let yield_farm_id = 2; + let global_farm_1_id = 1; + let yield_farm_1_id = 2; + let yield_farm_2_id = 3; //Arrange init_omnipool(); + seed_lm_pot(); + //necessary for oracle to have a price. + do_lrna_hdx_trade(); //NOTE: necessary to get oracle price. hydradx_run_to_block(100); @@ -1255,7 +1259,8 @@ fn update_global_farm_should_work() { create_global_farm(None, None); set_relaychain_block_number(200); - create_yield_farm(global_farm_id, ETH); + create_yield_farm(global_farm_1_id, ETH); + create_yield_farm(global_farm_1_id, DOT); set_relaychain_block_number(300); @@ -1265,34 +1270,91 @@ fn update_global_farm_should_work() { ETH, 10_000 * UNITS as i128, )); + let position_id = omnipool_add_liquidity(CHARLIE.into(), ETH, 1_000 * UNITS); + assert_nft_owner!( + hydradx_runtime::OmnipoolCollectionId::get(), + position_id, + CHARLIE.into() + ); set_relaychain_block_number(400); + let deposit_id = 1; + assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::deposit_shares( + RuntimeOrigin::signed(CHARLIE.into()), + global_farm_1_id, + yield_farm_1_id, + position_id + )); + + set_relaychain_block_number(500); + assert_ok!(hydradx_runtime::Currencies::update_balance( + hydradx_runtime::RuntimeOrigin::root(), + CHARLIE.into(), + DOT, + 10_000 * UNITS as i128, + )); + let position_id = omnipool_add_liquidity(CHARLIE.into(), DOT, 1 * UNITS); + assert_nft_owner!( + hydradx_runtime::OmnipoolCollectionId::get(), + position_id, + CHARLIE.into() + ); + + set_relaychain_block_number(400); + let deposit_id_2 = 2; assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::deposit_shares( RuntimeOrigin::signed(CHARLIE.into()), - global_farm_id, - yield_farm_id, + global_farm_1_id, + yield_farm_2_id, position_id )); - //Act - let planned_yielding_periods: BlockNumber = 1_000_000_000_u32; - let yield_per_period = Perquintill::from_percent(20); - let min_deposit = 20_000; + //Act - update farm + let planned_yielding_periods: BlockNumber = 2_000_000_u32; + let yield_per_period = Perquintill::from_parts(550_776_255_707); + let min_deposit = 5_000; assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::update_global_farm( RuntimeOrigin::root(), - global_farm_id, + global_farm_1_id, planned_yielding_periods, yield_per_period, min_deposit )); - //Assert - let g_farm = warehouse_liquidity_mining::GlobalFarm::::get(global_farm_id).unwrap(); + let g_farm = warehouse_liquidity_mining::GlobalFarm::::get(global_farm_1_id).unwrap(); assert_eq!(g_farm.planned_yielding_periods, planned_yielding_periods); assert_eq!(g_farm.yield_per_period, yield_per_period); assert_eq!(g_farm.min_deposit, min_deposit); + + let charlie_hdx_balance_0 = hydradx_runtime::Currencies::free_balance(HDX, &CHARLIE.into()); + //Act 1 - claim rewards for 2-nd yield-farm-entry + set_relaychain_block_number(600); + assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::claim_rewards( + RuntimeOrigin::signed(CHARLIE.into()), + deposit_id_2, + yield_farm_2_id + )); + + //Assert + //NOTE: can't assert state in the deposit because fields are private + let charlie_new_hdx_balance_after_first_claim = hydradx_runtime::Currencies::free_balance(HDX, &CHARLIE.into()); + assert!(charlie_new_hdx_balance_after_first_claim > charlie_hdx_balance_0, "Charlie's balance should be increased"); + assert_eq!(charlie_new_hdx_balance_after_first_claim, 1000136935112266); + + //Act 3 - claim rewards for differnt yield-farm-entry in the same period should work. + assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::claim_rewards( + RuntimeOrigin::signed(CHARLIE.into()), + deposit_id, + yield_farm_1_id + )); + + //Assert + //NOTE: can't assert state in the deposit because fields are private + let charlie_new_hdx_balance_after_2nd_claim = hydradx_runtime::Currencies::free_balance(HDX, &CHARLIE.into()); + assert!(charlie_new_hdx_balance_after_2nd_claim > charlie_new_hdx_balance_after_first_claim, "Charlie's balance should be increased"); + assert_eq!(charlie_new_hdx_balance_after_2nd_claim, 1000137314927403); }); } From 8dc4277d27e6a15a050adcac1547d22deec6a47e Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 10:24:58 +0200 Subject: [PATCH 19/37] formatting --- integration-tests/src/omnipool_liquidity_mining.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/integration-tests/src/omnipool_liquidity_mining.rs b/integration-tests/src/omnipool_liquidity_mining.rs index d64651ecc..852c04b3b 100644 --- a/integration-tests/src/omnipool_liquidity_mining.rs +++ b/integration-tests/src/omnipool_liquidity_mining.rs @@ -1323,7 +1323,9 @@ fn claim_rewards_should_work_when_farm_is_updated() { min_deposit )); //Assert - let g_farm = warehouse_liquidity_mining::GlobalFarm::::get(global_farm_1_id).unwrap(); + let g_farm = + warehouse_liquidity_mining::GlobalFarm::::get(global_farm_1_id) + .unwrap(); assert_eq!(g_farm.planned_yielding_periods, planned_yielding_periods); assert_eq!(g_farm.yield_per_period, yield_per_period); assert_eq!(g_farm.min_deposit, min_deposit); @@ -1340,7 +1342,10 @@ fn claim_rewards_should_work_when_farm_is_updated() { //Assert //NOTE: can't assert state in the deposit because fields are private let charlie_new_hdx_balance_after_first_claim = hydradx_runtime::Currencies::free_balance(HDX, &CHARLIE.into()); - assert!(charlie_new_hdx_balance_after_first_claim > charlie_hdx_balance_0, "Charlie's balance should be increased"); + assert!( + charlie_new_hdx_balance_after_first_claim > charlie_hdx_balance_0, + "Charlie's balance should be increased" + ); assert_eq!(charlie_new_hdx_balance_after_first_claim, 1000136935112266); //Act 3 - claim rewards for differnt yield-farm-entry in the same period should work. @@ -1353,7 +1358,10 @@ fn claim_rewards_should_work_when_farm_is_updated() { //Assert //NOTE: can't assert state in the deposit because fields are private let charlie_new_hdx_balance_after_2nd_claim = hydradx_runtime::Currencies::free_balance(HDX, &CHARLIE.into()); - assert!(charlie_new_hdx_balance_after_2nd_claim > charlie_new_hdx_balance_after_first_claim, "Charlie's balance should be increased"); + assert!( + charlie_new_hdx_balance_after_2nd_claim > charlie_new_hdx_balance_after_first_claim, + "Charlie's balance should be increased" + ); assert_eq!(charlie_new_hdx_balance_after_2nd_claim, 1000137314927403); }); } From e16f3f6af963bee786cc17a6642fa41de2f87f57 Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 10:26:54 +0200 Subject: [PATCH 20/37] formatting and renaming --- .../liquidity-mining/src/tests/invariants.rs | 228 +++++++++--------- 1 file changed, 114 insertions(+), 114 deletions(-) diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index af832c3d4..be291698d 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -929,6 +929,120 @@ fn deposit_idx_range() -> impl Strategy { 0..500_usize } +#[test] +//Update global farm for invariant one +//https://www.notion.so/Liquidity-mining-spec-b30ccfe470a74173b82c3702b1e8fca1#87868f45e4d04ecb92374c5f795a493d + +fn update_global_farm_invariant_1() { + //Number of sucessfull test cases that must execute for the test as a whole to pass. + let successfull_cases = 1_000; + //Number of blocks added to current block number in each test case run. This number should be + //reasonable smaller than total of runned test to make sure lot of claims is executed and + //multiple claims for same deposit to happen. + let blocks_offset_range = 1..10_u64; + //Index of deposit in `deposit` vec. This idx is used in each test case run and execute claim + //if deposit exits. + + let deposit_idx_range = 0..500_usize; + + invariants_externalities().execute_with(|| { + let mut runner = TestRunner::new(Config { + cases: successfull_cases, + source_file: Some("liquidity-mining/src/tests/invariants.rs"), + test_name: Some("update_global_farm_invariant_first"), + ..Config::default() + }); + let deposits: RefCell> = RefCell::new(Vec::new()); + //NOTE: farm ids start with 1 so skip 0, farm's id is used as index into array + let distributed_before_update: RefCell<[u128; 4]> = RefCell::new([0, 0, 0, 0]); + + runner + .run( + &( + arb_deposit2(), + blocks_offset_range, + deposit_idx_range, + planned_yielding_periods(), + percentage(), + ), + |(d, blocks_offset, deposit_idx, planned_yielding_period, percent)| { + deposits.borrow_mut().push(d.clone()); + + let yield_per_period = Perquintill::from_percent(percent); + + //Act + let _ = with_transaction(|| { + LiquidityMining::update_global_farm( + d.global_farm_id, + planned_yielding_period, + yield_per_period, + 1_000, + ) + .unwrap(); + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + let g_farm = LiquidityMining::global_farm(d.global_farm_id).unwrap(); + distributed_before_update.borrow_mut()[d.global_farm_id as usize] = + g_farm.accumulated_paid_rewards + g_farm.pending_rewards; + + let _ = with_transaction(|| { + assert_ok!(LiquidityMining::deposit_lp_shares( + d.global_farm_id, + d.yield_farm_id, + d.amm_pool_id, + d.shares, + |_, _, _| -> Result { Ok(d.valued_shares) } + )); + + set_block_number(mock::System::block_number() + blocks_offset); + + //claim rewards only if deposit exists + if deposit_idx < deposits.borrow().len() { + let d = &deposits.borrow()[deposit_idx]; + let deposit_id = deposit_idx as u128 + 1; + + assert_ok!(LiquidityMining::claim_rewards(ALICE, deposit_id, d.yield_farm_id, true)); + } + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + + //Assert: + G_FARMS.with(|v| { + v.borrow().clone().into_iter().for_each(|gf| { + let g_farm_balance = Tokens::free_balance( + gf.reward_currency, + &LiquidityMining::farm_account_id(gf.id).unwrap(), + ); + let g_farm_1 = LiquidityMining::global_farm(gf.id).unwrap(); + + //1.1 assert + let s_1 = g_farm_balance + g_farm_1.accumulated_paid_rewards + g_farm_1.pending_rewards; + //NOTE: This should be precise. + assert_eq!(gf.total_rewards, s_1); + + //1.2 assert + let s_1: u128 = g_farm_1.max_reward_per_period * g_farm_1.planned_yielding_periods as u128 + + distributed_before_update.borrow()[gf.id as usize]; + + //NOTE: Approax becasue of div in max_reward_per_period calculation. + assert!(gf.total_rewards >= s_1, "total_rewards >= distributed + max_reward_per_period * planned_yielding_periods"); + assert_eq_approx!( + gf.total_rewards, + s_1, + 10_000_000, + "total_rewards >= distributed + max_reward_per_period * planned_yielding_periods" + ); + }) + }); + + Ok(()) + }, + ) + .unwrap(); + }); +} + #[test] //Update global farm for invariants 1,2,3 //https://www.notion.so/Liquidity-mining-spec-b30ccfe470a74173b82c3702b1e8fca1#422dea2e23744859baeb704dbdb3caca @@ -1200,117 +1314,3 @@ fn update_global_farm_invariant_4() { .unwrap(); }); } - -#[test] -//Update global farm for invariant one -//https://www.notion.so/Liquidity-mining-spec-b30ccfe470a74173b82c3702b1e8fca1#87868f45e4d04ecb92374c5f795a493d - -fn update_global_farm_invariant_first() { - //Number of sucessfull test cases that must execute for the test as a whole to pass. - let successfull_cases = 1_000; - //Number of blocks added to current block number in each test case run. This number should be - //reasonable smaller than total of runned test to make sure lot of claims is executed and - //multiple claims for same deposit to happen. - let blocks_offset_range = 1..10_u64; - //Index of deposit in `deposit` vec. This idx is used in each test case run and execute claim - //if deposit exits. - - let deposit_idx_range = 0..500_usize; - - invariants_externalities().execute_with(|| { - let mut runner = TestRunner::new(Config { - cases: successfull_cases, - source_file: Some("liquidity-mining/src/tests/invariants.rs"), - test_name: Some("update_global_farm_invariant_first"), - ..Config::default() - }); - let deposits: RefCell> = RefCell::new(Vec::new()); - //NOTE: farm ids start with 1 so skip 0, farm's id is used as index into array - let distributed_before_update: RefCell<[u128; 4]> = RefCell::new([0, 0, 0, 0]); - - runner - .run( - &( - arb_deposit2(), - blocks_offset_range, - deposit_idx_range, - planned_yielding_periods(), - percentage(), - ), - |(d, blocks_offset, deposit_idx, planned_yielding_period, percent)| { - deposits.borrow_mut().push(d.clone()); - - let yield_per_period = Perquintill::from_percent(percent); - - //Act - let _ = with_transaction(|| { - LiquidityMining::update_global_farm( - d.global_farm_id, - planned_yielding_period, - yield_per_period, - 1_000, - ) - .unwrap(); - TransactionOutcome::Commit(DispatchResult::Ok(())) - }); - let g_farm = LiquidityMining::global_farm(d.global_farm_id).unwrap(); - distributed_before_update.borrow_mut()[d.global_farm_id as usize] = - g_farm.accumulated_paid_rewards + g_farm.pending_rewards; - - let _ = with_transaction(|| { - assert_ok!(LiquidityMining::deposit_lp_shares( - d.global_farm_id, - d.yield_farm_id, - d.amm_pool_id, - d.shares, - |_, _, _| -> Result { Ok(d.valued_shares) } - )); - - set_block_number(mock::System::block_number() + blocks_offset); - - //claim rewards only if deposit exists - if deposit_idx < deposits.borrow().len() { - let d = &deposits.borrow()[deposit_idx]; - let deposit_id = deposit_idx as u128 + 1; - - assert_ok!(LiquidityMining::claim_rewards(ALICE, deposit_id, d.yield_farm_id, true)); - } - - TransactionOutcome::Commit(DispatchResult::Ok(())) - }); - - //Assert: - G_FARMS.with(|v| { - v.borrow().clone().into_iter().for_each(|gf| { - let g_farm_balance = Tokens::free_balance( - gf.reward_currency, - &LiquidityMining::farm_account_id(gf.id).unwrap(), - ); - let g_farm_1 = LiquidityMining::global_farm(gf.id).unwrap(); - - //1.1 assert - let s_1 = g_farm_balance + g_farm_1.accumulated_paid_rewards + g_farm_1.pending_rewards; - //NOTE: This should be precise. - assert_eq!(gf.total_rewards, s_1); - - //1.2 assert - let s_1: u128 = g_farm_1.max_reward_per_period * g_farm_1.planned_yielding_periods as u128 - + distributed_before_update.borrow()[gf.id as usize]; - - //NOTE: Approax becasue of div in max_reward_per_period calculation. - assert!(gf.total_rewards >= s_1, "total_rewards >= distributed + max_reward_per_period * planned_yielding_periods"); - assert_eq_approx!( - gf.total_rewards, - s_1, - 10_000_000, - "total_rewards >= distributed + max_reward_per_period * planned_yielding_periods" - ); - }) - }); - - Ok(()) - }, - ) - .unwrap(); - }); -} From 34630312d8e0b5f02866979aee5f0250352faa3e Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 10:30:46 +0200 Subject: [PATCH 21/37] rebench omnipool lm on ref machine --- .../pallet_omnipool_liquidity_mining.rs | 63 +++++++++++-------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/runtime/hydradx/src/weights/pallet_omnipool_liquidity_mining.rs b/runtime/hydradx/src/weights/pallet_omnipool_liquidity_mining.rs index 0ce1a51ed..2c7a76dbb 100644 --- a/runtime/hydradx/src/weights/pallet_omnipool_liquidity_mining.rs +++ b/runtime/hydradx/src/weights/pallet_omnipool_liquidity_mining.rs @@ -19,7 +19,7 @@ //! Autogenerated weights for `pallet_omnipool_liquidity_mining` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-05-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-09-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `bench-bot`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` @@ -30,7 +30,7 @@ // pallet // --wasm-execution=compiled // --pallet -// * +// pallet_omnipool_liquidity_mining // --extrinsic // * // --heap-pages @@ -41,7 +41,7 @@ // 20 // --template=scripts/pallet-weight-template.hbs // --output -// weights/ +// ol.rs #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -71,13 +71,26 @@ impl pallet_omnipool_liquidity_mining::WeightInfo for H // Proof Size summary in bytes: // Measured: `557` // Estimated: `6196` - // Minimum execution time: 80_933_000 picoseconds. - Weight::from_parts(81_673_000, 6196) + // Minimum execution time: 83_911_000 picoseconds. + Weight::from_parts(84_650_000, 6196) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `OmnipoolWarehouseLM::GlobalFarm` (r:1 w:1) /// Proof: `OmnipoolWarehouseLM::GlobalFarm` (`max_values`: None, `max_size`: Some(205), added: 2680, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn update_global_farm() -> Weight { + // Proof Size summary in bytes: + // Measured: `573` + // Estimated: `3670` + // Minimum execution time: 22_855_000 picoseconds. + Weight::from_parts(23_088_000, 3670) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `OmnipoolWarehouseLM::GlobalFarm` (r:1 w:1) + /// Proof: `OmnipoolWarehouseLM::GlobalFarm` (`max_values`: None, `max_size`: Some(205), added: 2680, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:2 w:2) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `Duster::AccountBlacklist` (r:1 w:1) @@ -86,8 +99,8 @@ impl pallet_omnipool_liquidity_mining::WeightInfo for H // Proof Size summary in bytes: // Measured: `964` // Estimated: `6196` - // Minimum execution time: 79_070_000 picoseconds. - Weight::from_parts(79_648_000, 6196) + // Minimum execution time: 82_043_000 picoseconds. + Weight::from_parts(82_866_000, 6196) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -111,8 +124,8 @@ impl pallet_omnipool_liquidity_mining::WeightInfo for H // Proof Size summary in bytes: // Measured: `2337` // Estimated: `6294` - // Minimum execution time: 123_093_000 picoseconds. - Weight::from_parts(124_230_000, 6294) + // Minimum execution time: 126_484_000 picoseconds. + Weight::from_parts(127_302_000, 6294) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -134,8 +147,8 @@ impl pallet_omnipool_liquidity_mining::WeightInfo for H // Proof Size summary in bytes: // Measured: `2507` // Estimated: `6294` - // Minimum execution time: 126_053_000 picoseconds. - Weight::from_parts(127_134_000, 6294) + // Minimum execution time: 129_979_000 picoseconds. + Weight::from_parts(130_956_000, 6294) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -155,8 +168,8 @@ impl pallet_omnipool_liquidity_mining::WeightInfo for H // Proof Size summary in bytes: // Measured: `2146` // Estimated: `6294` - // Minimum execution time: 120_037_000 picoseconds. - Weight::from_parts(120_995_000, 6294) + // Minimum execution time: 124_701_000 picoseconds. + Weight::from_parts(125_711_000, 6294) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -178,8 +191,8 @@ impl pallet_omnipool_liquidity_mining::WeightInfo for H // Proof Size summary in bytes: // Measured: `2543` // Estimated: `6294` - // Minimum execution time: 124_191_000 picoseconds. - Weight::from_parts(124_920_000, 6294) + // Minimum execution time: 127_337_000 picoseconds. + Weight::from_parts(128_237_000, 6294) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -195,8 +208,8 @@ impl pallet_omnipool_liquidity_mining::WeightInfo for H // Proof Size summary in bytes: // Measured: `924` // Estimated: `6196` - // Minimum execution time: 75_542_000 picoseconds. - Weight::from_parts(75_959_000, 6196) + // Minimum execution time: 77_685_000 picoseconds. + Weight::from_parts(78_427_000, 6196) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -234,8 +247,8 @@ impl pallet_omnipool_liquidity_mining::WeightInfo for H // Proof Size summary in bytes: // Measured: `4072` // Estimated: `11598` - // Minimum execution time: 207_096_000 picoseconds. - Weight::from_parts(208_255_000, 11598) + // Minimum execution time: 213_332_000 picoseconds. + Weight::from_parts(215_220_000, 11598) .saturating_add(T::DbWeight::get().reads(17_u64)) .saturating_add(T::DbWeight::get().writes(14_u64)) } @@ -263,8 +276,8 @@ impl pallet_omnipool_liquidity_mining::WeightInfo for H // Proof Size summary in bytes: // Measured: `4381` // Estimated: `11598` - // Minimum execution time: 171_971_000 picoseconds. - Weight::from_parts(173_516_000, 11598) + // Minimum execution time: 177_225_000 picoseconds. + Weight::from_parts(178_486_000, 11598) .saturating_add(T::DbWeight::get().reads(15_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -286,8 +299,8 @@ impl pallet_omnipool_liquidity_mining::WeightInfo for H // Proof Size summary in bytes: // Measured: `2946` // Estimated: `8799` - // Minimum execution time: 165_734_000 picoseconds. - Weight::from_parts(167_004_000, 8799) + // Minimum execution time: 176_191_000 picoseconds. + Weight::from_parts(177_601_000, 8799) .saturating_add(T::DbWeight::get().reads(10_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -319,8 +332,8 @@ impl pallet_omnipool_liquidity_mining::WeightInfo for H // Proof Size summary in bytes: // Measured: `3940` // Estimated: `8799` - // Minimum execution time: 250_173_000 picoseconds. - Weight::from_parts(251_222_000, 8799) + // Minimum execution time: 260_267_000 picoseconds. + Weight::from_parts(263_572_000, 8799) .saturating_add(T::DbWeight::get().reads(15_u64)) .saturating_add(T::DbWeight::get().writes(15_u64)) } From 4265f1209955efa9c18147655b2656f3c537ae9c Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 10:38:19 +0200 Subject: [PATCH 22/37] make clippy happy --- pallets/liquidity-mining/src/tests/invariants.rs | 16 ---------------- pallets/omnipool-liquidity-mining/src/weights.rs | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index be291698d..a9e13b2fe 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -912,22 +912,6 @@ fn percentage() -> impl Strategy { fn min_deposit() -> impl Strategy { 1000..10000000u128 } -fn min_deposit2() -> impl Strategy { - 1000..10_000u128 -} - -//Number of blocks added to current block number in each test case run. This number should be -//reasonable smaller than total of runned test to make sure lot of claims is executed and -//multiple claims for same deposit to happen. -fn blocks_offset_range() -> impl Strategy { - 1..10u64 -} - -//Index of deposit in `deposit` vec. This idx is used in each test case run and execute claim -//if deposit exits -fn deposit_idx_range() -> impl Strategy { - 0..500_usize -} #[test] //Update global farm for invariant one diff --git a/pallets/omnipool-liquidity-mining/src/weights.rs b/pallets/omnipool-liquidity-mining/src/weights.rs index b145e46ee..8b0265865 100644 --- a/pallets/omnipool-liquidity-mining/src/weights.rs +++ b/pallets/omnipool-liquidity-mining/src/weights.rs @@ -55,6 +55,7 @@ use sp_std::marker::PhantomData; /// Weight functions needed for pallet_omnipool_liquidity_mining. pub trait WeightInfo { fn create_global_farm() -> Weight; + fn update_global_farm() -> Weight; fn terminate_global_farm() -> Weight; fn create_yield_farm() -> Weight; fn update_yield_farm() -> Weight; @@ -88,6 +89,21 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } + + /// Storage: `OmnipoolWarehouseLM::GlobalFarm` (r:1 w:1) + /// Proof: `OmnipoolWarehouseLM::GlobalFarm` (`max_values`: None, `max_size`: Some(205), added: 2680, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:0) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) + fn update_global_farm() -> Weight { + // Proof Size summary in bytes: + // Measured: `573` + // Estimated: `3670` + // Minimum execution time: 22_855_000 picoseconds. + Weight::from_parts(23_088_000, 3670) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `OmnipoolWarehouseLM::GlobalFarm` (r:1 w:1) /// Proof: `OmnipoolWarehouseLM::GlobalFarm` (`max_values`: None, `max_size`: Some(205), added: 2680, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:2 w:2) From 4cf5816f17a5a967d80ce4646db9472983d2911f Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 10:42:45 +0200 Subject: [PATCH 23/37] fix integration test --- integration-tests/src/omnipool_liquidity_mining.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/integration-tests/src/omnipool_liquidity_mining.rs b/integration-tests/src/omnipool_liquidity_mining.rs index 852c04b3b..3a68f404c 100644 --- a/integration-tests/src/omnipool_liquidity_mining.rs +++ b/integration-tests/src/omnipool_liquidity_mining.rs @@ -1302,7 +1302,7 @@ fn claim_rewards_should_work_when_farm_is_updated() { CHARLIE.into() ); - set_relaychain_block_number(400); + set_relaychain_block_number(550); let deposit_id_2 = 2; assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::deposit_shares( RuntimeOrigin::signed(CHARLIE.into()), @@ -1346,9 +1346,9 @@ fn claim_rewards_should_work_when_farm_is_updated() { charlie_new_hdx_balance_after_first_claim > charlie_hdx_balance_0, "Charlie's balance should be increased" ); - assert_eq!(charlie_new_hdx_balance_after_first_claim, 1000136935112266); + assert_eq!(charlie_new_hdx_balance_after_first_claim, 1000030740535405); - //Act 3 - claim rewards for differnt yield-farm-entry in the same period should work. + //Act 2 - claim rewards for differnt yield-farm-entry in the same period should work. assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::claim_rewards( RuntimeOrigin::signed(CHARLIE.into()), deposit_id, @@ -1362,7 +1362,7 @@ fn claim_rewards_should_work_when_farm_is_updated() { charlie_new_hdx_balance_after_2nd_claim > charlie_new_hdx_balance_after_first_claim, "Charlie's balance should be increased" ); - assert_eq!(charlie_new_hdx_balance_after_2nd_claim, 1000137314927403); + assert_eq!(charlie_new_hdx_balance_after_2nd_claim, 1000031130694537); }); } From 48e420089f5da9b78860949a9442cecbfb898108 Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 10:43:09 +0200 Subject: [PATCH 24/37] formatting --- pallets/liquidity-mining/src/tests/invariants.rs | 7 +++++-- .../src/tests/update_global_farm.rs | 16 +++++++--------- pallets/xyk-liquidity-mining/src/tests/mock.rs | 7 ++++++- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index a9e13b2fe..ed819035b 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -962,7 +962,7 @@ fn update_global_farm_invariant_1() { yield_per_period, 1_000, ) - .unwrap(); + .unwrap(); TransactionOutcome::Commit(DispatchResult::Ok(())) }); let g_farm = LiquidityMining::global_farm(d.global_farm_id).unwrap(); @@ -1010,7 +1010,10 @@ fn update_global_farm_invariant_1() { + distributed_before_update.borrow()[gf.id as usize]; //NOTE: Approax becasue of div in max_reward_per_period calculation. - assert!(gf.total_rewards >= s_1, "total_rewards >= distributed + max_reward_per_period * planned_yielding_periods"); + assert!( + gf.total_rewards >= s_1, + "total_rewards >= distributed + max_reward_per_period * planned_yielding_periods" + ); assert_eq_approx!( gf.total_rewards, s_1, diff --git a/pallets/omnipool-liquidity-mining/src/tests/update_global_farm.rs b/pallets/omnipool-liquidity-mining/src/tests/update_global_farm.rs index f5ed5f9f2..1f0a0a6a1 100644 --- a/pallets/omnipool-liquidity-mining/src/tests/update_global_farm.rs +++ b/pallets/omnipool-liquidity-mining/src/tests/update_global_farm.rs @@ -50,15 +50,13 @@ fn update_global_farm_should_work() { let min_deposit = 20_000; //Act - assert_ok!( - OmnipoolMining::update_global_farm( - RuntimeOrigin::root(), - global_farm_id, - planned_yielding_periods, - yield_per_period, - min_deposit, - ), - ); + assert_ok!(OmnipoolMining::update_global_farm( + RuntimeOrigin::root(), + global_farm_id, + planned_yielding_periods, + yield_per_period, + min_deposit, + ),); //Assert assert_last_event!(crate::Event::GlobalFarmUpdated { diff --git a/pallets/xyk-liquidity-mining/src/tests/mock.rs b/pallets/xyk-liquidity-mining/src/tests/mock.rs index 5cb63db8c..914ddb45b 100644 --- a/pallets/xyk-liquidity-mining/src/tests/mock.rs +++ b/pallets/xyk-liquidity-mining/src/tests/mock.rs @@ -813,7 +813,12 @@ impl hydradx_traits::liquidity_mining::Mutate f Err(sp_runtime::DispatchError::Other("Not implemented")) } - fn update_global_farm(global_farm_id: GlobalFarmId, planned_yielding_periods: Self::Period, yield_per_period: Perquintill, min_deposit: Self::Balance) -> Result<(), Self::Error> { + fn update_global_farm( + global_farm_id: GlobalFarmId, + planned_yielding_periods: Self::Period, + yield_per_period: Perquintill, + min_deposit: Self::Balance, + ) -> Result<(), Self::Error> { GLOBAL_FARMS.with(|v| { let mut p = v.borrow_mut(); From 86cf9e595935a892a5a423fe5c8cff996445496a Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 10:46:06 +0200 Subject: [PATCH 25/37] bump versions --- Cargo.lock | 10 +++++----- integration-tests/Cargo.toml | 2 +- pallets/liquidity-mining/Cargo.toml | 2 +- pallets/omnipool-liquidity-mining/Cargo.toml | 2 +- pallets/xyk-liquidity-mining/Cargo.toml | 2 +- traits/Cargo.toml | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d9baf8680..3711d9ecf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5073,7 +5073,7 @@ dependencies = [ [[package]] name = "hydradx-traits" -version = "3.5.0" +version = "3.6.0" dependencies = [ "frame-support", "impl-trait-for-tuples", @@ -8469,7 +8469,7 @@ dependencies = [ [[package]] name = "pallet-liquidity-mining" -version = "4.3.4" +version = "4.4.0" dependencies = [ "fixed", "frame-support", @@ -8719,7 +8719,7 @@ dependencies = [ [[package]] name = "pallet-omnipool-liquidity-mining" -version = "2.1.8" +version = "2.2.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -9450,7 +9450,7 @@ dependencies = [ [[package]] name = "pallet-xyk-liquidity-mining" -version = "1.1.11" +version = "1.1.12" dependencies = [ "frame-support", "frame-system", @@ -11929,7 +11929,7 @@ dependencies = [ [[package]] name = "runtime-integration-tests" -version = "1.23.3" +version = "1.23.4" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 2d816ba0a..c5a291a12 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "runtime-integration-tests" -version = "1.23.3" +version = "1.23.4" description = "Integration tests" authors = ["GalacticCouncil"] edition = "2021" diff --git a/pallets/liquidity-mining/Cargo.toml b/pallets/liquidity-mining/Cargo.toml index 567b9ed39..25fd7c2bc 100644 --- a/pallets/liquidity-mining/Cargo.toml +++ b/pallets/liquidity-mining/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-liquidity-mining" -version = "4.3.4" +version = "4.4.0" description = "Liquidity mining" authors = ["GalacticCouncil"] edition = "2021" diff --git a/pallets/omnipool-liquidity-mining/Cargo.toml b/pallets/omnipool-liquidity-mining/Cargo.toml index 67ea84795..e90e2ac97 100644 --- a/pallets/omnipool-liquidity-mining/Cargo.toml +++ b/pallets/omnipool-liquidity-mining/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-omnipool-liquidity-mining" -version = "2.1.8" +version = "2.2.0" authors = ['GalacticCouncil'] edition = "2021" license = "Apache-2.0" diff --git a/pallets/xyk-liquidity-mining/Cargo.toml b/pallets/xyk-liquidity-mining/Cargo.toml index caac8a418..2e09a71d6 100644 --- a/pallets/xyk-liquidity-mining/Cargo.toml +++ b/pallets/xyk-liquidity-mining/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-xyk-liquidity-mining" -version = "1.1.11" +version = "1.1.12" description = "Liquidity mining" authors = ["GalacticCouncil"] edition = "2021" diff --git a/traits/Cargo.toml b/traits/Cargo.toml index 2a08d0e31..e815c38ba 100644 --- a/traits/Cargo.toml +++ b/traits/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hydradx-traits" -version = "3.5.0" +version = "3.6.0" description = "Shared traits" authors = ["GalacticCouncil"] edition = "2021" From b2986ee2b66ecb609f736a74f027890f4d964e7f Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 10:46:42 +0200 Subject: [PATCH 26/37] bump main version --- Cargo.lock | 2 +- runtime/hydradx/Cargo.toml | 2 +- runtime/hydradx/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3711d9ecf..4b882fa1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4938,7 +4938,7 @@ dependencies = [ [[package]] name = "hydradx-runtime" -version = "256.0.0" +version = "257.0.0" dependencies = [ "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", diff --git a/runtime/hydradx/Cargo.toml b/runtime/hydradx/Cargo.toml index 285bfed06..cc8c89077 100644 --- a/runtime/hydradx/Cargo.toml +++ b/runtime/hydradx/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hydradx-runtime" -version = "256.0.0" +version = "257.0.0" authors = ["GalacticCouncil"] edition = "2021" license = "Apache 2.0" diff --git a/runtime/hydradx/src/lib.rs b/runtime/hydradx/src/lib.rs index 8e5c13482..601894f5f 100644 --- a/runtime/hydradx/src/lib.rs +++ b/runtime/hydradx/src/lib.rs @@ -113,7 +113,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("hydradx"), impl_name: create_runtime_str!("hydradx"), authoring_version: 1, - spec_version: 256, + spec_version: 257, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, From a48e3787705561381f7baa1b0529e8df320de04d Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 10:51:19 +0200 Subject: [PATCH 27/37] remove unnecessary comments --- pallets/liquidity-mining/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/pallets/liquidity-mining/src/lib.rs b/pallets/liquidity-mining/src/lib.rs index b9d02e17b..3123586c5 100644 --- a/pallets/liquidity-mining/src/lib.rs +++ b/pallets/liquidity-mining/src/lib.rs @@ -595,7 +595,6 @@ impl, I: 'static> Pallet { ensure!(global_farm.state.is_active(), Error::::GlobalFarmNotFound); - //Sync global farm to get right accumulated_rpz and pending rewards let current_period = Self::get_current_period(global_farm.blocks_per_period)?; Self::sync_global_farm(global_farm, current_period)?; @@ -612,7 +611,6 @@ impl, I: 'static> Pallet { Error::::InvalidPlannedYieldingPeriods ); - //Update global farm fields global_farm.planned_yielding_periods = planned_yielding_periods; global_farm.yield_per_period = yield_per_period; global_farm.min_deposit = min_deposit; From 26b709413a367a107a8d8809a9a5bac7738d9545 Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 12:29:17 +0200 Subject: [PATCH 28/37] remove unnecessary arb_deposit2 --- pallets/liquidity-mining/src/tests/invariants.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index ed819035b..5102e3549 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -506,20 +506,6 @@ prop_compose! { } } -prop_compose! { - fn arb_deposit2()( - shares in 1_000 * ONE..1_000_000 * ONE, - valued_shares in 10_001..10_000_000 * ONE, - g_idx in 0..3_usize, - y_idx in 0..2_usize, - ) -> Deposit { - let g_farm = G_FARMS.with(|v| v.borrow()[g_idx].clone()); - let y_farm = &g_farm.yield_farms[y_idx]; - - Deposit {global_farm_id: g_farm.id,yield_farm_id: y_farm.0, amm_pool_id: y_farm.1, shares, valued_shares} - } -} - #[test] //https://www.notion.so/Liquidity-mining-spec-b30ccfe470a74173b82c3702b1e8fca1#87868f45e4d04ecb92374c5f795a493d // @@ -943,7 +929,7 @@ fn update_global_farm_invariant_1() { runner .run( &( - arb_deposit2(), + arb_deposit(), blocks_offset_range, deposit_idx_range, planned_yielding_periods(), From dbf689865435891a3a36f3ec48fa800a55c0815a Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 12:30:38 +0200 Subject: [PATCH 29/37] fix invariant test name --- pallets/liquidity-mining/src/tests/invariants.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index 5102e3549..b982b09ae 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -919,7 +919,7 @@ fn update_global_farm_invariant_1() { let mut runner = TestRunner::new(Config { cases: successfull_cases, source_file: Some("liquidity-mining/src/tests/invariants.rs"), - test_name: Some("update_global_farm_invariant_first"), + test_name: Some("update_global_farm_invariant_1"), ..Config::default() }); let deposits: RefCell> = RefCell::new(Vec::new()); @@ -952,6 +952,7 @@ fn update_global_farm_invariant_1() { TransactionOutcome::Commit(DispatchResult::Ok(())) }); let g_farm = LiquidityMining::global_farm(d.global_farm_id).unwrap(); + //NOTE: `update_global_farm()` distributes rewards before update so this must be done after function execution but before any interaction with farm. distributed_before_update.borrow_mut()[d.global_farm_id as usize] = g_farm.accumulated_paid_rewards + g_farm.pending_rewards; From 5fcbaf956db3785d8d9f5601b0311a84a7deef10 Mon Sep 17 00:00:00 2001 From: Daniel Moka Date: Wed, 18 Sep 2024 12:30:53 +0200 Subject: [PATCH 30/37] Update pallets/liquidity-mining/src/tests/invariants.rs Co-authored-by: martin fridrich --- pallets/liquidity-mining/src/tests/invariants.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index b982b09ae..f740f0e06 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -996,11 +996,11 @@ fn update_global_farm_invariant_1() { let s_1: u128 = g_farm_1.max_reward_per_period * g_farm_1.planned_yielding_periods as u128 + distributed_before_update.borrow()[gf.id as usize]; - //NOTE: Approax becasue of div in max_reward_per_period calculation. assert!( gf.total_rewards >= s_1, "total_rewards >= distributed + max_reward_per_period * planned_yielding_periods" ); + //NOTE: Approax becasue of div in max_reward_per_period calculation. assert_eq_approx!( gf.total_rewards, s_1, From 003d81c218342492d75e6ac69f59e5aaf21c124e Mon Sep 17 00:00:00 2001 From: Daniel Moka Date: Wed, 18 Sep 2024 12:31:30 +0200 Subject: [PATCH 31/37] Update pallets/omnipool-liquidity-mining/src/lib.rs Co-authored-by: martin fridrich --- pallets/omnipool-liquidity-mining/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/omnipool-liquidity-mining/src/lib.rs b/pallets/omnipool-liquidity-mining/src/lib.rs index e7377cd60..dbee10206 100644 --- a/pallets/omnipool-liquidity-mining/src/lib.rs +++ b/pallets/omnipool-liquidity-mining/src/lib.rs @@ -902,7 +902,7 @@ pub mod pallet { /// /// Emits `GlobalFarmUpdated` event when successful. #[pallet::call_index(12)] - #[pallet::weight(::WeightInfo::create_global_farm())] + #[pallet::weight(::WeightInfo::update_global_farm())] pub fn update_global_farm( origin: OriginFor, global_farm_id: GlobalFarmId, From 0103f6ceafe7af39a3b1f86382bda79e3411259f Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 12:35:10 +0200 Subject: [PATCH 32/37] fix invariant 3 assertions as it was not invariant 3, but 2 --- .../liquidity-mining/src/tests/invariants.rs | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index f740f0e06..cbeee1a3a 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -1018,10 +1018,10 @@ fn update_global_farm_invariant_1() { } #[test] -//Update global farm for invariants 1,2,3 +//Update global farm for invariants 2,3 //https://www.notion.so/Liquidity-mining-spec-b30ccfe470a74173b82c3702b1e8fca1#422dea2e23744859baeb704dbdb3caca // -fn update_global_farm_invariant_1_2_3() { +fn update_global_farm_invariant_2_3() { //Number of sucessfull test cases that must execute for the test as a whole to pass. let successfull_cases = 1_000; //Number of blocks added to current block number in each test case run. This number should be @@ -1138,43 +1138,43 @@ fn update_global_farm_invariant_1_2_3() { //INVARIANT 3 //Calculate necessary values and assert - let (total_rewards_sum, farm_balances_sum, pot_balance_sum) = G_FARMS.with(|v| { - let mut total_rewards_sum = 0_u128; - let mut farm_balances_sum = 0_u128; - let mut pot_balance_sum = 0_u128; - let mut already_summed_balances: Vec = Vec::new(); - - v.borrow().clone().into_iter().for_each(|gf| { - farm_balances_sum += Tokens::free_balance( - gf.reward_currency, - &LiquidityMining::farm_account_id(gf.id).unwrap(), - ); - - total_rewards_sum += gf.total_rewards; - - if !already_summed_balances.contains(&gf.reward_currency) { - pot_balance_sum += Tokens::total_balance(gf.reward_currency, &pot); - already_summed_balances.push(gf.reward_currency); - } - }); - (total_rewards_sum, farm_balances_sum, pot_balance_sum) - }); - let last_deposit_id = LiquidityMining::deposit_id(); - let mut claimed_by_users_sum = 0_u128; + let mut claimed_by_user_per_yield_farm: HashMap<(GlobalFarmId, YieldFarmId), u128> = HashMap::new(); for i in 1..=last_deposit_id { let d = LiquidityMining::deposit(i).unwrap(); let claimed_amount = d.yield_farm_entries[0].accumulated_claimed_rewards; - claimed_by_users_sum += claimed_amount; + let global_farm_id = d.yield_farm_entries[0].global_farm_id; + let yield_farm_id = d.yield_farm_entries[0].yield_farm_id; + *claimed_by_user_per_yield_farm + .entry((global_farm_id, yield_farm_id)) + .or_insert(0) += claimed_amount; } - //WARN: There is no room for rounding errors in this invariant. Any discrepancy - //in this assert means we are loosing tokens somewhere. - assert_eq!( - total_rewards_sum, - farm_balances_sum + pot_balance_sum + claimed_by_users_sum, - ); + G_FARMS.with(|v| { + v.borrow().clone().into_iter().for_each(|gf| { + let g_farm = LiquidityMining::global_farm(gf.id).unwrap(); + let mut y_farms_let_to_distribute_sum = 0_u128; + + let mut claimed_by_yield_farms_in_global_farm = 0_u128; + gf.yield_farms.iter().for_each(|yf| { + y_farms_let_to_distribute_sum += LiquidityMining::yield_farm((yf.1, gf.id, yf.0)) + .unwrap() + .left_to_distribute; + + //NOTE this run for each iteration of test so record in HashMap may + //not exists if deposit doesn't exists yet. + claimed_by_yield_farms_in_global_farm += + claimed_by_user_per_yield_farm.get(&(gf.id, yf.0)).unwrap_or(&0_u128); + }); + + assert_eq!( + g_farm.accumulated_paid_rewards, + y_farms_let_to_distribute_sum + claimed_by_yield_farms_in_global_farm + ); + }) + }); + Ok(()) }, From a7248358f0c8ea1ba5ae9a0381ddc24b27de4289 Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 12:49:06 +0200 Subject: [PATCH 33/37] add unit test for claiming after update --- .../src/tests/update_global_farm.rs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/pallets/liquidity-mining/src/tests/update_global_farm.rs b/pallets/liquidity-mining/src/tests/update_global_farm.rs index caa0da2c5..5b4e5c31b 100644 --- a/pallets/liquidity-mining/src/tests/update_global_farm.rs +++ b/pallets/liquidity-mining/src/tests/update_global_farm.rs @@ -304,3 +304,41 @@ fn update_global_farm_should_fail_when_yield_period_is_zero() { }); }); } + +#[test] +fn claim_rewards_should_work_after_claiming_rewards() { + predefined_test_ext_with_deposits().execute_with(|| { + let _ = with_transaction(|| { + //Arrange + let planned_yielding_periods: BlockNumber = 1_000u64; + let yield_per_period = Perquintill::from_percent(20); + let min_deposit = 20_000; + + set_block_number(100_000); + + //Act + assert_ok!(LiquidityMining::update_global_farm( + GC_FARM, + planned_yielding_periods, + yield_per_period, + min_deposit, + )); + + set_block_number(1_000_000); + + //Assert + assert_eq!( + LiquidityMining::claim_rewards( + ALICE, + PREDEFINED_DEPOSIT_IDS[0], + GC_BSX_TKN1_YIELD_FARM_ID, + false + ) + .unwrap(), + (GC_FARM, BSX, 28495477087879389002, 142022912120610998) + ); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); +} \ No newline at end of file From c3861760fbad42a81da67873f737dc9d4c7eff91 Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 12:56:43 +0200 Subject: [PATCH 34/37] bump patch versions --- Cargo.lock | 4 ++-- pallets/omnipool/Cargo.toml | 2 +- pallets/xyk/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b882fa1d..c64490657 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8692,7 +8692,7 @@ dependencies = [ [[package]] name = "pallet-omnipool" -version = "4.3.2" +version = "4.3.3" dependencies = [ "bitflags 1.3.2", "frame-benchmarking", @@ -9424,7 +9424,7 @@ dependencies = [ [[package]] name = "pallet-xyk" -version = "6.4.4" +version = "6.4.5" dependencies = [ "frame-benchmarking", "frame-support", diff --git a/pallets/omnipool/Cargo.toml b/pallets/omnipool/Cargo.toml index ec37db74f..d7307ad76 100644 --- a/pallets/omnipool/Cargo.toml +++ b/pallets/omnipool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-omnipool" -version = "4.3.2" +version = "4.3.3" authors = ['GalacticCouncil'] edition = "2021" license = "Apache-2.0" diff --git a/pallets/xyk/Cargo.toml b/pallets/xyk/Cargo.toml index 99c415ede..cc43a5eb1 100644 --- a/pallets/xyk/Cargo.toml +++ b/pallets/xyk/Cargo.toml @@ -1,6 +1,6 @@ [package] name = 'pallet-xyk' -version = "6.4.4" +version = "6.4.5" description = 'XYK automated market maker' authors = ['GalacticCouncil'] edition = '2021' From 316f374da62b094779da9ae028a09aff201fb4ef Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 12:57:27 +0200 Subject: [PATCH 35/37] fix test name --- pallets/liquidity-mining/src/tests/invariants.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index cbeee1a3a..e8714483f 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -1037,7 +1037,7 @@ fn update_global_farm_invariant_2_3() { let mut runner = TestRunner::new(Config { cases: successfull_cases, source_file: Some("liquidity-mining/src/tests/invariants.rs"), - test_name: Some("update_global_farm_invariant_1_2_3"), + test_name: Some("update_global_farm_invariant_2_3"), ..Config::default() }); let deposits: RefCell> = RefCell::new(Vec::new()); From 84a86bbb05aae9b44f3b23706c72a6b6f9853afa Mon Sep 17 00:00:00 2001 From: dmoka Date: Wed, 18 Sep 2024 13:03:11 +0200 Subject: [PATCH 36/37] formatting --- pallets/liquidity-mining/src/tests/invariants.rs | 1 - pallets/liquidity-mining/src/tests/update_global_farm.rs | 9 ++------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/pallets/liquidity-mining/src/tests/invariants.rs b/pallets/liquidity-mining/src/tests/invariants.rs index e8714483f..16390df59 100644 --- a/pallets/liquidity-mining/src/tests/invariants.rs +++ b/pallets/liquidity-mining/src/tests/invariants.rs @@ -1175,7 +1175,6 @@ fn update_global_farm_invariant_2_3() { }) }); - Ok(()) }, ) diff --git a/pallets/liquidity-mining/src/tests/update_global_farm.rs b/pallets/liquidity-mining/src/tests/update_global_farm.rs index 5b4e5c31b..2362a5173 100644 --- a/pallets/liquidity-mining/src/tests/update_global_farm.rs +++ b/pallets/liquidity-mining/src/tests/update_global_farm.rs @@ -328,12 +328,7 @@ fn claim_rewards_should_work_after_claiming_rewards() { //Assert assert_eq!( - LiquidityMining::claim_rewards( - ALICE, - PREDEFINED_DEPOSIT_IDS[0], - GC_BSX_TKN1_YIELD_FARM_ID, - false - ) + LiquidityMining::claim_rewards(ALICE, PREDEFINED_DEPOSIT_IDS[0], GC_BSX_TKN1_YIELD_FARM_ID, false) .unwrap(), (GC_FARM, BSX, 28495477087879389002, 142022912120610998) ); @@ -341,4 +336,4 @@ fn claim_rewards_should_work_after_claiming_rewards() { TransactionOutcome::Commit(DispatchResult::Ok(())) }); }); -} \ No newline at end of file +} From d890ed58fe698f00558c3ba0e913198de4151b3b Mon Sep 17 00:00:00 2001 From: martinfridrich Date: Wed, 18 Sep 2024 15:02:41 +0200 Subject: [PATCH 37/37] rename and move claim rewards after global farm update test --- .../src/tests/claim_rewards.rs | 33 +++++++++++++++++++ .../src/tests/update_global_farm.rs | 33 ------------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/pallets/liquidity-mining/src/tests/claim_rewards.rs b/pallets/liquidity-mining/src/tests/claim_rewards.rs index 28cb85db8..40b06970b 100644 --- a/pallets/liquidity-mining/src/tests/claim_rewards.rs +++ b/pallets/liquidity-mining/src/tests/claim_rewards.rs @@ -1263,3 +1263,36 @@ fn claim_rewards_should_claim_correct_amount_when_yield_was_resumed_multiple_tim }); }); } + +#[test] +fn claim_rewards_should_work_when_global_farm_was_updated() { + predefined_test_ext_with_deposits().execute_with(|| { + let _ = with_transaction(|| { + //Arrange + let planned_yielding_periods: BlockNumber = 1_000u64; + let yield_per_period = Perquintill::from_percent(20); + let min_deposit = 20_000; + + set_block_number(100_000); + + //Act + assert_ok!(LiquidityMining::update_global_farm( + GC_FARM, + planned_yielding_periods, + yield_per_period, + min_deposit, + )); + + set_block_number(1_000_000); + + //Assert + assert_eq!( + LiquidityMining::claim_rewards(ALICE, PREDEFINED_DEPOSIT_IDS[0], GC_BSX_TKN1_YIELD_FARM_ID, false) + .unwrap(), + (GC_FARM, BSX, 28495477087879389002, 142022912120610998) + ); + + TransactionOutcome::Commit(DispatchResult::Ok(())) + }); + }); +} diff --git a/pallets/liquidity-mining/src/tests/update_global_farm.rs b/pallets/liquidity-mining/src/tests/update_global_farm.rs index 2362a5173..caa0da2c5 100644 --- a/pallets/liquidity-mining/src/tests/update_global_farm.rs +++ b/pallets/liquidity-mining/src/tests/update_global_farm.rs @@ -304,36 +304,3 @@ fn update_global_farm_should_fail_when_yield_period_is_zero() { }); }); } - -#[test] -fn claim_rewards_should_work_after_claiming_rewards() { - predefined_test_ext_with_deposits().execute_with(|| { - let _ = with_transaction(|| { - //Arrange - let planned_yielding_periods: BlockNumber = 1_000u64; - let yield_per_period = Perquintill::from_percent(20); - let min_deposit = 20_000; - - set_block_number(100_000); - - //Act - assert_ok!(LiquidityMining::update_global_farm( - GC_FARM, - planned_yielding_periods, - yield_per_period, - min_deposit, - )); - - set_block_number(1_000_000); - - //Assert - assert_eq!( - LiquidityMining::claim_rewards(ALICE, PREDEFINED_DEPOSIT_IDS[0], GC_BSX_TKN1_YIELD_FARM_ID, false) - .unwrap(), - (GC_FARM, BSX, 28495477087879389002, 142022912120610998) - ); - - TransactionOutcome::Commit(DispatchResult::Ok(())) - }); - }); -}