Skip to content

Commit

Permalink
fix fungibles::Inspect::balance (#926)
Browse files Browse the repository at this point in the history
* fix fungibles::Inspect::balance

* update
  • Loading branch information
wangjj9219 authored Jun 16, 2023
1 parent 56d66f6 commit 041006c
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 16 deletions.
23 changes: 17 additions & 6 deletions tokens/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1768,7 +1768,7 @@ impl<T: Config> fungibles::Inspect<T::AccountId> for Pallet<T> {
}

fn balance(asset_id: Self::AssetId, who: &T::AccountId) -> Self::Balance {
Self::accounts(who, asset_id).total()
Self::accounts(who, asset_id).free
}

fn total_balance(asset_id: Self::AssetId, who: &T::AccountId) -> Self::Balance {
Expand Down Expand Up @@ -1869,11 +1869,21 @@ impl<T: Config> fungibles::Unbalanced<T::AccountId> for Pallet<T> {
who: &T::AccountId,
amount: Self::Balance,
) -> Result<Option<Self::Balance>, DispatchError> {
let max_reduction = <Self as fungibles::Inspect<_>>::reducible_balance(
asset_id,
who,
Preservation::Expendable,
Fortitude::Force,
);

// Balance is the same type and will not overflow
let (_, dust_amount) = Self::try_mutate_account(who, asset_id, |account, _| -> Result<(), DispatchError> {
// free = new_balance - reserved
account.free = amount.checked_sub(&account.reserved).ok_or(TokenError::BelowMinimum)?;
// Make sure the reduction (if there is one) is no more than the maximum
// allowed.
let reduction = account.free.saturating_sub(amount);
ensure!(reduction <= max_reduction, Error::<T>::BalanceTooLow);

account.free = amount;
Self::deposit_event(Event::BalanceSet {
currency_id: asset_id,
who: who.clone(),
Expand Down Expand Up @@ -1911,9 +1921,10 @@ impl<T: Config> fungibles::Unbalanced<T::AccountId> for Pallet<T> {
amount = amount.min(free);
}
let new_balance = old_balance.checked_sub(&amount).ok_or(TokenError::FundsUnavailable)?;
// Original implementation was not returning burnt dust in result
let dust_burnt = Self::write_balance(asset, who, new_balance)?.unwrap_or_default();
Ok(old_balance.saturating_sub(new_balance).saturating_add(dust_burnt))
let _dust_amount = Self::write_balance(asset, who, new_balance)?.unwrap_or_default();

// here just return decrease amount, shouldn't count the dust_amount
Ok(old_balance.saturating_sub(new_balance))
}
}

Expand Down
2 changes: 1 addition & 1 deletion tokens/src/tests_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ fn pallet_fungibles_unbalanced_deposit_events() {
System::assert_last_event(RuntimeEvent::Tokens(crate::Event::BalanceSet {
currency_id: DOT,
who: ALICE,
free: 450,
free: 500,
reserved: 50,
}));

Expand Down
63 changes: 54 additions & 9 deletions tokens/src/tests_fungibles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,24 @@ fn fungibles_unbalanced_trait_should_work() {
Preservation::Expendable,
Fortitude::Polite
),
Ok(5)
Ok(4)
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 0);
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_balance(DOT, &ALICE), 0);
// set reserved
assert_ok!(<Tokens as fungibles::Unbalanced<_>>::write_balance(DOT, &ALICE, 100));
assert_ok!(<Tokens as MultiReservableCurrency<AccountId>>::reserve(DOT, &ALICE, 50));
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 50);
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_balance(DOT, &ALICE), 100);
assert_eq!(
<Tokens as fungibles::Inspect<_>>::reducible_balance(
DOT,
&ALICE,
Preservation::Protect,
Fortitude::Polite
),
50
);
assert_noop!(
<Tokens as fungibles::Unbalanced<_>>::decrease_balance(
DOT,
Expand All @@ -134,7 +146,7 @@ fn fungibles_unbalanced_trait_should_work() {
Preservation::Protect,
Fortitude::Polite
),
TokenError::BelowMinimum
TokenError::FundsUnavailable
);
assert_eq!(
<Tokens as fungibles::Unbalanced<_>>::decrease_balance(
Expand All @@ -147,16 +159,19 @@ fn fungibles_unbalanced_trait_should_work() {
),
Ok(50)
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 50);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 0);
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_balance(DOT, &ALICE), 50);
assert_eq!(
<Tokens as MultiReservableCurrency<AccountId>>::unreserve(DOT, &ALICE, 50),
0
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 50);
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_balance(DOT, &ALICE), 50);

// decrease_balance_at_most
assert_ok!(<Tokens as fungibles::Unbalanced<_>>::write_balance(DOT, &ALICE, 10));
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 10);
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_balance(DOT, &ALICE), 10);
assert_eq!(
<Tokens as fungibles::Unbalanced<_>>::decrease_balance(
DOT,
Expand All @@ -168,6 +183,8 @@ fn fungibles_unbalanced_trait_should_work() {
),
Ok(10)
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 0);
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_balance(DOT, &ALICE), 0);
assert_ok!(<Tokens as fungibles::Unbalanced<_>>::write_balance(DOT, &ALICE, 10));
assert_eq!(
<Tokens as fungibles::Unbalanced<_>>::decrease_balance(
Expand All @@ -181,6 +198,8 @@ fn fungibles_unbalanced_trait_should_work() {
Ok(5)
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 5);
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_balance(DOT, &ALICE), 5);

// new balance < ExistentialDeposits, clean dust
assert_eq!(
<Tokens as fungibles::Unbalanced<_>>::decrease_balance(
Expand All @@ -191,12 +210,24 @@ fn fungibles_unbalanced_trait_should_work() {
Preservation::Expendable,
Fortitude::Polite
),
Ok(5)
Ok(4)
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 0);
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_balance(DOT, &ALICE), 0);
// set reserved
assert_ok!(<Tokens as fungibles::Unbalanced<_>>::write_balance(DOT, &ALICE, 100));
assert_ok!(<Tokens as MultiReservableCurrency<AccountId>>::reserve(DOT, &ALICE, 50));
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 50);
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_balance(DOT, &ALICE), 100);
assert_eq!(
<Tokens as fungibles::Inspect<_>>::reducible_balance(
DOT,
&ALICE,
Preservation::Protect,
Fortitude::Polite
),
50
);
assert_eq!(
<Tokens as fungibles::Unbalanced<_>>::decrease_balance(
DOT,
Expand All @@ -208,12 +239,14 @@ fn fungibles_unbalanced_trait_should_work() {
),
Ok(50),
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 50);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 0);
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_balance(DOT, &ALICE), 50);
assert_eq!(
<Tokens as MultiReservableCurrency<AccountId>>::unreserve(DOT, &ALICE, 50),
0
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 50);
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_balance(DOT, &ALICE), 50);

