From fdf746d379e03a90a16827e60aaa81f05202a41a Mon Sep 17 00:00:00 2001 From: nakul1010 Date: Mon, 26 Jun 2023 15:35:02 +0530 Subject: [PATCH] fix: self redeem fee less only if redeemable amount is equal to requested redeem amount --- crates/redeem/src/lib.rs | 8 +-- crates/redeem/src/tests.rs | 101 ++++++++++++++++++++++++++++++++++--- 2 files changed, 100 insertions(+), 9 deletions(-) diff --git a/crates/redeem/src/lib.rs b/crates/redeem/src/lib.rs index e580d02f97..de653056d2 100644 --- a/crates/redeem/src/lib.rs +++ b/crates/redeem/src/lib.rs @@ -404,7 +404,7 @@ mod self_redeem { } /// returns (fees, consumed_issued_tokens) - fn calculate_token_amounts( + pub fn calculate_token_amounts( vault_id: &DefaultVaultId, requested_redeem_amount: &Amount, ) -> Result<(Amount, Amount), DispatchError> { @@ -479,9 +479,11 @@ impl Pallet { // Make sure this can't happen again. ensure!(!btc_address.is_zero(), btc_relay::Error::::InvalidBtcHash); - // todo: currently allowed to redeem from one currency to the other for free - decide if this is desirable let fee_wrapped = if redeemer == vault_id.account_id { - Amount::zero(vault_id.wrapped_currency()) + // allow to redeem for zero fee if and only if redeemable amount is equal to requested redeem amount + let (fees, _consumed_issued_tokens) = + self_redeem::calculate_token_amounts::(&vault_id, &amount_wrapped)?; + fees } else { ext::fee::get_redeem_fee::(&amount_wrapped)? }; diff --git a/crates/redeem/src/tests.rs b/crates/redeem/src/tests.rs index dc75e3e650..252e536370 100644 --- a/crates/redeem/src/tests.rs +++ b/crates/redeem/src/tests.rs @@ -246,16 +246,17 @@ fn test_request_redeem_fails_with_default_btc_address() { } #[test] -fn test_request_redeem_succeeds_with_self_redeem() { +fn test_request_redeem_succeeds_with_self_redeem_feeless_call() { run_test(|| { convert_to.mock_safe(|_, x| MockResult::Return(Ok(x))); + let issued_tokens = 10; >::insert_vault( &VAULT, vault_registry::Vault { id: VAULT, to_be_replaced_tokens: 0, to_be_issued_tokens: 0, - issued_tokens: 10, + issued_tokens, to_be_redeemed_tokens: 0, active_replace_collateral: 0, replace_collateral: 0, @@ -267,13 +268,13 @@ fn test_request_redeem_succeeds_with_self_redeem() { ); let redeemer = VAULT.account_id; - let amount = 90; + let amount = issued_tokens; let btc_address = BtcAddress::random(); + let redeem_fee = 5; ext::vault_registry::try_increase_to_be_redeemed_tokens::.mock_safe(move |vault_id, amount_btc| { assert_eq!(vault_id, &VAULT); assert_eq!(amount_btc, &wrapped(amount)); - MockResult::Return(Ok(())) }); @@ -286,11 +287,13 @@ fn test_request_redeem_succeeds_with_self_redeem() { ext::security::get_secure_id::.mock_safe(move |_| MockResult::Return(H256::zero())); ext::vault_registry::is_vault_below_premium_threshold::.mock_safe(move |_| MockResult::Return(Ok(false))); + ext::fee::get_redeem_fee::.mock_safe(move |_| MockResult::Return(Ok(wrapped(redeem_fee)))); + let btc_fee = Redeem::get_current_inclusion_fee(DEFAULT_WRAPPED_CURRENCY).unwrap(); assert_ok!(Redeem::request_redeem( RuntimeOrigin::signed(redeemer), - amount, + issued_tokens, btc_address, VAULT )); @@ -299,7 +302,7 @@ fn test_request_redeem_succeeds_with_self_redeem() { redeem_id: H256::zero(), redeemer, amount: amount - btc_fee.amount(), - fee: 0, + fee: 0, //redeem fee zero since all redeemable tokens redeem by vault premium: 0, vault_id: VAULT, btc_address, @@ -307,6 +310,7 @@ fn test_request_redeem_succeeds_with_self_redeem() { .unwrap() .amount() }); + assert_ok!( Redeem::get_open_redeem_request_from_id(&H256::zero()), RedeemRequest { @@ -328,6 +332,91 @@ fn test_request_redeem_succeeds_with_self_redeem() { }) } +#[test] +fn test_request_redeem_succeeds_with_self_redeem_but_pays_fee() { + run_test(|| { + convert_to.mock_safe(|_, x| MockResult::Return(Ok(x))); + >::insert_vault( + &VAULT, + vault_registry::Vault { + id: VAULT, + to_be_replaced_tokens: 0, + to_be_issued_tokens: 0, + issued_tokens: 10, + to_be_redeemed_tokens: 0, + active_replace_collateral: 0, + replace_collateral: 0, + banned_until: None, + secure_collateral_threshold: None, + status: VaultStatus::Active(true), + liquidated_collateral: 0, + }, + ); + + let redeemer = VAULT.account_id; + let amount = 90; + let btc_address = BtcAddress::random(); + let redeem_fee = 5; + + ext::vault_registry::try_increase_to_be_redeemed_tokens::.mock_safe(move |vault_id, amount_btc| { + assert_eq!(vault_id, &VAULT); + assert_eq!(amount_btc, &wrapped(amount - redeem_fee)); + MockResult::Return(Ok(())) + }); + + Amount::::lock_on.mock_safe(move |amount_wrapped, account| { + assert_eq!(account, &redeemer); + assert_eq!(amount_wrapped, &wrapped(amount)); + + MockResult::Return(Ok(())) + }); + + ext::security::get_secure_id::.mock_safe(move |_| MockResult::Return(H256::zero())); + ext::vault_registry::is_vault_below_premium_threshold::.mock_safe(move |_| MockResult::Return(Ok(false))); + ext::fee::get_redeem_fee::.mock_safe(move |_| MockResult::Return(Ok(wrapped(redeem_fee)))); + + let btc_fee = Redeem::get_current_inclusion_fee(DEFAULT_WRAPPED_CURRENCY).unwrap(); + + assert_ok!(Redeem::request_redeem( + RuntimeOrigin::signed(redeemer), + amount, + btc_address, + VAULT + )); + + assert_emitted!(Event::RequestRedeem { + redeem_id: H256::zero(), + redeemer, + amount: amount - btc_fee.amount() - redeem_fee, + fee: redeem_fee, + premium: 0, + vault_id: VAULT, + btc_address, + transfer_fee: Redeem::get_current_inclusion_fee(DEFAULT_WRAPPED_CURRENCY) + .unwrap() + .amount() + }); + assert_ok!( + Redeem::get_open_redeem_request_from_id(&H256::zero()), + RedeemRequest { + period: Redeem::redeem_period(), + vault: VAULT, + opentime: 1, + fee: redeem_fee, + amount_btc: amount - btc_fee.amount() - redeem_fee, + premium: 0, + redeemer, + btc_address, + btc_height: 0, + status: RedeemRequestStatus::Pending, + transfer_fee_btc: Redeem::get_current_inclusion_fee(DEFAULT_WRAPPED_CURRENCY) + .unwrap() + .amount(), + } + ); + }) +} + #[test] fn test_liquidation_redeem_succeeds() { run_test(|| {