From bbfaf8bbcfb9fa0890e9d7bff21643c77af6d74c Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 31 Oct 2024 11:59:04 +0100 Subject: [PATCH] change trade intrusctions calculation --- integration-tests/src/ice/omni.rs | 34 ++++--------- pallets/ice/src/lib.rs | 80 ++++++++++++++----------------- 2 files changed, 47 insertions(+), 67 deletions(-) diff --git a/integration-tests/src/ice/omni.rs b/integration-tests/src/ice/omni.rs index e432da97d..99161e76a 100644 --- a/integration-tests/src/ice/omni.rs +++ b/integration-tests/src/ice/omni.rs @@ -64,32 +64,18 @@ fn solver_should_find_solution_with_one_intent() { assert_eq!( trades, - vec![ - pallet_ice::types::TradeInstruction::SwapExactIn { + vec![pallet_ice::types::TradeInstruction::SwapExactIn { + asset_in: 0, + asset_out: 27, + amount_in: 99853645824127, + amount_out: 1148028627591, + route: pallet_ice::types::BoundedRoute::try_from(vec![Trade { + pool: PoolType::Omnipool, asset_in: 0, - asset_out: 1, - amount_in: 99853645824127, - amount_out: 17567099869, - route: pallet_ice::types::BoundedRoute::try_from(vec![Trade { - pool: PoolType::Omnipool, - asset_in: 0, - asset_out: 1, - }]) - .unwrap() - }, - pallet_ice::types::TradeInstruction::SwapExactOut { - asset_in: 1, asset_out: 27, - amount_in: 16161402305, - amount_out: 1148028627591, - route: pallet_ice::types::BoundedRoute::try_from(vec![Trade { - pool: PoolType::Omnipool, - asset_in: 1, - asset_out: 27, - }]) - .unwrap() - } - ] + }]) + .unwrap() + },] ); assert_eq!(score, 1000000); diff --git a/pallets/ice/src/lib.rs b/pallets/ice/src/lib.rs index f1b819a8f..e9b1efeee 100644 --- a/pallets/ice/src/lib.rs +++ b/pallets/ice/src/lib.rs @@ -520,53 +520,47 @@ impl Pallet { let mut matched_amounts = Vec::new(); let mut trades_instructions = Vec::new(); - // Sell all for lrna - for (asset_id, amount) in amounts_in.iter() { - let amount_out = *amounts_out.get(asset_id).unwrap_or(&0u128); - - matched_amounts.push((*asset_id, (*amount).min(amount_out))); - - if *amount > amount_out { - let route = T::RoutingSupport::get_route(*asset_id, T::HubAssetId::get()); - let diff = amount.saturating_sub(amount_out); - - let lrna_bought = T::RoutingSupport::calculate_amount_out(&route, diff)?; - lrna_aquired.saturating_accrue(lrna_bought); - trades_instructions.push(TradeInstruction::SwapExactIn { - asset_in: *asset_id, - asset_out: T::HubAssetId::get(), - amount_in: amount.saturating_sub(amount_out), //Swap only difference - amount_out: lrna_bought, - route: BoundedRoute::try_from(route).unwrap(), - }); + let mut delta_in: BTreeMap = amounts_in.clone(); + let mut delta_out: BTreeMap = amounts_out.clone(); + + // Calculate deltas to trade + for (asset_id, amount_out) in amounts_out.iter() { + if let Some((_, amount_in)) = amounts_in.get_key_value(asset_id) { + if *amount_out == *amount_in { + // nothing to trade here, all matched + matched_amounts.push((*asset_id, *amount_out)); + } else if *amount_out > *amount_in { + // there is something left to buy + matched_amounts.push((*asset_id, *amount_out - *amount_in)); + delta_out.insert(*asset_id, *amount_out - *amount_in); + } else { + // there is something left to sell + matched_amounts.push((*asset_id, *amount_in - *amount_out)); + delta_in.insert(*asset_id, *amount_in - *amount_out); + } + } else { + // there is no sell of this asset, only buy + delta_out.insert(*asset_id, *amount_out); } } - let mut lrna_sold = 0u128; - - for (asset_id, amount) in amounts_out { - let amount_in = *amounts_in.get(&asset_id).unwrap_or(&0u128); - - if amount > amount_in { - let route = T::RoutingSupport::get_route(T::HubAssetId::get(), asset_id); - let diff = amount.saturating_sub(amount_in); - let lrna_in = T::RoutingSupport::calculate_amount_in(&route, diff)?; - lrna_sold.saturating_accrue(lrna_in); - trades_instructions.push(TradeInstruction::SwapExactOut { - asset_in: T::HubAssetId::get(), - asset_out: asset_id, - amount_in: lrna_in, - amount_out: amount.saturating_sub(amount_in), //Swap only difference - route: BoundedRoute::try_from(route).unwrap(), - }); - } + // delta_in count should equal to delta_out count. + debug_assert_eq!(delta_in.len(), delta_out.len()); + + // Try to figure out what trades to do for deltas + // TODO: this might need some adjustments, as it might no be possible to sell exact amount of asset in for asset out - might try different pair if more assets + for ((asset_out, amount_out), (asset_in, amount_in)) in delta_out.iter().zip(delta_in.iter()) { + let route = T::RoutingSupport::get_route(*asset_in, *asset_out); + let amount_bought = T::RoutingSupport::calculate_amount_out(&route, *amount_in)?; + debug_assert!(amount_bought >= *amount_out); + trades_instructions.push(TradeInstruction::SwapExactIn { + asset_in: *asset_in, + asset_out: *asset_out, + amount_in: *amount_in, + amount_out: *amount_out, + route: BoundedRoute::try_from(route).unwrap(), + }); } - assert!( - lrna_aquired >= lrna_sold, - "lrna_aquired < lrna_sold ({} < {})", - lrna_aquired, - lrna_sold - ); let score = Self::score_solution(resolved_intents.len() as u128, matched_amounts).map_err(|_| ())?; Ok((trades_instructions, score))