Skip to content

Commit 9d70e37

Browse files
committed
impl DelayTaskHooks for Task to process
1 parent ffd4ebb commit 9d70e37

File tree

6 files changed

+587
-199
lines changed

6 files changed

+587
-199
lines changed

asset-registry/src/mock/para.rs

+2-14
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,17 @@ use frame_support::{
1111
};
1212
use frame_system::{EnsureRoot, EnsureSignedBy};
1313
use orml_traits::{
14-
define_combined_task,
1514
location::{AbsoluteReserveProvider, RelativeReserveProvider},
16-
parameter_type_with_key,
17-
task::{DispatchableTask, TaskResult},
18-
FixedConversionRateProvider, MultiCurrency,
15+
parameter_type_with_key, FixedConversionRateProvider, MultiCurrency,
1916
};
2017
use orml_xcm_support::{IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset};
21-
use orml_xtokens::XtokensTask;
2218
use pallet_xcm::XcmPassthrough;
2319
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
2420
use polkadot_parachain_primitives::primitives::Sibling;
25-
use scale_info::TypeInfo;
2621
use sp_core::Get;
2722
use sp_runtime::{
2823
traits::{AccountIdConversion, Convert, IdentityLookup},
29-
AccountId32, DispatchResult, RuntimeDebug,
24+
AccountId32,
3025
};
3126
use xcm::v4::{prelude::*, Weight};
3227
use xcm_builder::{
@@ -315,13 +310,6 @@ parameter_type_with_key! {
315310
};
316311
}
317312

