Skip to content

Commit

Permalink
add include_refund_fee param to show only required fee for lock funds…
Browse files Browse the repository at this point in the history
… swap step
  • Loading branch information
dimxy committed Mar 22, 2024
1 parent 1f9c42c commit ee9fc7a
Show file tree
Hide file tree
Showing 22 changed files with 65 additions and 32 deletions.
24 changes: 17 additions & 7 deletions mm2src/coins/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5395,15 +5395,21 @@ impl MmCoin for EthCoin {
&self,
value: TradePreimageValue,
stage: FeeApproxStage,
include_refund_fee: bool,
) -> TradePreimageResult<TradeFee> {
let pay_for_gas_option = self.get_swap_pay_for_gas_option(self.get_swap_transaction_fee_policy()).compat().await?;
let pay_for_gas_option = increase_gas_price_by_stage(pay_for_gas_option, &stage);
let gas_limit = match self.coin_type {
let mut gas_limit = match self.coin_type {
EthCoinType::Eth => {
// this gas_limit includes gas for `ethPayment` and `senderRefund` contract calls
U256::from(300_000)
// this gas_limit includes gas for `ethPayment` and optionally `senderRefund` contract calls
if include_refund_fee {
U256::from(swap_gas::ETH_PAYMENT)
} else {
U256::from(swap_gas::ETH_PAYMENT) + U256::from(swap_gas::ETH_SENDER_REFUND)
}
},
EthCoinType::Erc20 { token_addr, .. } => {
let gas = U256::from(swap_gas::ERC20_PAYMENT);
let value = match value {
TradePreimageValue::Exact(value) | TradePreimageValue::UpperBound(value) => {
wei_from_big_decimal(&value, self.decimals)?
Expand All @@ -5422,16 +5428,20 @@ impl MmCoin for EthCoin {
.compat()
.await?;

// this gas_limit includes gas for `approve`, `erc20Payment` and `senderRefund` contract calls
U256::from(300_000) + approve_gas_limit
// this gas_limit includes gas for `approve`, `erc20Payment` contract calls
gas + approve_gas_limit
} else {
// this gas_limit includes gas for `erc20Payment` and `senderRefund` contract calls
U256::from(300_000)
// this gas_limit includes gas for `erc20Payment` contract calls
gas
}
},
EthCoinType::Nft { .. } => return MmError::err(TradePreimageError::NftProtocolNotSupported),
};

if include_refund_fee {
gas_limit += U256::from(swap_gas::ERC20_SENDER_REFUND); // add 'senderRefund' gas if requested
}

let total_fee = calc_total_fee(gas_limit, &pay_for_gas_option)?;
let amount = u256_to_big_decimal(total_fee, ETH_DECIMALS)?;
let fee_coin = match &self.coin_type {
Expand Down
13 changes: 7 additions & 6 deletions mm2src/coins/eth/eth_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,25 +613,26 @@ fn get_sender_trade_preimage() {
let actual = block_on(coin.get_sender_trade_fee(
TradePreimageValue::UpperBound(150.into()),
FeeApproxStage::WithoutApprox,
true,
))
.expect("!get_sender_trade_fee");
let expected = expected_fee(GAS_PRICE);
assert_eq!(actual, expected);

let value = u256_to_big_decimal(100.into(), 18).expect("!u256_to_big_decimal");
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(value), FeeApproxStage::OrderIssue))
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(value), FeeApproxStage::OrderIssue, true))
.expect("!get_sender_trade_fee");
let expected = expected_fee(GAS_PRICE_APPROXIMATION_ON_ORDER_ISSUE);
assert_eq!(actual, expected);

let value = u256_to_big_decimal(1.into(), 18).expect("!u256_to_big_decimal");
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(value), FeeApproxStage::StartSwap))
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(value), FeeApproxStage::StartSwap, true))
.expect("!get_sender_trade_fee");
let expected = expected_fee(GAS_PRICE_APPROXIMATION_ON_START_SWAP);
assert_eq!(actual, expected);

