Skip to content

Commit ff5edef

Browse files
authored
sweep dust method (#604)
* sweep dust method * fix mocks * make sure there's no frozen * add weight
1 parent 59df1df commit ff5edef

File tree

6 files changed

+131
-20
lines changed

6 files changed

+131
-20
lines changed

currencies/src/mock.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![cfg(test)]
44

55
use super::*;
6-
use frame_support::{construct_runtime, parameter_types, PalletId};
6+
use frame_support::{construct_runtime, ord_parameter_types, parameter_types, PalletId};
77
use orml_traits::parameter_type_with_key;
88
use sp_core::H256;
99
use sp_runtime::{
@@ -75,11 +75,16 @@ parameter_types! {
7575
pub MaxLocks: u32 = 100_000;
7676
}
7777

78+
ord_parameter_types! {
79+
pub const Admin: AccountId = ALICE;
80+
}
81+
7882
impl orml_tokens::Config for Runtime {
7983
type Event = Event;
8084
type Balance = Balance;
8185
type Amount = i64;
8286
type CurrencyId = CurrencyId;
87+
type SweepOrigin = frame_system::EnsureSignedBy<Admin, AccountId>;
8388
type WeightInfo = ();
8489
type ExistentialDeposits = ExistentialDeposits;
8590
type OnDust = orml_tokens::TransferDust<Runtime, DustAccount>;

tokens/src/lib.rs

+26
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ pub mod module {
189189
/// The currency ID type
190190
type CurrencyId: Parameter + Member + Copy + MaybeSerializeDeserialize + Ord;
191191

192+
/// The AccountId that can perform a sweep dust.
193+
type SweepOrigin: EnsureOrigin<Self::Origin>;
194+
192195
/// Weight information for extrinsics in this module.
193196
type WeightInfo: WeightInfo;
194197

@@ -509,6 +512,29 @@ pub mod module {
509512
Ok(())
510513
})
511514
}
515+
516+
#[pallet::weight(T::WeightInfo::sweep_dust(accounts.len() as u32))]
517+
pub fn sweep_dust(
518+
origin: OriginFor<T>,
519+
currency_id: T::CurrencyId,
520+
accounts: Vec<T::AccountId>,
521+
) -> DispatchResult {
522+
T::SweepOrigin::ensure_origin(origin)?;
523+
for account in accounts {
524+
let account_data = Accounts::<T>::get(&account, &currency_id);
525+
if account_data.free.is_zero() {
526+
continue;
527+
}
528+
if !account_data.reserved.is_zero() {
529+
continue;
530+
}
531+
if account_data.free < T::ExistentialDeposits::get(&currency_id) {
532+
T::OnDust::on_dust(&account, currency_id, account_data.free);
533+
Self::deposit_event(Event::DustLost(currency_id, account, account_data.free));
534+
}
535+
}
536+
Ok(())
537+
}
512538
}
513539
}
514540

tokens/src/mock.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use super::*;
66
use frame_support::{
7-
construct_runtime, parameter_types,
7+
construct_runtime, ord_parameter_types, parameter_types,
88
traits::{ChangeMembers, ContainsLengthBound, GenesisBuild, SaturatingCurrencyToVote, SortedMembers},
99
PalletId,
1010
};
@@ -226,11 +226,16 @@ parameter_types! {
226226
pub MaxLocks: u32 = 2;
227227
}
228228

229+
ord_parameter_types! {
230+
pub const Admin: AccountId = ALICE;
231+
}
232+
229233
impl Config for Runtime {
230234
type Event = Event;
231235
type Balance = Balance;
232236
type Amount = i64;
233237
type CurrencyId = CurrencyId;
238+
type SweepOrigin = frame_system::EnsureSignedBy<Admin, AccountId>;
234239
type WeightInfo = ();
235240
type ExistentialDeposits = ExistentialDeposits;
236241
type OnDust = TransferDust<Runtime, DustReceiver>;

tokens/src/tests.rs

+61
Original file line numberDiff line numberDiff line change
@@ -2079,3 +2079,64 @@ fn fungibles_mutate_hold_trait_should_work() {
20792079
);
20802080
});
20812081
}
2082+
2083+
#[test]
2084+
fn sweep_dust_works() {
2085+
ExtBuilder::default().build().execute_with(|| {
2086+
Accounts::<Runtime>::insert(
2087+
BOB,
2088+
DOT,
2089+
AccountData {
2090+
free: 1,
2091+
frozen: 0,
2092+
reserved: 0,
2093+
},
2094+
);
2095+
Accounts::<Runtime>::insert(
2096+
CHARLIE,
2097+
DOT,
2098+
AccountData {
2099+
free: 2,
2100+
frozen: 0,
2101+
reserved: 0,
2102+
},
2103+
);
2104+
Accounts::<Runtime>::insert(
2105+
DAVE,
2106+
DOT,
2107+
AccountData {
2108+
free: 0,
2109+
frozen: 1,
2110+
reserved: 0,
2111+
},
2112+
);
2113+
TotalIssuance::<Runtime>::insert(DOT, 3);
2114+
2115+
let accounts = vec![BOB, CHARLIE, DAVE];
2116+
2117+
// cannot be called by root or anyone expect SweepOrigin
2118+
assert_noop!(
2119+
Tokens::sweep_dust(Origin::root(), DOT, accounts.clone()),
2120+
DispatchError::BadOrigin
2121+
);
2122+
assert_noop!(
2123+
Tokens::sweep_dust(Origin::signed(BOB), DOT, accounts.clone()),
2124+
DispatchError::BadOrigin
2125+
);
2126+
2127+
assert_ok!(Tokens::sweep_dust(Origin::signed(ALICE), DOT, accounts.clone()));
2128+
System::assert_last_event(Event::Tokens(crate::Event::DustLost(DOT, BOB, 1)));
2129+
2130+
// Bob's account is gone
2131+
assert_eq!(Accounts::<Runtime>::contains_key(BOB, DOT), false);
2132+
assert_eq!(Tokens::free_balance(DOT, &BOB), 0);
2133+
2134+
// Charlie's account remains, not below ED
2135+
assert_eq!(Tokens::free_balance(DOT, &CHARLIE), 2);
2136+
2137+
// Dust transferred to dust receiver
2138+
assert_eq!(Tokens::free_balance(DOT, &DustReceiver::get()), 1);
2139+
// Total issuance remains the same
2140+
assert_eq!(Tokens::total_issuance(DOT), 3);
2141+
});
2142+
}

