Skip to content

Commit

Permalink
Merge pull request #762 from galacticcouncil/feat/lm-bonds-distribution
Browse files Browse the repository at this point in the history
feat: liquidity mining - use underlying asset's oracle for bonds distribution
  • Loading branch information
martinfridrich authored Feb 22, 2024
2 parents 7ac267b + f495f81 commit dd578de
Show file tree
Hide file tree
Showing 11 changed files with 228 additions and 27 deletions.
10 changes: 6 additions & 4 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.18.1"
version = "1.19.0"
description = "Integration tests"
authors = ["GalacticCouncil"]
edition = "2021"
Expand Down
155 changes: 141 additions & 14 deletions integration-tests/src/omnipool_liquidity_mining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,17 @@ use warehouse_liquidity_mining::{
};

use orml_traits::MultiCurrency;
use primitives::AssetId;
use primitives::{constants::currency::UNITS, AssetId};
use sp_runtime::{
traits::{One, Zero},
FixedPointNumber, FixedU128, Permill, Perquintill,
};
use xcm_emulator::TestExt;

use hydradx_runtime::{Balance, RuntimeOrigin};
use hydradx_runtime::{AssetRegistry, Balance, Bonds, RuntimeOrigin};
use pallet_asset_registry::AssetType;
use pretty_assertions::assert_eq;
use primitives::constants::time::unix_time::MONTH;

