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

Add get_oracle_amount_by_currency_and_amount_in #1429

Merged
merged 3 commits into from
Sep 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions pallets/fee-share/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,14 @@ impl PriceFeeder for MockPriceFeeder {
fn get_normal_price(_asset_id: &CurrencyId) -> Option<u128> {
todo!()
}

fn get_oracle_amount_by_currency_and_amount_in(
_currency_in: &CurrencyId,
_amount_in: bifrost_primitives::Balance,
_currency_out: &CurrencyId,
) -> Option<bifrost_primitives::Balance> {
todo!()
}
}

pub struct ParaInfo;
Expand Down
8 changes: 8 additions & 0 deletions pallets/lend-market/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,14 @@ impl PriceFeeder for MockPriceFeeder {
fn get_normal_price(_asset_id: &CurrencyId) -> Option<u128> {
todo!()
}

fn get_oracle_amount_by_currency_and_amount_in(
_currency_in: &CurrencyId,
_amount_in: Balance,
_currency_out: &CurrencyId,
) -> Option<Balance> {
todo!()
}
}

parameter_types! {
Expand Down
8 changes: 8 additions & 0 deletions pallets/leverage-staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,14 @@ impl PriceFeeder for MockPriceFeeder {
fn get_normal_price(_asset_id: &CurrencyId) -> Option<u128> {
todo!()
}

fn get_oracle_amount_by_currency_and_amount_in(
_currency_in: &CurrencyId,
_amount_in: Balance,
_currency_out: &CurrencyId,
) -> Option<Balance> {
todo!()
}
}

parameter_types! {
Expand Down
24 changes: 24 additions & 0 deletions pallets/prices/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ impl<T: Config> Pallet<T> {
})
}

fn get_storage_price(asset_id: &CurrencyId) -> Option<Price> {
EmergencyPrice::<T>::get(asset_id)
.or_else(|| T::Source::get(asset_id).and_then(|price| Some(price.value)))
}

fn get_asset_mantissa(asset_id: &CurrencyId) -> Option<u128> {
10u128.checked_pow(
asset_id
Expand Down Expand Up @@ -248,6 +253,25 @@ impl<T: Config> PriceFeeder for Pallet<T> {
.and_then(|price| Some(price.value.into_inner().saturating_div(decimals)))
})
}

/// Get the amount of currencies according to the oracle price data.
fn get_oracle_amount_by_currency_and_amount_in(
currency_in: &CurrencyId,
amount_in: Balance,
currency_out: &CurrencyId,
) -> Option<Balance> {
let currency_in_mantissa = Self::get_asset_mantissa(currency_in)?;
let currency_out_mantissa = Self::get_asset_mantissa(currency_out)?;
let currency_in_price = Self::get_storage_price(currency_in)?;
let currency_out_price = Self::get_storage_price(currency_out)?;
let total_value = currency_in_price
.mul(FixedU128::from_inner(amount_in))
.div(FixedU128::from_inner(currency_in_mantissa));
let amount_out = total_value
.mul(FixedU128::from_inner(currency_out_mantissa))
.div(currency_out_price);
Some(amount_out.into_inner())
}
}

