Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 66 additions & 6 deletions zenlink-protocol/src/fee/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under Apache 2.0.

use super::mock::*;
use crate::{AssetId, Error, MultiAssetsHandler};
use crate::{AssetId, MultiAssetsHandler};
use frame_support::{assert_noop, assert_ok, error::BadOrigin};
use frame_system::RawOrigin;
use sp_core::U256;
Expand Down Expand Up @@ -44,11 +44,6 @@ fn fee_meta_setter_should_not_work() {
);

assert_noop!(DexPallet::set_fee_point(RawOrigin::Signed(BOB).into(), 0), BadOrigin);

assert_noop!(
DexPallet::set_fee_point(RawOrigin::Root.into(), 31u8),
Error::<Test>::InvalidFeePoint
);
})
}

Expand Down Expand Up @@ -507,3 +502,68 @@ fn turn_on_protocol_fee_swap_have_fee_at_should_work() {
assert_eq!(lp_total, lp_of_alice_0 + alice_lp_add + lp_of_bob);
});
}

#[test]
fn assert_higher_fee_point_decreases_protocol_fee() {
new_test_ext().execute_with(|| {
assert_ok!(DexPallet::set_fee_receiver(RawOrigin::Root.into(), Some(BOB)));

assert_ok!(DexPallet::foreign_mint(DOT_ASSET_ID, &ALICE, 100_000_000 * DOT_UNIT));
assert_ok!(DexPallet::foreign_mint(BTC_ASSET_ID, &ALICE, 100_000_000 * BTC_UNIT));
assert_ok!(DexPallet::foreign_mint(DOT_ASSET_ID, &CHARLIE, 100_000_000 * DOT_UNIT));

assert_ok!(DexPallet::create_pair(RawOrigin::Root.into(), DOT_ASSET_ID, BTC_ASSET_ID,));

let total_supply_dot: u128 = 1_000_000 * DOT_UNIT;
let total_supply_btc: u128 = 1_000_000 * BTC_UNIT;

assert_ok!(DexPallet::add_liquidity(
RawOrigin::Signed(ALICE).into(),
DOT_ASSET_ID,
BTC_ASSET_ID,
total_supply_dot,
total_supply_btc,
0,
0,
100
));

assert_ok!(DexPallet::inner_swap_exact_assets_for_assets(
&CHARLIE,
DOT_UNIT,
1,
&vec![DOT_ASSET_ID, BTC_ASSET_ID],
&CHARLIE,
));

fn mint_fee_for_point(fee_point: u8) -> u128 {
let reserve_0 =
<Test as Config>::MultiAssetsHandler::balance_of(DOT_ASSET_ID, &PAIR_DOT_BTC);
let reserve_1 =
<Test as Config>::MultiAssetsHandler::balance_of(BTC_ASSET_ID, &PAIR_DOT_BTC);
let total_supply = <Test as Config>::MultiAssetsHandler::total_supply(LP_DOT_BTC);
assert_ok!(DexPallet::set_fee_point(RawOrigin::Root.into(), fee_point));
DexPallet::mint_protocol_fee(
reserve_0,
reserve_1,
DOT_ASSET_ID,
BTC_ASSET_ID,
total_supply,
)
.unwrap()
}

// 1/(1/1)-1=0
let total_fee = mint_fee_for_point(0);
// 1/(1/2)-1=1
assert_eq!(mint_fee_for_point(1), total_fee / 2);
// 1/(1/4)-1=3
assert_eq!(mint_fee_for_point(3), total_fee / 4);
// 1/(1/6)-1=5
assert_eq!(mint_fee_for_point(5), total_fee / 6);
// 1/(1/10)-1=9
assert_eq!(mint_fee_for_point(9), total_fee / 10);
// 1/(1/100)-1=99
assert_eq!(mint_fee_for_point(99), total_fee / 100);
});
}
22 changes: 8 additions & 14 deletions zenlink-protocol/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,10 @@ pub mod pallet {
#[pallet::genesis_config]
/// Refer: https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2Pair.sol#L88
pub struct GenesisConfig<T: Config> {
/// The admin of the protocol fee.
// pub fee_admin: T::AccountId,
/// The receiver of the protocol fee.
pub fee_receiver: Option<T::AccountId>,
/// The fee point which integer between [0,30]
/// 0 means no protocol fee.
/// 30 means 0.3% * 100% = 0.0030.
/// default is 5 and means 0.3% * 1 / 6 = 0.0005.
/// The higher the fee point, the smaller the
/// cut of the exchange fee taken from LPs.
pub fee_point: u8,
}

Expand Down Expand Up @@ -391,8 +387,6 @@ pub mod pallet {
RequireProtocolAdmin,
/// Require the admin candidate who can become new admin after confirm.
RequireProtocolAdminCandidate,
/// Invalid fee_point
InvalidFeePoint,
/// Unsupported AssetId by this ZenlinkProtocol Version.
UnsupportedAssetType,
/// Account balance must be greater than or equal to the transfer amount.
Expand Down Expand Up @@ -469,7 +463,7 @@ pub mod pallet {
/// - `send_to`:
/// (1) Some(receiver): it turn on the protocol fee and the new receiver account.
/// (2) None: it turn off the protocol fee.
#[pallet::call_index(0)]
#[pallet::call_index(0)]
#[pallet::weight(T::WeightInfo::set_fee_receiver())]
pub fn set_fee_receiver(
origin: OriginFor<T>,
Expand All @@ -495,15 +489,15 @@ pub mod pallet {
/// # Arguments
///
/// - `fee_point`:
/// The fee_point which integer between [0,30]
/// 0 means no protocol fee.
/// 30 means 0.3% * 100% = 0.0030.
/// default is 5 and means 0.3% * 1 / 6 = 0.0005.
/// An integer y which satisfies the equation `1/x-1=y`
/// where x is the percentage of the exchange fee, a
/// value of 0 gives everything to the fee receiver
/// e.g. 1/(1/6)-1=5, 1/(1/2)-1=1
/// See section 2.4 of the Uniswap v2 whitepaper
#[pallet::call_index(1)]
#[pallet::weight(T::WeightInfo::set_fee_point())]
pub fn set_fee_point(origin: OriginFor<T>, fee_point: u8) -> DispatchResult {
ensure_root(origin)?;
ensure!(fee_point <= 30, Error::<T>::InvalidFeePoint);

FeeMeta::<T>::mutate(|fee_meta| fee_meta.1 = fee_point);

Expand Down
53 changes: 24 additions & 29 deletions zenlink-protocol/src/swap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl<T: Config> Pallet<T> {
parameter.total_supply,
)?;
if let Some(fee_to) = Self::fee_meta().0 {
if mint_fee > 0 && Self::fee_meta().1 > 0 {
if mint_fee > 0 {
T::MultiAssetsHandler::deposit(lp_asset_id, &fee_to, mint_fee)
.map(|_| mint_fee)?;
parameter.total_supply = parameter
Expand Down Expand Up @@ -125,18 +125,16 @@ impl<T: Config> Pallet<T> {
T::MultiAssetsHandler::transfer(asset_1, who, &parameter.pair_account, amount_1)?;

if let Some(_fee_to) = Self::fee_meta().0 {
if Self::fee_meta().1 > 0 {
// update reserve_0 and reserve_1
let reserve_0 =
T::MultiAssetsHandler::balance_of(asset_0, &parameter.pair_account);
let reserve_1 =
T::MultiAssetsHandler::balance_of(asset_1, &parameter.pair_account);

let last_k_value = U256::from(reserve_0)
.checked_mul(U256::from(reserve_1))
.ok_or(Error::<T>::Overflow)?;
Self::mutate_k_last(asset_0, asset_1, last_k_value);
}
// update reserve_0 and reserve_1
let reserve_0 =
T::MultiAssetsHandler::balance_of(asset_0, &parameter.pair_account);
let reserve_1 =
T::MultiAssetsHandler::balance_of(asset_1, &parameter.pair_account);

let last_k_value = U256::from(reserve_0)
.checked_mul(U256::from(reserve_1))
.ok_or(Error::<T>::Overflow)?;
Self::mutate_k_last(asset_0, asset_1, last_k_value);
}

Self::deposit_event(Event::LiquidityAdded(
Expand Down Expand Up @@ -198,7 +196,7 @@ impl<T: Config> Pallet<T> {
parameter.total_supply,
)?;
if let Some(fee_to) = Self::fee_meta().0 {
if mint_fee > 0 && Self::fee_meta().1 > 0 {
if mint_fee > 0 {
//Self::mutate_liquidity(asset_0, asset_1, &fee_to, mint_fee, true)?;
T::MultiAssetsHandler::deposit(lp_asset_id, &fee_to, mint_fee)
.map(|_| mint_fee)?;
Expand Down Expand Up @@ -232,18 +230,16 @@ impl<T: Config> Pallet<T> {
)?;

if let Some(_fee_to) = Self::fee_meta().0 {
if Self::fee_meta().1 > 0 {
// update reserve_0 and reserve_1
let reserve_0 =
T::MultiAssetsHandler::balance_of(asset_0, &parameter.pair_account);
let reserve_1 =
T::MultiAssetsHandler::balance_of(asset_1, &parameter.pair_account);

let last_k_value = U256::from(reserve_0)
.checked_mul(U256::from(reserve_1))
.ok_or(Error::<T>::Overflow)?;
Self::mutate_k_last(asset_0, asset_1, last_k_value);
}
// update reserve_0 and reserve_1
let reserve_0 =
T::MultiAssetsHandler::balance_of(asset_0, &parameter.pair_account);
let reserve_1 =
T::MultiAssetsHandler::balance_of(asset_1, &parameter.pair_account);

let last_k_value = U256::from(reserve_0)
.checked_mul(U256::from(reserve_1))
.ok_or(Error::<T>::Overflow)?;
Self::mutate_k_last(asset_0, asset_1, last_k_value);
}

Self::deposit_event(Event::LiquidityRemoved(
Expand Down Expand Up @@ -362,7 +358,7 @@ impl<T: Config> Pallet<T> {
let mut mint_fee: AssetBalance = 0;

if let Some(_fee_to) = Self::fee_meta().0 {
if !new_k_last.is_zero() && Self::fee_meta().1 > 0 {
if !new_k_last.is_zero() {
let root_k = U256::from(reserve_0)
.checked_mul(U256::from(reserve_1))
.map(|n| n.integer_sqrt())
Expand All @@ -371,13 +367,12 @@ impl<T: Config> Pallet<T> {
let root_k_last = new_k_last.integer_sqrt();
if root_k > root_k_last {
let fee_point = Self::fee_meta().1;
let fix_fee_point = (30 - fee_point) / fee_point;
let numerator = U256::from(total_liquidity)
.checked_mul(root_k.checked_sub(root_k_last).ok_or(Error::<T>::Overflow)?)
.ok_or(Error::<T>::Overflow)?;

let denominator = root_k
.checked_mul(U256::from(fix_fee_point))
.checked_mul(U256::from(fee_point))
.and_then(|n| n.checked_add(root_k_last))
.ok_or(Error::<T>::Overflow)?;

Expand Down