Skip to content

Commit 574eb1a

Browse files
authored
Merge pull request #8 from oraichain/single-step
Single step
2 parents b6b0b96 + 884b545 commit 574eb1a

File tree

3 files changed

+146
-40
lines changed

3 files changed

+146
-40
lines changed
1.85 KB
Binary file not shown.

contracts/cw-ics20-latest/src/ibc.rs

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,11 @@ pub fn reply(deps: DepsMut, _env: Env, reply: Reply) -> Result<Response, Contrac
121121
true,
122122
)?;
123123

124-
Ok(Response::new().set_data(ack_fail(err)))
124+
Ok(Response::new().set_data(ack_fail(err)).add_attributes(vec![
125+
attr("undo_reduce_channel", reply_args.channel),
126+
attr("undo_reduce_channel_ibc_denom", reply_args.denom),
127+
attr("undo_reduce_channel_amount", reply_args.amount),
128+
]))
125129
}
126130
},
127131
NATIVE_RECEIVE_ID => match reply.result {
@@ -150,7 +154,12 @@ pub fn reply(deps: DepsMut, _env: Env, reply: Reply) -> Result<Response, Contrac
150154

151155
Ok(Response::new()
152156
.set_data(ack_fail(err.clone()))
153-
.add_attribute("error_transferring_ibc_tokens_to_cw20", err))
157+
.add_attribute("error_transferring_ibc_tokens_to_cw20", err)
158+
.add_attributes(vec![
159+
attr("undo_increase_channel", reply_args.channel),
160+
attr("undo_increase_channel_ibc_denom", reply_args.denom),
161+
attr("undo_increase_channel_amount", reply_args.amount),
162+
]))
154163
}
155164
},
156165
FOLLOW_UP_FAILURE_ID => match reply.result {
@@ -440,17 +449,10 @@ pub fn get_follow_up_msgs(
440449
) -> Result<(Vec<CosmosMsg>, String), ContractError> {
441450
let config = CONFIG.load(storage)?;
442451
let mut cosmos_msgs: Vec<CosmosMsg> = vec![];
443-
if memo.is_empty() {
444-
return Ok((
445-
vec![send_amount(to_send, receiver.to_string(), None)],
446-
"".to_string(),
447-
));
448-
}
449452
let destination: DestinationInfo = DestinationInfo::from_str(memo);
450-
// if destination denom, then we simply transfers cw20 to the receiver address.
451-
if destination.destination_denom.is_empty() {
453+
if is_follow_up_msgs_only_send_amount(&memo, &destination.destination_denom) {
452454
return Ok((
453-
vec![send_amount(to_send, destination.receiver.clone(), None)],
455+
vec![send_amount(to_send, receiver.to_string(), None)],
454456
"".to_string(),
455457
));
456458
}
@@ -476,22 +478,25 @@ pub fn get_follow_up_msgs(
476478
config.fee_denom.as_str(),
477479
&destination.destination_denom,
478480
);
479-
480-
let response: SimulateSwapOperationsResponse = querier.query_wasm_smart(
481-
config.swap_router_contract.clone(),
482-
&oraiswap::router::QueryMsg::SimulateSwapOperations {
483-
offer_amount: to_send.amount().clone(),
484-
operations: swap_operations.clone(),
485-
},
486-
)?;
481+
let mut minimum_receive = to_send.amount();
482+
if swap_operations.len() > 0 {
483+
let response: SimulateSwapOperationsResponse = querier.query_wasm_smart(
484+
config.swap_router_contract.clone(),
485+
&oraiswap::router::QueryMsg::SimulateSwapOperations {
486+
offer_amount: to_send.amount().clone(),
487+
operations: swap_operations.clone(),
488+
},
489+
)?;
490+
minimum_receive = response.amount;
491+
}
487492

488493
let ibc_msg = build_ibc_msg(
489494
storage,
490495
env,
491496
receiver_asset_info,
492497
receiver,
493498
packet.dest.channel_id.as_str(),
494-
response.amount.clone(),
499+
minimum_receive.clone(),
495500
&sender,
496501
&destination,
497502
config.default_timeout,
@@ -508,17 +513,35 @@ pub fn get_follow_up_msgs(
508513
ibc_error_msg = ibc_msg.unwrap_err().to_string();
509514
}
510515
build_swap_msgs(
511-
response.amount,
516+
minimum_receive,
512517
&config.swap_router_contract,
513518
to_send.amount(),
514519
initial_receive_asset_info,
515520
to,
516521
&mut cosmos_msgs,
517522
swap_operations,
518523
)?;
524+
// fallback case. If there's no cosmos messages then we return send amount
525+
if cosmos_msgs.is_empty() {
526+
return Ok((
527+
vec![send_amount(to_send, receiver.to_string(), None)],
528+
ibc_error_msg,
529+
));
530+
}
519531
return Ok((cosmos_msgs, ibc_error_msg));
520532
}
521533

534+
pub fn is_follow_up_msgs_only_send_amount(memo: &str, destination_denom: &str) -> bool {
535+
if memo.is_empty() {
536+
return true;
537+
}
538+
// if destination denom, then we simply transfers cw20 to the receiver address.
539+
if destination_denom.is_empty() {
540+
return true;
541+
}
542+
false
543+
}
544+
522545
pub fn build_swap_operations(
523546
receiver_asset_info: AssetInfo,
524547
initial_receive_asset_info: AssetInfo,
@@ -529,21 +552,21 @@ pub fn build_swap_operations(
529552
let fee_denom_asset_info = AssetInfo::NativeToken {
530553
denom: fee_denom.to_string(),
531554
};
532-
let mut swap_operations = vec![
533-
SwapOperation::OraiSwap {
555+
let mut swap_operations = vec![];
556+
if receiver_asset_info.eq(&initial_receive_asset_info) {
557+
return vec![];
558+
}
559+
if initial_receive_asset_info.ne(&fee_denom_asset_info) {
560+
swap_operations.push(SwapOperation::OraiSwap {
534561
offer_asset_info: initial_receive_asset_info.clone(),
535562
ask_asset_info: fee_denom_asset_info.clone(),
536-
},
537-
SwapOperation::OraiSwap {
563+
})
564+
}
565+
if destination_denom.ne(fee_denom) {
566+
swap_operations.push(SwapOperation::OraiSwap {
538567
offer_asset_info: fee_denom_asset_info.clone(),
539568
ask_asset_info: receiver_asset_info,
540-
},
541-
];
542-
if destination_denom.eq(fee_denom) {
543-
swap_operations.pop();
544-
}
545-
if initial_receive_asset_info.eq(&fee_denom_asset_info) {
546-
swap_operations.pop();
569+
});
547570
}
548571
swap_operations
549572
}
@@ -710,8 +733,9 @@ pub fn handle_follow_up_failure(
710733
false,
711734
)?;
712735
response = response.add_attributes(vec![
713-
attr("ibc_denom_undo_channel_balance", ibc_data.ibc_denom),
714-
attr("remote_amount_undo_channel_balance", ibc_data.remote_amount),
736+
attr("undo_reduce_channel", reply_args.channel),
737+
attr("undo_reduce_channel_ibc_denom", ibc_data.ibc_denom),
738+
attr("undo_reduce_channel_balance", ibc_data.remote_amount),
715739
]);
716740
}
717741
let refund_amount = Amount::from_parts(

contracts/cw-ics20-latest/src/ibc_tests.rs

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ mod test {
77

88
use crate::ibc::{
99
ack_fail, build_ibc_msg, build_swap_msgs, check_gas_limit, handle_follow_up_failure,
10-
ibc_packet_receive, parse_voucher_denom, send_amount, Ics20Ack, Ics20Packet, RECEIVE_ID,
11-
REFUND_FAILURE_ID,
10+
ibc_packet_receive, is_follow_up_msgs_only_send_amount, parse_voucher_denom, send_amount,
11+
Ics20Ack, Ics20Packet, RECEIVE_ID, REFUND_FAILURE_ID,
1212
};
1313
use crate::ibc::{build_swap_operations, get_follow_up_msgs};
1414
use crate::test_helpers::*;
@@ -513,13 +513,13 @@ mod test {
513513
#[test]
514514
fn test_swap_operations() {
515515
let receiver_asset_info = AssetInfo::Token {
516-
contract_addr: Addr::unchecked("foobar"),
516+
contract_addr: Addr::unchecked("contract"),
517517
};
518518
let mut initial_asset_info = AssetInfo::Token {
519519
contract_addr: Addr::unchecked("addr"),
520520
};
521521
let fee_denom = "orai".to_string();
522-
let destination: DestinationInfo = DestinationInfo {
522+
let mut destination: DestinationInfo = DestinationInfo {
523523
receiver: "cosmos".to_string(),
524524
destination_channel: "channel-1".to_string(),
525525
destination_denom: "foobar".to_string(),
@@ -541,16 +541,54 @@ mod test {
541541
&destination.destination_denom,
542542
);
543543
assert_eq!(operations.len(), 1);
544+
assert_eq!(
545+
operations[0],
546+
SwapOperation::OraiSwap {
547+
offer_asset_info: initial_asset_info.clone(),
548+
ask_asset_info: AssetInfo::NativeToken {
549+
denom: fee_denom.clone()
550+
}
551+
}
552+
);
544553
initial_asset_info = AssetInfo::NativeToken {
545554
denom: "foobar".to_string(),
546555
};
547556
let operations = build_swap_operations(
548-
receiver_asset_info,
557+
receiver_asset_info.clone(),
549558
initial_asset_info.clone(),
550559
&fee_denom,
551560
&destination.destination_denom,
552561
);
553562
assert_eq!(operations.len(), 0);
563+
564+
destination.destination_denom = "atom".to_string();
565+
let operations = build_swap_operations(
566+
receiver_asset_info.clone(),
567+
initial_asset_info.clone(),
568+
&fee_denom,
569+
&destination.destination_denom,
570+
);
571+
assert_eq!(operations.len(), 1);
572+
assert_eq!(
573+
operations[0],
574+
SwapOperation::OraiSwap {
575+
offer_asset_info: AssetInfo::NativeToken {
576+
denom: fee_denom.clone()
577+
},
578+
ask_asset_info: receiver_asset_info.clone()
579+
}
580+
);
581+
582+
// initial = receiver => build swap ops length = 0
583+
let operations = build_swap_operations(
584+
AssetInfo::NativeToken {
585+
denom: "foobar".to_string(),
586+
},
587+
initial_asset_info.clone(),
588+
"not_foo_bar",
589+
&destination.destination_denom,
590+
);
591+
assert_eq!(operations.len(), 0);
554592
}
555593

556594
#[test]
@@ -849,7 +887,41 @@ mod test {
849887
vec![CosmosMsg::Wasm(WasmMsg::Execute {
850888
contract_addr: env.contract.address.to_string(),
851889
msg: to_binary(&Cw20ExecuteMsg::Transfer {
852-
recipient: "cosmosabcd".to_string(),
890+
recipient: receiver.to_string(),
891+
amount: amount.clone()
892+
})
893+
.unwrap(),
894+
funds: vec![]
895+
})]
896+
);
897+
898+
// 3rd case, cosmos msgs empty case, also send amount
899+
let memo = "cosmosabcd:orai";
900+
let result = get_follow_up_msgs(
901+
deps_mut.storage,
902+
deps_mut.api,
903+
&deps_mut.querier,
904+
env.clone(),
905+
Amount::Cw20(Cw20Coin {
906+
address: "foobar".to_string(),
907+
amount,
908+
}),
909+
AssetInfo::NativeToken {
910+
denom: "orai".to_string(),
911+
},
912+
"foobar",
913+
"foobar",
914+
memo,
915+
&mock_receive_packet_remote_to_local("channel", 1u128, "foobar", "foobar"),
916+
)
917+
.unwrap();
918+
919+
assert_eq!(
920+
result.0,
921+
vec![CosmosMsg::Wasm(WasmMsg::Execute {
922+
contract_addr: env.contract.address.to_string(),
923+
msg: to_binary(&Cw20ExecuteMsg::Transfer {
924+
recipient: receiver.to_string(),
853925
amount: amount.clone()
854926
})
855927
.unwrap(),
@@ -933,4 +1005,14 @@ mod test {
9331005
// should undo reduce channel state
9341006
assert_eq!(channel_state.outstanding, remote_amount)
9351007
}
1008+
1009+
#[test]
1010+
fn test_is_follow_up_msgs_only_send_amount() {
1011+
assert_eq!(is_follow_up_msgs_only_send_amount("", "dest denom"), true);
1012+
assert_eq!(is_follow_up_msgs_only_send_amount("memo", ""), true);
1013+
assert_eq!(
1014+
is_follow_up_msgs_only_send_amount("memo", "dest denom"),
1015+
false
1016+
);
1017+
}
9361018
}

0 commit comments

Comments
 (0)