{"record":{"id":"4fb0f6ef1bc41748","repo":"nautechsystems/nautilus_trader","slug":"raw-wei-value-exceeds-128-bit-range","errorCode":null,"errorMessage":"raw wei value exceeds 128-bit range","messagePattern":"raw wei value exceeds 128-bit range","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/defi/types/money.rs","lineNumber":62,"sourceCode":"    /// # Panics\n    ///\n    /// Panics if `currency.precision` is not 18, or if the raw wei value exceeds the\n    /// signed 128-bit range.\n    pub fn from_wei<U>(raw_wei: U, currency: Currency) -> Self\n    where\n        U: Into<U256>,\n    {\n        assert!(\n            currency.precision == 18,\n            \"`from_wei` requires a currency with precision 18, was {} for {}\",\n            currency.precision,\n            currency.code,\n        );\n\n        let raw_u256: U256 = raw_wei.into();\n        let raw_u128: u128 = raw_u256\n            .try_into()\n            .expect(\"raw wei value exceeds 128-bit range\");\n\n        assert!(\n            raw_u128 <= i128::MAX as u128,\n            \"raw wei value exceeds signed 128-bit range\"\n        );\n\n        let raw_i128: i128 = raw_u128 as i128;\n        Self::from_raw(raw_i128, currency)\n    }\n\n    /// Converts this [`Money`] instance to raw wei value.\n    ///\n    /// # Panics\n    ///\n    /// Panics if `self.currency.precision` is not 18 or `self.raw` is negative.\n    /// For other precisions convert to precision 18 first.\n    #[must_use]\n    pub fn to_wei(&self) -> U256 {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/defi/types/money.rs#L44-L80","documentation":"Money::from_wei accepts a raw wei value as U256 but the internal fixed-precision representation only stores values up to i128. The U256-to-u128 TryInto conversion is unwrapped with expect, so any wei amount larger than u128::MAX panics with this message (a follow-up assert also rejects values above i128::MAX). The library throws it because amounts exceeding the native integer width cannot be represented losslessly in Money.","triggerScenarios":"Calling Money::from_wei (or its Python/FFI wrapper money_from_wei) with a raw wei value > u128::MAX (≈3.4e38), e.g. huge token supplies or overflowed aggregation results, or passing a negative/wrapped U256 produced by a downstream ABI decode bug.","commonSituations":"Indexing a token with an enormous total supply (or high decimals) whose raw wei amounts overflow 128 bits; feeding raw on-chain values from a mis-decoded log; upgrading a data pipeline to aggregate balances across many wallets so the sum overflows.","solutions":["Check the raw value before conversion: only call from_wei when raw_wei <= U256::from(u128::MAX) (and <= i128::MAX if sign matters).","Reject or clamp the value at the data-ingestion layer; skip the token/instrument or log a warning instead of converting.","Verify the ABI/log decoding that produced the U256 — a decode bug can yield spuriously large values.","If such magnitudes are legitimate, request upstream support for a big-number (U256) representation instead of working around it."],"exampleFix":"// before\nlet money = Money::from_wei(raw_wei_u256, currency); // panics if raw > u128::MAX\n// after\nlet money = if raw_wei_u256 <= U256::from(u128::MAX) {\n    Money::from_wei(raw_wei_u256, currency)\n} else {\n    return Err(\"wei amount exceeds 128-bit range\".to_string());\n};","handlingStrategy":"validation","validationCode":"use alloy_primitives::U256;\nfn wei_fits_u128(raw_wei: U256) -> bool {\n    raw_wei <= U256::from(i128::MAX)\n}","typeGuard":"fn fits_i128(raw: U256) -> Option<u128> {\n    let r: u128 = raw.try_into().ok()?;\n    (r <= i128::MAX as u128).then_some(r)\n}","tryCatchPattern":null,"preventionTips":["Range-check raw wei against u128/i128 bounds before any from_wei conversion.","Sanity-check token supplies and decoded amounts at ingestion time.","Watch for double-scaling of wei values in adapter code."],"tags":["rust","panic","overflow","defi","fixed-precision"],"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"}