{"record":{"id":"7b373cb90955dfbc","repo":"nautechsystems/nautilus_trader","slug":"derived-minimum-output-is-zero-for-quoted-output","errorCode":null,"errorMessage":"Derived minimum output is zero for quoted output {quoted_amount_out} at {slippage_bps} bps slippage","messagePattern":"Derived minimum output is zero for quoted output (.+?) at (.+?) bps slippage","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":5295,"sourceCode":"    if !amount.is_negative() {\n        anyhow::bail!(\"Swap quote output amount {amount} is not a positive output\");\n    }\n    Ok(amount.unsigned_abs())\n}\n\n/// Derives the minimum output accepted for the swap: the quoted output reduced by\n/// `slippage_bps`, in exact integer arithmetic. Rejects a zero minimum, which would leave\n/// the swap without slippage protection.\nfn derive_min_amount_out(quoted_amount_out: U256, slippage_bps: u32) -> anyhow::Result<U256> {\n    if slippage_bps >= BPS_DENOMINATOR {\n        anyhow::bail!(\"Slippage {slippage_bps} bps must be below {BPS_DENOMINATOR}\");\n    }\n    let min_amount_out = quoted_amount_out\n        .checked_mul(U256::from(BPS_DENOMINATOR - slippage_bps))\n        .and_then(|scaled| scaled.checked_div(U256::from(BPS_DENOMINATOR)))\n        .ok_or_else(|| anyhow::anyhow!(\"Minimum output derivation overflow\"))?;\n    if min_amount_out.is_zero() {\n        anyhow::bail!(\n            \"Derived minimum output is zero for quoted output {quoted_amount_out} at {slippage_bps} bps slippage\"\n        );\n    }\n    Ok(min_amount_out)\n}\n\nimpl BlockchainExecutionClient {\n    async fn build_execution_verification_migration(\n        &self,\n        snapshot: ExecutionVerificationMigrationSnapshot,\n        finalized: VerifiedBlockHeader,\n        finalized_headers: &[VerifiedBlockHeader],\n        nonce_verification: &Verified<u64>,\n    ) -> anyhow::Result<ExecutionVerificationMigration> {\n        let next_canonical_nonce = nonce_verification.value;\n        let mut hashes_by_intent: HashMap<i64, Vec<&ExecutionTransactionHashRow>> = HashMap::new();\n        for hash in &snapshot.hashes {\n            hashes_by_intent","sourceCodeStart":5277,"sourceCodeEnd":5313,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L5277-L5313","documentation":"After applying slippage, if the derived minimum output rounds down to zero the swap would have no slippage protection (any output accepted). The adapter bails with the quoted output and slippage values to force the caller to use a tighter slippage or larger trade size.","triggerScenarios":"derive_min_amount_out with a very small quoted_amount_out relative to slippage_bps, e.g. quoted output of a few wei with 1000+ bps slippage, so quoted * (10000-bps) / 10000 truncates to 0.","commonSituations":"Tiny dust-sized swaps; extremely wide slippage tolerance on a small quote; illiquid pool returning near-zero quotes.","solutions":["Reduce slippage_bps so the derived minimum stays positive","Increase the trade size; the quoted output is too small to protect","Treat as dust and skip the trade; failing open with min 0 is unsafe"],"exampleFix":"// before\nlet min_out = derive_min_amount_out(U256::from(3u8), 5000)?; // -> 0\n// after\nlet min_out = derive_min_amount_out(U256::from(3_000_000u32), 100)?; // keep min > 0","handlingStrategy":"validation","validationCode":"let bps = slippage_bps.min(9_999);\nif quoted_amount_out * U256::from(BPS_DENOMINATOR - bps) < U256::from(BPS_DENOMINATOR) {\n    return Err(anyhow::anyhow!(\"quote too small for slippage; min would round to 0\"));\n}","typeGuard":null,"tryCatchPattern":"match derive_min_amount_out(quoted, bps) {\n    Ok(min) => swap(min),\n    Err(e) if e.to_string().contains(\"is zero\") => skip_dust_trade(),\n    Err(e) => return Err(e),\n}","preventionTips":["Pre-check quoted output magnitude against slippage before submitting","Never accept min_amount_out == 0; skip or resize the trade"],"tags":["blockchain","slippage","overflow"],"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"}