{"record":{"id":"69757bf66db55f9b","repo":"nautechsystems/nautilus_trader","slug":"overflow-in-money-from-mantissa-exponent","errorCode":null,"errorMessage":"Overflow in Money::from_mantissa_exponent","messagePattern":"Overflow in Money::from_mantissa_exponent","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/types/money.rs","lineNumber":281,"sourceCode":"    /// Creates a new [`Money`] from a mantissa/exponent pair using pure integer arithmetic.\n    ///\n    /// The value is `mantissa * 10^exponent`. This avoids all floating-point and Decimal\n    /// operations, making it ideal for exchange data that arrives as mantissa/exponent pairs.\n    ///\n    /// # Panics\n    ///\n    /// Panics if the resulting raw value exceeds [`MONEY_RAW_MAX`] or [`MONEY_RAW_MIN`].\n    #[must_use]\n    pub fn from_mantissa_exponent(mantissa: i64, exponent: i8, currency: Currency) -> Self {\n        check_fixed_precision(currency.precision).expect_display(FAILED);\n\n        if mantissa == 0 {\n            return Self { raw: 0, currency };\n        }\n\n        let raw_i128 =\n            mantissa_exponent_to_fixed_i128(i128::from(mantissa), exponent, currency.precision)\n                .expect(\"Overflow in Money::from_mantissa_exponent\");\n\n        #[allow(\n            clippy::useless_conversion,\n            reason = \"i128 to MoneyRaw is real when not high-precision\"\n        )]\n        let raw: MoneyRaw = raw_i128\n            .try_into()\n            .expect(\"Raw value exceeds MoneyRaw range in Money::from_mantissa_exponent\");\n        assert!(\n            raw >= MONEY_RAW_MIN && raw <= MONEY_RAW_MAX,\n            \"`raw` value {raw} exceeded bounds [{MONEY_RAW_MIN}, {MONEY_RAW_MAX}] for Money\"\n        );\n\n        Self { raw, currency }\n    }\n\n    /// Creates a new [`Money`] instance with a value of zero with the given [`Currency`].\n    ///","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/types/money.rs#L263-L299","documentation":"Money::from_mantissa_exponent builds a Money from a mantissa and decimal exponent, converting the mantissa into a fixed-point raw via mantissa_exponent_to_fixed_i128 for the currency precision. When the intermediate i128 computation overflows (mantissa too large for the exponent/precision combination) the expect panics with this message.","triggerScenarios":"Money::from_mantissa_exponent(mantissa, exponent, currency) with a mantissa whose magnitude, when adjusted by exponent to the currency precision, exceeds i128 range — e.g. i64::MAX mantissa with a negative exponent demanding many extra digits.","commonSituations":"Constructing money amounts from raw exchange-feed mantissa/exponent pairs where the exponent assumption is wrong (off-by-N in exponent parsing), or accumulating huge totals before conversion.","solutions":["Validate that mantissa magnitude is compatible with exponent and currency.precision before calling.","Normalize the exponent first (shift digits so the mantissa is small) before constructing Money.","Use the Money::new / from raw constructors with validated Decimal inputs instead."],"exampleFix":"// before\nlet m = Money::from_mantissa_exponent(i64::MAX, -30, USD); // panics\n// after\nlet dec = Decimal::new(mantissa, exponent.unsigned_abs()); // normalize via Decimal\nlet m = Money::new(dec, USD);","handlingStrategy":"validation","validationCode":"let scaled = (mantissa as i128).checked_mul(10i128.pow(exponent.unsigned_abs() + currency.precision as u32));\nif scaled.is_none() || scaled.unwrap().abs() > i128::MAX / 2 {\n    return Err(\"mantissa/exponent out of representable range\");\n}\nlet m = Money::from_mantissa_exponent(mantissa, exponent, currency);","typeGuard":"fn mantissa_fits(mantissa: i64, exponent: i8, precision: u8) -> bool {\n    (mantissa as i128)\n        .checked_mul(10i128.pow((exponent.unsigned_abs() as u32).saturating_add(precision as u32)))\n        .is_some()\n}","tryCatchPattern":null,"preventionTips":["Normalize mantissa/exponent pairs from feeds into Decimal before constructing Money.","Verify exponent parsing conventions of each venue (some use negative exponents differently).","Range-check extreme amounts before conversion."],"tags":["rust","overflow","money","fixed-point"],"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"}