Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(fee): remove fixed 0.0001 min threshold for TakerFee #1971

Merged
merged 8 commits into from
Oct 3, 2023
20 changes: 4 additions & 16 deletions mm2src/mm2_main/src/lp_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -669,17 +669,6 @@ pub fn lp_atomic_locktime(maker_coin: &str, taker_coin: &str, version: AtomicLoc
}
}

pub fn dex_fee_threshold(min_tx_amount: MmNumber) -> MmNumber {
// Todo: This should be reduced for lightning swaps.
// 0.0001
let min_fee = MmNumber::from((1, 10000));
if min_fee < min_tx_amount {
min_tx_amount
} else {
min_fee
}
}

fn dex_fee_rate(base: &str, rel: &str) -> MmNumber {
let fee_discount_tickers: &[&str] = if var("MYCOIN_FEE_DISCOUNT").is_ok() {
&["KMD", "MYCOIN"]
Expand All @@ -694,20 +683,19 @@ fn dex_fee_rate(base: &str, rel: &str) -> MmNumber {
}
}

pub fn dex_fee_amount(base: &str, rel: &str, trade_amount: &MmNumber, dex_fee_threshold: &MmNumber) -> MmNumber {
pub fn dex_fee_amount(base: &str, rel: &str, trade_amount: &MmNumber, min_tx_amount: &MmNumber) -> MmNumber {
let rate = dex_fee_rate(base, rel);
let fee_amount = trade_amount * &rate;
if &fee_amount < dex_fee_threshold {
dex_fee_threshold.clone()
if &fee_amount < min_tx_amount {
min_tx_amount.clone()
} else {
fee_amount
}
}

pub fn dex_fee_amount_from_taker_coin(taker_coin: &MmCoinEnum, maker_coin: &str, trade_amount: &MmNumber) -> MmNumber {
let min_tx_amount = MmNumber::from(taker_coin.min_tx_amount());
let dex_fee_threshold = dex_fee_threshold(min_tx_amount);
dex_fee_amount(taker_coin.ticker(), maker_coin, trade_amount, &dex_fee_threshold)
dex_fee_amount(taker_coin.ticker(), maker_coin, trade_amount, &min_tx_amount)
}

#[derive(Clone, Debug, Eq, Deserialize, PartialEq, Serialize)]
Expand Down
71 changes: 34 additions & 37 deletions mm2src/mm2_main/src/lp_swap/taker_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use super::swap_lock::{SwapLock, SwapLockOps};
use super::swap_watcher::{watcher_topic, SwapWatcherMsg};
use super::trade_preimage::{TradePreimageRequest, TradePreimageRpcError, TradePreimageRpcResult};
use super::{broadcast_my_swap_status, broadcast_swap_message, broadcast_swap_msg_every,
check_other_coin_balance_for_swap, dex_fee_amount_from_taker_coin, dex_fee_rate, dex_fee_threshold,
get_locked_amount, recv_swap_msg, swap_topic, wait_for_maker_payment_conf_until, AtomicSwap, LockedAmount,
MySwapInfo, NegotiationDataMsg, NegotiationDataV2, NegotiationDataV3, RecoveredSwap, RecoveredSwapAction,
SavedSwap, SavedSwapIo, SavedTradeFee, SwapConfirmationsSettings, SwapError, SwapMsg, SwapPubkeys,
SwapTxDataMsg, SwapsContext, TransactionIdentifier, WAIT_CONFIRM_INTERVAL_SEC};
check_other_coin_balance_for_swap, dex_fee_amount_from_taker_coin, dex_fee_rate, get_locked_amount,
recv_swap_msg, swap_topic, wait_for_maker_payment_conf_until, AtomicSwap, LockedAmount, MySwapInfo,
NegotiationDataMsg, NegotiationDataV2, NegotiationDataV3, RecoveredSwap, RecoveredSwapAction, SavedSwap,
SavedSwapIo, SavedTradeFee, SwapConfirmationsSettings, SwapError, SwapMsg, SwapPubkeys, SwapTxDataMsg,
SwapsContext, TransactionIdentifier, WAIT_CONFIRM_INTERVAL_SEC};
use crate::mm2::lp_network::subscribe_to_topic;
use crate::mm2::lp_ordermatch::TakerOrderBuilder;
use crate::mm2::lp_swap::{broadcast_p2p_tx_msg, broadcast_swap_msg_every_delayed, tx_helper_topic,
Expand Down Expand Up @@ -2577,13 +2577,12 @@ pub fn max_taker_vol_from_available(
rel: &str,
min_tx_amount: &MmNumber,
) -> Result<MmNumber, MmError<MaxTakerVolumeLessThanDust>> {
let fee_threshold = dex_fee_threshold(min_tx_amount.clone());
let dex_fee_rate = dex_fee_rate(base, rel);
let threshold_coef = &(&MmNumber::from(1) + &dex_fee_rate) / &dex_fee_rate;
let max_vol = if available > &fee_threshold * &threshold_coef {
let max_vol = if available > min_tx_amount * &threshold_coef {
available / (MmNumber::from(1) + dex_fee_rate)
} else {
available - fee_threshold
available - min_tx_amount.clone()
artemii235 marked this conversation as resolved.
Show resolved Hide resolved
};

if &max_vol <= min_tx_amount {
Expand Down Expand Up @@ -2948,21 +2947,19 @@ mod taker_swap_tests {

#[test]
fn test_max_taker_vol_from_available() {
let dex_fee_threshold = MmNumber::from("0.0001");
let min_tx_amount = MmNumber::from("0.00001");

// For these `availables` the dex_fee must be greater than threshold
// For these `availables` the dex_fee must be greater than min_tx_amount
let source = vec![
("0.0779", false),
("0.1", false),
("0.135", false),
("12.000001", false),
("999999999999999999999999999999999999999999999999999999", false),
("0.0778000000000000000000000000000000000000000000000002", false),
("0.0779", false),
("0.0778000000000000000000000000000000000000000000000001", false),
("0.0863333333333333333333333333333333333333333333333334", true),
("0.0863333333333333333333333333333333333333333333333333", true),
("0.00779", false),
("0.01", false),
("0.0135", false),
("1.2000001", false),
("99999999999999999999999999999999999999999999999999999", false),
("0.00778000000000000000000000000000000000000000000000002", false),
("0.00778000000000000000000000000000000000000000000000001", false),
("0.00863333333333333333333333333333333333333333333333334", true),
("0.00863333333333333333333333333333333333333333333333333", true),
];
for (available, is_kmd) in source {
let available = MmNumber::from(available);
Expand All @@ -2971,52 +2968,52 @@ mod taker_swap_tests {
let max_taker_vol = max_taker_vol_from_available(available.clone(), "RICK", "MORTY", &min_tx_amount)
.expect("!max_taker_vol_from_available");

let dex_fee = dex_fee_amount(base, "MORTY", &max_taker_vol, &dex_fee_threshold);
assert!(dex_fee_threshold < dex_fee);
let dex_fee = dex_fee_amount(base, "MORTY", &max_taker_vol, &min_tx_amount);
assert!(min_tx_amount < dex_fee);
assert!(min_tx_amount <= max_taker_vol);
assert_eq!(max_taker_vol + dex_fee, available);
}

// for these `availables` the dex_fee must be the same as `threshold`
// for these `availables` the dex_fee must be the same as min_tx_amount
let source = vec![
("0.0863333333333333333333333333333333333333333333333332", true),
("0.0863333333333333333333333333333333333333333333333331", true),
("0.0777999999999999999999999999999999999999999999999999", false),
("0.0777", false),
("0.0002", false),
("0.00863333333333333333333333333333333333333333333333332", true),
("0.00863333333333333333333333333333333333333333333333331", true),
("0.00777999999999999999999999999999999999999999999999999", false),
("0.00777", false),
("0.00002001", false),
];
for (available, is_kmd) in source {
let available = MmNumber::from(available);
// no matter base or rel is KMD
let base = if is_kmd { "KMD" } else { "RICK" };
let max_taker_vol = max_taker_vol_from_available(available.clone(), base, "MORTY", &min_tx_amount)
.expect("!max_taker_vol_from_available");
let dex_fee = dex_fee_amount(base, "MORTY", &max_taker_vol, &dex_fee_threshold);
let dex_fee = dex_fee_amount(base, "MORTY", &max_taker_vol, &min_tx_amount);
println!(
"available={:?} max_taker_vol={:?} dex_fee={:?}",
available.to_decimal(),
max_taker_vol.to_decimal(),
dex_fee.to_decimal()
);
assert_eq!(dex_fee_threshold, dex_fee);
assert_eq!(min_tx_amount, dex_fee);
assert!(min_tx_amount <= max_taker_vol);
assert_eq!(max_taker_vol + dex_fee, available);
}

// these `availables` must return an error
let availables = vec![
"0.0001999",
"0.00011",
"0.0001000000000000000000000000000000000000000000000001",
"0.0001",
"0.0000999999999999999999999999999999999999999999999999",
"0.0000000000000000000000000000000000000000000000000001",
"0.00002",
"0.000011",
"0.00001000000000000000000000000000000000000000000000001",
"0.00001",
"0.00000999999999999999999999999999999999999999999999999",
"0.00000000000000000000000000000000000000000000000000001",
"0",
"-2",
];
for available in availables {
let available = MmNumber::from(available);
max_taker_vol_from_available(available.clone(), "KMD", "MORTY", &dex_fee_threshold)
max_taker_vol_from_available(available.clone(), "KMD", "MORTY", &min_tx_amount)
.expect_err("!max_taker_vol_from_available success but should be error");
}
}
Expand Down
8 changes: 4 additions & 4 deletions mm2src/mm2_main/tests/docker_tests/docker_tests_inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2005,8 +2005,8 @@ fn test_get_max_taker_vol() {

// https://github.com/KomodoPlatform/atomicDEX-API/issues/733
#[test]
fn test_get_max_taker_vol_dex_fee_threshold() {
let (_ctx, _, alice_priv_key) = generate_utxo_coin_with_random_privkey("MYCOIN1", "0.05328455".parse().unwrap());
fn test_get_max_taker_vol_dex_fee_min_tx_amount() {
let (_ctx, _, alice_priv_key) = generate_utxo_coin_with_random_privkey("MYCOIN1", "0.00532845".parse().unwrap());
let coins = json!([mycoin_conf(10000), mycoin1_conf(10000)]);
let mm_alice = MarketMakerIt::start(
json!({
Expand Down Expand Up @@ -2034,8 +2034,8 @@ fn test_get_max_taker_vol_dex_fee_threshold() {
.unwrap();
assert!(rc.0.is_success(), "!max_taker_vol: {}", rc.1);
let json: Json = serde_json::from_str(&rc.1).unwrap();
// the result of equation x + 0.0001 (dex fee) + 0.0002 (miner fee * 2) = 0.05328455
assert_eq!(json["result"]["numer"], Json::from("1059691"));
// the result of equation x + 0.00001 (dex fee) + 0.0002 (miner fee * 2) = 0.00532845
assert_eq!(json["result"]["numer"], Json::from("102369"));
assert_eq!(json["result"]["denom"], Json::from("20000000"));

let rc = block_on(mm_alice.rpc(&json!({
Expand Down
28 changes: 9 additions & 19 deletions mm2src/mm2_main/tests/docker_tests/swap_watcher_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use coins::{ConfirmPaymentInput, FoundSwapTxSpend, MarketCoinOps, MmCoin, MmCoin
use common::{block_on, now_sec_u32, wait_until_sec, DEX_FEE_ADDR_RAW_PUBKEY};
use crypto::privkey::{key_pair_from_secret, key_pair_from_seed};
use futures01::Future;
use mm2_main::mm2::lp_swap::{dex_fee_amount, dex_fee_amount_from_taker_coin, dex_fee_threshold, get_payment_locktime,
MakerSwap, MAKER_PAYMENT_SENT_LOG, MAKER_PAYMENT_SPEND_FOUND_LOG,
MAKER_PAYMENT_SPEND_SENT_LOG, TAKER_PAYMENT_REFUND_SENT_LOG, WATCHER_MESSAGE_SENT_LOG};
use mm2_main::mm2::lp_swap::{dex_fee_amount, dex_fee_amount_from_taker_coin, get_payment_locktime, MakerSwap,
MAKER_PAYMENT_SENT_LOG, MAKER_PAYMENT_SPEND_FOUND_LOG, MAKER_PAYMENT_SPEND_SENT_LOG,
TAKER_PAYMENT_REFUND_SENT_LOG, WATCHER_MESSAGE_SENT_LOG};
use mm2_number::BigDecimal;
use mm2_number::MmNumber;
use mm2_test_helpers::for_tests::{enable_eth_coin, eth_jst_testnet_conf, eth_testnet_conf, mm_dump, my_balance,
Expand Down Expand Up @@ -352,15 +352,10 @@ fn test_watcher_spends_maker_payment_eth_utxo() {

let eth_volume = BigDecimal::from_str("0.01").unwrap();
let mycoin_volume = BigDecimal::from_str("1").unwrap();
let dex_fee_threshold = dex_fee_threshold(BigDecimal::from_str("0.00001").unwrap().into());
let min_tx_amount = BigDecimal::from_str("0.00001").unwrap().into();

let dex_fee: BigDecimal = dex_fee_amount(
"MYCOIN",
"ETH",
&MmNumber::from(mycoin_volume.clone()),
&dex_fee_threshold,
)
.into();
let dex_fee: BigDecimal =
dex_fee_amount("MYCOIN", "ETH", &MmNumber::from(mycoin_volume.clone()), &min_tx_amount).into();
let alice_mycoin_reward_sent = balances.alice_acoin_balance_before
- balances.alice_acoin_balance_after.clone()
- mycoin_volume.clone()
Expand Down Expand Up @@ -510,14 +505,9 @@ fn test_watcher_spends_maker_payment_erc20_utxo() {
let mycoin_volume = BigDecimal::from_str("1").unwrap();
let jst_volume = BigDecimal::from_str("1").unwrap();

let dex_fee_threshold = dex_fee_threshold(BigDecimal::from_str("0.00001").unwrap().into());
let dex_fee: BigDecimal = dex_fee_amount(
"MYCOIN",
"JST",
&MmNumber::from(mycoin_volume.clone()),
&dex_fee_threshold,
)
.into();
let min_tx_amount = BigDecimal::from_str("0.00001").unwrap().into();
let dex_fee: BigDecimal =
dex_fee_amount("MYCOIN", "JST", &MmNumber::from(mycoin_volume.clone()), &min_tx_amount).into();
let alice_mycoin_reward_sent = balances.alice_acoin_balance_before
- balances.alice_acoin_balance_after.clone()
- mycoin_volume.clone()
Expand Down
Loading