Skip to content
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
33 changes: 20 additions & 13 deletions pallets/limit-orders/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ pub mod pallet {
/// Call on_runtime_upgrade or wait for genesis to complete registration
/// before enabling the pallet.
PalletHotkeyNotRegistered,
/// A TAO -> alpha conversion overflowed the fixed-point range.
ArithmeticOverflow,
}

// ── Hooks ─────────────────────────────────────────────────────────────────
Expand Down Expand Up @@ -867,7 +869,7 @@ pub mod pallet {
total_sell_net,
total_sell_tao_equiv,
current_price,
);
)?;
Self::deposit_event(Event::GroupExecutionSummary {
netuid,
net_side,
Expand Down Expand Up @@ -1015,7 +1017,7 @@ pub mod pallet {
};
Ok((OrderSide::Buy, actual_alpha))
} else {
let total_buy_alpha_equiv = Self::tao_to_alpha(total_buy_net, current_price);
let total_buy_alpha_equiv = Self::tao_to_alpha(total_buy_net, current_price)?;
let net_alpha = (total_sell_net.saturating_sub(total_buy_alpha_equiv)) as u64;
let actual_tao = if net_alpha > 0 {
let out = T::SwapInterface::sell_alpha(
Expand Down Expand Up @@ -1054,7 +1056,7 @@ pub mod pallet {
) -> DispatchResult {
let total_alpha: u128 = match net_side {
OrderSide::Buy => actual_out.saturating_add(total_sell_net),
OrderSide::Sell => Self::tao_to_alpha(total_buy_net, current_price),
OrderSide::Sell => Self::tao_to_alpha(total_buy_net, current_price)?,
};

for e in buys.iter() {
Expand Down Expand Up @@ -1206,30 +1208,35 @@ pub mod pallet {
total_sell_net: u128,
total_sell_tao_equiv: u128,
current_price: U96F32,
) -> u64 {
) -> Result<u64, DispatchError> {
match net_side {
OrderSide::Buy => (total_buy_net.saturating_sub(total_sell_tao_equiv)) as u64,
OrderSide::Buy => Ok((total_buy_net.saturating_sub(total_sell_tao_equiv)) as u64),
OrderSide::Sell => {
let buy_alpha_equiv = Self::tao_to_alpha(total_buy_net, current_price) as u64;
(total_sell_net as u64).saturating_sub(buy_alpha_equiv)
let buy_alpha_equiv = Self::tao_to_alpha(total_buy_net, current_price)? as u64;
Ok((total_sell_net as u64).saturating_sub(buy_alpha_equiv))
}
}
}

/// Convert a TAO amount to alpha at `price` (TAO/alpha).
/// Returns 0 when `price` is zero.
#[allow(clippy::arithmetic_side_effects)]
fn tao_to_alpha(tao: u128, price: U96F32) -> u128 {
///
/// A zero `price` yields `Ok(0)` (no alpha is purchasable). A genuine
/// fixed-point overflow returns `Err(ArithmeticOverflow)` so the caller
/// aborts the batch.
fn tao_to_alpha(tao: u128, price: U96F32) -> Result<u128, DispatchError> {
if price == U96F32::from_num(0u32) {
return 0u128;
return Ok(0u128);
}
(U96F32::from_num(tao) / price).saturating_to_num::<u128>()
U96F32::saturating_from_num(tao)
.checked_div(price)
.map(|alpha| alpha.saturating_to_num::<u128>())
.ok_or(Error::<T>::ArithmeticOverflow.into())
}

/// Convert an alpha amount to TAO at `price` (TAO/alpha).
fn alpha_to_tao(alpha: u128, price: U96F32) -> u128 {
price
.saturating_mul(U96F32::from_num(alpha))
.saturating_mul(U96F32::saturating_from_num(alpha))
.saturating_to_num::<u128>()
}
}
Expand Down
9 changes: 6 additions & 3 deletions pallets/limit-orders/src/tests/auxiliary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ fn net_amount_for_event_buy_dominant() {
150u128, // total_sell_net (alpha) ← not used in Buy branch
300u128, // total_sell_tao_equiv
price,
);
)
.expect("conversion does not overflow");
assert_eq!(net, 700u64);
});
}
Expand All @@ -48,7 +49,8 @@ fn net_amount_for_event_sell_dominant() {
500u128, // total_sell_net (alpha)
400u128, // total_sell_tao_equiv (not used in Sell branch directly)
price,
);
)
.expect("conversion does not overflow");
// buy_alpha_equiv = 200 / 2 = 100; net = 500 - 100 = 400
assert_eq!(net, 400u64);
});
Expand All @@ -65,7 +67,8 @@ fn net_amount_for_event_perfectly_offset() {
100u128,
200u128,
price,
);
)
.expect("conversion does not overflow");
assert_eq!(net, 0u64);
});
}
Expand Down
Loading