Skip to content

Commit

Permalink
fix: linear pricing
Browse files Browse the repository at this point in the history
  • Loading branch information
mustermeiszer committed Apr 15, 2024
1 parent 3df5900 commit e004106
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 20 deletions.
3 changes: 2 additions & 1 deletion pallets/loans/src/entities/loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use crate::{
BorrowLoanError, BorrowRestrictions, CloseLoanError, CreateLoanError, LoanRestrictions,
MutationError, RepaidAmount, RepayLoanError, RepayRestrictions, RepaymentSchedule,
},
PriceOf,
};

/// Loan information.
Expand Down Expand Up @@ -290,7 +291,7 @@ impl<T: Config> ActiveLoan<T> {
pub fn present_value_by<Rates>(
&self,
rates: &Rates,
prices: &BTreeMap<T::PriceId, T::Balance>,
prices: &BTreeMap<T::PriceId, PriceOf<T>>,
) -> Result<T::Balance, DispatchError>
where
Rates: RateCollection<T::Rate, T::Balance, T::Balance>,
Expand Down
41 changes: 30 additions & 11 deletions pallets/loans/src/entities/pricing/external.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use sp_std::collections::btree_map::BTreeMap;
use crate::{
entities::interest::ActiveInterestRate,
pallet::{Config, Error},
PriceOf,
};

#[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo, RuntimeDebugNoBound, MaxEncodedLen)]
Expand Down Expand Up @@ -150,9 +151,14 @@ impl<T: Config> ExternalActivePricing<T> {
}
}

fn linear_accrual_price(&self, maturity: Seconds) -> Result<T::Balance, DispatchError> {
fn linear_accrual_price(
&self,
maturity: Seconds,
price: T::Balance,
price_last_updated: Seconds,
) -> Result<T::Balance, DispatchError> {
Ok(cfg_utils::math::y_coord_in_rect(
(self.settlement_price_updated, self.latest_settlement_price),
(price_last_updated, price),
(maturity, self.info.notional),
T::Time::now(),
)?)
Expand All @@ -163,10 +169,26 @@ impl<T: Config> ExternalActivePricing<T> {
pool_id: T::PoolId,
maturity: Seconds,
) -> Result<T::Balance, DispatchError> {
Ok(match T::PriceRegistry::get(&self.info.price_id, &pool_id) {
Ok(data) => data.0,
Err(_) => self.linear_accrual_price(maturity)?,
})
self.current_price_inner(
maturity,
T::PriceRegistry::get(&self.info.price_id, &pool_id).ok(),
)
}

fn current_price_inner(
&self,
maturity: Seconds,
oracle: Option<PriceOf<T>>,
) -> Result<T::Balance, DispatchError> {
if let Some((oracle_price, oracle_provided_at)) = oracle {
self.linear_accrual_price(maturity, oracle_price, oracle_provided_at.into_seconds())
} else {
self.linear_accrual_price(
maturity,
self.latest_settlement_price,
self.settlement_price_updated,
)
}
}

pub fn outstanding_principal(
Expand Down Expand Up @@ -197,13 +219,10 @@ impl<T: Config> ExternalActivePricing<T> {

pub fn present_value_cached(
&self,
cache: &BTreeMap<T::PriceId, T::Balance>,
cache: &BTreeMap<T::PriceId, PriceOf<T>>,
maturity: Seconds,
) -> Result<T::Balance, DispatchError> {
let price = match cache.get(&self.info.price_id) {
Some(data) => *data,
None => self.linear_accrual_price(maturity)?,
};
let price = self.current_price_inner(maturity, cache.get(&self.info.price_id).copied())?;
Ok(self.outstanding_quantity.ensure_mul_int(price)?)
}

Expand Down
11 changes: 7 additions & 4 deletions pallets/loans/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pub mod pallet {

pub type PortfolioInfoOf<T> = Vec<(<T as Config>::LoanId, ActiveLoanInfo<T>)>;
pub type AssetOf<T> = (<T as Config>::CollectionId, <T as Config>::ItemId);
pub type PriceOf<T> = (<T as Config>::Balance, <T as Config>::Moment);
pub type PriceOf<T> = (<T as Config>::Balance, Seconds);

const STORAGE_VERSION: StorageVersion = StorageVersion::new(3);

Expand Down Expand Up @@ -1050,15 +1050,15 @@ pub mod pallet {

pub fn registered_prices(
pool_id: T::PoolId,
) -> Result<BTreeMap<T::PriceId, T::Balance>, DispatchError> {
) -> Result<BTreeMap<T::PriceId, PriceOf<T>>, DispatchError> {
let collection = T::PriceRegistry::collection(&pool_id)?;
Ok(ActiveLoans::<T>::get(pool_id)
.iter()
.filter_map(|(_, loan)| loan.price_id())
.filter_map(|price_id| {
collection
.get(&price_id)
.map(|price| (price_id, price.0))
.map(|price| (price_id, (price.0, price.1.into_seconds())))
.ok()
})
.collect::<BTreeMap<_, _>>())
Expand All @@ -1071,7 +1071,10 @@ pub mod pallet {
let rates = T::InterestAccrual::rates();
let prices = match input_prices {
PriceCollectionInput::Empty => BTreeMap::default(),
PriceCollectionInput::Custom(prices) => prices.into(),
PriceCollectionInput::Custom(prices) => {
let now = T::Time::now();
prices.map(|(_, price)| (price, now)).into()
}
PriceCollectionInput::FromRegistry => Self::registered_prices(pool_id)?,
};

Expand Down
23 changes: 19 additions & 4 deletions runtime/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub mod xcm;

use cfg_primitives::Balance;
use cfg_types::{fee_keys::FeeKey, pools::PoolNav, tokens::CurrencyId};
use frame_support::BoundedBTreeMap;
use orml_traits::GetByKey;
use pallet_loans::entities::input::PriceCollectionInput;
use pallet_pool_system::Nav;
Expand All @@ -37,7 +38,7 @@ use sp_runtime::{
traits::{Get, Zero},
DispatchError,
};
use sp_std::marker::PhantomData;
use sp_std::{collections::btree_map::BTreeMap, marker::PhantomData};

parameter_types! {
/// The native currency identifier of our currency id enum
Expand Down Expand Up @@ -103,9 +104,23 @@ where
{
let input_prices: PriceCollectionInput<T> =
if let Ok(prices) = pallet_loans::Pallet::<T>::registered_prices(pool_id) {
PriceCollectionInput::Custom(prices.try_into().map_err(|_| {
DispatchError::Other("Map expected to fit as it is coming from loans itself.")
})?)
PriceCollectionInput::Custom(
BoundedBTreeMap::<
T::PriceId,
<T as pallet_pool_system::Config>::Balance,
T::MaxActiveLoansPerPool,
>::try_from(
prices
.into_iter()
.map(|(price_id, (price, _))| (price_id, price))
.collect::<BTreeMap<_, _>>(),
)
.map_err(|_| {
DispatchError::Other(
"Collection is overwheight. Should be at most MaxActiveLoansPerPool large.",
)
})?,
)
} else {
PriceCollectionInput::Empty
};
Expand Down

0 comments on commit e004106

Please sign in to comment.