{"record":{"id":"4319c60301f99085","repo":"nautechsystems/nautilus_trader","slug":"finalized-swap-side-does-not-match-sell-order","errorCode":null,"errorMessage":"Finalized Swap side {} does not match Sell order","messagePattern":"Finalized Swap side (.+?) does not match Sell order","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":2281,"sourceCode":"        included.receipt.block_hash,\n        block.hash\n    );\n    let timestamp_ns = block\n        .timestamp\n        .checked_mul(NANOSECONDS_IN_SECOND)\n        .ok_or_else(|| anyhow::anyhow!(\"Finalized block timestamp overflows nanoseconds\"))?;\n    let mut swap = event.to_pool_swap(\n        plan.pool.chain.clone(),\n        plan.instrument_id,\n        plan.pool.pool_identifier,\n        UnixNanos::from(timestamp_ns),\n    );\n    swap.calculate_trade_info(&plan.pool.token0, &plan.pool.token1, None)?;\n    let trade = swap\n        .trade_info\n        .as_ref()\n        .ok_or_else(|| anyhow::anyhow!(\"Finalized Swap has no calculated trade information\"))?;\n    anyhow::ensure!(\n        trade.order_side == OrderSide::Sell,\n        \"Finalized Swap side {} does not match Sell order\",\n        trade.order_side\n    );\n    let gas_cost = included\n        .receipt\n        .effective_gas_price\n        .checked_mul(U256::from(included.receipt.gas_used))\n        .ok_or_else(|| anyhow::anyhow!(\"Finalized transaction gas commission overflow\"))?;\n    let commission = Money::from_u256(gas_cost, plan.pool.chain.native_currency())?;\n    let trade_digest = keccak256(format!(\"{}:{}\", included.tx_hash, swap.log_index));\n    let trade_digest = trade_digest.to_string();\n    let trade_id = TradeId::new_checked(&trade_digest[2..38])?;\n\n    if plan\n        .order\n        .trade_ids()\n        .iter()","sourceCodeStart":2263,"sourceCodeEnd":2299,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/d1527c24afdf475115785557f89a55c3e336c51f/crates/adapters/blockchain/src/execution/client.rs#L2263-L2299","documentation":"Side check in emit_finalized_swap_fill: the executor only sells the base token for quote, so the order is a Sell and the calculated trade.side derived from the Swap event must equal OrderSide::Sell. The mismatch means the decoded swap moved the tokens in the opposite direction to what the order implies.","triggerScenarios":"Pool registered with token0/token1 reversed relative to on-chain order, making the direction derivation flip; a swap direction (zero_for_one) inverted between quoting and signing; submitting a Buy order through this sell-only execution path.","commonSituations":"Pool metadata imported with token0/token1 swapped; a strategy configured to buy the base token although the adapter only supports selling base for quote; direction flags computed from a stale pool snapshot.","solutions":["Compare the pool's token0/token1 registration against the on-chain pool contract (slot0/token0/token1 getters).","Confirm the order submitted is a Sell of the base instrument, matching the executor's supported direction.","Re-derive zero_for_one from the current pool ordering before signing.","Re-register the pool with corrected token ordering and let reconciliation reprocess."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before submitting:\nlet expected_side = OrderSide::Sell; // this executor only sells base\nif order.side() != expected_side {\n    anyhow::bail!(\"only Sell orders supported by the swap executor\");\n}\n// verify token ordering against chain\nassert_eq!(pool.token0.address, chain_pool.token0().await?);","typeGuard":"fn order_supported_by_swap_executor(order: &Order) -> bool {\n    order.side() == OrderSide::Sell\n}","tryCatchPattern":"Catch the side mismatch, halt fills for that pool, and re-validate pool token registration before any retry; treat as a data-integrity fault, not a transient error.","preventionTips":["Validate pool token0/token1 against the on-chain contract at registration time.","Restrict strategy submission to Sell orders on this execution route."],"tags":["blockchain","order-side","swap-fill","pool-metadata"],"backgroundTag":"order-side-mismatch","analyzedSha":"d1527c24afdf475115785557f89a55c3e336c51f","analyzedAt":"2026-08-21T11:28:30.864Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}