Skip to content

Commit

Permalink
add token price UTs
Browse files Browse the repository at this point in the history
  • Loading branch information
lemunozm committed Jun 27, 2024
1 parent e5c8926 commit 55d661f
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 58 deletions.
14 changes: 8 additions & 6 deletions libs/mocks/src/pools.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#[frame_support::pallet(dev_mode)]
pub mod pallet {
use cfg_traits::{
investments::InvestmentAccountant, PoolInspect, PoolReserve, PriceValue, Seconds,
TrancheTokenPrice,
investments::InvestmentAccountant, PoolInspect, PoolReserve, Seconds, TrancheTokenPrice,
};
use cfg_types::investments::InvestmentInfo;
use frame_support::pallet_prelude::*;
Expand Down Expand Up @@ -86,6 +85,12 @@ pub mod pallet {
register_call!(move |(a, b, c, d)| f(a, b, c, d));
}

pub fn mock_get_price(
f: impl Fn(T::PoolId, T::TrancheId) -> Option<(T::BalanceRatio, Seconds)> + 'static,
) {
register_call!(move |(a, b)| f(a, b));
}

#[allow(non_snake_case)]
pub fn mock_InvestmentAccountant_deposit(
f: impl Fn(&T::AccountId, T::TrancheCurrency, T::Balance) -> DispatchResult + 'static,
Expand Down Expand Up @@ -168,10 +173,7 @@ pub mod pallet {
type PoolId = T::PoolId;
type TrancheId = T::TrancheId;

fn get(
a: T::PoolId,
b: T::TrancheId,
) -> Option<PriceValue<T::CurrencyId, T::BalanceRatio, Seconds>> {
fn get_price(a: T::PoolId, b: T::TrancheId) -> Option<(T::BalanceRatio, Seconds)> {
execute_call!((a, b))
}
}
Expand Down
29 changes: 2 additions & 27 deletions libs/traits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ pub trait TrancheTokenPrice<AccountId, CurrencyId> {
type BalanceRatio;
type Moment;

fn get(
fn get_price(
pool_id: Self::PoolId,
tranche_id: Self::TrancheId,
) -> Option<PriceValue<CurrencyId, Self::BalanceRatio, Self::Moment>>;
) -> Option<(Self::BalanceRatio, Self::Moment)>;
}

/// Variants for valid Pool updates to send out as events
Expand Down Expand Up @@ -206,31 +206,6 @@ pub trait PoolWriteOffPolicyMutate<PoolId> {
fn worst_case_policy() -> Self::Policy;
}

/// A trait that can be used to retrieve the current price for a currency
pub struct CurrencyPair<CurrencyId> {
pub base: CurrencyId,
pub quote: CurrencyId,
}

pub struct PriceValue<CurrencyId, Rate, Moment> {
pub pair: CurrencyPair<CurrencyId>,
pub price: Rate,
pub last_updated: Moment,
}

pub trait CurrencyPrice<CurrencyId> {
type Rate;
type Moment;

/// Retrieve the latest price of `base` currency, denominated in the `quote`
/// currency If `quote` currency is not passed, then the default `quote`
/// currency is used (when possible)
fn get_latest(
base: CurrencyId,
quote: Option<CurrencyId>,
) -> Option<PriceValue<CurrencyId, Self::Rate, Self::Moment>>;
}

pub trait Permissions<AccountId> {
type Scope;
type Role;
Expand Down
6 changes: 3 additions & 3 deletions pallets/liquidity-pools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ pub mod pallet {
// TODO(future): Once we diverge from 1-to-1 conversions for foreign and pool
// currencies, this price must be first converted into the currency_id and then
// re-denominated to 18 decimals (i.e. `Ratio` precision)
let price_value = T::TrancheTokenPrice::get(pool_id, tranche_id)
let (price, computed_at) = T::TrancheTokenPrice::get_price(pool_id, tranche_id)
.ok_or(Error::<T>::MissingTranchePrice)?;

// Check that the registered asset location matches the destination
Expand All @@ -447,8 +447,8 @@ pub mod pallet {
pool_id,
tranche_id,
currency,
price: price_value.price,
computed_at: price_value.last_updated,
price,
computed_at,
},
)?;

Expand Down
4 changes: 2 additions & 2 deletions pallets/liquidity-pools/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ use cfg_types::{
};
use frame_support::derive_impl;
use orml_traits::parameter_type_with_key;
use sp_runtime::{traits::IdentityLookup, AccountId32, DispatchResult, FixedU64};
use sp_runtime::{traits::IdentityLookup, AccountId32, DispatchResult, FixedU128};

use crate::pallet as pallet_liquidity_pools;

pub type Balance = u128;
pub type AccountId = AccountId32;
pub type Ratio = FixedU64;
pub type Ratio = FixedU128;

frame_support::construct_runtime!(
pub enum Runtime {
Expand Down
85 changes: 81 additions & 4 deletions pallets/liquidity-pools/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const NAME: &[u8] = b"Token name";
const SYMBOL: &[u8] = b"Token symbol";
const DECIMALS: u8 = 6;
const TRANCHE_CURRENCY: CurrencyId = CurrencyId::Tranche(POOL_ID, TRANCHE_ID);
const PRICE: Ratio = Ratio::from_rational(10, 1);

mod util {
use super::*;
Expand Down Expand Up @@ -118,7 +119,7 @@ mod transfer {
})
}

mod erroring_out_when {
mod erroring_out {
use super::*;

#[test]
Expand Down Expand Up @@ -326,7 +327,7 @@ mod transfer_tranche_tokens {
})
}

mod erroring_out_when {
mod erroring_out {
use super::*;

#[test]
Expand Down Expand Up @@ -461,7 +462,7 @@ mod add_pool {
})
}

mod erroring_out_when {
mod erroring_out {
use super::*;

#[test]
Expand Down Expand Up @@ -540,7 +541,7 @@ mod add_tranche {
})
}

mod erroring_out_when {
mod erroring_out {
use super::*;

#[test]
Expand Down Expand Up @@ -619,6 +620,82 @@ mod add_tranche {
}
}

mod update_token_price {
use super::*;

#[test]
fn success() {
System::externalities().execute_with(|| {
Pools::mock_get_price(|_, _| Some((PRICE, 1234)));
AssetRegistry::mock_metadata(|_| Some(util::wrapped_transferable_metadata()));
Gateway::mock_submit(|sender, destination, msg| {
assert_eq!(sender, ALICE);
assert_eq!(destination, EVM_ADDRESS.domain());
assert_eq!(
msg,
Message::UpdateTrancheTokenPrice {
pool_id: POOL_ID,
tranche_id: TRANCHE_ID,
currency: util::currency_index(CURRENCY_ID),
price: PRICE,
computed_at: 1234
}
);
Ok(())
});

assert_ok!(LiquidityPools::update_token_price(
RuntimeOrigin::signed(ALICE),
POOL_ID,
TRANCHE_ID,
CURRENCY_ID,
EVM_ADDRESS.domain(),
));
})
}

mod erroring_out {
use super::*;

#[test]
fn with_missing_tranche_price() {
System::externalities().execute_with(|| {
Pools::mock_get_price(|_, _| None);

assert_noop!(
LiquidityPools::update_token_price(
RuntimeOrigin::signed(ALICE),
POOL_ID,
TRANCHE_ID,
CURRENCY_ID,
EVM_ADDRESS.domain(),
),
Error::<Runtime>::MissingTranchePrice,
);
})
}

#[test]
fn with_no_transferible_asset() {
System::externalities().execute_with(|| {
Pools::mock_get_price(|_, _| Some((PRICE, 1234)));
AssetRegistry::mock_metadata(|_| Some(util::default_metadata()));

assert_noop!(
LiquidityPools::update_token_price(
RuntimeOrigin::signed(ALICE),
POOL_ID,
TRANCHE_ID,
CURRENCY_ID,
EVM_ADDRESS.domain(),
),
Error::<Runtime>::AssetNotLiquidityPoolsTransferable,
);
})
}
}
}

#[test]
fn receiving_output_message() {
System::externalities().execute_with(|| {
Expand Down
20 changes: 4 additions & 16 deletions pallets/pool-system/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use cfg_traits::{
changes::ChangeGuard,
fee::{PoolFeeBucket, PoolFeesMutate},
investments::{InvestmentAccountant, TrancheCurrency},
CurrencyPair, PoolUpdateGuard, PriceValue, TrancheTokenPrice, UpdateState,
PoolUpdateGuard, TrancheTokenPrice, UpdateState,
};
use cfg_types::{epoch::EpochState, investments::InvestmentInfo, pools::PoolFeeInfo};
use frame_support::traits::{
Expand Down Expand Up @@ -62,10 +62,10 @@ impl<T: Config> TrancheTokenPrice<T::AccountId, T::CurrencyId> for Pallet<T> {
type PoolId = T::PoolId;
type TrancheId = T::TrancheId;

fn get(
fn get_price(
pool_id: Self::PoolId,
tranche_id: Self::TrancheId,
) -> Option<PriceValue<T::CurrencyId, T::BalanceRatio, Seconds>> {
) -> Option<(T::BalanceRatio, Seconds)> {
let now = T::Time::now();
let mut pool = Pool::<T>::get(pool_id)?;

Expand All @@ -84,21 +84,9 @@ impl<T: Config> TrancheTokenPrice<T::AccountId, T::CurrencyId> for Pallet<T> {
.calculate_prices::<T::BalanceRatio, T::Tokens, _>(total_assets, now)
.ok()?;

let base = pool
.tranches
.tranche_currency(TrancheLoc::Id(tranche_id))?
.into();

let price = prices.get(tranche_index).cloned()?;

Some(PriceValue {
pair: CurrencyPair {
base,
quote: pool.currency,
},
price,
last_updated: nav_last_updated,
})
Some((price, nav_last_updated))
}
}

Expand Down

0 comments on commit 55d661f

Please sign in to comment.