{"record":{"id":"6fdab83736ec1725","repo":"nautechsystems/nautilus_trader","slug":"inverted-price-denominator-exceeds-u256-range","errorCode":null,"errorMessage":"Inverted price denominator exceeds U256 range","messagePattern":"Inverted price denominator exceeds U256 range","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/defi/tick_map/sqrt_price_math.rs","lineNumber":404,"sourceCode":"        token1_scalar / token0_scalar\n    };\n    let fixed_scalar = FullMath::pow10(FIXED_PRECISION)?;\n    let divisor_base: U256 = U256::from(1u128) << 192;\n\n    let price_raw = if invert {\n        if decimal_diff >= 0 {\n            let numerator = divisor_base\n                .checked_mul(fixed_scalar)\n                .ok_or_else(|| anyhow::anyhow!(\"Inverted price numerator exceeds U256 range\"))?;\n            let price_square: U512 = sqrt_price.widening_mul(sqrt_price);\n            let max_square = U512::from(numerator / decimal_adjustment);\n\n            if price_square > max_square {\n                U256::ZERO\n            } else {\n                let price_square = U256::checked_from_limbs_slice(price_square.as_limbs())\n                    .ok_or_else(|| {\n                        anyhow::anyhow!(\"Inverted price denominator exceeds U256 range\")\n                    })?;\n                let denominator =\n                    price_square\n                        .checked_mul(decimal_adjustment)\n                        .ok_or_else(|| {\n                            anyhow::anyhow!(\"Inverted price denominator exceeds U256 range\")\n                        })?;\n                FullMath::mul_div(numerator, U256::from(1), denominator)?\n            }\n        } else {\n            let price_square: U512 = sqrt_price.widening_mul(sqrt_price);\n            anyhow::ensure!(\n                !price_square.is_zero(),\n                \"Cannot decode inverted price from zero sqrt_price_x96\"\n            );\n            let numerator = U512::from(divisor_base)\n                .checked_mul(U512::from(decimal_adjustment))\n                .and_then(|value| value.checked_mul(U512::from(fixed_scalar)))","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/defi/tick_map/sqrt_price_math.rs#L386-L422","documentation":"In the same inverted-price branch of `decode_sqrt_price_x96_to_price_tokens_adjusted`, the squared sqrt price (computed as U512) must be narrowed back to U256, and then `price_square * decimal_adjustment` is computed with checked multiplication. The library throws this error when either the U512→U256 narrowing fails or the multiplication overflows U256.","triggerScenarios":"Inverted price computation where sqrt_price is large enough that sqrt_price^2 does not fit in U256, or where multiplying the square by the decimal adjustment scalar overflows U256 — despite the earlier `price_square > max_square` guard allowing the path.","commonSituations":"Extremely high price ratios in pools with asymmetric decimals; edge cases near the guard threshold where the square fits but the adjustment multiplication does not.","solutions":["Correct token decimals metadata if decimal_adjustment is inflated by wrong decimals.","Pre-check `price_square <= U256::MAX / decimal_adjustment` conceptually and return a saturated/clamped price for extreme ratios instead.","Skip inversion: compute the non-inverted price and take its reciprocal in wider precision.","Perform the adjustment in U512 and narrow after division."],"exampleFix":"// before\nlet price = decode_sqrt_price_x96_to_price_tokens_adjusted(sqrt_price, b, q, true)?;\n// after\nlet max_adj = U256::MAX / decimal_adjustment;\nif price_square_candidate > max_adj {\n    return Ok(U256::ZERO); // saturated extreme price, mirroring guard above\n}\nlet price = decode_sqrt_price_x96_to_price_tokens_adjusted(sqrt_price, b, q, true)?;","handlingStrategy":"try-catch","validationCode":"fn adjustment_fits(price_square: U256, decimal_adjustment: U256) -> bool {\n    decimal_adjustment.is_zero() || price_square <= U256::MAX / decimal_adjustment\n}","typeGuard":null,"tryCatchPattern":"match decode_sqrt_price_x96_to_price_tokens_adjusted(sqrt_price, b, q, invert) {\n    Ok(p) if p.is_zero() => {\n        log::debug!(\"saturated/extreme price for sqrt_price {sqrt_price}\");\n        handle_extreme_price()\n    }\n    Ok(p) => p,\n    Err(e) if e.to_string().contains(\"denominator exceeds U256\") => fallback_wide_math(),\n    Err(e) => return Err(e),\n}","preventionTips":["Check token decimals metadata before trusting decimal_adjustment","Treat a zero returned price as the extreme-ratio signal and guard callers against division by it","Fall back to U512-based computation for pools near the representable bounds"],"tags":["math","u256-overflow","sqrt-price","defi"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}