Skip to content

Commit

Permalink
fix: bug on oracle fetching (#1750)
Browse files Browse the repository at this point in the history
* fix: bug on oracle fetching

* feat: tests for oracle provider. WTF...

* feat: enable for runtimes

* chore: add no-std feat gate migration tuples

* fix: compilation

* feat: final tests

* chore: rm unused test mod

* fix: change request

* fix: review request

* fix: unused import

* fix: integration tests

---------

Co-authored-by: William Freudenberger <[email protected]>
  • Loading branch information
mustermeiszer and wischli authored Mar 1, 2024
1 parent 10aed20 commit 472d1af
Show file tree
Hide file tree
Showing 10 changed files with 332 additions and 123 deletions.
12 changes: 0 additions & 12 deletions runtime/centrifuge/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,6 @@ pub type UpgradeCentrifuge1025 = (
burn_unburned::Migration<super::Runtime>,
);

// Copyright 2021 Centrifuge Foundation (centrifuge.io).
//
// This file is part of the Centrifuge chain project.
// Centrifuge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version (see http://www.gnu.org/licenses).
// Centrifuge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

mod burn_unburned {
const LOG_PREFIX: &str = "BurnUnburnedMigration: ";
const LP_ETH_USDC: CurrencyId = CurrencyId::ForeignAsset(100_001);
Expand Down
4 changes: 2 additions & 2 deletions runtime/common/src/oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ where
(from, to): &(CurrencyId, CurrencyId),
) -> Result<Option<Self::Value>, DispatchError> {
let locally_coupled_assets = match (from, to) {
(_, &CurrencyId::LocalAsset(_)) => from.is_local_representation_of(to),
(&CurrencyId::LocalAsset(_), _) => to.is_local_representation_of(from),
(_, &CurrencyId::LocalAsset(_)) => to.is_local_representation_of(from),
(&CurrencyId::LocalAsset(_), _) => from.is_local_representation_of(to),
_ => Ok(false),
}?;

Expand Down
22 changes: 11 additions & 11 deletions runtime/integration-tests/src/generic/cases/investments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ mod common {
let mut env = E::from_parachain_storage(
Genesis::<T>::default()
.add(genesis::balances(T::ExistentialDeposit::get() + FOR_FEES))
.add(genesis::assets(vec![Usd6::ID]))
.add(genesis::tokens(vec![(Usd6::ID, Usd6::ED)]))
.add(genesis::assets(vec![Box::new(Usd6)]))
.add(genesis::tokens(vec![(Usd6.id(), Usd6.ed())]))
.storage(),
);

env.parachain_state_mut(|| {
// Create a pool
utils::give_balance::<T>(POOL_ADMIN.id(), T::PoolDeposit::get());
utils::create_empty_pool::<T>(POOL_ADMIN.id(), POOL_A, Usd6::ID);
utils::create_empty_pool::<T>(POOL_ADMIN.id(), POOL_A, Usd6.id());

// Grant permissions
let tranche_id = T::Api::tranche_id(POOL_A, 0).unwrap();
Expand All @@ -73,7 +73,7 @@ fn investment_portfolio_single_tranche<T: Runtime>() {

// Invest to have pending pool currency
env.parachain_state_mut(|| {
utils::give_tokens::<T>(INVESTOR.id(), Usd6::ID, EXPECTED_POOL_BALANCE);
utils::give_tokens::<T>(INVESTOR.id(), Usd6.id(), EXPECTED_POOL_BALANCE);
utils::invest::<T>(INVESTOR.id(), POOL_A, tranche_id, EXPECTED_POOL_BALANCE);
assert_eq!(
pallet_investments::InvestOrders::<T>::get(INVESTOR.id(), invest_id)
Expand All @@ -87,7 +87,7 @@ fn investment_portfolio_single_tranche<T: Runtime>() {
investment_portfolio,
vec![(
invest_id,
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6::ID)
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6.id())
.with_pending_invest_currency(EXPECTED_POOL_BALANCE)
)]
);
Expand All @@ -102,7 +102,7 @@ fn investment_portfolio_single_tranche<T: Runtime>() {
investment_portfolio,
vec![(
invest_id,
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6::ID)
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6.id())
.with_claimable_tranche_tokens(EXPECTED_POOL_BALANCE)
)]
);
Expand All @@ -116,7 +116,7 @@ fn investment_portfolio_single_tranche<T: Runtime>() {
investment_portfolio,
vec![(
invest_id,
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6::ID)
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6.id())
.with_free_tranche_tokens(EXPECTED_POOL_BALANCE)
)]
);
Expand All @@ -130,7 +130,7 @@ fn investment_portfolio_single_tranche<T: Runtime>() {
investment_portfolio,
vec![(
invest_id,
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6::ID)
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6.id())
.with_free_tranche_tokens(EXPECTED_POOL_BALANCE - REDEEM_AMOUNT)
.with_pending_redeem_tranche_tokens(REDEEM_AMOUNT)
)]
Expand All @@ -146,7 +146,7 @@ fn investment_portfolio_single_tranche<T: Runtime>() {
investment_portfolio,
vec![(
invest_id,
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6::ID)
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6.id())
.with_free_tranche_tokens(EXPECTED_POOL_BALANCE - REDEEM_AMOUNT)
.with_claimable_currency(REDEEM_AMOUNT)
)]
Expand All @@ -161,7 +161,7 @@ fn investment_portfolio_single_tranche<T: Runtime>() {
investment_portfolio,
vec![(
invest_id,
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6::ID)
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6.id())
.with_free_tranche_tokens(EXPECTED_POOL_BALANCE - REDEEM_AMOUNT)
)]
);
Expand All @@ -181,7 +181,7 @@ fn investment_portfolio_single_tranche<T: Runtime>() {
investment_portfolio,
vec![(
invest_id,
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6::ID)
InvestmentPortfolio::<Balance, CurrencyId>::new(Usd6.id())
.with_free_tranche_tokens(EXPECTED_POOL_BALANCE - REDEEM_AMOUNT - HOLD_AMOUNT)
.with_reserved_tranche_tokens(HOLD_AMOUNT)
)]
Expand Down
24 changes: 16 additions & 8 deletions runtime/integration-tests/src/generic/cases/loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ mod common {
let mut env = E::from_parachain_storage(
Genesis::<T>::default()
.add(genesis::balances(T::ExistentialDeposit::get() + FOR_FEES))
.add(genesis::assets(vec![Usd6::ID]))
.add(genesis::tokens(vec![(Usd6::ID, Usd6::ED)]))
.add(genesis::assets(vec![Box::new(Usd6)]))
.add(genesis::tokens(vec![(Usd6.id(), Usd6.ed())]))
.storage(),
);

env.parachain_state_mut(|| {
// Creating a pool
utils::give_balance::<T>(POOL_ADMIN.id(), T::PoolDeposit::get());
utils::create_empty_pool::<T>(POOL_ADMIN.id(), POOL_A, Usd6::ID);
utils::create_empty_pool::<T>(POOL_ADMIN.id(), POOL_A, Usd6.id());

// Setting borrower
utils::give_pool_role::<T>(BORROWER.id(), POOL_A, PoolRole::Borrower);
Expand All @@ -94,7 +94,7 @@ mod common {
let tranche_id = T::Api::tranche_id(POOL_A, 0).unwrap();
let tranche_investor = PoolRole::TrancheInvestor(tranche_id, Seconds::MAX);
utils::give_pool_role::<T>(INVESTOR.id(), POOL_A, tranche_investor);
utils::give_tokens::<T>(INVESTOR.id(), Usd6::ID, EXPECTED_POOL_BALANCE);
utils::give_tokens::<T>(INVESTOR.id(), Usd6.id(), EXPECTED_POOL_BALANCE);
utils::invest::<T>(INVESTOR.id(), POOL_A, tranche_id, EXPECTED_POOL_BALANCE);
});

Expand Down Expand Up @@ -161,13 +161,13 @@ mod common {
Pricing::External(ExternalPricing {
price_id: PRICE_A,
max_borrow_amount: ExtMaxBorrowAmount::Quantity(QUANTITY),
notional: currency::price_to_currency(PRICE_VALUE_A, Usd6::ID),
notional: currency::price_to_currency(PRICE_VALUE_A, Usd6),
max_price_variation: rate_from_percent(50),
})
}

pub fn price_to_usd6(price: Quantity) -> Balance {
currency::price_to_currency(price, Usd6::ID)
currency::price_to_currency(price, Usd6)
}
}

Expand Down Expand Up @@ -286,7 +286,11 @@ fn internal_priced<T: Runtime>() {
env.parachain_state_mut(|| {
// Give required tokens to the borrower to be able to repay the interest accrued
// until this moment
utils::give_tokens::<T>(BORROWER.id(), Usd6::ID, loan_portfolio.outstanding_interest);
utils::give_tokens::<T>(
BORROWER.id(),
Usd6.id(),
loan_portfolio.outstanding_interest,
);
});

env.submit_now(
Expand Down Expand Up @@ -326,7 +330,11 @@ fn oracle_priced<T: Runtime>() {
env.parachain_state_mut(|| {
// Give required tokens to the borrower to be able to repay the interest accrued
// until this moment
utils::give_tokens::<T>(BORROWER.id(), Usd6::ID, loan_portfolio.outstanding_interest);
utils::give_tokens::<T>(
BORROWER.id(),
Usd6.id(),
loan_portfolio.outstanding_interest,
);

// Oracle modify the value
utils::oracle::feed_from_root::<T>(PRICE_A, PRICE_VALUE_B);
Expand Down
171 changes: 171 additions & 0 deletions runtime/integration-tests/src/generic/cases/oracles.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// Copyright 2021 Centrifuge Foundation (centrifuge.io).
//
// This file is part of the Centrifuge chain project.
// Centrifuge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version (see http://www.gnu.org/licenses).
// Centrifuge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

//! Testing setups around our oracles
mod ratio_provider {
use cfg_traits::ValueProvider;
use cfg_types::{
fixed_point::Ratio,
oracles::OracleKey,
tokens::{CrossChainTransferability, CurrencyId, CustomMetadata, LocalAssetId},
};
use frame_support::traits::OriginTrait;
use runtime_common::oracle::Feeder;
use sp_runtime::{traits::One, FixedPointNumber};

use crate::{
generic::{
config::Runtime,
env::Env,
envs::runtime_env::RuntimeEnv,
utils::currency::{register_currency, CurrencyInfo, CONST_DEFAULT_CUSTOM},
},
test_for_runtimes,
};

pub struct OtherLocal;
impl CurrencyInfo for OtherLocal {
fn id(&self) -> CurrencyId {
CurrencyId::LocalAsset(LocalAssetId(2))
}

fn custom(&self) -> CustomMetadata {
CustomMetadata {
pool_currency: true,
transferability: CrossChainTransferability::None,
..CONST_DEFAULT_CUSTOM
}
}
}

pub struct LocalUSDC;
impl CurrencyInfo for LocalUSDC {
fn id(&self) -> CurrencyId {
CurrencyId::LocalAsset(LocalAssetId(1))
}

fn custom(&self) -> CustomMetadata {
CustomMetadata {
pool_currency: true,
transferability: CrossChainTransferability::None,
..CONST_DEFAULT_CUSTOM
}
}
}

pub struct DomainUSDC;
impl CurrencyInfo for DomainUSDC {
fn id(&self) -> CurrencyId {
CurrencyId::ForeignAsset(100_001)
}

fn custom(&self) -> CustomMetadata {
CustomMetadata {
pool_currency: true,
transferability: CrossChainTransferability::LiquidityPools,
local_representation: Some(LocalAssetId(1)),
..CONST_DEFAULT_CUSTOM
}
}
}

fn feeder<T: Runtime>() -> Feeder<T::RuntimeOriginExt> {
pallet_order_book::MarketFeederId::<T>::get().unwrap()
}

fn get_rate_with<T: Runtime>(
key: (CurrencyId, CurrencyId),
setup: impl FnOnce(),
) -> Option<Ratio> {
let mut env = RuntimeEnv::<T>::default();

env.parachain_state_mut(|| {
register_currency::<T>(LocalUSDC, |_| {});
register_currency::<T>(DomainUSDC, |_| {});
register_currency::<T>(OtherLocal, |_| {});

pallet_order_book::Pallet::<T>::set_market_feeder(
T::RuntimeOriginExt::root(),
Feeder::<T::RuntimeOriginExt>::root(),
)
.unwrap();

setup();

<T as pallet_order_book::Config>::RatioProvider::get(&feeder::<T>(), &key).unwrap()
})
}

fn get_rate<T: Runtime>(key: (CurrencyId, CurrencyId)) -> Option<Ratio> {
get_rate_with::<T>(key, || {})
}

fn local_to_variant<T: Runtime>() {
assert_eq!(
get_rate::<T>((LocalUSDC.id(), DomainUSDC.id())),
Some(Ratio::one())
);
}

fn variant_to_local<T: Runtime>() {
assert_eq!(
get_rate::<T>((DomainUSDC.id(), LocalUSDC.id())),
Some(Ratio::one())
);
}

fn variant_to_other_local<T: Runtime>() {
assert_eq!(get_rate::<T>((DomainUSDC.id(), OtherLocal.id())), None);
}

fn other_local_to_variant<T: Runtime>() {
assert_eq!(get_rate::<T>((OtherLocal.id(), DomainUSDC.id())), None);
}

fn variant_to_local_rate_set<T: Runtime>() {
let pair = (LocalUSDC.id(), DomainUSDC.id());
assert_eq!(
get_rate_with::<T>(pair, || {
pallet_oracle_feed::Pallet::<T>::feed(
feeder::<T>().0.into(),
OracleKey::ConversionRatio(pair.1, pair.0),
Ratio::checked_from_rational(1, 5).unwrap(),
)
.unwrap();
}),
Some(Ratio::one())
);
}

fn local_to_variant_rate_set<T: Runtime>() {
let pair = (LocalUSDC.id(), DomainUSDC.id());
assert_eq!(
get_rate_with::<T>(pair, || {
pallet_oracle_feed::Pallet::<T>::feed(
feeder::<T>().0.into(),
OracleKey::ConversionRatio(pair.0, pair.1),
Ratio::checked_from_rational(1, 5).unwrap(),
)
.unwrap();
}),
Some(Ratio::one())
);
}

test_for_runtimes!(all, variant_to_local);
test_for_runtimes!(all, local_to_variant);
test_for_runtimes!(all, variant_to_other_local);
test_for_runtimes!(all, other_local_to_variant);
test_for_runtimes!(all, variant_to_local_rate_set);
test_for_runtimes!(all, local_to_variant_rate_set);
}
Loading

0 comments on commit 472d1af

Please sign in to comment.