Skip to content

Commit face78f

Browse files
committed
add tests for XTokensTaskHooks
1 parent be4e526 commit face78f

File tree

3 files changed

+224
-26
lines changed

3 files changed

+224
-26
lines changed

delay-tasks/src/lib.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use orml_traits::{
1313
task::{DelayTaskHooks, DelayTasksManager, DispatchableTask},
1414
MultiCurrency, NamedMultiReservableCurrency,
1515
};
16+
use orml_xtokens::XtokensTask;
1617
use parity_scale_codec::FullCodec;
1718
use scale_info::TypeInfo;
1819
use sp_runtime::{
@@ -271,17 +272,17 @@ pub mod module {
271272
}
272273

273274
pub struct DelayedXtokensTaskHooks<T>(PhantomData<T>);
274-
impl<T: Config + orml_xtokens::Config> DelayTaskHooks<orml_xtokens::XtokensTask<T>> for DelayedXtokensTaskHooks<T>
275+
impl<T: Config + orml_xtokens::Config> DelayTaskHooks<XtokensTask<T>> for DelayedXtokensTaskHooks<T>
275276
where
276277
<T as Config>::Currency: MultiCurrency<
277278
T::AccountId,
278279
CurrencyId = <T as orml_xtokens::Config>::CurrencyId,
279280
Balance = <T as orml_xtokens::Config>::Balance,
280281
>,
281282
{
282-
fn pre_delay(task: &orml_xtokens::XtokensTask<T>) -> DispatchResult {
283+
fn pre_delay(task: &XtokensTask<T>) -> DispatchResult {
283284
match task {
284-
orml_xtokens::XtokensTask::<T>::TransferAssets { who, assets, .. } => {
285+
XtokensTask::<T>::TransferAssets { who, assets, .. } => {
285286
let asset_len = assets.len();
286287
for i in 0..asset_len {
287288
let asset = assets.get(i).ok_or(Error::<T>::AssetIndexNonExistent)?;
@@ -303,9 +304,9 @@ pub mod module {
303304
Ok(())
304305
}
305306

306-
fn pre_delayed_execute(task: &orml_xtokens::XtokensTask<T>) -> DispatchResult {
307+
fn pre_delayed_execute(task: &XtokensTask<T>) -> DispatchResult {
307308
match task {
308-
orml_xtokens::XtokensTask::<T>::TransferAssets { who, assets, .. } => {
309+
XtokensTask::<T>::TransferAssets { who, assets, .. } => {
309310
let asset_len = assets.len();
310311
for i in 0..asset_len {
311312
let asset = assets.get(i).ok_or(Error::<T>::AssetIndexNonExistent)?;
@@ -327,7 +328,7 @@ pub mod module {
327328
Ok(())
328329
}
329330

330-
fn pre_cancel(task: &orml_xtokens::XtokensTask<T>) -> DispatchResult {
331+
fn pre_cancel(task: &XtokensTask<T>) -> DispatchResult {
331332
Self::pre_delayed_execute(task)
332333
}
333334
}

delay-tasks/src/mock.rs

+86-20
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
use super::*;
66
use frame_support::{
77
construct_runtime, derive_impl, parameter_types,
8-
traits::{ConstU128, EqualPrivilegeOnly, Everything},
8+
traits::{EqualPrivilegeOnly, Everything},
99
};
1010
use frame_system::EnsureRoot;
11-
use orml_traits::{define_combined_task_and_bind_delay_hooks, parameter_type_with_key, task::TaskResult};
11+
use orml_traits::{
12+
define_combined_task_and_bind_delay_hooks, location::AbsoluteReserveProvider, parameter_type_with_key,
13+
task::TaskResult,
14+
};
1215
use serde::{Deserialize, Serialize};
1316
use sp_runtime::{traits::IdentityLookup, AccountId32, BuildStorage, DispatchError};
1417
use sp_std::cell::RefCell;
@@ -29,23 +32,6 @@ impl frame_system::Config for Runtime {
2932
type AccountId = AccountId;
3033
type Lookup = IdentityLookup<Self::AccountId>;
3134
type Block = Block;
32-
type AccountData = pallet_balances::AccountData<Balance>;
33-
}
34-
35-
impl pallet_balances::Config for Runtime {
36-
type MaxLocks = ConstU32<50>;
37-
type Balance = Balance;
38-
type RuntimeEvent = RuntimeEvent;
39-
type DustRemoval = ();
40-
type ExistentialDeposit = ConstU128<1>;
41-
type AccountStore = System;
42-
type WeightInfo = ();
43-
type MaxReserves = ConstU32<50>;
44-
type ReserveIdentifier = [u8; 8];
45-
type RuntimeHoldReason = RuntimeHoldReason;
46-
type RuntimeFreezeReason = RuntimeFreezeReason;
47-
type FreezeIdentifier = [u8; 8];
48-
type MaxFreezes = ();
4935
}
5036

5137
impl pallet_preimage::Config for Runtime {
@@ -181,6 +167,85 @@ impl orml_tokens::Config for Runtime {
181167
type DustRemovalWhitelist = Everything;
182168
}
183169

170+
parameter_types! {
171+
pub SelfLocation: Location = Location::new(1, [Parachain(2000)]);
172+
}
173+
174+
pub struct AccountIdToLocation;
175+
impl Convert<AccountId, Location> for AccountIdToLocation {
176+
fn convert(account: AccountId) -> Location {
177+
[Junction::AccountId32 {
178+
network: None,
179+
id: account.into(),
180+
}]
181+
.into()
182+
}
183+
}
184+
185+
parameter_type_with_key! {
186+
pub ParachainMinFee: |location: Location| -> Option<u128> {
187+
#[allow(clippy::match_ref_pats)] // false positive
188+
match (location.parents, location.first_interior()) {
189+
(1, Some(Parachain(3))) => Some(100),
190+
_ => None,
191+
}
192+
};
193+
}
194+
195+
pub enum Weightless {}
196+
impl PreparedMessage for Weightless {
197+
fn weight_of(&self) -> Weight {
198+
unreachable!()
199+
}
200+
}
201+
202+
pub struct MockExec;
203+
impl ExecuteXcm<RuntimeCall> for MockExec {
204+
type Prepared = Weightless;
205+
206+
fn prepare(_message: Xcm<RuntimeCall>) -> Result<Self::Prepared, Xcm<RuntimeCall>> {
207+
unreachable!()
208+
}
209+
210+
fn execute(_origin: impl Into<Location>, _pre: Weightless, _hash: &mut XcmHash, _weight_credit: Weight) -> Outcome {
211+
unreachable!()
212+
}
213+
214+
fn charge_fees(_location: impl Into<Location>, _fees: Assets) -> XcmResult {
215+
Err(XcmError::Unimplemented)
216+
}
217+
}
218+
219+
parameter_types! {
220+
pub UniversalLocation: InteriorLocation = Here;
221+
pub const UnitWeightCost: Weight = Weight::from_parts(10, 10);
222+
pub const BaseXcmWeight: Weight = Weight::from_parts(100_000_000, 100_000_000);
223+
pub const MaxInstructions: u32 = 100;
224+
pub const MaxAssetsIntoHolding: u32 = 64;
225+
pub const MaxAssetsForTransfer: usize = 2;
226+
}
227+
228+
impl orml_xtokens::Config for Runtime {
229+
type RuntimeEvent = RuntimeEvent;
230+
type Balance = Balance;
231+
type CurrencyId = CurrencyId;
232+
type CurrencyIdConvert = CurrencyIdConvert;
233+
type AccountIdToLocation = AccountIdToLocation;
234+
type SelfLocation = SelfLocation;
235+
type XcmExecutor = MockExec;
236+
type Weigher = xcm_builder::FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
237+
type BaseXcmWeight = BaseXcmWeight;
238+
type UniversalLocation = UniversalLocation;
239+
type MaxAssetsForTransfer = MaxAssetsForTransfer;
240+
type MinXcmFee = ParachainMinFee;
241+
type LocationsFilter = Everything;
242+
type ReserveProvider = AbsoluteReserveProvider;
243+
type RateLimiter = ();
244+
type RateLimiterId = ();
245+
type Task = MockTaskType;
246+
type DelayTasks = DelayTasks;
247+
}
248+
184249
thread_local! {
185250
pub static DISPATCH_SUCCEEDED: RefCell<u32> = RefCell::new(0);
186251
pub static DISPATCH_FAILED: RefCell<u32> = RefCell::new(0);
@@ -325,6 +390,7 @@ define_combined_task_and_bind_delay_hooks! {
325390
FailPreDelay(FailPreDelayTask, FailPreDelayTaskHook),
326391
FailPreDelayedExecute(FailPreDelayedExecuteTask, FailPreDelayedExecuteTaskHook),
327392
FailPreCancel(FailPreCancelTask, FailPreCancelTaskHook),
393+
Xtokens(XtokensTask<Runtime>, DelayedXtokensTaskHooks<Runtime>),
328394
}
329395
}
330396

@@ -356,7 +422,7 @@ construct_runtime!(
356422
Scheduler: pallet_scheduler,
357423
Preimage: pallet_preimage,
358424
Tokens: orml_tokens,
359-
Balances: pallet_balances,
425+
XTokens: orml_xtokens,
360426
}
361427
);
362428

delay-tasks/src/tests.rs

+131
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,134 @@ fn do_delayed_execute_work() {
301301
assert_eq!(PRE_DELAYED_EXECUTE_SUCCEEDED.with(|v| *v.borrow()), 2);
302302
});
303303
}
304+
305+
#[test]
306+
fn delayed_xtokens_task_hooks_work() {
307+
ExtBuilder::default().build().execute_with(|| {
308+
let assets: Assets = Assets::from(vec![
309+
(Location::parent(), 1000).into(),
310+
(
311+
(
312+
Parent,
313+
Parachain(1),
314+
Junction::from(BoundedVec::try_from(b"A".to_vec()).unwrap()),
315+
),
316+
2000,
317+
)
318+
.into(),
319+
(
320+
(
321+
Parent,
322+
Parachain(2),
323+
Junction::from(BoundedVec::try_from(b"B".to_vec()).unwrap()),
324+
),
325+
3000,
326+
)
327+
.into(),
328+
]);
329+
let fee: Asset = (Location::parent(), 1000).into();
330+
let dest: Location = (
331+
Parent,
332+
Parachain(2),
333+
Junction::AccountId32 {
334+
network: None,
335+
id: BOB.into(),
336+
},
337+
)
338+
.into();
339+
let task = XtokensTask::<Runtime>::TransferAssets {
340+
who: ALICE,
341+
assets,
342+
fee,
343+
dest,
344+
dest_weight_limit: WeightLimit::Unlimited,
345+
};
346+
347+
assert_ok!(Tokens::deposit(CurrencyId::R, &ALICE, 3000));
348+
assert_ok!(Tokens::deposit(CurrencyId::A, &ALICE, 3000));
349+
assert_ok!(Tokens::deposit(CurrencyId::B, &ALICE, 3000));
350+
assert_eq!(Tokens::free_balance(CurrencyId::R, &ALICE), 3000);
351+
assert_eq!(Tokens::free_balance(CurrencyId::A, &ALICE), 3000);
352+
assert_eq!(Tokens::free_balance(CurrencyId::B, &ALICE), 3000);
353+
assert_eq!(
354+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::R, &ALICE),
355+
0
356+
);
357+
assert_eq!(
358+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::A, &ALICE),
359+
0
360+
);
361+
assert_eq!(
362+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::B, &ALICE),
363+
0
364+
);
365+
366+
assert_ok!(DelayedXtokensTaskHooks::<Runtime>::pre_delay(&task));
367+
assert_eq!(Tokens::free_balance(CurrencyId::R, &ALICE), 2000);
368+
assert_eq!(Tokens::free_balance(CurrencyId::A, &ALICE), 1000);
369+
assert_eq!(Tokens::free_balance(CurrencyId::B, &ALICE), 0);
370+
assert_eq!(
371+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::R, &ALICE),
372+
1000
373+
);
374+
assert_eq!(
375+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::A, &ALICE),
376+
2000
377+
);
378+
assert_eq!(
379+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::B, &ALICE),
380+
3000
381+
);
382+
383+
assert_ok!(DelayedXtokensTaskHooks::<Runtime>::pre_delayed_execute(&task));
384+
assert_eq!(Tokens::free_balance(CurrencyId::R, &ALICE), 3000);
385+
assert_eq!(Tokens::free_balance(CurrencyId::A, &ALICE), 3000);
386+
assert_eq!(Tokens::free_balance(CurrencyId::B, &ALICE), 3000);
387+
assert_eq!(
388+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::R, &ALICE),
389+
0
390+
);
391+
assert_eq!(
392+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::A, &ALICE),
393+
0
394+
);
395+
assert_eq!(
396+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::B, &ALICE),
397+
0
398+
);
399+
400+
assert_ok!(DelayedXtokensTaskHooks::<Runtime>::pre_delay(&task));
401+
assert_eq!(Tokens::free_balance(CurrencyId::R, &ALICE), 2000);
402+
assert_eq!(Tokens::free_balance(CurrencyId::A, &ALICE), 1000);
403+
assert_eq!(Tokens::free_balance(CurrencyId::B, &ALICE), 0);
404+
assert_eq!(
405+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::R, &ALICE),
406+
1000
407+
);
408+
assert_eq!(
409+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::A, &ALICE),
410+
2000
411+
);
412+
assert_eq!(
413+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::B, &ALICE),
414+
3000
415+
);
416+
417+
assert_ok!(DelayedXtokensTaskHooks::<Runtime>::pre_cancel(&task));
418+
assert_eq!(Tokens::free_balance(CurrencyId::R, &ALICE), 3000);
419+
assert_eq!(Tokens::free_balance(CurrencyId::A, &ALICE), 3000);
420+
assert_eq!(Tokens::free_balance(CurrencyId::B, &ALICE), 3000);
421+
assert_eq!(
422+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::R, &ALICE),
423+
0
424+
);
425+
assert_eq!(
426+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::A, &ALICE),
427+
0
428+
);
429+
assert_eq!(
430+
Tokens::reserved_balance_named(&ReserveId::get(), CurrencyId::B, &ALICE),
431+
0
432+
);
433+
});
434+
}

0 commit comments

Comments
 (0)