// increase_balance
assert_ok!(<Tokens as fungibles::Unbalanced<_>>::write_balance(DOT, &ALICE, 0));
Expand Down Expand Up @@ -285,11 +318,15 @@ fn fungibles_mutate_hold_trait_should_work() {
<Tokens as fungibles::InspectHold<_>>::balance_on_hold(DOT, REASON, &ALICE),
0
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 100);

assert_ok!(<Tokens as fungibles::MutateHold<_>>::hold(DOT, REASON, &ALICE, 100));
assert_eq!(
<Tokens as fungibles::InspectHold<_>>::balance_on_hold(DOT, REASON, &ALICE),
100
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 0);

assert_eq!(
<Tokens as fungibles::MutateHold<_>>::release(DOT, REASON, &ALICE, 40, Precision::Exact),
Ok(40)
Expand All @@ -298,6 +335,7 @@ fn fungibles_mutate_hold_trait_should_work() {
<Tokens as fungibles::InspectHold<_>>::balance_on_hold(DOT, REASON, &ALICE),
60
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 40);

// exceed hold amount when not in best_effort
assert_noop!(
Expand All @@ -314,17 +352,20 @@ fn fungibles_mutate_hold_trait_should_work() {
<Tokens as fungibles::InspectHold<_>>::balance_on_hold(DOT, REASON, &ALICE),
0
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 100);

assert_ok!(<Tokens as fungibles::MutateHold<_>>::hold(DOT, REASON, &ALICE, 70));
assert_eq!(
<Tokens as fungibles::InspectHold<_>>::balance_on_hold(DOT, REASON, &ALICE),
70
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &BOB), 100);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 30);

assert_eq!(
<Tokens as fungibles::InspectHold<_>>::balance_on_hold(DOT, REASON, &BOB),
0
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &BOB), 100);
assert_eq!(
<Tokens as fungibles::MutateHold<_>>::transfer_on_hold(
DOT,
Expand All @@ -342,11 +383,13 @@ fn fungibles_mutate_hold_trait_should_work() {
<Tokens as fungibles::InspectHold<_>>::balance_on_hold(DOT, REASON, &ALICE),
65
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &BOB), 105);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 30);
assert_eq!(
<Tokens as fungibles::InspectHold<_>>::balance_on_hold(DOT, REASON, &BOB),
0
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &BOB), 105);

assert_eq!(
<Tokens as fungibles::MutateHold<_>>::transfer_on_hold(
DOT,
Expand All @@ -364,11 +407,12 @@ fn fungibles_mutate_hold_trait_should_work() {
<Tokens as fungibles::InspectHold<_>>::balance_on_hold(DOT, REASON, &ALICE),
60
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &BOB), 110);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 30);
assert_eq!(
<Tokens as fungibles::InspectHold<_>>::balance_on_hold(DOT, REASON, &BOB),
5
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &BOB), 105);

// exceed hold amount when not in best_effort
assert_noop!(
Expand Down Expand Up @@ -403,11 +447,12 @@ fn fungibles_mutate_hold_trait_should_work() {
<Tokens as fungibles::InspectHold<_>>::balance_on_hold(DOT, REASON, &ALICE),
0
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &BOB), 170);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 30);
assert_eq!(
<Tokens as fungibles::InspectHold<_>>::balance_on_hold(DOT, REASON, &BOB),
65
);
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &BOB), 105);
});
}

Expand Down

0 comments on commit 041006c

Please sign in to comment.