Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion artifacts/checksums.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
40bc067d21fb1a80e05b57d8f95cb10296dc1db322dddb56daf68d6f53ad64c3 dex_aggregator.wasm
6751147df3820468674b76e49dd069642513f36b59404847de1ca5e9ce4eca7c dex_aggregator.wasm
46dcce8409830a30b424dd342887f1cc203ef9c203f4b754b172c2203a7c0ad7 mock_swap.wasm
Binary file modified artifacts/dex_aggregator.wasm
Binary file not shown.
32 changes: 28 additions & 4 deletions contracts/dex_aggregator/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,27 @@ pub fn create_swap_cosmos_msg(
}
}
Operation::OrderbookSwap(ob_op) => {
let tick_size_atomic = ob_op.min_quantity_tick_size;

if tick_size_atomic.is_zero() {
return Err(ContractError::Std(StdError::generic_err(
"min_quantity_tick_size cannot be zero",
)));
}

let ratio = amount / tick_size_atomic;
let rounded_atomic_amount = ratio * tick_size_atomic;

if rounded_atomic_amount.is_zero() {
return Ok(CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: env.contract.address.to_string(),
msg: to_json_binary(&{})?,
funds: vec![],
}));
}

let quantity_for_query_fp = FPDecimal::from(rounded_atomic_amount);

