{"record":{"id":"a1b2b8ba08697942","repo":"nautechsystems/nautilus_trader","slug":"mul-div-overflow","errorCode":null,"errorMessage":"mul_div overflow","messagePattern":"mul_div overflow","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/defi/tick_map/sqrt_price_math.rs","lineNumber":64,"sourceCode":"    // To maintain precision, we'll calculate: sqrt(amount0 * 2^192 / amount1)\n    // This is because: sqrt(amount0/amount1) * 2^96 = sqrt(amount0 * 2^192 / amount1)\n\n    // First, scale amount0 by 2^192\n    let q192 = U256::from(1u128) << 192;\n\n    // Check if amount0 * 2^192 would overflow\n    if amount0_u256 > U256::MAX / q192 {\n        // If it would overflow, we need to handle it differently\n        // We'll use: sqrt(amount0) * 2^96 / sqrt(amount1)\n        let sqrt_amount0 = FullMath::sqrt(amount0_u256);\n        let sqrt_amount1 = FullMath::sqrt(amount1_u256);\n\n        assert!(!sqrt_amount1.is_zero(), \"Division by zero in sqrt\");\n\n        let q96 = U256::from(1u128) << 96;\n\n        // Use FullMath for precise division\n        let result = FullMath::mul_div(sqrt_amount0, q96, sqrt_amount1).expect(\"mul_div overflow\");\n\n        // Convert to U160, truncating if necessary\n        return if result > U256::from(U160::MAX) {\n            U160::MAX\n        } else {\n            U160::from(result)\n        };\n    }\n\n    // Standard path: calculate (amount0 * 2^192) / amount1, then sqrt\n    let ratio_q192 = FullMath::mul_div(amount0_u256, q192, amount1_u256).expect(\"mul_div overflow\");\n\n    // Take the square root of the ratio\n    let sqrt_result = FullMath::sqrt(ratio_q192);\n\n    // Convert to U160, truncating if necessary\n    if sqrt_result > U256::from(U160::MAX) {\n        U160::MAX","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/defi/tick_map/sqrt_price_math.rs#L46-L82","documentation":"encode_sqrt_ratio_x96 computes sqrt(amount0/amount1) * 2^96 using FullMath::mul_div; the expect panics when mul_div returns None. On the sqrt branch this happens when sqrt_amount0 * 2^96 overflows or sqrt_amount1 is effectively zero relative to the numerator, so the exact multiplication-division cannot be represented.","triggerScenarios":"Calling encode_sqrt_ratio_x96 with extreme amount ratios — sqrt_amount0 * q96 not fitting in U256, or sqrt_amount1 near zero producing an unrepresentable quotient — commonly from hand-constructed extreme prices in tests or malformed token amounts.","commonSituations":"Tests or fixtures encoding prices for tokens with wildly different decimals; callers passing amounts that were not pre-scaled; price ratios beyond U256 fixed-point capacity.","solutions":["Pre-scale inputs so amount0 and amount1 are comparable magnitudes (adjust for token decimals) before encoding.","Replace expect with match on the Option and fall back to a clamped/saturating computation or return an error.","Check for zero/near-zero denominator amounts before calling."],"exampleFix":"// before\nlet result = FullMath::mul_div(sqrt_amount0, q96, sqrt_amount1).expect(\"mul_div overflow\");\n// after\nlet result = FullMath::mul_div(sqrt_amount0, q96, sqrt_amount1)\n    .unwrap_or(U256::from(U160::MAX)); // or return an error to the caller","handlingStrategy":"validation","validationCode":"if sqrt_amount1.is_zero() || sqrt_amount0.checked_mul(q96).is_none() { return Err(anyhow!(\"inputs out of representable range\")); }","typeGuard":"fn encodable(a0: U256, a1: U256) -> bool { !a1.is_zero() && a0 <= U256::MAX >> 96 }","tryCatchPattern":"let result = FullMath::mul_div(sqrt_amount0, q96, sqrt_amount1)\n    .unwrap_or_else(|| return default_sqrt_price());","preventionTips":["Scale amounts for token decimals before encoding prices.","Reject zero or near-zero denominators early.","Avoid pre-multiplied Q64.96 inputs to this function."],"tags":["rust","panic","arithmetic-overflow","uniswap-v3","fixed-point-math"],"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-14T00:17:10.932Z"}