Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update global farm #904

Merged
merged 38 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
9ee0414
add init implementation for update global farm
dmoka Sep 11, 2024
23ff445
add validations for update global farm params
dmoka Sep 11, 2024
b00cee4
add upate global farm to omnipool LM
dmoka Sep 11, 2024
8167b80
add doc for omni update_global_farm
dmoka Sep 11, 2024
f037aa4
added doc
dmoka Sep 11, 2024
7943ab2
fix compilation error
dmoka Sep 11, 2024
08afc61
add todo for invariant test
dmoka Sep 11, 2024
7883a83
add benchmark for update global farm
dmoka Sep 11, 2024
51fbd92
wip - add full run test
dmoka Sep 12, 2024
f86ce37
fix update faram and full run test
dmoka Sep 12, 2024
17582c8
add lp share withdraw
dmoka Sep 12, 2024
063d1e2
add redeposit to full farm test
dmoka Sep 12, 2024
7ecd04e
formatting
dmoka Sep 12, 2024
49fef60
add invariant 2-3-4 for update global farm
dmoka Sep 16, 2024
67f3d1a
add invariant test for 1st invariant
dmoka Sep 17, 2024
f2b7b5d
add integration test for updating global farm
dmoka Sep 17, 2024
9109b27
fix update_global_farm_invariant_first() invariant test
martinfridrich Sep 17, 2024
c134f2f
make update global farm integratio ntest more complex
dmoka Sep 18, 2024
8dc4277
formatting
dmoka Sep 18, 2024
e16f3f6
formatting and renaming
dmoka Sep 18, 2024
7ad67c2
Merge remote-tracking branch 'origin/master' into feat/update-global-…
dmoka Sep 18, 2024
3463031
rebench omnipool lm on ref machine
dmoka Sep 18, 2024
4265f12
make clippy happy
dmoka Sep 18, 2024
4cf5816
fix integration test
dmoka Sep 18, 2024
48e4200
formatting
dmoka Sep 18, 2024
86cf9e5
bump versions
dmoka Sep 18, 2024
b2986ee
bump main version
dmoka Sep 18, 2024
a48e378
remove unnecessary comments
dmoka Sep 18, 2024
26b7094
remove unnecessary arb_deposit2
dmoka Sep 18, 2024
dbf6898
fix invariant test name
dmoka Sep 18, 2024
5fcbaf9
Update pallets/liquidity-mining/src/tests/invariants.rs
dmoka Sep 18, 2024
003d81c
Update pallets/omnipool-liquidity-mining/src/lib.rs
dmoka Sep 18, 2024
0103f6c
fix invariant 3 assertions as it was not invariant 3, but 2
dmoka Sep 18, 2024
a724835
add unit test for claiming after update
dmoka Sep 18, 2024
c386176
bump patch versions
dmoka Sep 18, 2024
316f374
fix test name
dmoka Sep 18, 2024
84a86bb
formatting
dmoka Sep 18, 2024
d890ed5
rename and move claim rewards after global farm update test
martinfridrich Sep 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading