Skip to content

Commit

Permalink
fix bug about bridge fee (#57)
Browse files Browse the repository at this point in the history
* fix bug about bridge fee

* update prams name

* update  trait name

* rename error

* remove unused import
  • Loading branch information
StewartYe authored Mar 10, 2023
1 parent 04d8b57 commit e296ecb
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 33 deletions.
28 changes: 23 additions & 5 deletions pallets/chainbridge-handler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub mod pallet {
transactional,
};
use frame_system::{ensure_signed, pallet_prelude::*};
use fuso_support::traits::DecimalsTransformer;
use fuso_support::{
chainbridge::*,
traits::{PriceOracle, Token},
Expand All @@ -44,6 +45,10 @@ pub mod pallet {
<T as frame_system::Config>::AccountId,
>>::Balance;

type BalanceOfExternal<T> = <<T as bridge::Config>::Fungibles as Token<
<T as frame_system::Config>::AccountId,
>>::Balance;

const STORAGE_VERSION: StorageVersion = StorageVersion::new(0);

const QUINTILL: u128 = 1_000_000_000_000_000_000;
Expand Down Expand Up @@ -163,7 +168,7 @@ pub mod pallet {
#[pallet::weight(195_000_0000)]
pub fn transfer_out(
origin: OriginFor<T>,
amount: BalanceOf<T>,
amount: BalanceOfExternal<T>,
r_id: ResourceId,
recipient: Vec<u8>,
dest_id: ChainId,
Expand Down Expand Up @@ -363,7 +368,7 @@ pub mod pallet {
#[transactional]
pub(crate) fn do_burn_assets(
who: T::AccountId,
amount: BalanceOf<T>,
amount: BalanceOfExternal<T>,
r_id: ResourceId,
recipient: Vec<u8>,
dest_id: ChainId,
Expand All @@ -372,15 +377,28 @@ pub mod pallet {
decode_resource_id(r_id).map_err(|_| Error::<T>::InvalidResourceId)?;
let token_id = T::AssetIdByName::try_get_asset_id(chain_id, maybe_contract)
.map_err(|_| Error::<T>::InvalidResourceId)?;
let external_decimals = T::Fungibles::token_external_decimals(&token_id)?;
let unified_ammount =
T::Fungibles::transform_decimals_to_standard(amount, external_decimals);
let fee = Self::calculate_bridging_fee(&token_id);
ensure!(amount > fee + fee, Error::<T>::LessThanBridgingThreshold);
ensure!(
unified_ammount > fee + fee,
Error::<T>::LessThanBridgingThreshold
);
T::Fungibles::transfer_token(&who, token_id, fee, &T::TreasuryAccount::get())?;
T::Fungibles::burn_from(token_id, &who, amount - fee)?;
let bridge_amount = unified_ammount - fee;
T::Fungibles::burn_from(token_id, &who, bridge_amount)?;
bridge::Pallet::<T>::transfer_fungible(
dest_id,
r_id,
recipient.clone(),
U256::from((amount - fee).saturated_into::<u128>()),
U256::from(
(T::Fungibles::transform_decimals_to_external(
bridge_amount,
external_decimals,
))
.saturated_into::<u128>(),
),
)?;
Ok(())
}
Expand Down
5 changes: 3 additions & 2 deletions pallets/chainbridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub mod pallet {
use frame_support::traits::fungibles::Mutate;
use frame_support::{dispatch::GetDispatchInfo, pallet_prelude::*, Blake2_128Concat};
use frame_system::pallet_prelude::*;
use fuso_support::traits::Token;
use fuso_support::traits::{DecimalsTransformer, Token};

type AssetId<T> =
<<T as Config>::Fungibles as Token<<T as frame_system::Config>::AccountId>>::TokenId;
Expand Down Expand Up @@ -137,7 +137,8 @@ pub mod pallet {

/// Expose customizable associated type of asset transfer, lock and unlock
type Fungibles: Mutate<Self::AccountId, AssetId = AssetId<Self>, Balance = BalanceOf<Self>>
+ Token<Self::AccountId>;
+ Token<Self::AccountId>
+ DecimalsTransformer<BalanceOf<Self>>;

type NativeResourceId: Get<ResourceId>;

Expand Down
7 changes: 7 additions & 0 deletions pallets/fuso-support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ pub trait Token<AccountId> {
token: &Self::TokenId,
f: impl FnOnce(&mut Self::Balance) -> Result<(), DispatchError>,
) -> Result<(), DispatchError>;

fn token_external_decimals(token: &Self::TokenId) -> Result<u8, DispatchError>;
}

pub trait DecimalsTransformer<Balance> {
fn transform_decimals_to_standard(amount: Balance, external_decimals: u8) -> Balance;
fn transform_decimals_to_external(amount: Balance, external_decimals: u8) -> Balance;
}

pub trait ReservableToken<AccountId>: Token<AccountId> {
Expand Down
98 changes: 73 additions & 25 deletions pallets/token/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub mod pallet {
transactional,
};
use frame_system::pallet_prelude::*;
use fuso_support::traits::ChainIdOf;
use fuso_support::traits::{ChainIdOf, DecimalsTransformer};
use fuso_support::{
constants::*,
traits::{ReservableToken, Token},
Expand Down Expand Up @@ -113,7 +113,7 @@ pub mod pallet {
BalanceLow,
BalanceZero,
InvalidTokenName,
InvalidToken,
TokenNotFound,
InsufficientBalance,
Overflow,
TooManyReserves,
Expand Down Expand Up @@ -191,13 +191,13 @@ pub mod pallet {
pub fn mark_stable(origin: OriginFor<T>, id: T::TokenId) -> DispatchResultWithPostInfo {
let _ = ensure_root(origin)?;
Tokens::<T>::try_mutate_exists(id, |info| -> DispatchResult {
ensure!(info.is_some(), Error::<T>::InvalidToken);
ensure!(info.is_some(), Error::<T>::TokenNotFound);
let mut token_info = info.take().unwrap();
match token_info {
XToken::NEP141(_, _, _, ref mut stable, _) => *stable = true,
XToken::ERC20(_, _, _, ref mut stable, _) => *stable = true,
XToken::BEP20(_, _, _, ref mut stable, _) => *stable = true,
XToken::FND10(_, _) => return Err(Error::<T>::InvalidToken.into()),
XToken::FND10(_, _) => return Err(Error::<T>::TokenNotFound.into()),
}
info.replace(token_info);
Ok(())
Expand Down Expand Up @@ -236,22 +236,6 @@ pub mod pallet {
where
BalanceOf<T>: From<u128> + Into<u128>,
{
pub fn unify_decimals(amount: BalanceOf<T>, decimals: u8) -> BalanceOf<T> {
let mut amount: u128 = amount.into();
if decimals > STANDARD_DECIMALS {
let diff = decimals - STANDARD_DECIMALS;
for _i in 0..diff {
amount /= 10
}
} else {
let diff = STANDARD_DECIMALS - decimals;
for _i in 0..diff {
amount *= 10
}
}
amount.into()
}

/// the verifier requests all amount should be 10^18, the `do_mint` is called by oct-pallets,
/// the parameter `amount` is 10^decimals_of_metadata, in anthor word, the real storage of token amount unified
#[transactional]
Expand All @@ -265,13 +249,13 @@ pub mod pallet {
return Ok(());
}
Tokens::<T>::try_mutate_exists(&token, |token_info| -> DispatchResult {
ensure!(token_info.is_some(), Error::<T>::InvalidToken);
ensure!(token_info.is_some(), Error::<T>::TokenNotFound);
let mut info = token_info.take().unwrap();
let unified_amount = match info {
XToken::NEP141(_, _, ref mut total, _, decimals)
| XToken::ERC20(_, _, ref mut total, _, decimals)
| XToken::BEP20(_, _, ref mut total, _, decimals) => {
let unified_amount = Self::unify_decimals(amount, decimals);
let unified_amount = Self::transform_decimals_to_standard(amount, decimals);
*total = total
.checked_add(&unified_amount)
.ok_or(Error::<T>::InsufficientBalance)?;
Expand Down Expand Up @@ -317,7 +301,7 @@ pub mod pallet {
XToken::NEP141(_, _, ref mut total, _, decimals)
| XToken::ERC20(_, _, ref mut total, _, decimals)
| XToken::BEP20(_, _, ref mut total, _, decimals) => {
let unified_amount = Self::unify_decimals(amount, decimals);
let unified_amount = Self::transform_decimals_to_standard(amount, decimals);
*total = total
.checked_sub(&unified_amount)
.ok_or(Error::<T>::InsufficientBalance)?;
Expand Down Expand Up @@ -624,6 +608,70 @@ pub mod pallet {
Zero::zero()
}
}

fn token_external_decimals(token: &T::TokenId) -> Result<u8, DispatchError> {
if *token == Self::native_token_id() {
return Ok(STANDARD_DECIMALS);
}
let token_info = Self::get_token_info(token);
if token_info.is_some() {
let token = token_info.unwrap();
match token {
XToken::NEP141(_, _, _, _, decimals)
| XToken::ERC20(_, _, _, _, decimals)
| XToken::BEP20(_, _, _, _, decimals) => Ok(decimals),
XToken::FND10(_, _) => Err(Error::<T>::TokenNotFound.into()),
}
} else {
Err(Error::<T>::TokenNotFound.into())
}
}
}

impl<T: Config> DecimalsTransformer<BalanceOf<T>> for Pallet<T>
where
BalanceOf<T>: From<u128> + Into<u128>,
{
fn transform_decimals_to_standard(
amount: BalanceOf<T>,
external_decimals: u8,
) -> BalanceOf<T>
where
BalanceOf<T>: From<u128> + Into<u128>,
{
let mut amount: u128 = amount.into();
if external_decimals > STANDARD_DECIMALS {
let diff = external_decimals - STANDARD_DECIMALS;
for _i in 0..diff {
amount /= 10
}
} else {
let diff = STANDARD_DECIMALS - external_decimals;
for _i in 0..diff {
amount *= 10
}
}
amount.into()
}

fn transform_decimals_to_external(
amount: BalanceOf<T>,
external_decimals: u8,
) -> BalanceOf<T> {
let mut amount: u128 = amount.into();
if external_decimals > STANDARD_DECIMALS {
let diff = external_decimals - STANDARD_DECIMALS;
for _i in 0..diff {
amount *= 10
}
} else {
let diff = STANDARD_DECIMALS - external_decimals;
for _i in 0..diff {
amount /= 10
}
}
amount.into()
}
}

impl<T: Config> ReservableToken<T::AccountId> for Pallet<T> {
Expand Down Expand Up @@ -824,11 +872,11 @@ pub mod pallet {
XToken::NEP141(_, _, _, _, decimals)
| XToken::ERC20(_, _, _, _, decimals)
| XToken::BEP20(_, _, _, _, decimals) => {
Self::unify_decimals(balance, decimals)
Self::transform_decimals_to_standard(balance, decimals)
}
XToken::FND10(..) => balance,
})
.map_err(|_| Error::<T>::InvalidToken.into())
.map_err(|_| Error::<T>::TokenNotFound.into())
}
}

Expand Down
2 changes: 1 addition & 1 deletion pallets/token/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ fn test_xtoken_should_work() {
);
assert_noop!(
Token::do_mint(3, &alice, 100000000000, Option::None),
Error::<Test>::InvalidToken
Error::<Test>::TokenNotFound
);

assert_ok!(Token::do_mint(1, &alice, 1000000000, Option::None));
Expand Down

0 comments on commit e296ecb

Please sign in to comment.