Skip to content

Commit

Permalink
add non-kmd burn activation with negotiation msg V4
Browse files Browse the repository at this point in the history
  • Loading branch information
dimxy committed Aug 11, 2024
1 parent 26552c3 commit c02253a
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 71 deletions.
31 changes: 18 additions & 13 deletions mm2src/coins/lp_coins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3656,7 +3656,12 @@ impl DexFee {
}

/// Creates a new `DexFee` for a taker coin to sell.
pub fn new_from_taker_coin(taker_coin: &dyn MmCoin, rel_ticker: &str, trade_amount: &MmNumber) -> DexFee {
pub fn new_from_taker_coin(
taker_coin: &dyn MmCoin,
rel_ticker: &str,
trade_amount: &MmNumber,
burn_active: bool,
) -> DexFee {
// calc dex fee
let rate = Self::dex_fee_rate(taker_coin.ticker(), rel_ticker);
let dex_fee = trade_amount * &rate;
Expand All @@ -3665,17 +3670,17 @@ impl DexFee {
return DexFee::Standard(min_tx_amount);
}

if taker_coin.should_burn_dex_fee() {
if taker_coin.is_kmd() {
// use a special dex fee option for kmd
let (fee_amount, burn_amount) = Self::calc_burn_amount_for_op_return(&dex_fee, &min_tx_amount);
return DexFee::WithBurn {
fee_amount,
burn_amount,
burn_destination: DexFeeBurnDestination::KmdOpReturn,
};
} else {
// burn dex fee to the burn account
if taker_coin.is_kmd() {
// use a special dex fee option for kmd
let (fee_amount, burn_amount) = Self::calc_burn_amount_for_op_return(&dex_fee, &min_tx_amount);
return DexFee::WithBurn {
fee_amount,
burn_amount,
burn_destination: DexFeeBurnDestination::KmdOpReturn,
};
} else {
if taker_coin.should_burn_dex_fee() && burn_active {
// send part of dex fee to the 'pre-burn' account
let (fee_amount, burn_amount) = Self::calc_burn_amount_for_burn_account(&dex_fee, &min_tx_amount);
// burn_amount can be set to zero if it is dust
if burn_amount > MmNumber::from(0) {
Expand All @@ -3697,7 +3702,7 @@ impl DexFee {
Ok(_) => &["KMD", "MYCOIN"],
Err(_) => &["KMD"],
};

#[cfg(not(any(feature = "for-tests", test)))]
let fee_discount_tickers: &[&str] = &["KMD"];

Expand Down
9 changes: 5 additions & 4 deletions mm2src/mm2_main/src/lp_ordermatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,13 @@ use crate::mm2::lp_network::{broadcast_p2p_msg, request_any_relay, request_one_p
use crate::mm2::lp_swap::maker_swap_v2::{self, MakerSwapStateMachine, MakerSwapStorage};
use crate::mm2::lp_swap::taker_swap_v2::{self, TakerSwapStateMachine, TakerSwapStorage};
use crate::mm2::lp_swap::{calc_max_maker_vol, check_balance_for_maker_swap, check_balance_for_taker_swap,
check_other_coin_balance_for_swap, detect_secret_hash_algo, dex_fee_amount_from_taker_coin,
check_other_coin_balance_for_swap, detect_secret_hash_algo, dex_fee_from_taker_coin,
generate_secret, get_max_maker_vol, insert_new_swap_to_db, is_pubkey_banned,
lp_atomic_locktime, p2p_keypair_and_peer_id_to_broadcast,
p2p_private_and_peer_id_to_broadcast, run_maker_swap, run_taker_swap, swap_v2_topic,
AtomicLocktimeVersion, CheckBalanceError, CheckBalanceResult, CoinVolumeInfo, MakerSwap,
RunMakerSwapInput, RunTakerSwapInput, SwapConfirmationsSettings, TakerSwap, LEGACY_SWAP_TYPE};
RunMakerSwapInput, RunTakerSwapInput, SwapConfirmationsSettings, TakerSwap,
LEGACY_SWAP_TYPE, PRE_BURN_ACCOUNT_ACTIVE};

#[cfg(any(test, feature = "run-docker-tests"))]
use crate::mm2::lp_swap::taker_swap::FailAt;
Expand Down Expand Up @@ -2986,7 +2987,7 @@ fn lp_connect_start_bob(ctx: MmArc, maker_match: MakerMatch, maker_order: MakerO
maker_volume: maker_amount,
secret,
taker_coin: t.clone(),
dex_fee: dex_fee_amount_from_taker_coin(&t, m.ticker(), &taker_amount),
dex_fee: dex_fee_from_taker_coin(&t, m.ticker(), &taker_amount, PRE_BURN_ACCOUNT_ACTIVE),
taker_volume: taker_amount,
taker_premium: Default::default(),
conf_settings: my_conf_settings,
Expand Down Expand Up @@ -3144,7 +3145,7 @@ fn lp_connected_alice(ctx: MmArc, taker_order: TakerOrder, taker_match: TakerMat
maker_coin: m.clone(),
maker_volume: maker_amount,
taker_coin: t.clone(),
dex_fee: dex_fee_amount_from_taker_coin(&t, maker_coin_ticker, &taker_amount),
dex_fee: dex_fee_from_taker_coin(&t, maker_coin_ticker, &taker_amount, PRE_BURN_ACCOUNT_ACTIVE),
taker_volume: taker_amount,
taker_premium: Default::default(),
secret_hash_algo,
Expand Down
58 changes: 33 additions & 25 deletions mm2src/mm2_main/src/lp_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -806,8 +806,13 @@ pub fn lp_atomic_locktime(maker_coin: &str, taker_coin: &str, version: AtomicLoc
}

/// Calculates DEX fee with a threshold based on min tx amount of the taker coin.
pub fn dex_fee_amount_from_taker_coin(taker_coin: &dyn MmCoin, maker_coin: &str, trade_amount: &MmNumber) -> DexFee {
DexFee::new_from_taker_coin(taker_coin, maker_coin, trade_amount)
pub fn dex_fee_from_taker_coin(
taker_coin: &dyn MmCoin,
maker_coin: &str,
trade_amount: &MmNumber,
burn_active: bool,
) -> DexFee {
DexFee::new_from_taker_coin(taker_coin, maker_coin, trade_amount, burn_active)
}

#[derive(Clone, Debug, Eq, Deserialize, PartialEq, Serialize)]
Expand Down Expand Up @@ -1829,6 +1834,9 @@ pub(crate) const INCLUDE_REFUND_FEE: bool = true;
/// Do not add refund fee to calculate fee needed only to make a successful swap
pub(crate) const NO_REFUND_FEE: bool = false;

/// Sending part of dex fee to the pre-burn account is active
pub const PRE_BURN_ACCOUNT_ACTIVE: bool = true;

#[cfg(all(test, not(target_arch = "wasm32")))]
mod lp_swap_tests {
use super::*;
Expand All @@ -1852,7 +1860,7 @@ mod lp_swap_tests {
TestCoin::min_tx_amount.mock_safe(|_| MockResult::Return(MmNumber::from("0.0001").into()));
let rel = "ETH";
let amount = 1.into();
let actual_fee = DexFee::new_from_taker_coin(&btc, rel, &amount);
let actual_fee = DexFee::new_from_taker_coin(&btc, rel, &amount, PRE_BURN_ACCOUNT_ACTIVE);
let expected_fee = DexFee::WithBurn {
fee_amount: amount.clone() / 777u64.into() * "0.75".into(),
burn_amount: amount / 777u64.into() * "0.25".into(),
Expand All @@ -1867,7 +1875,7 @@ mod lp_swap_tests {
TestCoin::min_tx_amount.mock_safe(|_| MockResult::Return(MmNumber::from("0.0001").into()));
let rel = "ETH";
let amount = 1.into();
let actual_fee = DexFee::new_from_taker_coin(&kmd, rel, &amount);
let actual_fee = DexFee::new_from_taker_coin(&kmd, rel, &amount, PRE_BURN_ACCOUNT_ACTIVE);
let expected_fee = amount.clone() * (9, 7770).into() * MmNumber::from("0.75");
let expected_burn_amount = amount * (9, 7770).into() * MmNumber::from("0.25");
assert_eq!(
Expand All @@ -1887,7 +1895,7 @@ mod lp_swap_tests {
TestCoin::min_tx_amount.mock_safe(|_| MockResult::Return(MmNumber::from("0.00001").into()));
let rel = "BTC";
let amount = (1001 * 777, 90000000).into();
let actual_fee = DexFee::new_from_taker_coin(&kmd, rel, &amount);
let actual_fee = DexFee::new_from_taker_coin(&kmd, rel, &amount, PRE_BURN_ACCOUNT_ACTIVE);
assert_eq!(
DexFee::WithBurn {
fee_amount: "0.00001".into(), // equals to min_tx_amount
Expand All @@ -1904,7 +1912,7 @@ mod lp_swap_tests {
TestCoin::min_tx_amount.mock_safe(|_| MockResult::Return(MmNumber::from("0.00001").into()));
let rel = "KMD";
let amount = 1.into();
let actual_fee = DexFee::new_from_taker_coin(&btc, rel, &amount);
let actual_fee = DexFee::new_from_taker_coin(&btc, rel, &amount, PRE_BURN_ACCOUNT_ACTIVE);
let expected_fee = DexFee::WithBurn {
fee_amount: amount.clone() * (9, 7770).into() * "0.75".into(),
burn_amount: amount * (9, 7770).into() * "0.25".into(),
Expand All @@ -1920,7 +1928,7 @@ mod lp_swap_tests {
TestCoin::min_tx_amount.mock_safe(|_| MockResult::Return(MmNumber::from("0.00001").into()));
let rel = "KMD";
let amount: MmNumber = "0.001".parse::<BigDecimal>().unwrap().into();
let actual_fee = DexFee::new_from_taker_coin(&btc, rel, &amount);
let actual_fee = DexFee::new_from_taker_coin(&btc, rel, &amount, PRE_BURN_ACCOUNT_ACTIVE);
assert_eq!(DexFee::Standard("0.00001".into()), actual_fee);
TestCoin::should_burn_dex_fee.clear_mock();

Expand All @@ -1932,7 +1940,7 @@ mod lp_swap_tests {
TestCoin::min_tx_amount.mock_safe(|_| MockResult::Return(MmNumber::from("0.00001").into()));
let rel = "KMD";
let amount: MmNumber = "0.03".parse::<BigDecimal>().unwrap().into();
let actual_fee = DexFee::new_from_taker_coin(&btc, rel, &amount);
let actual_fee = DexFee::new_from_taker_coin(&btc, rel, &amount, PRE_BURN_ACCOUNT_ACTIVE);
assert_eq!(DexFee::Standard(amount * (9, 7770).into()), actual_fee);
TestCoin::should_burn_dex_fee.clear_mock();

Expand All @@ -1943,7 +1951,7 @@ mod lp_swap_tests {
TestCoin::min_tx_amount.mock_safe(|_| MockResult::Return(MmNumber::from("0.00001").into()));
let rel = "BTC";
let amount: MmNumber = "1".parse::<BigDecimal>().unwrap().into();
let actual_fee = DexFee::new_from_taker_coin(&btc, rel, &amount);
let actual_fee = DexFee::new_from_taker_coin(&btc, rel, &amount, PRE_BURN_ACCOUNT_ACTIVE);
assert_eq!(DexFee::Standard(amount / "777".into()), actual_fee);
TestCoin::should_burn_dex_fee.clear_mock();
}
Expand Down Expand Up @@ -2463,23 +2471,23 @@ mod lp_swap_tests {

let kmd = coins::TestCoin::new("KMD");
TestCoin::should_burn_dex_fee.mock_safe(|_| MockResult::Return(true));
let (kmd_fee_amount, kmd_burn_amount) = match dex_fee_amount_from_taker_coin(&kmd, "ETH", &MmNumber::from(6150))
{
DexFee::Standard(_) => panic!("Wrong variant returned for KMD from `dex_fee_amount_from_taker_coin`."),
DexFee::WithBurn {
fee_amount,
burn_amount,
..
} => (fee_amount, burn_amount),
};
let (kmd_fee_amount, kmd_burn_amount) =
match dex_fee_from_taker_coin(&kmd, "ETH", &MmNumber::from(6150), PRE_BURN_ACCOUNT_ACTIVE) {
DexFee::Standard(_) => panic!("Wrong variant returned for KMD from `dex_fee_from_taker_coin`."),
DexFee::WithBurn {
fee_amount,
burn_amount,
..
} => (fee_amount, burn_amount),
};
TestCoin::should_burn_dex_fee.clear_mock();

let mycoin = coins::TestCoin::new("MYCOIN");
TestCoin::should_burn_dex_fee.mock_safe(|_| MockResult::Return(true));
let (mycoin_fee_amount, mycoin_burn_amount) =
match dex_fee_amount_from_taker_coin(&mycoin, "ETH", &MmNumber::from(6150)) {
match dex_fee_from_taker_coin(&mycoin, "ETH", &MmNumber::from(6150), PRE_BURN_ACCOUNT_ACTIVE) {
DexFee::Standard(_) => {
panic!("Wrong variant returned for MYCOIN from `dex_fee_amount_from_taker_coin`.")
panic!("Wrong variant returned for MYCOIN from `dex_fee_from_taker_coin`.")
},
DexFee::WithBurn {
fee_amount,
Expand All @@ -2499,15 +2507,15 @@ mod lp_swap_tests {
}

#[test]
fn test_dex_fee_amount_from_taker_coin_discount() {
fn test_dex_fee_from_taker_coin_discount() {
std::env::set_var("MYCOIN_FEE_DISCOUNT", "");

let mycoin = coins::TestCoin::new("MYCOIN");
TestCoin::should_burn_dex_fee.mock_safe(|_| MockResult::Return(true));
let (mycoin_taker_fee, mycoin_burn_amount) =
match dex_fee_amount_from_taker_coin(&mycoin, "", &MmNumber::from(6150)) {
match dex_fee_from_taker_coin(&mycoin, "", &MmNumber::from(6150), PRE_BURN_ACCOUNT_ACTIVE) {
DexFee::Standard(_) => {
panic!("Wrong variant returned for MYCOIN from `dex_fee_amount_from_taker_coin`.")
panic!("Wrong variant returned for MYCOIN from `dex_fee_from_taker_coin`.")
},
DexFee::WithBurn {
fee_amount,
Expand All @@ -2520,9 +2528,9 @@ mod lp_swap_tests {
let testcoin = coins::TestCoin::default();
TestCoin::should_burn_dex_fee.mock_safe(|_| MockResult::Return(true));
let (testcoin_taker_fee, testcoin_burn_amount) =
match dex_fee_amount_from_taker_coin(&testcoin, "", &MmNumber::from(6150)) {
match dex_fee_from_taker_coin(&testcoin, "", &MmNumber::from(6150), PRE_BURN_ACCOUNT_ACTIVE) {
DexFee::Standard(_) => {
panic!("Wrong variant returned for TEST coin from `dex_fee_amount_from_taker_coin`.")
panic!("Wrong variant returned for TEST coin from `dex_fee_from_taker_coin`.")
},
DexFee::WithBurn {
fee_amount,
Expand Down
31 changes: 29 additions & 2 deletions mm2src/mm2_main/src/lp_swap/maker_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,15 +635,25 @@ impl MakerSwap {
NEGOTIATION_TIMEOUT_SEC,
);
let taker_data = match recv_fut.await {
Ok(d) => d,
Ok(d) => { println!("received okay from recv_fut"); d},
Err(e) => {
println!("received error from recv_fut");
self.broadcast_negotiated_false();
return Ok((Some(MakerSwapCommand::Finish), vec![MakerSwapEvent::NegotiateFailed(
ERRL!("{:?}", e).into(),
)]));
},
};
drop(send_abort_handle);

let remote_version = taker_data.version();
if remote_version < MIN_SWAP_PROTOCOL_VERSION {
self.broadcast_negotiated_false();
return Ok((Some(MakerSwapCommand::Finish), vec![MakerSwapEvent::NegotiateFailed(
ERRL!("Taker protocol version {} too old", remote_version).into(),
)]));
}

let time_dif = self.r().data.started_at.abs_diff(taker_data.started_at());
if time_dif > MAX_STARTED_AT_DIFF {
self.broadcast_negotiated_false();
Expand Down Expand Up @@ -709,6 +719,7 @@ impl MakerSwap {

Ok((Some(MakerSwapCommand::WaitForTakerFee), vec![
MakerSwapEvent::Negotiated(TakerNegotiationData {
taker_version: Some(remote_version),
taker_payment_locktime: taker_data.payment_locktime(),
// using default to avoid misuse of this field
// maker_coin_htlc_pubkey and taker_coin_htlc_pubkey must be used instead
Expand All @@ -728,6 +739,7 @@ impl MakerSwap {
self.ctx.clone(),
swap_topic(&self.uuid),
negotiated,
None,
TAKER_FEE_RECV_TIMEOUT_SEC as f64 / 6.,
self.p2p_privkey,
);
Expand Down Expand Up @@ -786,7 +798,22 @@ impl MakerSwap {
info!("Taker fee tx {:02x}", hash);

let taker_amount = MmNumber::from(self.taker_amount.clone());
let dex_fee = dex_fee_amount_from_taker_coin(self.taker_coin.deref(), &self.r().data.maker_coin, &taker_amount);
let remote_version = self
.r()
.data
.taker_version
.ok_or("No swap protocol version".to_owned())?;
let is_burn_active = SwapFeature::is_active(SwapFeature::NonKmdToPreBurnAccount, remote_version);
let dex_fee = dex_fee_from_taker_coin(
self.taker_coin.deref(),
&self.r().data.maker_coin,
&taker_amount,
is_burn_active,
);
println!(
"wait_taker_fee remote_version={remote_version} is_burn_active={is_burn_active} dex_fee={:?}",
dex_fee
);
let other_taker_coin_htlc_pub = self.r().other_taker_coin_htlc_pub;
let taker_coin_start_block = self.r().data.taker_coin_start_block;

Expand Down
Loading

0 comments on commit c02253a

Please sign in to comment.