@@ -75,19 +75,20 @@ where
75
75
msg : & mut Option < Xcm < ( ) > > ,
76
76
) -> SendResult < Vec < u8 > > {
77
77
let d = dest. take ( ) . ok_or ( SendError :: MissingArgument ) ?;
78
- let xcm = msg. take ( ) . ok_or ( SendError :: MissingArgument ) ?;
79
78
80
79
if d. contains_parents_only ( 1 ) {
81
80
// An upward message for the relay chain.
81
+ let xcm = msg. take ( ) . ok_or ( SendError :: MissingArgument ) ?;
82
82
let price = P :: price_for_parent_delivery ( & xcm) ;
83
83
let versioned_xcm =
84
84
W :: wrap_version ( & d, xcm) . map_err ( |( ) | SendError :: DestinationUnsupported ) ?;
85
85
let data = versioned_xcm. encode ( ) ;
86
86
87
87
Ok ( ( data, price) )
88
88
} else {
89
+ // Anything else is unhandled. This includes a message that is not meant for us.
90
+ // We need to make sure that dest/msg is not consumed here.
89
91
* dest = Some ( d) ;
90
- // Anything else is unhandled. This includes a message this is meant for us.
91
92
Err ( SendError :: NotApplicable )
92
93
}
93
94
}
@@ -317,3 +318,104 @@ pub trait ChargeWeightInFungibles<AccountId, Assets: fungibles::Inspect<AccountI
317
318
weight : Weight ,
318
319
) -> Result < <Assets as Inspect < AccountId > >:: Balance , XcmError > ;
319
320
}
321
+
322
+ #[ cfg( test) ]
323
+ mod tests {
324
+ use super :: * ;
325
+ use cumulus_primitives_core:: UpwardMessage ;
326
+
327
+ /// Validates [`validate`] for required Some(destination) and Some(message)
328
+ struct OkFixedXcmHashWithAssertingRequiredInputsSender ;
329
+ impl OkFixedXcmHashWithAssertingRequiredInputsSender {
330
+ const FIXED_XCM_HASH : [ u8 ; 32 ] = [ 9 ; 32 ] ;
331
+
332
+ fn fixed_delivery_asset ( ) -> MultiAssets {
333
+ MultiAssets :: new ( )
334
+ }
335
+
336
+ fn expected_delivery_result ( ) -> Result < ( XcmHash , MultiAssets ) , SendError > {
337
+ Ok ( ( Self :: FIXED_XCM_HASH , Self :: fixed_delivery_asset ( ) ) )
338
+ }
339
+ }
340
+ impl SendXcm for OkFixedXcmHashWithAssertingRequiredInputsSender {
341
+ type Ticket = ( ) ;
342
+
343
+ fn validate (
344
+ destination : & mut Option < MultiLocation > ,
345
+ message : & mut Option < Xcm < ( ) > > ,
346
+ ) -> SendResult < Self :: Ticket > {
347
+ assert ! ( destination. is_some( ) ) ;
348
+ assert ! ( message. is_some( ) ) ;
349
+ Ok ( ( ( ) , OkFixedXcmHashWithAssertingRequiredInputsSender :: fixed_delivery_asset ( ) ) )
350
+ }
351
+
352
+ fn deliver ( _: Self :: Ticket ) -> Result < XcmHash , SendError > {
353
+ Ok ( Self :: FIXED_XCM_HASH )
354
+ }
355
+ }
356
+
357
+ /// Impl [`UpwardMessageSender`] that return `Other` error
358
+ struct OtherErrorUpwardMessageSender ;
359
+ impl UpwardMessageSender for OtherErrorUpwardMessageSender {
360
+ fn send_upward_message ( _: UpwardMessage ) -> Result < u32 , MessageSendError > {
361
+ Err ( MessageSendError :: Other )
362
+ }
363
+ }
364
+
365
+ #[ test]
366
+ fn parent_as_ump_does_not_consume_dest_or_msg_on_not_applicable ( ) {
367
+ // dummy message
368
+ let message = Xcm ( vec ! [ Trap ( 5 ) ] ) ;
369
+
370
+ // ParentAsUmp - check dest is really not applicable
371
+ let dest = ( Parent , Parent , Parent ) ;
372
+ let mut dest_wrapper = Some ( dest. clone ( ) . into ( ) ) ;
373
+ let mut msg_wrapper = Some ( message. clone ( ) ) ;
374
+ assert_eq ! (
375
+ Err ( SendError :: NotApplicable ) ,
376
+ <ParentAsUmp <( ) , ( ) , ( ) > as SendXcm >:: validate( & mut dest_wrapper, & mut msg_wrapper)
377
+ ) ;
378
+
379
+ // check wrapper were not consumed
380
+ assert_eq ! ( Some ( dest. clone( ) . into( ) ) , dest_wrapper. take( ) ) ;
381
+ assert_eq ! ( Some ( message. clone( ) ) , msg_wrapper. take( ) ) ;
382
+
383
+ // another try with router chain with asserting sender
384
+ assert_eq ! (
385
+ OkFixedXcmHashWithAssertingRequiredInputsSender :: expected_delivery_result( ) ,
386
+ send_xcm:: <( ParentAsUmp <( ) , ( ) , ( ) >, OkFixedXcmHashWithAssertingRequiredInputsSender ) >(
387
+ dest. into( ) ,
388
+ message
389
+ )
390
+ ) ;
391
+ }
392
+
393
+ #[ test]
394
+ fn parent_as_ump_consumes_dest_and_msg_on_ok_validate ( ) {
395
+ // dummy message
396
+ let message = Xcm ( vec ! [ Trap ( 5 ) ] ) ;
397
+
398
+ // ParentAsUmp - check dest/msg is valid
399
+ let dest = ( Parent , Here ) ;
400
+ let mut dest_wrapper = Some ( dest. clone ( ) . into ( ) ) ;
401
+ let mut msg_wrapper = Some ( message. clone ( ) ) ;
402
+ assert ! ( <ParentAsUmp <( ) , ( ) , ( ) > as SendXcm >:: validate(
403
+ & mut dest_wrapper,
404
+ & mut msg_wrapper
405
+ )
406
+ . is_ok( ) ) ;
407
+
408
+ // check wrapper were consumed
409
+ assert_eq ! ( None , dest_wrapper. take( ) ) ;
410
+ assert_eq ! ( None , msg_wrapper. take( ) ) ;
411
+
412
+ // another try with router chain with asserting sender
413
+ assert_eq ! (
414
+ Err ( SendError :: Transport ( "Other" ) ) ,
415
+ send_xcm:: <(
416
+ ParentAsUmp <OtherErrorUpwardMessageSender , ( ) , ( ) >,
417
+ OkFixedXcmHashWithAssertingRequiredInputsSender
418
+ ) >( dest. into( ) , message)
419
+ ) ;
420
+ }
421
+ }
0 commit comments