{"record":{"id":"e5e5a29159795e34","repo":"nautechsystems/nautilus_trader","slug":"order-amount-scaling-overflow","errorCode":null,"errorMessage":"Order amount scaling overflow","messagePattern":"Order amount scaling overflow","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":2454,"sourceCode":"}\n\n/// Converts a base-denominated order quantity into raw token units with exact integer\n/// scaling by the base token decimals.\n///\n/// `Quantity::raw` is scaled to the greater of its declared precision and `FIXED_PRECISION`;\n/// token amounts are scaled to the token's decimals. Quantities not exactly representable in\n/// token units are rejected rather than rounded.\nfn quantity_to_raw_amount(quantity: Quantity, decimals: u8) -> anyhow::Result<U256> {\n    if quantity.is_zero() {\n        anyhow::bail!(\"Order quantity must be positive\");\n    }\n\n    let raw = U256::from(quantity.raw);\n    let raw_precision = quantity.precision.max(FIXED_PRECISION);\n    if decimals >= raw_precision {\n        let scale = U256::from(10u64)\n            .checked_pow(U256::from(decimals - raw_precision))\n            .ok_or_else(|| anyhow::anyhow!(\"Order amount scaling overflow\"))?;\n        raw.checked_mul(scale).ok_or_else(|| {\n            anyhow::anyhow!(\"Order amount overflow scaling quantity to raw token units\")\n        })\n    } else {\n        let divisor = U256::from(10u64)\n            .checked_pow(U256::from(raw_precision - decimals))\n            .ok_or_else(|| anyhow::anyhow!(\"Order amount scaling overflow\"))?;\n        if !(raw % divisor).is_zero() {\n            anyhow::bail!(\n                \"Order quantity {quantity} is not exactly representable in {decimals} base token decimals\"\n            );\n        }\n        Ok(raw / divisor)\n    }\n}\n\n/// Extracts the positive output amount from an exact-input swap quote.\nfn exact_output_amount(quote: &SwapQuote, zero_for_one: bool) -> anyhow::Result<U256> {","sourceCodeStart":2436,"sourceCodeEnd":2472,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/2114cf6f761429e0adb5ca9596fcd7b895b16011/crates/adapters/blockchain/src/execution/client.rs#L2436-L2472","documentation":"Thrown in quantity_to_raw_amount (client.rs:2444) on the decimals >= raw_precision branch: it computes 10^(decimals - raw_precision) with checked_pow, and the power overflows U256 when the exponent exceeds 77 (10^78 > 2^256). raw_precision is max(quantity.precision, FIXED_PRECISION), so this fires for tokens whose declared decimals are implausibly large.","triggerScenarios":"Order submission for a token whose decimals metadata exceeds ~77 (u8 allows up to 255), e.g. 100 or 255 returned by a misbehaving ERC20 or a bad metadata source; a pool/token record with corrupted decimals.","commonSituations":"Token metadata scraped from a proxy contract that reverts and gets defaulted to a sentinel; hand-edited config with a typo in decimals (e.g., 180 instead of 18); test tokens with arbitrary decimals.","solutions":["Check the token's decimals() on-chain and in your pool/token records; real tokens are 0-18 (rarely up to ~36).","Fix the decimals value at its source rather than special-casing the order.","Validate decimals <= 18 (or at most 77) before submitting orders.","Reject the token for execution if it genuinely advertises absurd decimals."],"exampleFix":"// before\nlet amount = quantity_to_raw_amount(qty, token.decimals)?; // decimals = 180\n\n// after\nassert!(token.decimals <= 18, \"suspicious decimals {}\", token.decimals);\nlet amount = quantity_to_raw_amount(qty, token.decimals)?;","handlingStrategy":"validation","validationCode":"// before submitting any order:\nif token.decimals > 18 {\n    anyhow::bail!(\"token {} reports implausible decimals {}\", token.address, token.decimals);\n}","typeGuard":"fn decimals_are_plausible(decimals: u8) -> bool { decimals <= 18 }","tryCatchPattern":"Treat as a permanent data error: fail the token/order, fix the metadata source, never retry the same value.","preventionTips":["Validate token metadata once at registration against the on-chain decimals() call.","Alert on any token whose decimals exceed 18."],"tags":["blockchain","token-decimals","arithmetic-overflow","order-submission"],"backgroundTag":"token-decimals-overflow","analyzedSha":"2114cf6f761429e0adb5ca9596fcd7b895b16011","analyzedAt":"2026-08-21T11:28:30.864Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}