tokens/src/weights.rs

+25-16
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
//! Autogenerated weights for orml_tokens
22
//!
3-
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
4-
//! DATE: 2021-05-04, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: []
3+
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
4+
//! DATE: 2021-09-14, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]`
55
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128
66
77
// Executed Command:
8-
// /Users/xiliangchen/projects/acala/target/release/acala
8+
// /Users/ermal/Acala/target/release/acala
99
// benchmark
1010
// --chain=dev
1111
// --steps=50
@@ -15,9 +15,8 @@
1515
// --execution=wasm
1616
// --wasm-execution=compiled
1717
// --heap-pages=4096
18+
// --template=../templates/orml-weight-template.hbs
1819
// --output=./tokens/src/weights.rs
19-
// --template
20-
// ../templates/orml-weight-template.hbs
2120

2221

2322
#![cfg_attr(rustfmt, rustfmt_skip)]
@@ -35,33 +34,43 @@ pub trait WeightInfo {
3534
fn transfer_keep_alive() -> Weight;
3635
fn force_transfer() -> Weight;
3736
fn set_balance() -> Weight;
37+
fn sweep_dust(c: u32, ) -> Weight;
3838
}
3939

4040
/// Default weights.
4141
impl WeightInfo for () {
4242
fn transfer() -> Weight {
43-
(60_000_000 as Weight)
43+
(69_000_000 as Weight)
4444
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
4545
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
4646
}
4747
fn transfer_all() -> Weight {
48-
(62_000_000 as Weight)
48+
(69_000_000 as Weight)
4949
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
5050
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
5151
}
5252
fn transfer_keep_alive() -> Weight {
53-
(60_000_000 as Weight)
54-
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
55-
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
53+
(38_000_000 as Weight)
54+
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
55+
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
5656
}
5757
fn force_transfer() -> Weight {
58-
(60_000_000 as Weight)
59-
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
60-
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
58+
(45_000_000 as Weight)
59+
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
60+
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
6161
}
6262
fn set_balance() -> Weight {
63-
(60_000_000 as Weight)
64-
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
65-
.saturating_add(RocksDbWeight::get().writes(4 as Weight))
63+
(34_000_000 as Weight)
64+
.saturating_add(RocksDbWeight::get().reads(3 as Weight))
65+
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
66+
}
67+
fn sweep_dust(c: u32, ) -> Weight {
68+
(3_100_000 as Weight)
69+
// Standard Error: 597_000
70+
.saturating_add((27_100_000 as Weight).saturating_mul(c as Weight))
71+
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
72+
.saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(c as Weight)))
73+
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
74+
.saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(c as Weight)))
6675
}
6776
}

xtokens/src/mock/para.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use super::{Amount, Balance, CurrencyId, CurrencyIdConvert, ParachainXcmRouter};
1+
use super::{Amount, Balance, CurrencyId, CurrencyIdConvert, ParachainXcmRouter, ALICE};
22
use crate as orml_xtokens;
33

44
use frame_support::{
5-
construct_runtime, parameter_types,
5+
construct_runtime, ord_parameter_types, parameter_types,
66
traits::{Everything, Get},
77
weights::{constants::WEIGHT_PER_SECOND, Weight},
88
};
@@ -90,11 +90,16 @@ parameter_type_with_key! {
9090
};
9191
}
9292

93+
ord_parameter_types! {
94+
pub const Admin: AccountId = ALICE;
95+
}
96+
9397
impl orml_tokens::Config for Runtime {
9498
type Event = Event;
9599
type Balance = Balance;
96100
type Amount = Amount;
97101
type CurrencyId = CurrencyId;
102+
type SweepOrigin = frame_system::EnsureSignedBy<Admin, AccountId>;
98103
type WeightInfo = ();
99104
type ExistentialDeposits = ExistentialDeposits;
100105
type OnDust = ();

0 commit comments

Comments
 (0)