User can pause all auctions by overflow in mid-price average
| Title | User can pause all auctions by overflow in mid-price average |
|---|---|
| Reward | $3318, Unique |
| Contest | Dango Dex - 15 Sep 2025 on Sherlock |
| Author | Ziusz |
| Context | Math Overflow |
Unchecked addition of best_bid_price and best_ask_price when saving the mid price can pause the auction for every trader. An attacker places one very high-price ask and one low-price bid so that both best prices exist; then mid = bid + ask2 overflows, the auction submessage fails, and PAUSED is set to true.
In cron.rs:630 the mid price is computed by adding both prices and halving:
fn clear_orders_of_pair(...) -> anyhow::Result<()> {
// [...]
let mid_price = match (best_bid_price, best_ask_price) {
// @audit Can overflow Udec128_24 when ask is near max and bid > 0
(Some(bid), Some(ask)) => Some(bid.checked_add(ask)?.checked_mul(HALF)?),
(Some(bid), None) => Some(bid),
(None, Some(ask)) => Some(ask),
(None, None) => None,
};
// [...]
} ])
}
Adding two Price (Udec128_24) numbers can overflow when the ask is near the maximum and the bid is positive. The error bubbles up, the auction submessage fails, and the reply handler pauses trading in cron.rs:65:
pub fn reply(ctx: SudoCtx, msg: ReplyMsg, res: SubMsgResult) -> StdResult<Response> {
match msg {
ReplyMsg::AfterAuction {} => {
// [...]
// @audit Any error sets PAUSED to true globally
PAUSED.save(ctx.storage, &true)?;
Response::new().add_event(Paused { error: Some(error) })
},
}
}
Note: one condition is essential — the pair must not have passive pool reserves yet, so no passive orders cap the prices and the best bid and ask come only from user orders. Say so in the report, or it may be invalidated.
Attack Path
1. Attacker sends a GTC SELL (ask) with extreme price (A) close to Price max (Udec128_24).
2. Attacker sends a GTC BUY (bid) with small price (e.g., 1) and quote >= min_order_size (e.g., $10).
3. No match happens (1 < A), so at end of block, the contract saves resting book.
4. It computes mid_price = Some(bid.checked_add(ask)?.checked_mul(HALF)?).
5. bid + ask overflows Udec128_24, so the submessage errors and the reply handler sets PAUSED = true.
Alpha: always check every equation for overflow, underflow, downcasting and rounding.
Conclusion
This finding would earn you $3318, and you get to it by having "check every maths operation for correct behaviour" on your checklist. Also spend enough time pinning down the exact conditions and impact, so the report does not get invalidated.
Full Report
Codebase