diff --git a/token-lending/program/src/math/rate.rs b/token-lending/program/src/math/rate.rs index c956491337d..c404c8ff2b8 100644 --- a/token-lending/program/src/math/rate.rs +++ b/token-lending/program/src/math/rate.rs @@ -51,11 +51,6 @@ impl Rate { U128::from(WAD) } - // OPTIMIZE: use const slice when fixed in BPF toolchain - fn half_wad() -> U128 { - U128::from(HALF_WAD) - } - /// Create scaled decimal from percent value pub fn from_percent(percent: u8) -> Self { Self(U128::from(percent as u64 * PERCENT_SCALER)) @@ -72,16 +67,6 @@ impl Rate { Self(U128::from(scaled_val)) } - /// Round scaled decimal to u64 - pub fn try_round_u64(&self) -> Result { - let rounded_val = Self::half_wad() - .checked_add(self.0) - .ok_or(LendingError::MathOverflow)? - .checked_div(Self::wad()) - .ok_or(LendingError::MathOverflow)?; - Ok(u64::try_from(rounded_val).map_err(|_| LendingError::MathOverflow)?) - } - /// Calculates base^exp pub fn try_pow(&self, mut exp: u64) -> Result { let mut base = *self; diff --git a/token-lending/program/src/state/reserve.rs b/token-lending/program/src/state/reserve.rs index c29fa280a7a..fd51af49ce5 100644 --- a/token-lending/program/src/state/reserve.rs +++ b/token-lending/program/src/state/reserve.rs @@ -553,9 +553,8 @@ pub struct CollateralExchangeRate(Rate); impl CollateralExchangeRate { /// Convert reserve collateral to liquidity pub fn collateral_to_liquidity(&self, collateral_amount: u64) -> Result { - Decimal::from(collateral_amount) - .try_div(self.0)? - .try_round_u64() + self.decimal_collateral_to_liquidity(collateral_amount.into())? + .try_floor_u64() } /// Convert reserve collateral to liquidity @@ -568,7 +567,8 @@ impl CollateralExchangeRate { /// Convert reserve liquidity to collateral pub fn liquidity_to_collateral(&self, liquidity_amount: u64) -> Result { - self.0.try_mul(liquidity_amount)?.try_round_u64() + self.decimal_liquidity_to_collateral(liquidity_amount.into())? + .try_floor_u64() } /// Convert reserve liquidity to collateral @@ -662,9 +662,9 @@ impl ReserveFees { if borrow_fee_rate > Rate::zero() && amount > Decimal::zero() { let need_to_assess_host_fee = host_fee_rate > Rate::zero(); let minimum_fee = if need_to_assess_host_fee { - 2 // 1 token to owner, 1 to host + 2u64 // 1 token to owner, 1 to host } else { - 1 // 1 token to owner, nothing else + 1u64 // 1 token to owner, nothing else }; let borrow_fee_amount = match fee_calculation { @@ -678,14 +678,18 @@ impl ReserveFees { } }; - let borrow_fee = borrow_fee_amount.try_round_u64()?.max(minimum_fee); - if Decimal::from(borrow_fee) >= amount { + let borrow_fee_decimal = borrow_fee_amount.max(minimum_fee.into()); + if borrow_fee_decimal >= amount { msg!("Borrow amount is too small to receive liquidity after fees"); return Err(LendingError::BorrowTooSmall.into()); } + let borrow_fee = borrow_fee_decimal.try_round_u64()?; let host_fee = if need_to_assess_host_fee { - host_fee_rate.try_mul(borrow_fee)?.try_round_u64()?.max(1) + borrow_fee_decimal + .try_mul(host_fee_rate)? + .try_round_u64()? + .max(1u64) } else { 0 };