Skip to content

Commit

Permalink
feat: passing the minium receive and approver to msg
Browse files Browse the repository at this point in the history
  • Loading branch information
meomeocoj committed Mar 18, 2024
1 parent 8bf77c7 commit 383371c
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 142 deletions.
251 changes: 115 additions & 136 deletions src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,9 @@ pub fn instantiate(
) -> Result<Response, ContractError> {
set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

// check valid addr in apporver
let approver = match msg.approver {
Some(addrs) => {
let valid_addrs = addrs
.iter()
.map(|addr| -> StdResult<Addr> { deps.api.addr_validate(addr.as_str()) })
.collect::<StdResult<Vec<Addr>>>()?;
Some(valid_addrs)
}
None => None,
};
let config = Config {
owner: deps.api.addr_validate(msg.owner.as_str())?,
distribute_token: msg.distribute_token,
approver,
router: match msg.router {
Some(addr) => Some(deps.api.addr_validate(addr.as_str())?),
None => None,
Expand Down Expand Up @@ -85,8 +73,7 @@ pub fn execute(
ExecuteMsg::UpdateConfig {
owner,
distribute_token,
approver,
} => execute_update_config(deps, env, info, owner, distribute_token, approver),
} => execute_update_config(deps, env, info, owner, distribute_token),
ExecuteMsg::UpdateDistributeTarget { distribute_targets } => {
execute_update_distribute_target(deps, env, info, distribute_targets)
}
Expand All @@ -105,7 +92,6 @@ fn execute_update_config(
info: MessageInfo,
owner: Option<Addr>,
distribute_token: Option<Addr>,
approver: Option<Vec<Addr>>,
) -> Result<Response, ContractError> {
let config = CONFIG.load(deps.storage)?;
if config.owner != info.sender {
Expand All @@ -115,7 +101,6 @@ fn execute_update_config(
let new_config = Config {
owner: owner.unwrap_or(config.owner),
distribute_token: distribute_token.unwrap_or(config.distribute_token),
approver,
router: config.router,
};

Expand Down Expand Up @@ -194,140 +179,139 @@ pub fn execute_collect_fees(
) -> Result<Response, ContractError> {
let config = CONFIG.load(deps.storage)?;
let mut messages: Vec<CosmosMsg> = vec![];
if config.approver.is_none() || config.router.is_none() {
if config.router.is_none() {
return Err(ContractError::RouterAndApproverNotSet {});
}
let router_unwrap = config.router.unwrap();
let approver_unwrap = config.approver.unwrap();
// create a new variable for better code readability
let fees_receiver = env.contract.address;
for approver in approver_unwrap {
// build swap operations
let approver_messages = collect_fee_requirements
.iter()
.map(|requirement| -> StdResult<Option<Vec<CosmosMsg>>> {
let operations = requirement.clone().swap_operations;

let offer_asset = match &operations[0] {
SwapOperation::OraiSwap {
offer_asset_info, ..
} => offer_asset_info,
};

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,
};

// final ask asset should be distribute token
if distribute_asset_info != final_ask_asset.clone() {
return Ok(None);
}
// build swap operations
let approver_messages = collect_fee_requirements
.iter()
.map(|requirement| -> StdResult<Option<Vec<CosmosMsg>>> {
let operations = requirement.clone().swap_operations;

let balance = offer_asset
.query_pool(&deps.querier, approver.clone())
.unwrap_or_default();
if balance.is_zero() {
return Ok(None);
}
// Assume that the owner approve infinite allowance to the contract
match &offer_asset {
AssetInfo::Token { contract_addr } => {
// transfer from only if distribute asset equals to offer_asset
if distribute_asset_info == offer_asset.clone() {
return Ok(Some(vec![CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: contract_addr.clone().into(),
msg: to_json_binary(&Cw20ExecuteMsg::TransferFrom {
owner: approver.to_string(),
recipient: fees_receiver.to_string(),
amount: balance,
})?,
funds: vec![],
})]));
}
let offer_asset = match &operations[0] {
SwapOperation::OraiSwap {
offer_asset_info, ..
} => offer_asset_info,
};

Ok(Some(vec![CosmosMsg::Wasm(WasmMsg::Execute {
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,
};

// final ask asset should be distribute token
if distribute_asset_info != final_ask_asset.clone() {
return Ok(None);
}

let balance = offer_asset
.query_pool(&deps.querier, requirement.approver.clone())
.unwrap_or_default();

if balance.is_zero() {
return Ok(None);
}
// Assume that the owner approve infinite allowance to the contract
match &offer_asset {
AssetInfo::Token { contract_addr } => {
// transfer from only if distribute asset equals to offer_asset
if distribute_asset_info == offer_asset.clone() {
return Ok(Some(vec![CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: contract_addr.clone().into(),
msg: to_json_binary(&Cw20ExecuteMsg::SendFrom {
owner: approver.to_string(),
contract: router_unwrap.to_string(),
msg: to_json_binary(&Cw20ExecuteMsg::TransferFrom {
owner: requirement.approver.to_string(),
recipient: fees_receiver.to_string(),
amount: balance,
msg: to_json_binary(&Cw20RouterHookMsg::ExecuteSwapOperations {
operations,
minimum_receive: requirement.minimum_receive,
to: Some(fees_receiver.to_string()),
})?,
})?,
funds: vec![],
})]))
})]));
}
// handle native token
AssetInfo::NativeToken { denom } => {
let mut swap_amount = balance;
if denom == "orai" {
// Left 1 orai for transaction fee
swap_amount = swap_amount
.checked_sub(Uint128::from(1000000u128))
.unwrap_or_default();
}

if swap_amount.is_zero() {
return Ok(None);
}

let send = MsgSend {
from_address: approver.to_string(),
to_address: fees_receiver.to_string(),
amount: vec![Coin {
denom: denom.clone(),
amount: swap_amount.to_string(),
}],
};
let send_any_result = send.to_any();
if send_any_result.is_err() {
return Ok(None);
}

let stargate_value = Binary::from(
MsgExec {
grantee: fees_receiver.to_string(),
msgs: vec![send_any_result.unwrap()],
}
.encode_to_vec(),
);
// transfer_from native token
let stargate = CosmosMsg::Stargate {
type_url: "/cosmos.authz.v1beta1.MsgExec".to_string(),
value: stargate_value,
};

let wasm_swap = CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: router_unwrap.to_string(),
msg: to_json_binary(&RouterExecuteMsg::ExecuteSwapOperations {
operations: operations.clone(),
to: Some(fees_receiver.clone()),
Ok(Some(vec![CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: contract_addr.clone().into(),
msg: to_json_binary(&Cw20ExecuteMsg::SendFrom {
owner: requirement.approver.to_string(),
contract: router_unwrap.to_string(),
amount: balance,
msg: to_json_binary(&Cw20RouterHookMsg::ExecuteSwapOperations {
operations,
minimum_receive: requirement.minimum_receive,
to: Some(fees_receiver.to_string()),
})?,
funds: vec![cosmwasm_std::Coin {
denom: denom.clone(),
amount: swap_amount,
}],
});
})?,
funds: vec![],
})]))
}
// handle native token
AssetInfo::NativeToken { denom } => {
let mut swap_amount = balance;
if denom == "orai" {
// Left 1 orai for transaction fee
swap_amount = swap_amount
.checked_sub(Uint128::from(1000000u128))
.unwrap_or_default();
}

Ok(Some(vec![stargate, wasm_swap]))
if swap_amount.is_zero() {
return Ok(None);
}

let send = MsgSend {
from_address: requirement.approver.to_string(),
to_address: fees_receiver.to_string(),
amount: vec![Coin {
denom: denom.clone(),
amount: swap_amount.to_string(),
}],
};
let send_any_result = send.to_any();
if send_any_result.is_err() {
return Ok(None);
}

let stargate_value = Binary::from(
MsgExec {
grantee: fees_receiver.to_string(),
msgs: vec![send_any_result.unwrap()],
}
.encode_to_vec(),
);
// transfer_from native token
let stargate = CosmosMsg::Stargate {
type_url: "/cosmos.authz.v1beta1.MsgExec".to_string(),
value: stargate_value,
};

let wasm_swap = CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: router_unwrap.to_string(),
msg: to_json_binary(&RouterExecuteMsg::ExecuteSwapOperations {
operations: operations.clone(),
to: Some(fees_receiver.clone()),
minimum_receive: requirement.minimum_receive,
})?,
funds: vec![cosmwasm_std::Coin {
denom: denom.clone(),
amount: swap_amount,
}],
});

Ok(Some(vec![stargate, wasm_swap]))
}
})
.filter_map(|msgs| match msgs {
Ok(Some(cosmos_msgs)) => Some(cosmos_msgs),
_ => None,
})
.flatten()
.collect::<Vec<CosmosMsg>>();
}
})
.filter_map(|msgs| match msgs {
Ok(Some(cosmos_msgs)) => Some(cosmos_msgs),
_ => None,
})
.flatten()
.collect::<Vec<CosmosMsg>>();

messages.extend(approver_messages);
}
messages.extend(approver_messages);

let mut response = Response::new();

Expand Down Expand Up @@ -420,7 +404,6 @@ mod tests {
owner: Addr::unchecked("owner"),
distribute_token: Addr::unchecked("distribute_token"),
init_distribution_targets: init_distribution_targets.clone(),
approver: Some(vec![Addr::unchecked("approver1")]),
router: Some(Addr::unchecked("router")),
};

Expand All @@ -435,7 +418,6 @@ mod tests {
ConfigResponse(Config {
owner: Addr::unchecked("owner"),
distribute_token: Addr::unchecked("distribute_token"),
approver: Some(vec![Addr::unchecked("approver1")]),
router: Some(Addr::unchecked("router")),
})
);
Expand Down Expand Up @@ -504,7 +486,6 @@ mod tests {
let msg = ExecuteMsg::UpdateConfig {
owner: Some(Addr::unchecked("new_owner")),
distribute_token: Some(Addr::unchecked("new_distribute_token")),
approver: Some(vec![Addr::unchecked("approver2")]),
};

// act
Expand All @@ -519,7 +500,6 @@ mod tests {
config.0.distribute_token,
Addr::unchecked("new_distribute_token")
);
assert_eq!(config.0.approver, Some(vec![Addr::unchecked("approver2")]));
}

#[test]
Expand Down Expand Up @@ -584,7 +564,6 @@ mod tests {
ExecuteMsg::UpdateConfig {
owner: None,
distribute_token: None,
approver: None,
},
)
.unwrap_err();
Expand Down
3 changes: 1 addition & 2 deletions src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use crate::state::{Config, DistributeTarget};
pub struct InstantiateMsg {
pub owner: Addr,
pub distribute_token: Addr,
pub approver: Option<Vec<Addr>>,
pub router: Option<Addr>,
pub init_distribution_targets: Vec<DistributeTarget>,
}
Expand All @@ -18,7 +17,6 @@ pub enum ExecuteMsg {
UpdateConfig {
owner: Option<Addr>,
distribute_token: Option<Addr>,
approver: Option<Vec<Addr>>,
},
UpdateDistributeTarget {
distribute_targets: Vec<DistributeTarget>,
Expand All @@ -33,6 +31,7 @@ pub enum ExecuteMsg {

#[cw_serde]
pub struct CollectFeeRequirement {
pub approver: Addr,
pub swap_operations: Vec<SwapOperation>,
pub minimum_receive: Option<Uint128>,
}
Expand Down
1 change: 0 additions & 1 deletion src/multitest/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ impl TreasuryContract {
owner: owner.clone(),
distribute_token: distribute_token.clone(),
init_distribution_targets,
approver: Some(vec![Addr::unchecked(admin.clone().unwrap())]),
router: Some(router.clone()),
},
&[],
Expand Down
Loading

0 comments on commit 383371c

Please sign in to comment.