Skip to content

Commit 2769e8c

Browse files
extend named reservable
1 parent 67f4a79 commit 2769e8c

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

tokens/src/tests.rs

+88
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,94 @@ fn slashed_reserved_named_works() {
17731773
});
17741774
}
17751775

1776+
#[test]
1777+
fn named_multi_reservable_ensure_named_reserved_works() {
1778+
ExtBuilder::default()
1779+
.balances(vec![(ALICE, DOT, 100)])
1780+
.build()
1781+
.execute_with(|| {
1782+
assert_ok!(Tokens::reserve_named(&RID_1, DOT, &ALICE, 50));
1783+
assert_eq!(Tokens::free_balance(DOT, &ALICE), 50);
1784+
assert_eq!(Tokens::reserved_balance_named(&RID_1, DOT, &ALICE), 50);
1785+
assert_eq!(Tokens::total_issuance(DOT), 100);
1786+
1787+
assert_ok!(Tokens::ensure_reserved_named(&RID_1, DOT, &ALICE, 20));
1788+
assert_ok!(Tokens::ensure_reserved_named(&RID_1, DOT, &ALICE, 70));
1789+
1790+
assert_eq!(Tokens::free_balance(DOT, &ALICE), 30);
1791+
assert_eq!(Tokens::reserved_balance_named(&RID_1, DOT, &ALICE), 70);
1792+
});
1793+
}
1794+
1795+
#[test]
1796+
fn named_multi_reservable_unreserve_all_named() {
1797+
ExtBuilder::default()
1798+
.balances(vec![(ALICE, DOT, 100)])
1799+
.build()
1800+
.execute_with(|| {
1801+
assert_ok!(Tokens::reserve_named(&RID_1, DOT, &ALICE, 50));
1802+
assert_ok!(Tokens::reserve_named(&RID_1, DOT, &ALICE, 20));
1803+
assert_eq!(Tokens::free_balance(DOT, &ALICE), 30);
1804+
assert_eq!(Tokens::reserved_balance_named(&RID_1, DOT, &ALICE), 70);
1805+
1806+
let value = Tokens::unreserve_all_named(&RID_1, DOT, &ALICE);
1807+
assert!(value == 70);
1808+
1809+
assert_eq!(Tokens::free_balance(DOT, &ALICE), 100);
1810+
assert_eq!(Tokens::reserved_balance_named(&RID_1, DOT, &ALICE), 0);
1811+
});
1812+
}
1813+
1814+
#[test]
1815+
fn named_multi_reservable_slash_all_reserved_named() {
1816+
ExtBuilder::default()
1817+
.balances(vec![(ALICE, DOT, 100)])
1818+
.build()
1819+
.execute_with(|| {
1820+
assert_ok!(Tokens::reserve_named(&RID_1, DOT, &ALICE, 50));
1821+
assert_eq!(Tokens::free_balance(DOT, &ALICE), 50);
1822+
assert_eq!(Tokens::reserved_balance_named(&RID_1, DOT, &ALICE), 50);
1823+
1824+
let value = Tokens::slash_all_reserved_named(&RID_1, DOT, &ALICE);
1825+
assert!(value == 0);
1826+
1827+
assert_eq!(Tokens::free_balance(DOT, &ALICE), 50);
1828+
assert_eq!(Tokens::reserved_balance_named(&RID_1, DOT, &ALICE), 0);
1829+
});
1830+
}
1831+
1832+
#[test]
1833+
fn named_multi_reservable_repatriate_all_reserved_named_works() {
1834+
ExtBuilder::default()
1835+
.balances(vec![(ALICE, DOT, 100), (BOB, DOT, 100)])
1836+
.build()
1837+
.execute_with(|| {
1838+
assert_eq!(Tokens::free_balance(DOT, &ALICE), 100);
1839+
assert_eq!(Tokens::reserved_balance_named(&RID_1, DOT, &ALICE), 0);
1840+
assert_eq!(Tokens::reserved_balance_named(&RID_1, DOT, &BOB), 0);
1841+
assert_ok!(Tokens::reserve_named(&RID_1, DOT, &ALICE, 50));
1842+
1843+
assert_ok!(Tokens::repatriate_all_reserved_named(
1844+
&RID_1,
1845+
DOT,
1846+
&ALICE,
1847+
&BOB,
1848+
BalanceStatus::Reserved
1849+
));
1850+
1851+
assert_eq!(Tokens::free_balance(DOT, &BOB), 100);
1852+
assert_eq!(Tokens::reserved_balance_named(&RID_1, DOT, &BOB), 50);
1853+
1854+
System::assert_last_event(Event::Tokens(crate::Event::ReserveRepatriated {
1855+
currency_id: DOT,
1856+
from: ALICE,
1857+
to: BOB,
1858+
amount: 50,
1859+
status: BalanceStatus::Reserved,
1860+
}));
1861+
});
1862+
}
1863+
17761864
// *************************************************
17771865
// tests for CurrencyAdapter
17781866
// *************************************************

