Skip to content

Commit

Permalink
Fix fexiable fee token selection logic (#1604)
Browse files Browse the repository at this point in the history
* Flexiable Fee token selection logic fix----EVM

* Optimize the code for better performance and readability.

* Add a 10% buffer to account for potential inaccuracies in fee estimation.
  • Loading branch information
SunTiebing authored Jan 10, 2025
1 parent 715fae4 commit a770fe6
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 51 deletions.
7 changes: 6 additions & 1 deletion pallets/flexible-fee/src/impls/account_fee_currency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,13 @@ impl<T: Config> AccountFeeCurrency<T::AccountId> for Pallet<T> {
hopeless_currency = currency;
}

// Add a 10% buffer to account for potential inaccuracies in fee estimation.
let fee = fee
.checked_mul(10)
.and_then(|v| v.checked_div(100))
.ok_or(Error::<T>::PercentageCalculationFailed)?;
for maybe_currency in currency_list.iter() {
let comp_res = Self::cmp_with_precision(account, maybe_currency, fee, 18)?;
let comp_res = Self::cmp_with_weth(account, maybe_currency, fee)?;

match comp_res {
Ordering::Less => {
Expand Down
43 changes: 13 additions & 30 deletions pallets/flexible-fee/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
#![cfg_attr(not(feature = "std"), no_std)]

pub use crate::pallet::*;
use bifrost_asset_registry::{AssetMetadata, CurrencyIdMapping, TokenInfo};
use bifrost_asset_registry::{AssetMetadata, CurrencyIdMapping};
use bifrost_primitives::{
traits::XcmDestWeightAndFeeHandler, AssetHubChainId, Balance, BalanceCmp, CurrencyId,
DerivativeIndex, OraclePriceProvider, Price, TryConvertFrom, XcmOperationType, BNC, VBNC,
DerivativeIndex, OraclePriceProvider, Price, TryConvertFrom, XcmOperationType, BNC, VBNC, WETH,
};
use bifrost_xcm_interface::calls::{PolkadotXcmCall, RelaychainCall};
use core::convert::Into;
Expand Down Expand Up @@ -232,6 +232,8 @@ pub mod pallet {
EvmPermitCallExecutionError,
/// EVM permit call failed.
EvmPermitRunnerError,
/// Percentage calculation failed due to overflow.
PercentageCalculationFailed,
}

#[pallet::call]
Expand Down Expand Up @@ -718,49 +720,30 @@ impl<T: Config> BalanceCmp<T::AccountId> for Pallet<T> {
/// - `currency`: The currency ID to be compared.
/// - `amount`: The amount to compare against the account's balance, with the precision
/// specified by `amount_precision`.
/// - `amount_precision`: The precision of the `amount` specified. If greater than 18, the
/// precision of the `currency` will be adjusted accordingly.
///
/// # Returns
/// - `Ok(std::cmp::Ordering)`: Returns the ordering result (`Less`, `Equal`, `Greater`) based
/// on the comparison between the adjusted balance and the adjusted amount.
/// - `Err(Error<T>)`: Returns an error if the currency is not supported.
fn cmp_with_precision(
fn cmp_with_weth(
account: &T::AccountId,
currency: &CurrencyId,
amount: u128,
amount_precision: u32,
) -> Result<Ordering, Error<T>> {
// Get the reducible balance for the specified account and currency.
let mut balance = T::MultiCurrency::reducible_balance(
let balance = T::MultiCurrency::reducible_balance(
*currency,
account,
Preservation::Preserve,
Fortitude::Polite,
);

// Define the standard precision as 18 decimal places.
let standard_precision: u32 = amount_precision.max(18);

// Adjust the amount to the standard precision.
let precision_offset = standard_precision.saturating_sub(amount_precision);
let adjust_precision = 10u128.pow(precision_offset);
let amount = amount.saturating_mul(adjust_precision);

// Adjust the balance based on currency type.
let decimals = currency
.decimals()
.or_else(|| {
T::AssetIdMaps::get_currency_metadata(*currency)
.map(|metadata| metadata.decimals.into())
})
.ok_or(Error::<T>::CurrencyNotSupport)?;
let balance_precision_offset = standard_precision.saturating_sub(decimals.into());

// Apply precision adjustment to balance.
balance = balance.saturating_mul(10u128.pow(balance_precision_offset));

// Compare the adjusted balance with the input amount.
Ok(balance.cmp(&amount))
let (fee_amount, _, _) =
T::OraclePriceProvider::get_oracle_amount_by_currency_and_amount_in(
&WETH, amount, &currency,
)
.ok_or(Error::<T>::ConversionError)?;

Ok(balance.cmp(&fee_amount))
}
}
5 changes: 2 additions & 3 deletions pallets/flexible-fee/src/mocks/kusama_mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,13 +339,12 @@ parameter_types! {
impl BalanceCmp<AccountId> for Test {
type Error = Error<Test>;

fn cmp_with_precision(
fn cmp_with_weth(
account: &AccountId,
currency: &CurrencyId,
amount: u128,
amount_precision: u32,
) -> Result<Ordering, Self::Error> {
Pallet::<Test>::cmp_with_precision(account, currency, amount, amount_precision)
Pallet::<Test>::cmp_with_weth(account, currency, amount)
}
}

Expand Down
5 changes: 2 additions & 3 deletions pallets/flexible-fee/src/mocks/polkadot_mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,13 +332,12 @@ parameter_types! {
impl BalanceCmp<AccountId> for Test {
type Error = Error<Test>;

fn cmp_with_precision(
fn cmp_with_weth(
account: &AccountId,
currency: &CurrencyId,
amount: u128,
amount_precision: u32,
) -> Result<Ordering, Self::Error> {
Pallet::<Test>::cmp_with_precision(account, currency, amount, amount_precision)
Pallet::<Test>::cmp_with_weth(account, currency, amount)
}
}

Expand Down
23 changes: 12 additions & 11 deletions pallets/flexible-fee/src/tests/common_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,38 +781,39 @@ fn get_fee_currency_should_work_with_all_currency_poor() {
}

#[test]
fn cmp_with_precision_should_work_with_weth() {
fn cmp_with_weth_should_work_with_weth() {
new_test_ext().execute_with(|| {
ini_meta_data();

assert_ok!(Currencies::deposit(WETH, &ALICE, 10u128.pow(18) - 1)); // ETH
assert_ok!(Currencies::deposit(WETH, &ALICE, 10u128.pow(18) - 10)); // ETH

let ordering =
FlexibleFee::cmp_with_precision(&ALICE, &WETH, 10u128.pow(18), 18u32).unwrap();
let ordering = FlexibleFee::cmp_with_weth(&ALICE, &WETH, 10u128.pow(18)).unwrap();
assert_eq!(ordering, Less);
});
}

#[test]
fn cmp_with_precision_should_work_with_dot() {
fn cmp_with_weth_should_work_with_dot() {
new_test_ext().execute_with(|| {
ini_meta_data();

assert_ok!(Currencies::deposit(DOT, &ALICE, 10u128.pow(11) + 1)); // DOT
assert_ok!(Currencies::deposit(
DOT,
&ALICE,
600u128 * 10u128.pow(10) + 10
)); // DOT

let ordering =
FlexibleFee::cmp_with_precision(&ALICE, &DOT, 10u128.pow(18), 18u32).unwrap();
let ordering = FlexibleFee::cmp_with_weth(&ALICE, &DOT, 10u128.pow(18)).unwrap();
assert_eq!(ordering, Greater);
});
}

#[test]
fn cmp_with_precision_should_work_with_bnc() {
fn cmp_with_weth_should_work_with_bnc() {
new_test_ext().execute_with(|| {
assert_ok!(Currencies::deposit(BNC, &ALICE, 11u128.pow(12))); // BNC

let ordering =
FlexibleFee::cmp_with_precision(&ALICE, &BNC, 10u128.pow(18), 18u32).unwrap();
let ordering = FlexibleFee::cmp_with_weth(&ALICE, &BNC, 10u128.pow(12)).unwrap();
assert_eq!(ordering, Greater);
});
}
Expand Down
4 changes: 1 addition & 3 deletions primitives/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,17 +494,15 @@ pub trait BalanceCmp<AccountId> {
/// - `account`: The account ID whose balance is to be compared.
/// - `currency`: The currency ID whose balance is to be compared.
/// - `amount`: The amount to compare against.
/// - `amount_precision`: The precision of the input amount.
///
/// # Returns
/// - `Ok(std::cmp::Ordering)`: The result of the comparison, indicating whether the balance is
/// less than, equal to, or greater than the input amount.
/// - `Err(Self::Error)`: An error if the comparison fails.
fn cmp_with_precision(
fn cmp_with_weth(
account: &AccountId,
currency: &CurrencyId,
amount: u128,
amount_precision: u32,
) -> Result<Ordering, Self::Error>;
}

Expand Down

0 comments on commit a770fe6

Please sign in to comment.