let value = u256_to_big_decimal(10000000000u64.into(), 18).expect("!u256_to_big_decimal");
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(value), FeeApproxStage::TradePreimage))
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(value), FeeApproxStage::TradePreimage, true))
.expect("!get_sender_trade_fee");
let expected = expected_fee(GAS_PRICE_APPROXIMATION_ON_TRADE_PREIMAGE);
assert_eq!(actual, expected);
Expand Down Expand Up @@ -683,7 +684,7 @@ fn get_erc20_sender_trade_preimage() {
// value is greater than allowance
unsafe { ALLOWANCE = 999 };
let value = u256_to_big_decimal(1000.into(), 18).expect("u256_to_big_decimal");
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::UpperBound(value), FeeApproxStage::StartSwap))
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::UpperBound(value), FeeApproxStage::StartSwap, true))
.expect("!get_sender_trade_fee");
unsafe {
assert!(ESTIMATE_GAS_CALLED);
Expand All @@ -697,7 +698,7 @@ fn get_erc20_sender_trade_preimage() {
// value is allowed
unsafe { ALLOWANCE = 1000 };
let value = u256_to_big_decimal(999.into(), 18).expect("u256_to_big_decimal");
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(value), FeeApproxStage::OrderIssue))
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(value), FeeApproxStage::OrderIssue, true))
.expect("!get_sender_trade_fee");
unsafe { assert!(!ESTIMATE_GAS_CALLED) }
assert_eq!(
Expand All @@ -708,7 +709,7 @@ fn get_erc20_sender_trade_preimage() {
// value is greater than allowance
unsafe { ALLOWANCE = 1000 };
let value = u256_to_big_decimal(1500.into(), 18).expect("u256_to_big_decimal");
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(value), FeeApproxStage::TradePreimage))
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(value), FeeApproxStage::TradePreimage, true))
.expect("!get_sender_trade_fee");
unsafe {
assert!(ESTIMATE_GAS_CALLED);
Expand Down
1 change: 1 addition & 0 deletions mm2src/coins/lightning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,7 @@ impl MmCoin for LightningCoin {
&self,
_value: TradePreimageValue,
_stage: FeeApproxStage,
_include_refund_fee: bool,
) -> TradePreimageResult<TradeFee> {
Ok(TradeFee {
coin: self.ticker().to_owned(),
Expand Down
3 changes: 2 additions & 1 deletion mm2src/coins/lp_coins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3079,11 +3079,12 @@ pub trait MmCoin:
/// Get fee to be paid per 1 swap transaction
fn get_trade_fee(&self) -> Box<dyn Future<Item = TradeFee, Error = String> + Send>;

/// Get fee to be paid by sender per whole swap using the sending value and check if the wallet has sufficient balance to pay the fee.
/// Get fee to be paid by sender per whole swap (including possible refund) using the sending value and check if the wallet has sufficient balance to pay the fee.
async fn get_sender_trade_fee(
&self,
value: TradePreimageValue,
stage: FeeApproxStage,
include_refund_fee: bool,
) -> TradePreimageResult<TradeFee>;

/// Get fee to be paid by receiver per whole swap and check if the wallet has sufficient balance to pay the fee.
Expand Down
17 changes: 11 additions & 6 deletions mm2src/coins/qrc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,7 @@ impl MmCoin for Qrc20Coin {
&self,
value: TradePreimageValue,
stage: FeeApproxStage,
include_refund_fee: bool,
) -> TradePreimageResult<TradeFee> {
let decimals = self.utxo.decimals;
// pass the dummy params
Expand Down Expand Up @@ -1398,14 +1399,18 @@ impl MmCoin for Qrc20Coin {
.await?
};

let sender_refund_fee = {
let sender_refund_output =
self.sender_refund_output(&self.swap_contract_address, swap_id, value, secret_hash, receiver_addr)?;
self.preimage_trade_fee_required_to_send_outputs(vec![sender_refund_output], &stage)
.await?
let total_fee = if include_refund_fee {
let sender_refund_fee = {
let sender_refund_output =
self.sender_refund_output(&self.swap_contract_address, swap_id, value, secret_hash, receiver_addr)?;
self.preimage_trade_fee_required_to_send_outputs(vec![sender_refund_output], &stage)
.await?
};
erc20_payment_fee + sender_refund_fee
} else {
erc20_payment_fee
};

let total_fee = erc20_payment_fee + sender_refund_fee;
Ok(TradeFee {
coin: self.platform.clone(),
amount: total_fee.into(),
Expand Down
4 changes: 3 additions & 1 deletion mm2src/coins/qrc20/qrc20_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,7 @@ fn test_sender_trade_preimage_with_allowance() {
let actual = block_on(coin.get_sender_trade_fee(
TradePreimageValue::Exact(BigDecimal::try_from(2.5).unwrap()),
FeeApproxStage::WithoutApprox,
true,
))
.expect("!get_sender_trade_fee");
// the expected fee should not include any `approve` contract call
Expand All @@ -850,6 +851,7 @@ fn test_sender_trade_preimage_with_allowance() {
let actual = block_on(coin.get_sender_trade_fee(
TradePreimageValue::Exact(BigDecimal::try_from(3.5).unwrap()),
FeeApproxStage::WithoutApprox,
true,
))
.expect("!get_sender_trade_fee");
// two `approve` contract calls should be included into the expected trade fee
Expand Down Expand Up @@ -905,7 +907,7 @@ fn test_get_sender_trade_fee_preimage_for_correct_ticker() {
))
.unwrap();

let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(0.into()), FeeApproxStage::OrderIssue))
let actual = block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(0.into()), FeeApproxStage::OrderIssue, true))
.err()
.unwrap()
.into_inner();
Expand Down
1 change: 1 addition & 0 deletions mm2src/coins/solana.rs
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,7 @@ impl MmCoin for SolanaCoin {
&self,
_value: TradePreimageValue,
_stage: FeeApproxStage,
_include_refund_fee: bool,
) -> TradePreimageResult<TradeFee> {
unimplemented!()
}
Expand Down
1 change: 1 addition & 0 deletions mm2src/coins/solana/spl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ impl MmCoin for SplToken {
&self,
_value: TradePreimageValue,
_stage: FeeApproxStage,
_include_refund_fee: bool,
) -> TradePreimageResult<TradeFee> {
unimplemented!()
}
Expand Down
1 change: 1 addition & 0 deletions mm2src/coins/tendermint/tendermint_coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2145,6 +2145,7 @@ impl MmCoin for TendermintCoin {
&self,
value: TradePreimageValue,
_stage: FeeApproxStage,
_include_refund_fee: bool,
) -> TradePreimageResult<TradeFee> {
let amount = match value {
TradePreimageValue::Exact(decimal) | TradePreimageValue::UpperBound(decimal) => decimal,
Expand Down
1 change: 1 addition & 0 deletions mm2src/coins/tendermint/tendermint_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,7 @@ impl MmCoin for TendermintToken {
&self,
value: TradePreimageValue,
_stage: FeeApproxStage,
_include_refund_fee: bool,
) -> TradePreimageResult<TradeFee> {
let amount = match value {
TradePreimageValue::Exact(decimal) | TradePreimageValue::UpperBound(decimal) => decimal,
Expand Down
1 change: 1 addition & 0 deletions mm2src/coins/test_coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ impl MmCoin for TestCoin {
&self,
_value: TradePreimageValue,
_stage: FeeApproxStage,
_include_refund_fee: bool,
) -> TradePreimageResult<TradeFee> {
unimplemented!()
}
Expand Down
1 change: 1 addition & 0 deletions mm2src/coins/utxo/bch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,7 @@ impl MmCoin for BchCoin {
&self,
value: TradePreimageValue,
stage: FeeApproxStage,
_include_refund_fee: bool, // refund fee is taken from swap output
) -> TradePreimageResult<TradeFee> {
utxo_common::get_sender_trade_fee(self, value, stage).await
}
Expand Down
1 change: 1 addition & 0 deletions mm2src/coins/utxo/qtum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,7 @@ impl MmCoin for QtumCoin {
&self,
value: TradePreimageValue,
stage: FeeApproxStage,
_include_refund_fee: bool, // refund fee is taken from swap output
) -> TradePreimageResult<TradeFee> {
utxo_common::get_sender_trade_fee(self, value, stage).await
}
Expand Down
1 change: 1 addition & 0 deletions mm2src/coins/utxo/slp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1775,6 +1775,7 @@ impl MmCoin for SlpToken {
&self,
value: TradePreimageValue,
stage: FeeApproxStage,
_include_refund_fee: bool, // refund fee is taken from swap output
) -> TradePreimageResult<TradeFee> {
let slp_amount = match value {
TradePreimageValue::Exact(decimal) | TradePreimageValue::UpperBound(decimal) => {
Expand Down
1 change: 1 addition & 0 deletions mm2src/coins/utxo/utxo_standard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,7 @@ impl MmCoin for UtxoStandardCoin {
&self,
value: TradePreimageValue,
stage: FeeApproxStage,
_include_refund_fee: bool, // refund fee is taken from swap output
) -> TradePreimageResult<TradeFee> {
utxo_common::get_sender_trade_fee(self, value, stage).await
}
Expand Down
4 changes: 3 additions & 1 deletion mm2src/coins/utxo/utxo_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2514,6 +2514,7 @@ fn test_get_sender_trade_fee_dynamic_tx_fee() {
let fee1 = block_on(coin.get_sender_trade_fee(
TradePreimageValue::UpperBound(my_balance.clone()),
FeeApproxStage::WithoutApprox,
false,
))
.expect("!get_sender_trade_fee");

Expand All @@ -2522,14 +2523,15 @@ fn test_get_sender_trade_fee_dynamic_tx_fee() {
let fee2 = block_on(coin.get_sender_trade_fee(
TradePreimageValue::Exact(value_without_fee),
FeeApproxStage::WithoutApprox,
false,
))
.expect("!get_sender_trade_fee");
assert_eq!(fee1, fee2);

// `2.21934443` value was obtained as a result of executing the `max_taker_vol` RPC call for this wallet
let max_taker_vol = BigDecimal::from_str("2.21934443").expect("!BigDecimal::from_str");
let fee3 =
block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(max_taker_vol), FeeApproxStage::WithoutApprox))
block_on(coin.get_sender_trade_fee(TradePreimageValue::Exact(max_taker_vol), FeeApproxStage::WithoutApprox, false))
.expect("!get_sender_trade_fee");
assert_eq!(fee1, fee3);
}
Expand Down
1 change: 1 addition & 0 deletions mm2src/coins/z_coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1790,6 +1790,7 @@ impl MmCoin for ZCoin {
&self,
_value: TradePreimageValue,
_stage: FeeApproxStage,
_include_refund_fee: bool,
) -> TradePreimageResult<TradeFee> {
Ok(TradeFee {
coin: self.ticker().to_owned(),
Expand Down
8 changes: 4 additions & 4 deletions mm2src/mm2_main/src/lp_swap/maker_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ impl MakerSwap {
// do not use self.r().data here as it is not initialized at this step yet
let preimage_value = TradePreimageValue::Exact(self.maker_amount.clone());
let stage = FeeApproxStage::StartSwap;
let get_sender_trade_fee_fut = self.maker_coin.get_sender_trade_fee(preimage_value, stage);
let get_sender_trade_fee_fut = self.maker_coin.get_sender_trade_fee(preimage_value, stage, false);
let maker_payment_trade_fee = match get_sender_trade_fee_fut.await {
Ok(fee) => fee,
Err(e) => {
Expand Down Expand Up @@ -2177,7 +2177,7 @@ pub async fn check_balance_for_maker_swap(
None => {
let preimage_value = TradePreimageValue::Exact(volume.to_decimal());
let maker_payment_trade_fee = my_coin
.get_sender_trade_fee(preimage_value, stage)
.get_sender_trade_fee(preimage_value, stage, true) // use send+refund fee to check balance
.await
.mm_err(|e| CheckBalanceError::from_trade_preimage_error(e, my_coin.ticker()))?;
let taker_payment_spend_trade_fee = other_coin
Expand Down Expand Up @@ -2231,7 +2231,7 @@ pub async fn maker_swap_trade_preimage(

let preimage_value = TradePreimageValue::Exact(volume.to_decimal());
let base_coin_fee = base_coin
.get_sender_trade_fee(preimage_value, FeeApproxStage::TradePreimage)
.get_sender_trade_fee(preimage_value, FeeApproxStage::TradePreimage, false)
.await
.mm_err(|e| TradePreimageRpcError::from_trade_preimage_error(e, base_coin_ticker))?;
let rel_coin_fee = rel_coin
Expand Down Expand Up @@ -2313,7 +2313,7 @@ pub async fn calc_max_maker_vol(

let preimage_value = TradePreimageValue::UpperBound(volume.to_decimal());
let trade_fee = coin
.get_sender_trade_fee(preimage_value, stage)
.get_sender_trade_fee(preimage_value, stage, true) // use send+refund fee to get max trade amount
.await
.mm_err(|e| CheckBalanceError::from_trade_preimage_error(e, ticker))?;

Expand Down
2 changes: 1 addition & 1 deletion mm2src/mm2_main/src/lp_swap/maker_swap_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ impl<MakerCoin: MmCoin + MakerCoinSwapOpsV2, TakerCoin: MmCoin + TakerCoinSwapOp
let stage = FeeApproxStage::StartSwap;
let maker_payment_trade_fee = match state_machine
.maker_coin
.get_sender_trade_fee(preimage_value, stage)
.get_sender_trade_fee(preimage_value, stage, false)
.await
{
Ok(fee) => fee,
Expand Down
8 changes: 4 additions & 4 deletions mm2src/mm2_main/src/lp_swap/taker_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1010,7 +1010,7 @@ impl TakerSwap {
)]))
},
};
let get_sender_trade_fee_fut = self.taker_coin.get_sender_trade_fee(preimage_value, stage);
let get_sender_trade_fee_fut = self.taker_coin.get_sender_trade_fee(preimage_value, stage, false);
let taker_payment_trade_fee = match get_sender_trade_fee_fut.await {
Ok(fee) => fee,
Err(e) => {
Expand Down Expand Up @@ -2368,7 +2368,7 @@ pub async fn check_balance_for_taker_swap(
.mm_err(|e| CheckBalanceError::from_trade_preimage_error(e, my_coin.ticker()))?;
let preimage_value = TradePreimageValue::Exact(volume.to_decimal());
let taker_payment_trade_fee = my_coin
.get_sender_trade_fee(preimage_value, stage)
.get_sender_trade_fee(preimage_value, stage, true) // use send+refund fee to check balance for swap
.await
.mm_err(|e| CheckBalanceError::from_trade_preimage_error(e, my_coin.ticker()))?;
let maker_payment_spend_trade_fee = other_coin
Expand Down Expand Up @@ -2463,7 +2463,7 @@ pub async fn taker_swap_trade_preimage(

let preimage_value = TradePreimageValue::Exact(my_coin_volume.to_decimal());
let my_coin_trade_fee = my_coin
.get_sender_trade_fee(preimage_value, stage)
.get_sender_trade_fee(preimage_value, stage, false)
.await
.mm_err(|e| TradePreimageRpcError::from_trade_preimage_error(e, my_coin_ticker))?;
let other_coin_trade_fee = other_coin
Expand Down Expand Up @@ -2588,7 +2588,7 @@ pub async fn calc_max_taker_vol(
let max_possible = &balance - &locked;
let preimage_value = TradePreimageValue::UpperBound(max_possible.to_decimal());
let max_trade_fee = coin
.get_sender_trade_fee(preimage_value, stage)
.get_sender_trade_fee(preimage_value, stage, true) // use send+refund fee to get max trade amount
.await
.mm_err(|e| CheckBalanceError::from_trade_preimage_error(e, my_coin))?;

Expand Down
2 changes: 1 addition & 1 deletion mm2src/mm2_main/src/lp_swap/taker_swap_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,7 @@ impl<MakerCoin: MmCoin + MakerCoinSwapOpsV2, TakerCoin: MmCoin + TakerCoinSwapOp

let taker_payment_fee = match state_machine
.taker_coin
.get_sender_trade_fee(preimage_value, stage)
.get_sender_trade_fee(preimage_value, stage, false)
.await
{
Ok(fee) => fee,
Expand Down
1 change: 1 addition & 0 deletions mm2src/mm2_main/tests/docker_tests/qrc20_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,7 @@ fn test_get_max_taker_vol_and_trade_with_dynamic_trade_fee(coin: QtumCoin, priv_
let max_trade_fee = block_on(coin.get_sender_trade_fee(
TradePreimageValue::UpperBound(qtum_balance.clone()),
FeeApproxStage::TradePreimage,
true,
))
.expect("!get_sender_trade_fee");
let max_trade_fee = max_trade_fee.amount.to_decimal();
Expand Down

0 comments on commit ee9fc7a

Please sign in to comment.