use anchor_lang::prelude::*;
use crate::drift::SafeMath;
use crate::errors::ReflectErrorCodes;
use spl_math::precise_number::PreciseNumber;
pub fn compute_base_token(
receipt: u64,
deposited_vault: u64,
receipt_token_supply: u64,
) -> Result<u64> {
PreciseNumber::new(receipt as u128)
.ok_or_else(|| {
msg!("Failed to create PreciseNumber from receipt: {}", receipt);
ReflectErrorCodes::MathOverflow
})?
.checked_mul(
&PreciseNumber::new(deposited_vault as u128)
.ok_or_else(|| {
msg!("Failed to create PreciseNumber from deposited_vault: {}", deposited_vault);
ReflectErrorCodes::MathOverflow
})?
)
.ok_or_else(|| {
msg!(
"Multiplication overflow: receipt={} deposited_vault={}",
receipt, deposited_vault
);
ReflectErrorCodes::MathOverflow
})?
.checked_div(
&PreciseNumber::new(receipt_token_supply as u128)
.ok_or_else(|| {
msg!(
"Failed to create PreciseNumber from receipt_token_supply: {}",
receipt_token_supply
);
ReflectErrorCodes::MathOverflow
})?
)
.ok_or_else(|| {
msg!(
"Division overflow: numerator=receipt*deposited_vault denominator={}",
receipt_token_supply
);
ReflectErrorCodes::MathOverflow
})?
.to_imprecise()
.ok_or_else(|| {
msg!("Failed to convert PreciseNumber to imprecise (u128).");
ReflectErrorCodes::MathOverflow
})?
.try_into()
.map_err(|_| {
msg!("Failed to cast final imprecise value into u64.");
ReflectErrorCodes::MathOverflow.into()
})
}
pub fn compute_receipt_token<'info>(
deposit: u64,
deposited_vault: u64,
receipt_token_supply: u64,
) -> Result<u64> {
if receipt_token_supply == 0 {
msg!(
"Receipt token supply is zero, returning deposit={} directly.",
deposit
);
return Ok(deposit);
};
PreciseNumber::new(deposit as u128)
.ok_or_else(|| {
msg!("Failed to create PreciseNumber from deposit: {}", deposit);
ReflectErrorCodes::MathOverflow
})?
.checked_mul(
&PreciseNumber::new(receipt_token_supply as u128)
.ok_or_else(|| {
msg!(
"Failed to create PreciseNumber from receipt_token_supply: {}",
receipt_token_supply
);
ReflectErrorCodes::MathOverflow
})?
)
.ok_or_else(|| {
msg!(
"Multiplication overflow: deposit={} receipt_token_supply={}",
deposit, receipt_token_supply
);
ReflectErrorCodes::MathOverflow
})?
.checked_div(
&PreciseNumber::new(deposited_vault as u128)
.ok_or_else(|| {
msg!("Failed to create PreciseNumber from deposited_vault: {}", deposited_vault);
ReflectErrorCodes::MathOverflow
})?
)
.ok_or_else(|| {
msg!(
"Division overflow: numerator=deposit*receipt_token_supply denominator={}",
deposited_vault
);
ReflectErrorCodes::MathOverflow
})?
.to_imprecise()
.ok_or_else(|| {
msg!("Failed to convert PreciseNumber to imprecise (u128).");
ReflectErrorCodes::MathOverflow
})?
.try_into()
.map_err(|_| {
msg!("Failed to cast final imprecise value into u64.");
ReflectErrorCodes::MathOverflow.into()
})
}
#[inline(never)]
pub fn calc_cut(total_amount: u64, cut: u16) -> Result<u64> {
let numerator = (total_amount as u128) * (cut as u128);
let result = numerator / 10_000u128;
Ok(result as u64)
}
#[inline(never)]
pub fn calc_all_cuts(total_amount: u64, cuts: Vec<u16>) -> Result<Vec<u64>> {
if cuts.is_empty() {
return Err(ReflectErrorCodes::MathError.into());
}
if cuts.iter().sum::<u16>() != 10_000 {
return Err(ReflectErrorCodes::MathError.into());
}
let mut amounts: Vec<u64> = vec![];
let mut total_distributed: u64 = 0;
for i in 0..cuts.len()-1 {
let cut_amount = calc_cut(total_amount, cuts[i])?;
amounts.push(cut_amount);
total_distributed = total_distributed.safe_add(cut_amount)?;
}
let final_amount = total_amount.safe_sub(total_distributed)?;
amounts.push(final_amount);
Ok(amounts)
}