318-
define_combined_task! {
319-
#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
320-
pub enum DelayedTasks {
321-
Xtokens(XtokensTask<Runtime>),
322-
}
323-
}
324-
325313
impl orml_xtokens::Config for Runtime {
326314
type RuntimeEvent = RuntimeEvent;
327315
type Balance = Balance;

delay-tasks/Cargo.toml

+19
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,22 @@ orml-xtokens = { path = "../xtokens", version = "0.7.0", default-features = fals
2626
[dev-dependencies]
2727
sp-core = { workspace = true, features = ["std"] }
2828
sp-io = { workspace = true, features = ["std"] }
29+
pallet-balances = { workspace = true, features = ["std"] }
2930
pallet-preimage = { workspace = true, features = ["std"] }
3031
pallet-scheduler = { workspace = true, features = ["std"] }
32+
orml-tokens = { path = "../tokens", version = "0.7.0", features = ["std"] }
33+
34+
cumulus-pallet-xcm = { workspace = true, features = ["std"] }
35+
orml-xcm-mock-message-queue = { path = "../xcm-mock-message-queue" }
36+
orml-xcm = { path = "../xcm" }
37+
orml-xcm-support = { path = "../xcm-support" }
38+
pallet-xcm = { workspace = true, features = ["std"] }
39+
xcm-builder = { workspace = true, features = ["std"] }
40+
xcm-executor = { workspace = true, features = ["std"] }
41+
polkadot-parachain-primitives = { workspace = true, features = ["std"] }
42+
polkadot-runtime-parachains = { workspace = true, features = ["std"] }
43+
polkadot-runtime-common = { workspace = true, features = ["std"] }
44+
xcm-simulator = { workspace = true }
3145

3246
[features]
3347
default = [ "std" ]
@@ -43,6 +57,11 @@ std = [
4357
"sp-std/std",
4458
"xcm/std",
4559
]
60+
runtime-benchmarks = [
61+
"frame-support/runtime-benchmarks",
62+
"frame-system/runtime-benchmarks",
63+
"sp-runtime/runtime-benchmarks",
64+
]
4665
try-runtime = [
4766
"frame-support/try-runtime",
4867
"frame-system/try-runtime",

delay-tasks/src/lib.rs

+77-32
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use frame_support::{
1010
};
1111
use frame_system::pallet_prelude::*;
1212
use orml_traits::{
13-
task::{DelayTaskHooks, DelayTasksManager, DispatchableTask, TaskResult},
13+
task::{DelayTaskHooks, DelayTasksManager, DispatchableTask},
1414
MultiCurrency, NamedMultiReservableCurrency,
1515
};
1616
use parity_scale_codec::FullCodec;
@@ -38,7 +38,7 @@ pub struct EnsureDelayed;
3838
impl<O: Into<Result<DelayedExecuteOrigin, O>> + From<DelayedExecuteOrigin>> EnsureOrigin<O> for EnsureDelayed {
3939
type Success = ();
4040
fn try_origin(o: O) -> Result<Self::Success, O> {
41-
o.into().and_then(|_| Ok(()))
41+
o.into().map(|_| ())
4242
}
4343

4444
#[cfg(feature = "runtime-benchmarks")]
@@ -98,6 +98,8 @@ pub mod module {
9898
InvalidDelayBlock,
9999
InvalidId,
100100
FailedToSchedule,
101+
AssetIndexNonExistent,
102+
AssetConvertFailed,
101103
}
102104

103105
#[pallet::event]
@@ -119,6 +121,10 @@ pub mod module {
119121
DelayedTaskCanceled {
120122
id: Nonce,
121123
},
124+
DelayedTaskStuck {
125+
id: Nonce,
126+
error: DispatchError,
127+
},
122128
}
123129

124130
#[pallet::pallet]
@@ -143,12 +149,21 @@ pub mod module {
143149
pub fn delayed_execute(origin: OriginFor<T>, id: Nonce) -> DispatchResult {
144150
T::DelayOrigin::ensure_origin(origin)?;
145151

146-
let execute_result = Self::do_delayed_execute(id)?;
152+
let (delayed_task, _) = DelayedTasks::<T>::get(id).ok_or(Error::<T>::InvalidId)?;
153+
154+
// pre delayed execute
155+
if let Err(error) = T::DelayTaskHooks::pre_delayed_execute(&delayed_task) {
156+
Self::deposit_event(Event::<T>::DelayedTaskStuck { id, error });
157+
} else {
158+
let execute_result = delayed_task.dispatch(Weight::zero());
159+
160+
DelayedTasks::<T>::remove(id);
161+
Self::deposit_event(Event::<T>::DelayedTaskExecuted {
162+
id,
163+
result: execute_result.result,
164+
});
165+
}
147166

148-
Self::deposit_event(Event::<T>::DelayedTaskExecuted {
149-
id,
150-
result: execute_result.result,
151-
});
152167
Ok(())
153168
}
154169

@@ -171,11 +186,11 @@ pub mod module {
171186
};
172187
ensure!(new_execute_block > now, Error::<T>::InvalidDelayBlock);
173188

174-
*execute_block = new_execute_block;
175-
176189
T::Scheduler::reschedule_named((&DELAY_TASK_ID, id).encode(), DispatchTime::At(new_execute_block))
177190
.map_err(|_| Error::<T>::FailedToSchedule)?;
178191

192+
*execute_block = new_execute_block;
193+
179194
Self::deposit_event(Event::<T>::DelayedTaskReDelayed {
180195
id,
181196
execute_block: new_execute_block,
@@ -188,31 +203,26 @@ pub mod module {
188203

189204
#[pallet::call_index(2)]
190205
#[pallet::weight(Weight::zero())]
191-
pub fn cancel_delayed_task(origin: OriginFor<T>, id: Nonce) -> DispatchResult {
206+
pub fn cancel_delayed_task(origin: OriginFor<T>, id: Nonce, skip_pre_cancel: bool) -> DispatchResult {
192207
T::GovernanceOrigin::ensure_origin(origin)?;
193208

194-
let (task, _) = DelayedTasks::<T>::take(id).ok_or(Error::<T>::InvalidId)?;
209+
let (task, execute_block) = DelayedTasks::<T>::take(id).ok_or(Error::<T>::InvalidId)?;
195210

196-
// pre cancel
197-
T::DelayTaskHooks::on_cancel(&task)?;
211+
if !skip_pre_cancel {
212+
T::DelayTaskHooks::pre_cancel(&task)?;
213+
}
198214

199-
T::Scheduler::cancel_named((&DELAY_TASK_ID, id).encode()).map_err(|_| Error::<T>::FailedToSchedule)?;
215+
if frame_system::Pallet::<T>::block_number() < execute_block {
216+
// if now < execute_block, need cancel scheduler
217+
T::Scheduler::cancel_named((&DELAY_TASK_ID, id).encode()).map_err(|_| Error::<T>::FailedToSchedule)?;
218+
}
200219

201220
Self::deposit_event(Event::<T>::DelayedTaskCanceled { id });
202221
Ok(())
203222
}
204223
}
205224

206225
impl<T: Config> Pallet<T> {
207-
pub(crate) fn do_delayed_execute(id: Nonce) -> sp_std::result::Result<TaskResult, DispatchError> {
208-
let (delayed_task, _) = DelayedTasks::<T>::take(id).ok_or(Error::<T>::InvalidId)?;
209-
210-
// pre delayed dispatch
211-
T::DelayTaskHooks::pre_delayed_execute(&delayed_task)?;
212-
213-
Ok(delayed_task.dispatch(Weight::zero()))
214-
}
215-
216226
/// Retrieves the next delayed task ID from storage, and increment it by
217227
/// one.
218228
fn get_next_delayed_task_id() -> Result<Nonce, DispatchError> {
@@ -261,29 +271,64 @@ pub mod module {
261271
}
262272

263273
pub struct DelayedXtokensTaskHooks<T>(PhantomData<T>);
264-
impl<T: Config + orml_xtokens::Config> DelayTaskHooks<orml_xtokens::XtokensTask<T>> for DelayedXtokensTaskHooks<T> {
274+
impl<T: Config + orml_xtokens::Config> DelayTaskHooks<orml_xtokens::XtokensTask<T>> for DelayedXtokensTaskHooks<T>
275+
where
276+
<T as Config>::Currency: MultiCurrency<
277+
T::AccountId,
278+
CurrencyId = <T as orml_xtokens::Config>::CurrencyId,
279+
Balance = <T as orml_xtokens::Config>::Balance,
280+
>,
281+
{
265282
fn pre_delay(task: &orml_xtokens::XtokensTask<T>) -> DispatchResult {
266283
match task {
267-
orml_xtokens::XtokensTask::<T>::TransferAssets { who, assets, fee, .. } => {}
284+
orml_xtokens::XtokensTask::<T>::TransferAssets { who, assets, .. } => {
285+
let asset_len = assets.len();
286+
for i in 0..asset_len {
287+
let asset = assets.get(i).ok_or(Error::<T>::AssetIndexNonExistent)?;
288+
let currency_id: <T::Currency as MultiCurrency<T::AccountId>>::CurrencyId =
289+
<T as Config>::CurrencyIdConvert::convert(asset.id.0.clone())
290+
.ok_or(Error::<T>::AssetConvertFailed)?;
291+
let amount: T::Balance = match asset.fun {
292+
Fungibility::Fungible(amount) => {
293+
amount.try_into().map_err(|_| Error::<T>::AssetConvertFailed)?
294+
}
295+
Fungibility::NonFungible(_) => return Err(Error::<T>::AssetConvertFailed.into()),
296+
};
297+
298+
T::Currency::reserve_named(&T::ReserveId::get(), currency_id, who, amount)?;
299+
}
300+
}
268301
}
269302

270303
Ok(())
271304
}
272305

273306
fn pre_delayed_execute(task: &orml_xtokens::XtokensTask<T>) -> DispatchResult {
274307
match task {
275-
orml_xtokens::XtokensTask::<T>::TransferAssets { who, assets, fee, .. } => {}
308+
orml_xtokens::XtokensTask::<T>::TransferAssets { who, assets, .. } => {
309+
let asset_len = assets.len();
310+
for i in 0..asset_len {
311+
let asset = assets.get(i).ok_or(Error::<T>::AssetIndexNonExistent)?;
312+
let currency_id: <T::Currency as MultiCurrency<T::AccountId>>::CurrencyId =
313+
<T as Config>::CurrencyIdConvert::convert(asset.id.0.clone())
314+
.ok_or(Error::<T>::AssetConvertFailed)?;
315+
let amount: T::Balance = match asset.fun {
316+
Fungibility::Fungible(amount) => {
317+
amount.try_into().map_err(|_| Error::<T>::AssetConvertFailed)?
318+
}
319+
Fungibility::NonFungible(_) => return Err(Error::<T>::AssetConvertFailed.into()),
320+
};
321+
322+
T::Currency::unreserve_named(&T::ReserveId::get(), currency_id, who, amount);
323+
}
324+
}
276325
}
277326

278327
Ok(())
279328
}
280329

281-
fn on_cancel(task: &orml_xtokens::XtokensTask<T>) -> DispatchResult {
282-
match task {
283-
orml_xtokens::XtokensTask::<T>::TransferAssets { who, assets, fee, .. } => {}
284-
}
285-
286-
Ok(())
330+
fn pre_cancel(task: &orml_xtokens::XtokensTask<T>) -> DispatchResult {
331+
Self::pre_delayed_execute(task)
287332
}
288333
}
289334
}

0 commit comments

Comments
 (0)