let offer_denom =
match &ob_op.offer_asset_info {
amm::AssetInfo::NativeToken { denom } => denom.clone(),
Expand All @@ -150,7 +171,7 @@ pub fn create_swap_cosmos_msg(
};

let simulate_msg = msg::orderbook::QueryMsg::GetOutputQuantity {
from_quantity: amount.into(),
from_quantity: quantity_for_query_fp,
source_denom: offer_denom,
target_denom: target_denom.clone(),
};
Expand All @@ -159,18 +180,21 @@ pub fn create_swap_cosmos_msg(
.query_wasm_smart(&ob_op.swap_contract, &simulate_msg)?;
let expected_output_fp = simulation_response.result_quantity;
let slippage = FPDecimal::from_str("0.005")?;
let min_output_fp = expected_output_fp * (FPDecimal::ONE - slippage);

let min_output_with_slippage_fp = expected_output_fp * (FPDecimal::ONE - slippage);
let floored_min_output_fp = min_output_with_slippage_fp.int();

let swap_msg = orderbook::OrderbookExecuteMsg::SwapMinOutput {
target_denom,
min_output_quantity: min_output_fp,
min_output_quantity: floored_min_output_fp,
};

let funds = vec![Coin {
denom: match &ob_op.offer_asset_info {
amm::AssetInfo::NativeToken { denom } => denom.clone(),
_ => unreachable!(),
},
amount,
amount: rounded_atomic_amount,
}];

CosmosMsg::Wasm(WasmMsg::Execute {
Expand Down
1 change: 1 addition & 0 deletions contracts/dex_aggregator/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ pub struct OrderbookSwapOp {
pub swap_contract: String,
pub offer_asset_info: amm::AssetInfo,
pub ask_asset_info: amm::AssetInfo,
pub min_quantity_tick_size: Uint128,
}

#[cw_serde]
Expand Down
44 changes: 25 additions & 19 deletions contracts/dex_aggregator/src/reply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,28 +460,34 @@ fn parse_amount_from_swap_reply(msg: &Reply) -> Result<Uint128, ContractError> {
.map_err(|e| ContractError::SubmessageResultError { error: e })?
.events;

let amount_str_opt = events // Changed to an Option
.iter()
.find_map(|event| {
if !event.ty.starts_with("wasm") {
return None;
}
let key = if event.ty == "wasm-atomic_swap_execution" {
"swap_final_amount"
let amount_str_opt = events.iter().find_map(|event| {
if !event.ty.starts_with("wasm") {
return None;
}
let key = if event.ty == "wasm-atomic_swap_execution" {
"swap_final_amount"
} else {
"return_amount"
};
event
.attributes
.iter()
.find(|attr| attr.key == key)
.map(|attr| attr.value.clone())
});

match amount_str_opt {
Some(amount_str) => {
let integer_part_str = if let Some(period_pos) = amount_str.find('.') {
&amount_str[..period_pos]
} else {
"return_amount"
&amount_str
};
event
.attributes
.iter()
.find(|attr| attr.key == key)
.map(|attr| attr.value.clone())
});

match amount_str_opt {
Some(amount_str) => amount_str
.parse::<Uint128>()
.map_err(|_| ContractError::MalformedAmountInReply { value: amount_str }),
integer_part_str
.parse::<Uint128>()
.map_err(|_| ContractError::MalformedAmountInReply { value: amount_str })
}
None => Ok(Uint128::zero()),
}
}
Expand Down
6 changes: 1 addition & 5 deletions contracts/mock_swap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ crate-type = ["cdylib", "rlib"]
library = []

[dependencies]
cw2 = { version = "2.0.0" }
cw20 = { version = "2.0.0" }
cosmwasm-schema = { version = "2.2.2" }
cosmwasm-std = { version = "2.2.2", features = [
Expand All @@ -32,10 +31,7 @@ serde = { version = "1.0.219", default-features = false, features =
serde-json-wasm = { version = "1.0.0" }
serde_json = { version = "1.0.140" }
serde_repr = { version = "0.1.20" }

thiserror = { version = "2.0.12" }

hex = { version = "0.4.3" }
hex = { version = "0.4.3" }

[dev-dependencies]
injective-test-tube = { version = "1.16.3-1" }
Expand Down
15 changes: 15 additions & 0 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ fn test_aggregate_swap_success() {
offer_asset_info: amm::AssetInfo::NativeToken {
denom: "inj".to_string(),
},
min_quantity_tick_size: Uint128::new(1_000_000_000_000_000),
})],
},
],
Expand Down Expand Up @@ -407,6 +408,7 @@ fn test_multi_stage_aggregate_swap_success() {
offer_asset_info: amm::AssetInfo::NativeToken {
denom: "usdt".to_string(),
},
min_quantity_tick_size: Uint128::new(10000),
})],
}],
},
Expand Down Expand Up @@ -985,6 +987,7 @@ fn test_full_normalization_route() {
ask_asset_info: amm::AssetInfo::NativeToken {
denom: native_shroom_denom.clone(),
},
min_quantity_tick_size: Uint128::new(1_000_000_000_000_000),
})],
},
Split {
Expand Down Expand Up @@ -1070,6 +1073,7 @@ fn test_multi_stage_with_final_normalization() {
ask_asset_info: amm::AssetInfo::NativeToken {
denom: "inj".to_string(),
},
min_quantity_tick_size: Uint128::new(10000),
})],
}],
},
Expand Down Expand Up @@ -1098,6 +1102,7 @@ fn test_multi_stage_with_final_normalization() {
ask_asset_info: amm::AssetInfo::NativeToken {
denom: native_shroom_denom.clone(),
},
min_quantity_tick_size: Uint128::new(1_000_000_000_000_000),
})],
},
],
Expand Down Expand Up @@ -1278,6 +1283,7 @@ fn test_reverse_normalization_route() {
ask_asset_info: amm::AssetInfo::NativeToken {
denom: "usdt".to_string(),
},
min_quantity_tick_size: Uint128::new(10000),
})],
}],
},
Expand Down Expand Up @@ -1377,6 +1383,7 @@ fn test_failure_if_minimum_receive_not_met() {
offer_asset_info: amm::AssetInfo::NativeToken {
denom: "inj".to_string(),
},
min_quantity_tick_size: Uint128::new(1_000_000_000_000_000),
})],
},
],
Expand Down Expand Up @@ -1553,6 +1560,7 @@ fn test_mixed_input_unified_output_reconciliation() {
swap_contract: setup.mock_native_shroom_to_usdt_ob.clone(),
offer_asset_info: native_shroom_info.clone(),
ask_asset_info: usdt_info.clone(),
min_quantity_tick_size: Uint128::new(10000),
})],
},
Split {
Expand Down Expand Up @@ -1661,6 +1669,7 @@ fn test_cw20_input_with_initial_reconciliation() {
swap_contract: setup.mock_native_shroom_to_usdt_ob.clone(),
offer_asset_info: native_shroom_info.clone(),
ask_asset_info: usdt_info.clone(),
min_quantity_tick_size: Uint128::new(10000),
})],
},
Split {
Expand Down Expand Up @@ -1765,6 +1774,7 @@ fn test_complex_reconciliation_mixed_to_mixed() {
swap_contract: setup.mock_inj_to_native_shroom_ob.clone(),
offer_asset_info: inj_info.clone(),
ask_asset_info: native_shroom_info.clone(),
min_quantity_tick_size: Uint128::new(1_000_000_000_000_000),
})],
},
Split {
Expand All @@ -1789,6 +1799,7 @@ fn test_complex_reconciliation_mixed_to_mixed() {
swap_contract: setup.mock_native_shroom_to_usdt_ob.clone(),
offer_asset_info: native_shroom_info.clone(),
ask_asset_info: usdt_info.clone(),
min_quantity_tick_size: Uint128::new(10000),
})],
},
Split {
Expand Down Expand Up @@ -2161,6 +2172,7 @@ fn test_stage_with_single_hundred_percent_split() {
offer_asset_info: amm::AssetInfo::NativeToken {
denom: "usdt".to_string(),
},
min_quantity_tick_size: Uint128::new(10000),
})],
}],
};
Expand Down Expand Up @@ -2239,6 +2251,7 @@ fn test_intermediate_swap_failure_reverts_transaction() {
offer_asset_info: amm::AssetInfo::NativeToken {
denom: "usdt".to_string(),
},
min_quantity_tick_size: Uint128::new(10000),
})],
}],
};
Expand Down Expand Up @@ -3076,12 +3089,14 @@ fn test_multi_hop_path_with_mid_path_conversion() {
swap_contract: setup.mock_native_shroom_to_usdt_ob.clone(),
offer_asset_info: native_shroom_info.clone(),
ask_asset_info: usdt_info.clone(),
min_quantity_tick_size: Uint128::new(10000),
}),
// Hop 3: USDT -> INJ
Operation::OrderbookSwap(OrderbookSwapOp {
swap_contract: setup.mock_usdt_to_inj_ob.clone(),
offer_asset_info: usdt_info.clone(),
ask_asset_info: inj_info.clone(),
min_quantity_tick_size: Uint128::new(10000),
}),
];

Expand Down