#[macro_export]
macro_rules! assert_nft_owner {
Expand Down Expand Up @@ -113,7 +115,7 @@ fn create_yield_farm_should_work_when_asset_is_in_omnipool() {
init_omnipool();

set_relaychain_block_number(100);
create_global_farm();
create_global_farm(None);

set_relaychain_block_number(200);
assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::create_yield_farm(
Expand Down Expand Up @@ -152,7 +154,7 @@ fn deposit_shares_should_work_when_yield_farm_exists() {
//NOTE: necessary to get oracle price.
hydradx_run_to_block(100);
set_relaychain_block_number(100);
create_global_farm();
create_global_farm(None);

set_relaychain_block_number(200);
create_yield_farm(global_farm_id, ETH);
Expand Down Expand Up @@ -223,8 +225,8 @@ fn redeposit_shares_multiple_times_should_work_when_shares_already_deposited() {
//NOTE: necessary to get oracle price.
hydradx_run_to_block(100);
set_relaychain_block_number(100);
create_global_farm();
create_global_farm();
create_global_farm(None);
create_global_farm(None);

set_relaychain_block_number(200);
create_yield_farm(global_farm_1_id, ETH);
Expand Down Expand Up @@ -314,8 +316,8 @@ fn claim_rewards_should_work_when_rewards_are_accumulated_for_deposit() {
//NOTE: necessary to get oracle price.
hydradx_run_to_block(100);
set_relaychain_block_number(100);
create_global_farm();
create_global_farm();
create_global_farm(None);
create_global_farm(None);

set_relaychain_block_number(200);
create_yield_farm(global_farm_1_id, ETH);
Expand Down Expand Up @@ -419,8 +421,8 @@ fn withdraw_shares_should_work_when_deposit_exists() {
//NOTE: necessary to get oracle price.
hydradx_run_to_block(100);
set_relaychain_block_number(100);
create_global_farm();
create_global_farm();
create_global_farm(None);
create_global_farm(None);

set_relaychain_block_number(200);
create_yield_farm(global_farm_1_id, ETH);
Expand Down Expand Up @@ -595,7 +597,7 @@ fn init_omnipool() {
));
}

fn create_global_farm() {
fn create_global_farm(rewards_currency: Option<AssetId>) {
let total_rewards = 1_000_000 * UNITS;

assert_ok!(hydradx_runtime::Balances::force_set_balance(
Expand All @@ -609,7 +611,7 @@ fn create_global_farm() {
total_rewards,
1_000_000,
10,
HDX,
rewards_currency.unwrap_or(HDX),
Treasury::account_id(),
Perquintill::from_parts(570_776_255_707),
1_000,
Expand Down Expand Up @@ -688,7 +690,7 @@ fn position_should_be_valued_correctly_when_oracle_is_used() {
//NOTE: necessary to get oracle price.
hydradx_run_to_block(100);
set_relaychain_block_number(100);
create_global_farm();
create_global_farm(None);

set_relaychain_block_number(200);
create_yield_farm(global_farm_id, ETH);
Expand Down Expand Up @@ -767,7 +769,7 @@ fn price_adjustment_from_oracle_should_be_saved_in_global_farm_when_oracle_is_av
//NOTE: necessary to get oracle price.
hydradx_run_to_block(100);
set_relaychain_block_number(100);
create_global_farm();
create_global_farm(None);

set_relaychain_block_number(200);
create_yield_farm(global_farm_1_id, ETH);
Expand Down Expand Up @@ -814,3 +816,128 @@ fn price_adjustment_from_oracle_should_be_saved_in_global_farm_when_oracle_is_av
);
});
}

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

Hydra::execute_with(|| {
let global_farm_1_id = 1;
let yield_farm_1_id = 2;

//Arrange
init_omnipool();
seed_lm_pot();
//necessary for oracle to have a price.
do_lrna_hdx_trade();

//Create bodns
assert_ok!(hydradx_runtime::Balances::force_set_balance(
hydradx_runtime::RuntimeOrigin::root(),
Treasury::account_id(),
2_000_000 * UNITS,
));

let maturity = NOW + MONTH;
let bond_id = AssetRegistry::next_asset_id().unwrap();
assert_ok!(Bonds::issue(
RuntimeOrigin::signed(Treasury::account_id()),
HDX,
2_000_000 * UNITS,
maturity
));
assert_eq!(AssetRegistry::assets(bond_id).unwrap().asset_type, AssetType::Bond);
//NOTE: make bond sufficient because treasury account is whitelisted. In this case farm
//would have to pay ED for receiving insufficicient bods and farm's account has no balance.
assert_ok!(AssetRegistry::update(
hydradx_runtime::RuntimeOrigin::root(),
bond_id,
None,
None,
None,
None,
Some(true),
None,
None,
None,
));

// farm's rewards in test are less than ED.
assert_ok!(hydradx_runtime::Currencies::transfer(
hydradx_runtime::RuntimeOrigin::signed(Treasury::account_id()),
CHARLIE.into(),
bond_id,
2 * UNITS,
));

//NOTE: necessary to get oracle price.
hydradx_run_to_block(100);
set_relaychain_block_number(100);
create_global_farm(Some(bond_id));

set_relaychain_block_number(200);
create_yield_farm(global_farm_1_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);
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
));

let charlie_bonds_balance_0 = hydradx_runtime::Currencies::free_balance(bond_id, &CHARLIE.into());
set_relaychain_block_number(600);
assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::claim_rewards(
RuntimeOrigin::signed(CHARLIE.into()),
deposit_id,
yield_farm_1_id
));

//Assert
let expected_claimed_amount = 393_607_131_u128;
assert_eq!(
hydradx_runtime::Currencies::free_balance(bond_id, &CHARLIE.into()),
charlie_bonds_balance_0 + expected_claimed_amount
);

set_relaychain_block_number(700);
let charlie_bonds_balance_0 = hydradx_runtime::Currencies::free_balance(bond_id, &CHARLIE.into());
assert_ok!(hydradx_runtime::OmnipoolLiquidityMining::withdraw_shares(
RuntimeOrigin::signed(CHARLIE.into()),
deposit_id,
yield_farm_1_id
));

let expected_claimed_amount = 229_243_713_u128;
assert_eq!(
hydradx_runtime::Currencies::free_balance(bond_id, &CHARLIE.into()),
charlie_bonds_balance_0 + expected_claimed_amount
);

// NOTE: make sure oracle's price adjustment was used.
let global_farm = hydradx_runtime::OmnipoolWarehouseLM::global_farm(global_farm_1_id).unwrap();
let price_adjustment = DefaultPriceAdjustment::get(&global_farm).unwrap();
assert_eq!(
price_adjustment,
FixedU128::from_inner(830_817_151_946_084_689_817_u128)
);
});
}
2 changes: 1 addition & 1 deletion pallets/bonds/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pallet-bonds"
version = "2.1.0"
version = "2.2.0"
authors = ['GalacticCouncil']
edition = "2021"
license = "Apache-2.0"
Expand Down
12 changes: 11 additions & 1 deletion pallets/bonds/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ use frame_support::{
};
use frame_system::{ensure_signed, pallet_prelude::OriginFor};
use sp_core::MaxEncodedLen;
use sp_std::vec::Vec;
use sp_std::{mem, vec::Vec};

use hydradx_traits::{
registry::{Create, Inspect},
Expand Down Expand Up @@ -185,6 +185,8 @@ pub mod pallet {
AssetNotFound,
/// Generated name is not valid.
InvalidBondName,
/// Bond's name parsing was now successful
FailToParseName,
}

#[pallet::call]
Expand Down Expand Up @@ -326,4 +328,12 @@ impl<T: Config> Pallet<T> {

buf
}

pub fn parse_bond_name(name: Vec<u8>) -> Result<AssetId, Error<T>> {
Ok(AssetId::from_le_bytes(
name[..mem::size_of::<AssetId>()]
.try_into()
.map_err(|_| Error::<T>::FailToParseName)?,
))
}
}
2 changes: 2 additions & 0 deletions pallets/bonds/src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod issue;
pub mod mock;
mod redeem;
#[allow(clippy::module_inception)]
mod tests;
37 changes: 37 additions & 0 deletions pallets/bonds/src/tests/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// This file is part of HydraDX.

// Copyright (C) 2020-2022 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 crate::tests::mock::*;
use crate::*;

#[test]
fn parse_name_should_work() {
let n = Pallet::<Test>::bond_name(0_u32, 1689844300000_u64);
assert_eq!(Pallet::<Test>::parse_bond_name(n), Ok(0_u32));

let n = Pallet::<Test>::bond_name(u32::max_value(), 1689844300000_u64);
assert_eq!(Pallet::<Test>::parse_bond_name(n), Ok(u32::max_value()));

let n = Pallet::<Test>::bond_name(1, 1689844300000_u64);
assert_eq!(Pallet::<Test>::parse_bond_name(n), Ok(1));

let n = Pallet::<Test>::bond_name(13_124, 1689844300000_u64);
assert_eq!(Pallet::<Test>::parse_bond_name(n), Ok(13_124));

let n = Pallet::<Test>::bond_name(789_970_979, 1689844300000_u64);
assert_eq!(Pallet::<Test>::parse_bond_name(n), Ok(789_970_979));
}
7 changes: 6 additions & 1 deletion runtime/adapters/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "hydradx-adapters"
version = "1.1.1"
version = "1.2.0"
description = "Structs and other generic types for building runtimes."
authors = ["GalacticCouncil"]
edition = "2021"
Expand Down Expand Up @@ -30,6 +30,8 @@ pallet-currencies = { workspace = true }
pallet-stableswap = { workspace = true }
pallet-referrals = { workspace = true }
pallet-lbp = { workspace = true }
pallet-asset-registry = { workspace = true }
pallet-bonds = { workspace = true }

# Substrate dependencies
frame-support = { workspace = true }
Expand Down Expand Up @@ -87,4 +89,7 @@ std = [
"cumulus-pallet-parachain-system/std",
"polkadot-parachain/std",
"orml-tokens/std",
"pallet-asset-registry/std",
"pallet-omnipool-liquidity-mining/std",
"pallet-bonds/std",
]
Loading

0 comments on commit dd578de

Please sign in to comment.