nautechsystems/nautilus_trader · error
Scaled result exceeds 256-bit range
Error message
Scaled result exceeds 256-bit range
What it means
`mul_div_scaled` computes a high-precision a*b/denominator with extra decimal-scale correction steps. During each scale step the intermediate `quotient * scale` must still fit in U256; the library throws this error when that checked multiplication overflows the 256-bit range.
Source
Thrown at crates/model/src/defi/tick_map/full_math.rs:130
// is no longer required.
let result = prod_0 * inv;
Ok(result)
}
pub(crate) fn mul_div_scaled(
a: U256,
b: U256,
denominator: U256,
scales: &[U256],
) -> anyhow::Result<U256> {
let mut quotient = Self::mul_div(a, b, denominator)?;
let mut remainder = a.mul_mod(b, denominator);
for &scale in scales {
let scaled_quotient = quotient
.checked_mul(scale)
.ok_or_else(|| anyhow::anyhow!("Scaled result exceeds 256-bit range"))?;
let scaled_remainder = Self::mul_div(remainder, scale, denominator)?;
quotient = scaled_quotient
.checked_add(scaled_remainder)
.ok_or_else(|| anyhow::anyhow!("Scaled result exceeds 256-bit range"))?;
remainder = remainder.mul_mod(scale, denominator);
}
Ok(quotient)
}
pub(crate) fn check_decimal_exponent(exponent: u8) -> anyhow::Result<()> {
anyhow::ensure!(
exponent <= DECIMAL_EXPONENT_MAX,
"Decimal exponent {exponent} exceeds supported maximum {DECIMAL_EXPONENT_MAX}"
);
Ok(())
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Normalize/scale inputs before calling (use smaller intermediate values or divide early).
- Pre-check that quotient <= U256::MAX / scale before invoking.
- Reduce the decimal exponent used for scaling if the math allows (recompute the correction differently).
- Use U512 internally for the scaled step and convert back only if it fits.
Example fix
// before let q = mul_div_scaled(a, b, denominator, &[scale])?; // after let prelim = FullMath::mul_div(a, b, denominator)?; ensure!(prelim <= U256::MAX / scale, "inputs too large for scaled mul_div"); let q = mul_div_scaled(a, b, denominator, &[scale])?;
Defensive patterns
Strategy: validation
Validate before calling
fn can_scale(quotient: U256, scale: U256) -> bool {
quotient.checked_mul(scale).is_some()
} Try / catch
match mul_div_scaled(&a, &b, &denominator, scales) {
Ok(q) => q,
Err(e) if e.to_string().contains("exceeds 256-bit") => normalize_inputs_and_retry(),
Err(e) => return Err(e),
} Prevention
- Pre-normalize raw uint256 on-chain values before high-precision math
- Estimate result magnitude from inputs and reject early with a domain-level error
- Keep decimal scale exponents as small as the protocol math allows
When it happens
Trigger: Inputs where the preliminary quotient from `mul_div` is so large that multiplying by the decimal scale factor (10^k) exceeds 2^256 — extremely large `a` or `b` combined with a small denominator and a large scale.
Common situations: Feeding raw on-chain uint256 amounts near the U256 maximum into price/liquidity math with high decimal-exponent scales (e.g. 18-decimal tokens) rather than normalized values.
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
- Decimal exponent {exponent} exceeds U256 range
- Decimal exponent {exponent} exceeds supported maximum {DECIM
- Inverted price numerator exceeds U256 range
- Inverted price denominator exceeds U256 range
- WETH balance overflow for included transaction {tx_hash} at
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/0c84e87444ac0386.
Report an issue: GitHub.