Skip to content

Commit

Permalink
Merge pull request #904 from galacticcouncil/feat/update-global-farm
Browse files Browse the repository at this point in the history
feat: update global farm
  • Loading branch information
mrq1911 authored Sep 18, 2024
2 parents 75a3e25 + d890ed5 commit c32d963
Show file tree
Hide file tree
Showing 25 changed files with 1,279 additions and 52 deletions.
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "runtime-integration-tests"
version = "1.23.3"
version = "1.23.4"
description = "Integration tests"
authors = ["GalacticCouncil"]
edition = "2021"
Expand Down
128 changes: 128 additions & 0 deletions integration-tests/src/omnipool_liquidity_mining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,134 @@ fn liquidity_mining_should_work_when_farm_distribute_bonds() {
});
}

#[test]
fn claim_rewards_should_work_when_farm_is_updated() {
TestNet::reset();

Hydra::execute_with(|| {
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);
set_relaychain_block_number(100);
create_global_farm(None, None);

set_relaychain_block_number(200);
create_yield_farm(global_farm_1_id, ETH);
create_yield_farm(global_farm_1_id, DOT);

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);
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(550);
let deposit_id_2 = 2;
assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::deposit_shares(
RuntimeOrigin::signed(CHARLIE.into()),
global_farm_1_id,
yield_farm_2_id,
position_id
));

//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_1_id,
planned_yielding_periods,
yield_per_period,
min_deposit
));
//Assert
let g_farm =
warehouse_liquidity_mining::GlobalFarm::<hydradx_runtime::Runtime, Instance1>::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, 1000030740535405);

//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,
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, 1000031130694537);
});
}

pub fn expect_reward_claimed_events(e: Vec<RuntimeEvent>) {
let last_events = test_utils::last_events::<hydradx_runtime::RuntimeEvent, hydradx_runtime::Runtime>(10);

Expand Down
2 changes: 1 addition & 1 deletion pallets/liquidity-mining/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pallet-liquidity-mining"
version = "4.3.4"
version = "4.4.0"
description = "Liquidity mining"
authors = ["GalacticCouncil"]
edition = "2021"
Expand Down
60 changes: 60 additions & 0 deletions pallets/liquidity-mining/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,57 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
})
}

/// 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<T>,
yield_per_period: Perquintill,
min_deposit: Balance,
) -> Result<(), DispatchError> {
ensure!(min_deposit.ge(&MIN_DEPOSIT), Error::<T, I>::InvalidMinDeposit);
ensure!(
planned_yielding_periods >= T::MinPlannedYieldingPeriods::get(),
Error::<T, I>::InvalidPlannedYieldingPeriods
);
ensure!(!yield_per_period.is_zero(), Error::<T, I>::InvalidYieldPerPeriod);

<GlobalFarm<T, I>>::try_mutate(global_farm_id, |maybe_global_farm| {
let global_farm = maybe_global_farm.as_mut().ok_or(Error::<T, I>::GlobalFarmNotFound)?;

ensure!(global_farm.state.is_active(), Error::<T, I>::GlobalFarmNotFound);

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 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::<u128>::try_into(planned_yielding_periods).map_err(|_| ArithmeticError::Overflow)?;
let new_max_reward_period = total_rewards
.checked_div(planned_periods)
.ok_or(Error::<T, I>::InvalidPlannedYieldingPeriods)?;
ensure!(
!new_max_reward_period.is_zero(),
Error::<T, I>::InvalidPlannedYieldingPeriods
);

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`).
///
Expand Down Expand Up @@ -1816,6 +1867,15 @@ impl<T: Config<I>, I: 'static> hydradx_traits::liquidity_mining::Mutate<T::Accou
Self::update_global_farm_price_adjustment(who, global_farm_id, price_adjustment)
}

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)
}

fn terminate_global_farm(
who: T::AccountId,
global_farm_id: u32,
Expand Down
33 changes: 33 additions & 0 deletions pallets/liquidity-mining/src/tests/claim_rewards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(()))
});
});
}
Loading

0 comments on commit c32d963

Please sign in to comment.