nautechsystems/nautilus_trader · error · anyhow::Error
Order amount scaling overflow
Error message
Order amount scaling overflow
What it means
Thrown in quantity_to_raw_amount (client.rs:2444) on the decimals >= raw_precision branch: it computes 10^(decimals - raw_precision) with checked_pow, and the power overflows U256 when the exponent exceeds 77 (10^78 > 2^256). raw_precision is max(quantity.precision, FIXED_PRECISION), so this fires for tokens whose declared decimals are implausibly large.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:2454
}
/// Converts a base-denominated order quantity into raw token units with exact integer
/// scaling by the base token decimals.
///
/// `Quantity::raw` is scaled to the greater of its declared precision and `FIXED_PRECISION`;
/// token amounts are scaled to the token's decimals. Quantities not exactly representable in
/// token units are rejected rather than rounded.
fn quantity_to_raw_amount(quantity: Quantity, decimals: u8) -> anyhow::Result<U256> {
if quantity.is_zero() {
anyhow::bail!("Order quantity must be positive");
}
let raw = U256::from(quantity.raw);
let raw_precision = quantity.precision.max(FIXED_PRECISION);
if decimals >= raw_precision {
let scale = U256::from(10u64)
.checked_pow(U256::from(decimals - raw_precision))
.ok_or_else(|| anyhow::anyhow!("Order amount scaling overflow"))?;
raw.checked_mul(scale).ok_or_else(|| {
anyhow::anyhow!("Order amount overflow scaling quantity to raw token units")
})
} else {
let divisor = U256::from(10u64)
.checked_pow(U256::from(raw_precision - decimals))
.ok_or_else(|| anyhow::anyhow!("Order amount scaling overflow"))?;
if !(raw % divisor).is_zero() {
anyhow::bail!(
"Order quantity {quantity} is not exactly representable in {decimals} base token decimals"
);
}
Ok(raw / divisor)
}
}
/// Extracts the positive output amount from an exact-input swap quote.
fn exact_output_amount(quote: &SwapQuote, zero_for_one: bool) -> anyhow::Result<U256> {View on GitHub (pinned to 2114cf6f76)
Solutions
- Check the token's decimals() on-chain and in your pool/token records; real tokens are 0-18 (rarely up to ~36).
- Fix the decimals value at its source rather than special-casing the order.
- Validate decimals <= 18 (or at most 77) before submitting orders.
- Reject the token for execution if it genuinely advertises absurd decimals.
Example fix
// before
let amount = quantity_to_raw_amount(qty, token.decimals)?; // decimals = 180
// after
assert!(token.decimals <= 18, "suspicious decimals {}", token.decimals);
let amount = quantity_to_raw_amount(qty, token.decimals)?; Defensive patterns
Strategy: validation
Validate before calling
// before submitting any order:
if token.decimals > 18 {
anyhow::bail!("token {} reports implausible decimals {}", token.address, token.decimals);
} Type guard
fn decimals_are_plausible(decimals: u8) -> bool { decimals <= 18 } Try / catch
Treat as a permanent data error: fail the token/order, fix the metadata source, never retry the same value.
Prevention
- Validate token metadata once at registration against the on-chain decimals() call.
- Alert on any token whose decimals exceed 18.
When it happens
Trigger: Order submission for a token whose decimals metadata exceeds ~77 (u8 allows up to 255), e.g. 100 or 255 returned by a misbehaving ERC20 or a bad metadata source; a pool/token record with corrupted decimals.
Common situations: Token metadata scraped from a proxy contract that reverts and gets defaulted to a sentinel; hand-edited config with a typo in decimals (e.g., 180 instead of 18); test tokens with arbitrary decimals.
Related errors
- Maximum transaction cost overflow
- Order amount overflow scaling quantity to raw token units
- Maximum gas cost overflow
- Finalized block timestamp overflows nanoseconds
- Finalized transaction gas commission overflow
AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21).
Data as JSON: /api/errors/e5e5a29159795e34.
Report an issue: GitHub.