@@ -10,7 +10,7 @@ use frame_support::{
10
10
} ;
11
11
use frame_system:: pallet_prelude:: * ;
12
12
use orml_traits:: {
13
- task:: { DelayTaskHooks , DelayTasksManager , DispatchableTask , TaskResult } ,
13
+ task:: { DelayTaskHooks , DelayTasksManager , DispatchableTask } ,
14
14
MultiCurrency , NamedMultiReservableCurrency ,
15
15
} ;
16
16
use parity_scale_codec:: FullCodec ;
@@ -38,7 +38,7 @@ pub struct EnsureDelayed;
38
38
impl < O : Into < Result < DelayedExecuteOrigin , O > > + From < DelayedExecuteOrigin > > EnsureOrigin < O > for EnsureDelayed {
39
39
type Success = ( ) ;
40
40
fn try_origin ( o : O ) -> Result < Self :: Success , O > {
41
- o. into ( ) . and_then ( |_| Ok ( ( ) ) )
41
+ o. into ( ) . map ( |_| ( ) )
42
42
}
43
43
44
44
#[ cfg( feature = "runtime-benchmarks" ) ]
@@ -98,6 +98,8 @@ pub mod module {
98
98
InvalidDelayBlock ,
99
99
InvalidId ,
100
100
FailedToSchedule ,
101
+ AssetIndexNonExistent ,
102
+ AssetConvertFailed ,
101
103
}
102
104
103
105
#[ pallet:: event]
@@ -119,6 +121,10 @@ pub mod module {
119
121
DelayedTaskCanceled {
120
122
id : Nonce ,
121
123
} ,
124
+ DelayedTaskStuck {
125
+ id : Nonce ,
126
+ error : DispatchError ,
127
+ } ,
122
128
}
123
129
124
130
#[ pallet:: pallet]
@@ -143,12 +149,21 @@ pub mod module {
143
149
pub fn delayed_execute ( origin : OriginFor < T > , id : Nonce ) -> DispatchResult {
144
150
T :: DelayOrigin :: ensure_origin ( origin) ?;
145
151
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
+ }
147
166
148
- Self :: deposit_event ( Event :: < T > :: DelayedTaskExecuted {
149
- id,
150
- result : execute_result. result ,
151
- } ) ;
152
167
Ok ( ( ) )
153
168
}
154
169
@@ -171,11 +186,11 @@ pub mod module {
171
186
} ;
172
187
ensure ! ( new_execute_block > now, Error :: <T >:: InvalidDelayBlock ) ;
173
188
174
- * execute_block = new_execute_block;
175
-
176
189
T :: Scheduler :: reschedule_named ( ( & DELAY_TASK_ID , id) . encode ( ) , DispatchTime :: At ( new_execute_block) )
177
190
. map_err ( |_| Error :: < T > :: FailedToSchedule ) ?;
178
191
192
+ * execute_block = new_execute_block;
193
+
179
194
Self :: deposit_event ( Event :: < T > :: DelayedTaskReDelayed {
180
195
id,
181
196
execute_block : new_execute_block,
@@ -188,31 +203,26 @@ pub mod module {
188
203
189
204
#[ pallet:: call_index( 2 ) ]
190
205
#[ 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 {
192
207
T :: GovernanceOrigin :: ensure_origin ( origin) ?;
193
208
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 ) ?;
195
210
196
- // pre cancel
197
- T :: DelayTaskHooks :: on_cancel ( & task) ?;
211
+ if !skip_pre_cancel {
212
+ T :: DelayTaskHooks :: pre_cancel ( & task) ?;
213
+ }
198
214
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
+ }
200
219
201
220
Self :: deposit_event ( Event :: < T > :: DelayedTaskCanceled { id } ) ;
202
221
Ok ( ( ) )
203
222
}
204
223
}
205
224
206
225
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
-
216
226
/// Retrieves the next delayed task ID from storage, and increment it by
217
227
/// one.
218
228
fn get_next_delayed_task_id ( ) -> Result < Nonce , DispatchError > {
@@ -261,29 +271,64 @@ pub mod module {
261
271
}
262
272
263
273
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
+ {
265
282
fn pre_delay ( task : & orml_xtokens:: XtokensTask < T > ) -> DispatchResult {
266
283
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
+ }
268
301
}
269
302
270
303
Ok ( ( ) )
271
304
}
272
305
273
306
fn pre_delayed_execute ( task : & orml_xtokens:: XtokensTask < T > ) -> DispatchResult {
274
307
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
+ }
276
325
}
277
326
278
327
Ok ( ( ) )
279
328
}
280
329
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)
287
332
}
288
333
}
289
334
}
0 commit comments