{"record":{"id":"c657b80e72eb116e","repo":"nautechsystems/nautilus_trader","slug":"type-name-raw-value-raw-exceeds-raw-max-name","errorCode":null,"errorMessage":"{type_name} raw value {raw} exceeds {raw_max_name}={raw_max}","messagePattern":"(.+?) raw value (.+?) exceeds (.+?)=(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/decode.rs","lineNumber":127,"sourceCode":"        })?\n    } else if decimals > fixed_precision {\n        round_u256_half_even(amount, decimals - fixed_precision, type_name)?\n    } else {\n        amount\n    };\n\n    check_raw_range(raw, raw_max, type_name, raw_max_name)?;\n    Ok(raw)\n}\n\nfn check_raw_range(\n    raw: U256,\n    raw_max: U256,\n    type_name: &str,\n    raw_max_name: &str,\n) -> anyhow::Result<()> {\n    if raw > raw_max {\n        anyhow::bail!(\"{type_name} raw value {raw} exceeds {raw_max_name}={raw_max}\");\n    }\n\n    Ok(())\n}\n\nfn round_u256_half_even(amount: U256, excess: u8, type_name: &str) -> anyhow::Result<U256> {\n    let Some(divisor) = U256::from(10).checked_pow(U256::from(excess)) else {\n        // The divisor exceeds U256::MAX, so every U256 amount is below half a retained unit\n        return Ok(U256::ZERO);\n    };\n    let quotient = amount / divisor;\n    let remainder = amount % divisor;\n    let half = divisor / U256::from(2);\n\n    if remainder > half || (remainder == half && quotient.bit(0)) {\n        quotient.checked_add(U256::from(1)).ok_or_else(|| {\n            anyhow::anyhow!(\"{type_name} raw value overflows U256 while rounding half to even\")\n        })","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/decode.rs#L109-L145","documentation":"check_raw_range validates that a U256 raw value fits within a maximum representable value for a target type (Quantity, Price, or a scaled raw representation) and bails when raw > raw_max. This guards fixed-point conversions from silently wrapping or truncating when a decoded on-chain value exceeds the type's precision/width.","triggerScenarios":"Calling u256_to_quantity, u256_to_price, or scale_u256_to_raw with a decoded U256 (from an event log, reserves, or amounts) whose integer value exceeds the maximum raw value allowed by the target type's precision.","commonSituations":"Tokens with extreme supply/decimals producing amounts beyond the fixed-point raw max; malformed or malicious log data with huge values; decoding a non-standard token's balance/amount events with the standard decoder; scaling between precisions where the intermediate raw overflows the cap.","solutions":["Check the magnitude of the on-chain value before conversion and skip/reject out-of-range values","Verify the token's decimals and use a precision for the target type large enough for real values","Treat the offending log as malformed: log the tx/log id and exclude it from processing","Use U256-native or higher-precision types if your assets legitimately exceed the raw max"],"exampleFix":"// before: unchecked conversion of log amount\nlet qty = u256_to_quantity(raw_amount, decimals, precision)?;\n// after: pre-check range\nlet raw_max = max_raw_for_precision(precision);\nif raw_amount > raw_max {\n    tracing::warn!(\"skipping amount exceeding raw max: {raw_amount}\");\n    return Ok(None);\n}\nlet qty = u256_to_quantity(raw_amount, decimals, precision)?;","handlingStrategy":"validation","validationCode":"let raw_max = max_raw_for_precision(precision);\nif raw_amount > raw_max {\n    return Ok(None); // skip out-of-range value\n}","typeGuard":"fn fits_raw_max(raw: U256, raw_max: U256) -> bool { raw <= raw_max }","tryCatchPattern":"match u256_to_quantity(raw_amount, decimals, precision) {\n    Ok(q) => Some(q),\n    Err(e) if e.to_string().contains(\"exceeds\") => {\n        tracing::warn!(\"amount {raw_amount} exceeds raw max; skipping log\");\n        None\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Choose precision wide enough for the tokens you index","Pre-check magnitudes of decoded U256 values","Treat extreme values as malformed data and quarantine the log"],"tags":["blockchain","overflow","precision","decoding"],"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"}