frame_support/traits/tokens/fungible/conformance_tests/regular/
unbalanced.rs1use crate::traits::{
19 fungible::{Inspect, Unbalanced},
20 tokens::{Fortitude, Precision, Preservation},
21};
22use core::fmt::Debug;
23use sp_arithmetic::{traits::AtLeast8BitUnsigned, ArithmeticError};
24use sp_runtime::{traits::Bounded, TokenError};
25
26pub fn write_balance<T, AccountId>()
31where
32 T: Unbalanced<AccountId>,
33 <T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
34 AccountId: AtLeast8BitUnsigned,
35{
36 let account_0_ed = AccountId::from(0);
38 let account_1_gt_ed = AccountId::from(1);
39 let account_2_empty = AccountId::from(2);
40 T::increase_balance(&account_0_ed, T::minimum_balance(), Precision::Exact).unwrap();
41 T::increase_balance(&account_1_gt_ed, T::minimum_balance() + 5.into(), Precision::Exact)
42 .unwrap();
43
44 let amount = T::minimum_balance() + 10.into();
47 assert_eq!(T::write_balance(&account_0_ed, amount), Ok(None));
48 assert_eq!(T::write_balance(&account_1_gt_ed, amount), Ok(None));
49 assert_eq!(T::write_balance(&account_2_empty, amount), Ok(None));
50 assert_eq!(T::balance(&account_0_ed), amount);
51 assert_eq!(T::balance(&account_1_gt_ed), amount);
52 assert_eq!(T::balance(&account_2_empty), amount);
53
54 let amount = T::minimum_balance() - 1.into();
60 if T::minimum_balance() == 1.into() {
61 assert_eq!(T::write_balance(&account_0_ed, amount), Ok(None));
62 assert_eq!(T::write_balance(&account_1_gt_ed, amount), Ok(None));
63 assert_eq!(T::write_balance(&account_2_empty, amount), Ok(None));
64 } else if T::minimum_balance() > 1.into() {
65 assert_eq!(T::write_balance(&account_0_ed, amount), Ok(Some(amount)));
66 assert_eq!(T::write_balance(&account_1_gt_ed, amount), Ok(Some(amount)));
67 assert_eq!(T::write_balance(&account_2_empty, amount), Ok(Some(amount)));
68 }
69}
70
71pub fn decrease_balance_expendable<T, AccountId>()
73where
74 T: Unbalanced<AccountId>,
75 <T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
76 AccountId: AtLeast8BitUnsigned,
77{
78 let account_0 = AccountId::from(0);
80 let account_0_initial_balance = T::minimum_balance() + 10.into();
81 T::increase_balance(&account_0, account_0_initial_balance, Precision::Exact).unwrap();
82
83 let amount = 1.into();
85 assert_eq!(
86 T::decrease_balance(
87 &account_0,
88 amount,
89 Precision::Exact,
90 Preservation::Expendable,
91 Fortitude::Polite,
92 ),
93 Ok(amount),
94 );
95 assert_eq!(T::balance(&account_0), account_0_initial_balance - amount);
96
97 let balance_before = T::balance(&account_0);
99 assert_eq!(
100 T::decrease_balance(
101 &account_0,
102 account_0_initial_balance,
103 Precision::Exact,
104 Preservation::Expendable,
105 Fortitude::Polite,
106 ),
107 Err(TokenError::FundsUnavailable.into())
108 );
109 assert_eq!(T::balance(&account_0), balance_before);
111
112 assert_eq!(
114 T::decrease_balance(
115 &account_0,
116 account_0_initial_balance,
117 Precision::BestEffort,
118 Preservation::Expendable,
119 Fortitude::Polite,
120 ),
121 Ok(balance_before),
122 );
123 assert_eq!(T::balance(&account_0), 0.into());
125}
126
127pub fn decrease_balance_preserve<T, AccountId>()
129where
130 T: Unbalanced<AccountId>,
131 <T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
132 AccountId: AtLeast8BitUnsigned,
133{
134 let account_0 = AccountId::from(0);
136 let account_0_initial_balance = T::minimum_balance() + 10.into();
137 T::increase_balance(&account_0, account_0_initial_balance, Precision::Exact).unwrap();
138
139 let amount = 11.into();
141 assert_eq!(
142 T::decrease_balance(
143 &account_0,
144 amount,
145 Precision::Exact,
146 Preservation::Preserve,
147 Fortitude::Polite,
148 ),
149 Err(TokenError::FundsUnavailable.into()),
150 );
151 assert_eq!(T::balance(&account_0), account_0_initial_balance);
153
154 let amount = 11.into();
157 assert_eq!(
158 T::decrease_balance(
159 &account_0,
160 amount,
161 Precision::BestEffort,
162 Preservation::Preserve,
163 Fortitude::Polite,
164 ),
165 Ok(account_0_initial_balance - T::minimum_balance()),
166 );
167 assert_eq!(T::balance(&account_0), T::minimum_balance());
168}
169
170pub fn increase_balance<T, AccountId>()
172where
173 T: Unbalanced<AccountId>,
174 <T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
175 AccountId: AtLeast8BitUnsigned,
176{
177 let account_0 = AccountId::from(0);
178 assert_eq!(T::balance(&account_0), 0.into());
179
180 if T::minimum_balance() > 0.into() {
182 assert_eq!(
183 T::increase_balance(&account_0, T::minimum_balance() - 1.into(), Precision::Exact),
184 Err(TokenError::BelowMinimum.into()),
185 );
186 }
187 assert_eq!(T::balance(&account_0), 0.into());
188
189 if T::minimum_balance() > 0.into() {
191 assert_eq!(
192 T::increase_balance(&account_0, T::minimum_balance() - 1.into(), Precision::BestEffort),
193 Ok(0.into()),
194 );
195 }
196 assert_eq!(T::balance(&account_0), 0.into());
197
198 assert_eq!(
200 T::increase_balance(&account_0, T::minimum_balance(), Precision::Exact),
201 Ok(T::minimum_balance()),
202 );
203 assert_eq!(T::balance(&account_0), T::minimum_balance());
204 assert_eq!(T::increase_balance(&account_0, 5.into(), Precision::Exact), Ok(5.into()),);
205 assert_eq!(T::balance(&account_0), T::minimum_balance() + 5.into());
206
207 assert_eq!(
209 T::increase_balance(&account_0, T::Balance::max_value(), Precision::Exact),
210 Err(ArithmeticError::Overflow.into()),
211 );
212
213 let balance_before = T::balance(&account_0);
215 assert_eq!(
216 T::increase_balance(&account_0, T::Balance::max_value(), Precision::BestEffort),
217 Ok(T::Balance::max_value() - balance_before),
218 );
219 assert_eq!(T::balance(&account_0), T::Balance::max_value());
220}
221
222pub fn set_total_issuance<T, AccountId>()
224where
225 T: Unbalanced<AccountId>,
226 <T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
227 AccountId: AtLeast8BitUnsigned,
228{
229 T::set_total_issuance(1.into());
230 assert_eq!(T::total_issuance(), 1.into());
231
232 T::set_total_issuance(0.into());
233 assert_eq!(T::total_issuance(), 0.into());
234
235 T::set_total_issuance(T::minimum_balance());
236 assert_eq!(T::total_issuance(), T::minimum_balance());
237
238 T::set_total_issuance(T::minimum_balance() + 5.into());
239 assert_eq!(T::total_issuance(), T::minimum_balance() + 5.into());
240
241 if T::minimum_balance() > 0.into() {
242 T::set_total_issuance(T::minimum_balance() - 1.into());
243 assert_eq!(T::total_issuance(), T::minimum_balance() - 1.into());
244 }
245}
246
247pub fn deactivate_and_reactivate<T, AccountId>()
249where
250 T: Unbalanced<AccountId>,
251 <T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
252 AccountId: AtLeast8BitUnsigned,
253{
254 T::set_total_issuance(10.into());
255 assert_eq!(T::total_issuance(), 10.into());
256 assert_eq!(T::active_issuance(), 10.into());
257
258 T::deactivate(2.into());
259 assert_eq!(T::total_issuance(), 10.into());
260 assert_eq!(T::active_issuance(), 8.into());
261
262 T::reactivate(4.into());
264 assert_eq!(T::total_issuance(), 10.into());
265 assert_eq!(T::active_issuance(), 10.into());
266
267 T::deactivate(1.into());
269 assert_eq!(T::total_issuance(), 10.into());
270 assert_eq!(T::active_issuance(), 9.into());
271
272 T::deactivate(15.into());
274 assert_eq!(T::total_issuance(), 10.into());
275 assert_eq!(T::active_issuance(), 0.into());
276
277 T::reactivate(1.into());
279 assert_eq!(T::total_issuance(), 10.into());
280 assert_eq!(T::active_issuance(), 1.into());
281}