Skip to content

Commit 49c4e62

Browse files
authored
Fix fungibles unbalanced (#823)
* Add fungibles::Unbalanced tests * fix set_balance
1 parent 02b1462 commit 49c4e62

File tree

3 files changed

+118
-6
lines changed

3 files changed

+118
-6
lines changed

tokens/src/lib.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -1746,17 +1746,22 @@ impl<T: Config> fungibles::Transfer<T::AccountId> for Pallet<T> {
17461746
impl<T: Config> fungibles::Unbalanced<T::AccountId> for Pallet<T> {
17471747
fn set_balance(asset_id: Self::AssetId, who: &T::AccountId, amount: Self::Balance) -> DispatchResult {
17481748
// Balance is the same type and will not overflow
1749-
Self::mutate_account(who, asset_id, |account, _| {
1750-
account.free = amount;
1749+
Self::mutate_account(who, asset_id, |account, _| -> DispatchResult {
1750+
// fungibles::Unbalanced::decrease_balance didn't check account.reserved
1751+
// free = new_balance - reserved
1752+
account.free = amount
1753+
.checked_sub(&account.reserved)
1754+
.ok_or(ArithmeticError::Underflow)?;
17511755

17521756
Self::deposit_event(Event::BalanceSet {
17531757
currency_id: asset_id,
17541758
who: who.clone(),
1755-
free: amount,
1759+
free: account.free,
17561760
reserved: account.reserved,
17571761
});
1758-
});
1759-
Ok(())
1762+
1763+
Ok(())
1764+
})
17601765
}
17611766

17621767
fn set_total_issuance(asset_id: Self::AssetId, amount: Self::Balance) {

tokens/src/tests_events.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ fn pallet_fungibles_unbalanced_deposit_events() {
202202
System::assert_last_event(RuntimeEvent::Tokens(crate::Event::BalanceSet {
203203
currency_id: DOT,
204204
who: ALICE,
205-
free: 500,
205+
free: 450,
206206
reserved: 50,
207207
}));
208208

tokens/src/tests_fungibles.rs

+107
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use super::*;
66
use frame_support::{assert_noop, assert_ok};
77
use mock::*;
8+
use sp_runtime::{ArithmeticError, TokenError};
89

910
#[test]
1011
fn fungibles_inspect_trait_should_work() {
@@ -54,13 +55,119 @@ fn fungibles_unbalanced_trait_should_work() {
5455
.balances(vec![(ALICE, DOT, 100)])
5556
.build()
5657
.execute_with(|| {
58+
// set_balance
5759
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 100);
5860
assert_ok!(<Tokens as fungibles::Unbalanced<_>>::set_balance(DOT, &ALICE, 10));
5961
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 10);
6062

63+
// set_total_issuance
6164
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_issuance(DOT), 100);
6265
<Tokens as fungibles::Unbalanced<_>>::set_total_issuance(DOT, 10);
6366
assert_eq!(<Tokens as fungibles::Inspect<_>>::total_issuance(DOT), 10);
67+
68+
// decrease_balance
69+
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 10);
70+
assert_noop!(
71+
<Tokens as fungibles::Unbalanced<_>>::decrease_balance(DOT, &ALICE, 20),
72+
TokenError::NoFunds
73+
);
74+
assert_eq!(
75+
<Tokens as fungibles::Unbalanced<_>>::decrease_balance(DOT, &ALICE, 5),
76+
Ok(5)
77+
);
78+
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 5);
79+
// new balance < ExistentialDeposits, clean dust
80+
assert_eq!(
81+
<Tokens as fungibles::Unbalanced<_>>::decrease_balance(DOT, &ALICE, 4),
82+
Ok(5)
83+
);
84+
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 0);
85+
// set reserved
86+
assert_ok!(<Tokens as fungibles::Unbalanced<_>>::set_balance(DOT, &ALICE, 100));
87+
assert_ok!(<Tokens as MultiReservableCurrency<AccountId>>::reserve(DOT, &ALICE, 50));
88+
assert_noop!(
89+
<Tokens as fungibles::Unbalanced<_>>::decrease_balance(DOT, &ALICE, 60),
90+
ArithmeticError::Underflow
91+
);
92+
assert_eq!(
93+
<Tokens as fungibles::Unbalanced<_>>::decrease_balance(DOT, &ALICE, 50),
94+
Ok(50)
95+
);
96+
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 50);
97+
assert_eq!(
98+
<Tokens as MultiReservableCurrency<AccountId>>::unreserve(DOT, &ALICE, 50),
99+
0
100+
);
101+
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 50);
102+
103+
// decrease_balance_at_most
104+
assert_ok!(<Tokens as fungibles::Unbalanced<_>>::set_balance(DOT, &ALICE, 10));
105+
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 10);
106+
assert_eq!(
107+
<Tokens as fungibles::Unbalanced<_>>::decrease_balance_at_most(DOT, &ALICE, 20),
108+
10
109+
);
110+
assert_ok!(<Tokens as fungibles::Unbalanced<_>>::set_balance(DOT, &ALICE, 10));
111+
assert_eq!(
112+
<Tokens as fungibles::Unbalanced<_>>::decrease_balance_at_most(DOT, &ALICE, 5),
113+
5
114+
);
115+
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 5);
116+
// new balance < ExistentialDeposits, clean dust
117+
assert_eq!(
118+
<Tokens as fungibles::Unbalanced<_>>::decrease_balance_at_most(DOT, &ALICE, 4),
119+
5
120+
);
121+
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 0);
122+
// set reserved
123+
assert_ok!(<Tokens as fungibles::Unbalanced<_>>::set_balance(DOT, &ALICE, 100));
124+
assert_ok!(<Tokens as MultiReservableCurrency<AccountId>>::reserve(DOT, &ALICE, 50));
125+
assert_eq!(
126+
<Tokens as fungibles::Unbalanced<_>>::decrease_balance_at_most(DOT, &ALICE, 60),
127+
0
128+
);
129+
assert_eq!(
130+
<Tokens as fungibles::Unbalanced<_>>::decrease_balance_at_most(DOT, &ALICE, 50),
131+
50
132+
);
133+
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 50);
134+
assert_eq!(
135+
<Tokens as MultiReservableCurrency<AccountId>>::unreserve(DOT, &ALICE, 50),
136+
0
137+
);
138+
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 50);
139+
140+
// increase_balance
141+
assert_ok!(<Tokens as fungibles::Unbalanced<_>>::set_balance(DOT, &ALICE, 0));
142+
assert_noop!(
143+
<Tokens as fungibles::Unbalanced<_>>::increase_balance(DOT, &ALICE, 1),
144+
TokenError::BelowMinimum
145+
);
146+
assert_eq!(
147+
<Tokens as fungibles::Unbalanced<_>>::increase_balance(DOT, &ALICE, 2),
148+
Ok(2)
149+
);
150+
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 2);
151+
assert_noop!(
152+
<Tokens as fungibles::Unbalanced<_>>::increase_balance(DOT, &ALICE, Balance::MAX),
153+
ArithmeticError::Overflow
154+
);
155+
156+
// increase_balance_at_most
157+
assert_ok!(<Tokens as fungibles::Unbalanced<_>>::set_balance(DOT, &ALICE, 0));
158+
assert_eq!(
159+
<Tokens as fungibles::Unbalanced<_>>::increase_balance_at_most(DOT, &ALICE, 1),
160+
0
161+
);
162+
assert_eq!(
163+
<Tokens as fungibles::Unbalanced<_>>::increase_balance_at_most(DOT, &ALICE, 2),
164+
2
165+
);
166+
assert_eq!(<Tokens as fungibles::Inspect<_>>::balance(DOT, &ALICE), 2);
167+
assert_eq!(
168+
<Tokens as fungibles::Unbalanced<_>>::increase_balance_at_most(DOT, &ALICE, Balance::MAX),
169+
Balance::MAX - 2
170+
);
64171
});
65172
}
66173

0 commit comments

Comments
 (0)