impl<T: Config> EmergencyPriceFeeder<CurrencyId, Price> for Pallet<T> {
Expand Down
10 changes: 9 additions & 1 deletion pallets/prices/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use sp_runtime::{traits::IdentityLookup, FixedPointNumber};
use bifrost_asset_registry::AssetIdMaps;
pub use bifrost_primitives::{
currency::{FIL, VFIL},
DOT, KSM, VDOT,
DOT, KSM, MANTA, VDOT,
};
use bifrost_primitives::{Moment, ASTR, BNC, DOT_U, GLMR};
use sp_runtime::BuildStorage;
Expand Down Expand Up @@ -54,10 +54,18 @@ pub struct MockDataProvider;
impl DataProvider<CurrencyId, TimeStampedPrice> for MockDataProvider {
fn get(asset_id: &CurrencyId) -> Option<TimeStampedPrice> {
match *asset_id {
BNC => Some(TimeStampedPrice {
value: Price::from_inner(200_000_000_000_000_000),
timestamp: 0,
}),
DOT =>
Some(TimeStampedPrice { value: Price::saturating_from_integer(100), timestamp: 0 }),
KSM =>
Some(TimeStampedPrice { value: Price::saturating_from_integer(500), timestamp: 0 }),
MANTA => Some(TimeStampedPrice {
value: Price::from_inner(600_000_000_000_000_000),
timestamp: 0,
}),
VDOT => Some(TimeStampedPrice {
value: Price::from_inner(15000000000_0000000000),
timestamp: 0,
Expand Down
77 changes: 76 additions & 1 deletion pallets/prices/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
//! Unit tests for the prices pallet.

use super::*;
use bifrost_primitives::VKSM;
use bifrost_asset_registry::AssetMetadata;
use bifrost_primitives::{BNC, MANTA, VKSM};
use frame_support::{assert_noop, assert_ok};
use mock::{RuntimeEvent, *};
use sp_runtime::{traits::BadOrigin, FixedPointNumber};
Expand Down Expand Up @@ -194,3 +195,77 @@ fn get_foreign_token_price_work() {
assert_eq!(Prices::get_price(&FIL), Prices::get_price(&VFIL));
});
}

#[test]
fn fixed_u128() {
new_test_ext().execute_with(|| {
let bnc_decimal = 10u128.pow(12);
let bnc_amount = 100 * 10u128.pow(12);
let bnc_price = FixedU128::from_inner(200_000_000_000_000_000);
// 100 * 0.2 = 20 U
let dot_decimal = 10u128.pow(10);
let dot_amount = 5 * 10u128.pow(10);
let dot_price = FixedU128::from(4);

let bnc_total_value =
bnc_price / FixedU128::from_inner(bnc_decimal) * FixedU128::from_inner(bnc_amount);
let dot_total_value =
dot_price / FixedU128::from_inner(dot_decimal) * FixedU128::from_inner(dot_amount);
let dot_amount_fixed_u128 =
dot_total_value * FixedU128::from_inner(dot_decimal) / dot_price;
assert_eq!(bnc_total_value, dot_total_value);
println!("{:?}", bnc_total_value);
println!("{:?}", dot_amount_fixed_u128);
assert_eq!(dot_amount, dot_amount_fixed_u128.into_inner());
})
}

#[test]
fn get_oracle_amount_by_currency_and_amount_in() {
new_test_ext().execute_with(|| {
assert_ok!(AssetRegistry::do_register_metadata(
MANTA,
&AssetMetadata {
name: b"Manta".to_vec(),
symbol: b"Manta".to_vec(),
decimals: 18,
minimal_balance: 1_000_000_000_000_000u128,
}
));
// 100 * 0.2 = 20u
let bnc_amount = 100 * 10u128.pow(12);
// 0.2 DOT
assert_eq!(
Some(2_000_000_000),
Prices::get_oracle_amount_by_currency_and_amount_in(&BNC, bnc_amount, &DOT)
);
// 0.04 KSM
assert_eq!(
Some(40_000_000_000),
Prices::get_oracle_amount_by_currency_and_amount_in(&BNC, bnc_amount, &KSM)
);
// 33.33333333333333333333
assert_eq!(
Some(33_333_333_333_333_333_333),
Prices::get_oracle_amount_by_currency_and_amount_in(&BNC, bnc_amount, &MANTA)
);

// 0.01 * 0.2 = 0.002 U
let bnc_amount = 10u128.pow(10);
// 0.00002 DOT * 100 = 0.002 U
assert_eq!(
Some(200_000),
Prices::get_oracle_amount_by_currency_and_amount_in(&BNC, bnc_amount, &DOT)
);
// 0.000004 KSM * 500 = 0.002 U
assert_eq!(
Some(4_000_000),
Prices::get_oracle_amount_by_currency_and_amount_in(&BNC, bnc_amount, &KSM)
);
// 0.003333333333333333333333 MANTA
assert_eq!(
Some(3_333_333_333_333_333),
Prices::get_oracle_amount_by_currency_and_amount_in(&BNC, bnc_amount, &MANTA)
);
});
}
7 changes: 6 additions & 1 deletion pallets/traits/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![cfg_attr(not(feature = "std"), no_std)]

use bifrost_primitives::{CurrencyId, PriceDetail};
use bifrost_primitives::{Balance, CurrencyId, PriceDetail};
use num_bigint::{BigUint, ToBigUint};

pub mod evm;
Expand All @@ -15,6 +15,11 @@ pub trait EmergencyCallFilter<Call> {
pub trait PriceFeeder {
fn get_price(asset_id: &CurrencyId) -> Option<PriceDetail>;
fn get_normal_price(asset_id: &CurrencyId) -> Option<u128>;
fn get_oracle_amount_by_currency_and_amount_in(
currency_in: &CurrencyId,
amount_in: Balance,
currency_out: &CurrencyId,
) -> Option<Balance>;
}

pub trait EmergencyPriceFeeder<CurrencyId, Price> {
Expand Down