nautechsystems/nautilus_trader · error

Inverted price numerator exceeds U256 range

Error message

Inverted price numerator exceeds U256 range

What it means

In `decode_sqrt_price_x96_to_price_tokens_adjusted`, when the price must be inverted (token0/token1 direction swap) and the decimal difference is non-negative, the numerator `divisor_base * fixed_scalar` is computed with checked multiplication. The library throws this error when that product exceeds the U256 range, i.e. the fixed scalar is too large for the inversion path.

Source

Thrown at crates/model/src/defi/tick_map/sqrt_price_math.rs:395

    invert: bool,
) -> anyhow::Result<Price> {
    let sqrt_price = U256::from(sqrt_price_x96);
    let decimal_diff = i32::from(token0_decimals) - i32::from(token1_decimals);
    let token0_scalar = FullMath::pow10(token0_decimals)?;
    let token1_scalar = FullMath::pow10(token1_decimals)?;
    let decimal_adjustment = if decimal_diff >= 0 {
        token0_scalar / token1_scalar
    } else {
        token1_scalar / token0_scalar
    };
    let fixed_scalar = FullMath::pow10(FIXED_PRECISION)?;
    let divisor_base: U256 = U256::from(1u128) << 192;

    let price_raw = if invert {
        if decimal_diff >= 0 {
            let numerator = divisor_base
                .checked_mul(fixed_scalar)
                .ok_or_else(|| anyhow::anyhow!("Inverted price numerator exceeds U256 range"))?;
            let price_square: U512 = sqrt_price.widening_mul(sqrt_price);
            let max_square = U512::from(numerator / decimal_adjustment);

            if price_square > max_square {
                U256::ZERO
            } else {
                let price_square = U256::checked_from_limbs_slice(price_square.as_limbs())
                    .ok_or_else(|| {
                        anyhow::anyhow!("Inverted price denominator exceeds U256 range")
                    })?;
                let denominator =
                    price_square
                        .checked_mul(decimal_adjustment)
                        .ok_or_else(|| {
                            anyhow::anyhow!("Inverted price denominator exceeds U256 range")
                        })?;
                FullMath::mul_div(numerator, U256::from(1), denominator)?
            }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify token decimals metadata is correct; a wrong decimals field inflates decimal_diff.
  2. Handle inversion by swapping the numerator/denominator arguments instead of requesting invert with a huge scalar.
  3. Pre-check `decimal_diff` bounds before calling and clamp the adjustment.
  4. Compute the scalar in U512 and only narrow after division.

Example fix

// before
let price = decode_sqrt_price_x96_to_price_tokens_adjusted(sqrt_price, base_dec, quote_dec, true)?;
// after
ensure!((base_dec - quote_dec).abs() <= 36, "decimal diff too large for inversion");
let price = decode_sqrt_price_x96_to_price_tokens_adjusted(sqrt_price, base_dec, quote_dec, true)?;
Defensive patterns

Strategy: validation

Validate before calling

fn inversion_safe(decimal_diff: i32) -> bool {
    // divisor_base = 2^192; require scalar = 10^decimal_diff to fit alongside it in U256
    decimal_diff <= 19
}

Try / catch

match decode_sqrt_price_x96_to_price_tokens_adjusted(sqrt_price, base, quote, invert) {
    Ok(p) if p.is_zero() => handle_extreme_price(),
    Ok(p) => p,
    Err(e) if e.to_string().contains("numerator exceeds U256") => recompute_without_inversion(),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling the decode/spot-price function with `invert=true` and a large `decimal_diff` whose adjustment scalar, multiplied by 2^192, overflows U256 — e.g. very asymmetric token decimals combined with inversion.

Common situations: Pools pairing tokens with wildly different decimals (e.g. 18 vs 0-2 decimals) where quote-direction inversion is requested; misreported token decimals inflating `decimal_diff`.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/692550a776a46cf1. Report an issue: GitHub.