Skip to content

Commit

Permalink
feat: calculate minium receive
Browse files Browse the repository at this point in the history
  • Loading branch information
meomeocoj committed Mar 15, 2024
1 parent 8bf77c7 commit 5f0ef8a
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 17 deletions.
29 changes: 26 additions & 3 deletions src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[cfg(not(feature = "library"))]
use crate::helpers::asset_info_from_string;
use crate::helpers::calculate_minium_receive;
use crate::msg::{
CollectFeeRequirement, ConfigResponse, DistributeTargetsResponse, ExecuteMsg, InstantiateMsg,
MigrateMsg, QueryMsg,
Expand Down Expand Up @@ -95,7 +96,8 @@ pub fn execute(
}
ExecuteMsg::CollectFees {
collect_fee_requirements,
} => execute_collect_fees(deps, env, info, collect_fee_requirements),
slippage,
} => execute_collect_fees(deps, env, info, collect_fee_requirements, slippage),
}
}

Expand Down Expand Up @@ -191,12 +193,16 @@ pub fn execute_collect_fees(
env: Env,
_info: MessageInfo,
collect_fee_requirements: Vec<CollectFeeRequirement>,
slippage: Option<Uint128>,
) -> Result<Response, ContractError> {
let config = CONFIG.load(deps.storage)?;
let mut messages: Vec<CosmosMsg> = vec![];
if config.approver.is_none() || config.router.is_none() {
return Err(ContractError::RouterAndApproverNotSet {});
}
// DEFAULT 5% slippage
let slippage = slippage.unwrap_or(Uint128::from(5u128));

let router_unwrap = config.router.unwrap();
let approver_unwrap = config.approver.unwrap();
// create a new variable for better code readability
Expand All @@ -216,6 +222,7 @@ pub fn execute_collect_fees(

let distribute_asset_info =
asset_info_from_string(deps.api, config.distribute_token.clone().into());

let final_ask_asset = match &operations[operations.len() - 1] {
SwapOperation::OraiSwap { ask_asset_info, .. } => ask_asset_info,
};
Expand All @@ -228,6 +235,15 @@ pub fn execute_collect_fees(
let balance = offer_asset
.query_pool(&deps.querier, approver.clone())
.unwrap_or_default();

let mut minimum_receive = calculate_minium_receive(
deps.querier,
router_unwrap.clone(),
balance,
operations.clone(),
slippage,
)?;

if balance.is_zero() {
return Ok(None);
}
Expand Down Expand Up @@ -255,7 +271,7 @@ pub fn execute_collect_fees(
amount: balance,
msg: to_json_binary(&Cw20RouterHookMsg::ExecuteSwapOperations {
operations,
minimum_receive: requirement.minimum_receive,
minimum_receive: Some(minimum_receive),
to: Some(fees_receiver.to_string()),
})?,
})?,
Expand All @@ -270,6 +286,13 @@ pub fn execute_collect_fees(
swap_amount = swap_amount
.checked_sub(Uint128::from(1000000u128))
.unwrap_or_default();
minimum_receive = calculate_minium_receive(
deps.querier,
router_unwrap.clone(),
swap_amount,
operations.clone(),
slippage,
)?;
}

if swap_amount.is_zero() {
Expand Down Expand Up @@ -307,7 +330,7 @@ pub fn execute_collect_fees(
msg: to_json_binary(&RouterExecuteMsg::ExecuteSwapOperations {
operations: operations.clone(),
to: Some(fees_receiver.clone()),
minimum_receive: requirement.minimum_receive,
minimum_receive: Some(minimum_receive),
})?,
funds: vec![cosmwasm_std::Coin {
denom: denom.clone(),
Expand Down
29 changes: 27 additions & 2 deletions src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use cosmwasm_std::Api;
use oraiswap::asset::AssetInfo;
use cosmwasm_std::{Addr, Api, QuerierWrapper, StdResult, Uint128};
use oraiswap::{
asset::AssetInfo,
router::{self, SimulateSwapOperationsResponse, SwapOperation},
};

pub fn asset_info_from_string(api: &dyn Api, asset: String) -> AssetInfo {
match api.addr_validate(&asset) {
Expand All @@ -11,3 +14,25 @@ pub fn asset_info_from_string(api: &dyn Api, asset: String) -> AssetInfo {
},
}
}

pub fn calculate_minium_receive(
querier: QuerierWrapper,
router_address: Addr,
offer_amount: Uint128,
operations: Vec<SwapOperation>,
slippage: Uint128,
) -> StdResult<Uint128> {
let simulate_amount = querier
.query_wasm_smart::<SimulateSwapOperationsResponse>(
router_address,
&router::QueryMsg::SimulateSwapOperations {
offer_amount,
operations: operations.clone(),

Check failure on line 30 in src/helpers.rs

View workflow job for this annotation

GitHub Actions / Lints

redundant clone

Check failure on line 30 in src/helpers.rs

View workflow job for this annotation

GitHub Actions / Lints

redundant clone
},
)?
.amount;

Ok(simulate_amount
.checked_mul(Uint128::from(100u128) - slippage)?
.checked_div(Uint128::from(100u128))?)
}
2 changes: 1 addition & 1 deletion src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ pub enum ExecuteMsg {
},
CollectFees {
collect_fee_requirements: Vec<CollectFeeRequirement>,
slippage: Option<Uint128>,
},
}

#[cw_serde]
pub struct CollectFeeRequirement {
pub swap_operations: Vec<SwapOperation>,
pub minimum_receive: Option<Uint128>,
}

#[cw_serde]
Expand Down
17 changes: 13 additions & 4 deletions src/multitest/mock_router_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ use cosmwasm_std::{
use cw20::{Cw20ExecuteMsg, Cw20ReceiveMsg};
use cw_multi_test::{ContractWrapper, Executor};
use cw_storage_plus::Item;
use oraiswap::router::ExecuteMsg as RouterExecuteMsg;
use oraiswap::router::{self, ExecuteMsg as RouterExecuteMsg};

use super::tests::StargateAccpetingModuleApp;

#[cw_serde]
pub enum MockQueryMsg {}
pub type MockQueryMsg = router::QueryMsg;

#[cw_serde]
pub enum Cw20Hook {
Expand Down Expand Up @@ -99,7 +98,17 @@ impl MockRouter {
}
},
instantiate,
|_, _, _: MockQueryMsg| -> StdResult<Binary> { Ok(Binary::default()) },
|_, _, msg: MockQueryMsg| -> StdResult<Binary> {
match msg {
router::QueryMsg::SimulateSwapOperations {
offer_amount,
operations: _,
} => Ok(to_json_binary(&router::SimulateSwapOperationsResponse {
amount: offer_amount,
})?),
_ => Ok(Binary::default()),
}
},
);
app.store_code(Box::new(contract))
}
Expand Down
46 changes: 39 additions & 7 deletions src/multitest/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::contract::execute_collect_fees;
use crate::helpers::calculate_minium_receive;
use crate::msg::{CollectFeeRequirement, ExecuteMsg};
use crate::state::{Config, CONFIG};
use crate::{state::DistributeTarget, ContractError};
Expand Down Expand Up @@ -225,11 +226,11 @@ fn test_execute_collect_fees_router_approver_not_set() {
let result = execute_collect_fees(
deps.as_mut(),
mock_env(),
mock_info("sender", &vec![]),
mock_info("sender", &[]),
vec![CollectFeeRequirement {
swap_operations: vec![],
minimum_receive: None,
}],
Some(Uint128::from(0u128)),
)
.unwrap_err();
assert_eq!(result, ContractError::RouterAndApproverNotSet {});
Expand All @@ -249,11 +250,11 @@ fn test_execute_collect_fees_router_approver_not_set() {
let result = execute_collect_fees(
deps.as_mut(),
mock_env(),
mock_info("sender", &vec![]),
mock_info("sender", &[]),
vec![CollectFeeRequirement {
swap_operations: vec![],
minimum_receive: None,
}],
Some(Uint128::from(0u128)),
)
.unwrap_err();
assert_eq!(result, ContractError::RouterAndApproverNotSet {});
Expand Down Expand Up @@ -306,7 +307,6 @@ fn test_collect_fees_balance_distribute() {
contract_addr: usdc.addr().clone(),
},
}],
minimum_receive: None,
},
CollectFeeRequirement {
swap_operations: vec![SwapOperation::OraiSwap {
Expand All @@ -317,7 +317,6 @@ fn test_collect_fees_balance_distribute() {
contract_addr: usdc.addr().clone(),
},
}],
minimum_receive: None,
},
CollectFeeRequirement {
swap_operations: vec![SwapOperation::OraiSwap {
Expand All @@ -328,9 +327,9 @@ fn test_collect_fees_balance_distribute() {
contract_addr: usdc.addr().clone(),
},
}],
minimum_receive: None,
},
],
slippage: Some(Uint128::from(2u128)),
},
&[],
)
Expand All @@ -340,6 +339,7 @@ fn test_collect_fees_balance_distribute() {
let balance = cw20.query_balance(&app, router.addr());
let native_balance = app.wrap().query_balance(router.addr(), "orai").unwrap();
let usdc_treasury_balance = usdc.query_balance(&app, treasury.addr());

assert_eq!(
native_balance.amount,
Uint128::from(INITAL_BALANCE)
Expand All @@ -354,3 +354,35 @@ fn test_collect_fees_balance_distribute() {
.unwrap()
);
}

#[test]
fn test_calculate_minium_receive() {
let (app, _treasury, _cw20, _ping_pong, router, usdc) = mock_app();
let offer_amount = Uint128::from(100u64);
let slippage = Uint128::from(2u128);

let result = calculate_minium_receive(
app.wrap(),
router.addr().clone(),
offer_amount,
vec![SwapOperation::OraiSwap {
offer_asset_info: AssetInfo::NativeToken {
denom: "orai".into(),
},
ask_asset_info: AssetInfo::Token {
contract_addr: usdc.addr().clone(),
},
}],
slippage,
)
.unwrap();

assert_eq!(
result,
offer_amount
.checked_mul(Uint128::from(98u128))
.unwrap()
.checked_div(Uint128::from(100u128))
.unwrap()
);
}

0 comments on commit 5f0ef8a

Please sign in to comment.