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

  1. Check the token's decimals() on-chain and in your pool/token records; real tokens are 0-18 (rarely up to ~36).
  2. Fix the decimals value at its source rather than special-casing the order.
  3. Validate decimals <= 18 (or at most 77) before submitting orders.
  4. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21). Data as JSON: /api/errors/e5e5a29159795e34. Report an issue: GitHub.