traits/src/currency.rs

+70
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,76 @@ pub trait NamedMultiReservableCurrency<AccountId>: MultiReservableCurrency<Accou
288288
value: Self::Balance,
289289
status: BalanceStatus,
290290
) -> result::Result<Self::Balance, DispatchError>;
291+
292+
/// Ensure the reserved balance is equal to `value`.
293+
///
294+
/// This will reserve extra amount of current reserved balance is less than
295+
/// `value`. And unreserve if current reserved balance is greater than
296+
/// `value`.
297+
fn ensure_reserved_named(
298+
id: &Self::ReserveIdentifier,
299+
currency_id: Self::CurrencyId,
300+
who: &AccountId,
301+
value: Self::Balance,
302+
) -> DispatchResult {
303+
let current = Self::reserved_balance_named(id, currency_id, who);
304+
if current > value {
305+
// we always have enough balance to unreserve here
306+
Self::unreserve_named(id, currency_id, who, current - value);
307+
Ok(())
308+
} else if value > current {
309+
// we checked value > current
310+
Self::reserve_named(id, currency_id, who, value - current)
311+
} else {
312+
// current == value
313+
Ok(())
314+
}
315+
}
316+
317+
/// Unreserve all the named reserved balances, returning unreserved amount.
318+
///
319+
/// Is a no-op if the value to be unreserved is zero.
320+
fn unreserve_all_named(
321+
id: &Self::ReserveIdentifier,
322+
currency_id: Self::CurrencyId,
323+
who: &AccountId,
324+
) -> Self::Balance {
325+
let value = Self::reserved_balance_named(id, currency_id, who);
326+
Self::unreserve_named(id, currency_id, who, value);
327+
value
328+
}
329+
330+
/// Slash all the reserved balance, returning the negative imbalance
331+
/// created.
332+
///
333+
/// Is a no-op if the value to be slashed is zero.
334+
fn slash_all_reserved_named(
335+
id: &Self::ReserveIdentifier,
336+
currency_id: Self::CurrencyId,
337+
who: &AccountId,
338+
) -> Self::Balance {
339+
let value = Self::reserved_balance_named(id, currency_id, who);
340+
Self::slash_reserved_named(id, currency_id, who, value)
341+
}
342+
343+
/// Move all the named reserved balance of one account into the balance of
344+
/// another, according to `status`. If `status` is `Reserved`, the balance
345+
/// will be reserved with given `id`.
346+
///
347+
/// Is a no-op if:
348+
/// - the value to be moved is zero; or
349+
/// - the `slashed` id equal to `beneficiary` and the `status` is
350+
/// `Reserved`.
351+
fn repatriate_all_reserved_named(
352+
id: &Self::ReserveIdentifier,
353+
currency_id: Self::CurrencyId,
354+
slashed: &AccountId,
355+
beneficiary: &AccountId,
356+
status: BalanceStatus,
357+
) -> DispatchResult {
358+
let value = Self::reserved_balance_named(id, currency_id, slashed);
359+
Self::repatriate_reserved_named(id, currency_id, slashed, beneficiary, value, status).map(|_| ())
360+
}
291361
}
292362

293363
/// Abstraction over a fungible (single) currency system.

0 commit comments

Comments
 (0)