{"record":{"id":"83fc2296699ee7bb","repo":"nautechsystems/nautilus_trader","slug":"cannot-calculate-execution-price-with-zero-amounts","errorCode":null,"errorMessage":"Cannot calculate execution price with zero amounts","messagePattern":"Cannot calculate execution price with zero amounts","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/defi/data/swap_trade_info.rs","lineNumber":399,"sourceCode":"    /// ```text\n    /// price_raw = (quote_amount * 10^base_decimals * 10^FIXED_PRECISION) / (base_amount * 10^quote_decimals)\n    /// ```\n    ///\n    /// # Base/Quote Logic\n    /// - When `is_inverted=false`: quote=token1, base=token0 → price = amount1/amount0\n    /// - When `is_inverted=true`: quote=token0, base=token1 → price = amount0/amount1\n    ///\n    /// # Use Cases\n    /// - Trade accounting and P&L calculation\n    /// - Comparing quoted vs executed prices\n    /// - Cost analysis (includes all fees and price impact)\n    /// - Performance reporting\n    fn execution_price(&self) -> anyhow::Result<Price> {\n        let amount0 = self.raw_swap_data.amount0.unsigned_abs();\n        let amount1 = self.raw_swap_data.amount1.unsigned_abs();\n\n        if amount0.is_zero() || amount1.is_zero() {\n            anyhow::bail!(\"Cannot calculate execution price with zero amounts\");\n        }\n\n        // Determine base and quote amounts/decimals based on inversion\n        let (quote_amount, base_amount, quote_decimals, base_decimals) = if self.is_inverted {\n            // inverted: token0=quote, token1=base\n            (amount0, amount1, self.token0.decimals, self.token1.decimals)\n        } else {\n            // not inverted: token0=base, token1=quote\n            (amount1, amount0, self.token1.decimals, self.token0.decimals)\n        };\n\n        FullMath::check_decimal_exponent(base_decimals)?;\n        FullMath::check_decimal_exponent(quote_decimals)?;\n\n        let exponent =\n            i16::from(base_decimals) + i16::from(FIXED_PRECISION) - i16::from(quote_decimals);\n        let price_raw_u256 = if exponent >= 0 {\n            let exponent = u8::try_from(exponent)","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/defi/data/swap_trade_info.rs#L381-L417","documentation":"execution_price on SwapTradeInfo derives the swap's effective execution price from raw_swap_data.amount0/amount1 and token decimals. If either amount is zero the ratio is undefined, so the method bails instead of producing a zero or infinite price. This is a data-integrity guard against malformed or degenerate swap events.","triggerScenarios":"Calling execution_price on a SwapTradeInfo whose raw_swap_data.amount0 or amount1 is zero — e.g. zero-value swap events, truncated/mis-decoded event logs, or synthetic swaps with no amounts.","commonSituations":"Indexing real chain events where some swaps emit amount0=0 or amount1=0 (single-sided or minimum-liquidity artifacts); bad ABI decoding filling zeros; flash-swap callbacks with zero amounts.","solutions":["Check amount0 and amount1 are non-zero before calling execution_price and skip such swaps","Filter out zero-amount swap events at ingestion/decoding time so they never reach analysis","If the zero amount is legitimate, treat the swap as non-price-forming and exclude it from price statistics","Re-verify the event decoding (decimals, signed fields) if amounts should not be zero"],"exampleFix":"// before\nlet price = swap.execution_price()?;\n// after\nif swap.raw_swap_data.amount0.unsigned_abs().is_zero()\n    || swap.raw_swap_data.amount1.unsigned_abs().is_zero()\n{\n    return Ok(None); // no meaningful execution price\n}\nlet price = swap.execution_price()?;","handlingStrategy":"validation","validationCode":"let a0 = swap.raw_swap_data.amount0.unsigned_abs();\nlet a1 = swap.raw_swap_data.amount1.unsigned_abs();\nif a0.is_zero() || a1.is_zero() { /* skip: no execution price */ }","typeGuard":"fn has_pricing_amounts(s: &SwapTradeInfo) -> bool {\n    !s.raw_swap_data.amount0.unsigned_abs().is_zero()\n        && !s.raw_swap_data.amount1.unsigned_abs().is_zero()\n}","tryCatchPattern":"match swap.execution_price() {\n    Ok(p) => Some(p),\n    Err(e) if e.to_string().contains(\"zero amounts\") => None,\n    Err(e) => return Err(e),\n}","preventionTips":["Filter zero-amount swap events at decoding time","Treat single-sided/zero-value swaps as non-price-forming","Audit ABI decoding so amounts aren't silently zero","Skip rather than propagate when the price metric is optional"],"tags":["rust","defi","swap","zero-amount","price"],"backgroundTag":"empty-required-field","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"}