@@ -54,29 +54,37 @@ fn para_to_para_assethub_hop_assertions(t: ParaToParaThroughAHTest) {
5454fn ah_to_para_transfer_assets ( t : SystemParaToParaTest ) -> DispatchResult {
5555 let fee_idx = t. args . fee_asset_item as usize ;
5656 let fee: Asset = t. args . assets . inner ( ) . get ( fee_idx) . cloned ( ) . unwrap ( ) ;
57- <AssetHubRococo as AssetHubRococoPallet >:: PolkadotXcm :: transfer_assets_using_type (
57+ let custom_xcm_on_dest = Xcm :: < ( ) > ( vec ! [ DepositAsset {
58+ assets: Wild ( AllCounted ( t. args. assets. len( ) as u32 ) ) ,
59+ beneficiary: t. args. beneficiary,
60+ } ] ) ;
61+ <AssetHubRococo as AssetHubRococoPallet >:: PolkadotXcm :: transfer_assets_using_type_and_then (
5862 t. signed_origin ,
5963 bx ! ( t. args. dest. into( ) ) ,
60- bx ! ( t. args. beneficiary. into( ) ) ,
6164 bx ! ( t. args. assets. into( ) ) ,
6265 bx ! ( TransferType :: LocalReserve ) ,
6366 bx ! ( fee. id. into( ) ) ,
6467 bx ! ( TransferType :: LocalReserve ) ,
68+ bx ! ( VersionedXcm :: from( custom_xcm_on_dest) ) ,
6569 t. args . weight_limit ,
6670 )
6771}
6872
6973fn para_to_ah_transfer_assets ( t : ParaToSystemParaTest ) -> DispatchResult {
7074 let fee_idx = t. args . fee_asset_item as usize ;
7175 let fee: Asset = t. args . assets . inner ( ) . get ( fee_idx) . cloned ( ) . unwrap ( ) ;
72- <PenpalA as PenpalAPallet >:: PolkadotXcm :: transfer_assets_using_type (
76+ let custom_xcm_on_dest = Xcm :: < ( ) > ( vec ! [ DepositAsset {
77+ assets: Wild ( AllCounted ( t. args. assets. len( ) as u32 ) ) ,
78+ beneficiary: t. args. beneficiary,
79+ } ] ) ;
80+ <PenpalA as PenpalAPallet >:: PolkadotXcm :: transfer_assets_using_type_and_then (
7381 t. signed_origin ,
7482 bx ! ( t. args. dest. into( ) ) ,
75- bx ! ( t. args. beneficiary. into( ) ) ,
7683 bx ! ( t. args. assets. into( ) ) ,
7784 bx ! ( TransferType :: DestinationReserve ) ,
7885 bx ! ( fee. id. into( ) ) ,
7986 bx ! ( TransferType :: DestinationReserve ) ,
87+ bx ! ( VersionedXcm :: from( custom_xcm_on_dest) ) ,
8088 t. args . weight_limit ,
8189 )
8290}
@@ -85,44 +93,56 @@ fn para_to_para_transfer_assets_through_ah(t: ParaToParaThroughAHTest) -> Dispat
8593 let fee_idx = t. args . fee_asset_item as usize ;
8694 let fee: Asset = t. args . assets . inner ( ) . get ( fee_idx) . cloned ( ) . unwrap ( ) ;
8795 let asset_hub_location: Location = PenpalA :: sibling_location_of ( AssetHubRococo :: para_id ( ) ) ;
88- <PenpalA as PenpalAPallet >:: PolkadotXcm :: transfer_assets_using_type (
96+ let custom_xcm_on_dest = Xcm :: < ( ) > ( vec ! [ DepositAsset {
97+ assets: Wild ( AllCounted ( t. args. assets. len( ) as u32 ) ) ,
98+ beneficiary: t. args. beneficiary,
99+ } ] ) ;
100+ <PenpalA as PenpalAPallet >:: PolkadotXcm :: transfer_assets_using_type_and_then (
89101 t. signed_origin ,
90102 bx ! ( t. args. dest. into( ) ) ,
91- bx ! ( t. args. beneficiary. into( ) ) ,
92103 bx ! ( t. args. assets. into( ) ) ,
93104 bx ! ( TransferType :: RemoteReserve ( asset_hub_location. clone( ) . into( ) ) ) ,
94105 bx ! ( fee. id. into( ) ) ,
95106 bx ! ( TransferType :: RemoteReserve ( asset_hub_location. into( ) ) ) ,
107+ bx ! ( VersionedXcm :: from( custom_xcm_on_dest) ) ,
96108 t. args . weight_limit ,
97109 )
98110}
99111
100112fn para_to_asset_hub_teleport_foreign_assets ( t : ParaToSystemParaTest ) -> DispatchResult {
101113 let fee_idx = t. args . fee_asset_item as usize ;
102114 let fee: Asset = t. args . assets . inner ( ) . get ( fee_idx) . cloned ( ) . unwrap ( ) ;
103- <PenpalA as PenpalAPallet >:: PolkadotXcm :: transfer_assets_using_type (
115+ let custom_xcm_on_dest = Xcm :: < ( ) > ( vec ! [ DepositAsset {
116+ assets: Wild ( AllCounted ( t. args. assets. len( ) as u32 ) ) ,
117+ beneficiary: t. args. beneficiary,
118+ } ] ) ;
119+ <PenpalA as PenpalAPallet >:: PolkadotXcm :: transfer_assets_using_type_and_then (
104120 t. signed_origin ,
105121 bx ! ( t. args. dest. into( ) ) ,
106- bx ! ( t. args. beneficiary. into( ) ) ,
107122 bx ! ( t. args. assets. into( ) ) ,
108123 bx ! ( TransferType :: Teleport ) ,
109124 bx ! ( fee. id. into( ) ) ,
110125 bx ! ( TransferType :: DestinationReserve ) ,
126+ bx ! ( VersionedXcm :: from( custom_xcm_on_dest) ) ,
111127 t. args . weight_limit ,
112128 )
113129}
114130
115131fn asset_hub_to_para_teleport_foreign_assets ( t : SystemParaToParaTest ) -> DispatchResult {
116132 let fee_idx = t. args . fee_asset_item as usize ;
117133 let fee: Asset = t. args . assets . inner ( ) . get ( fee_idx) . cloned ( ) . unwrap ( ) ;
118- <AssetHubRococo as AssetHubRococoPallet >:: PolkadotXcm :: transfer_assets_using_type (
134+ let custom_xcm_on_dest = Xcm :: < ( ) > ( vec ! [ DepositAsset {
135+ assets: Wild ( AllCounted ( t. args. assets. len( ) as u32 ) ) ,
136+ beneficiary: t. args. beneficiary,
137+ } ] ) ;
138+ <AssetHubRococo as AssetHubRococoPallet >:: PolkadotXcm :: transfer_assets_using_type_and_then (
119139 t. signed_origin ,
120140 bx ! ( t. args. dest. into( ) ) ,
121- bx ! ( t. args. beneficiary. into( ) ) ,
122141 bx ! ( t. args. assets. into( ) ) ,
123142 bx ! ( TransferType :: Teleport ) ,
124143 bx ! ( fee. id. into( ) ) ,
125144 bx ! ( TransferType :: LocalReserve ) ,
145+ bx ! ( VersionedXcm :: from( custom_xcm_on_dest) ) ,
126146 t. args . weight_limit ,
127147 )
128148}
@@ -626,3 +646,166 @@ fn bidirectional_teleport_foreign_asset_between_para_and_asset_hub_using_explici
626646 asset_hub_to_para_teleport_foreign_assets,
627647 ) ;
628648}
649+
650+ // ===============================================================
651+ // ===== Transfer - Native Asset - Relay->AssetHub->Parachain ====
652+ // ===============================================================
653+ /// Transfers of native asset Relay to Parachain (using AssetHub reserve). Parachains want to avoid
654+ /// managing SAs on all system chains, thus want all their DOT-in-reserve to be held in their
655+ /// Sovereign Account on Asset Hub.
656+ #[ test]
657+ fn transfer_native_asset_from_relay_to_para_through_asset_hub ( ) {
658+ // Init values for Relay
659+ let destination = Rococo :: child_location_of ( PenpalA :: para_id ( ) ) ;
660+ let sender = RococoSender :: get ( ) ;
661+ let amount_to_send: Balance = ROCOCO_ED * 1000 ;
662+
663+ // Init values for Parachain
664+ let relay_native_asset_location = RelayLocation :: get ( ) ;
665+ let receiver = PenpalAReceiver :: get ( ) ;
666+
667+ // Init Test
668+ let test_args = TestContext {
669+ sender,
670+ receiver : receiver. clone ( ) ,
671+ args : TestArgs :: new_relay ( destination. clone ( ) , receiver. clone ( ) , amount_to_send) ,
672+ } ;
673+ let mut test = RelayToParaThroughAHTest :: new ( test_args) ;
674+
675+ let sov_penpal_on_ah = AssetHubRococo :: sovereign_account_id_of (
676+ AssetHubRococo :: sibling_location_of ( PenpalA :: para_id ( ) ) ,
677+ ) ;
678+ // Query initial balances
679+ let sender_balance_before = test. sender . balance ;
680+ let sov_penpal_on_ah_before = AssetHubRococo :: execute_with ( || {
681+ <AssetHubRococo as AssetHubRococoPallet >:: Balances :: free_balance ( sov_penpal_on_ah. clone ( ) )
682+ } ) ;
683+ let receiver_assets_before = PenpalA :: execute_with ( || {
684+ type ForeignAssets = <PenpalA as PenpalAPallet >:: ForeignAssets ;
685+ <ForeignAssets as Inspect < _ > >:: balance ( relay_native_asset_location. clone ( ) , & receiver)
686+ } ) ;
687+
688+ fn relay_assertions ( t : RelayToParaThroughAHTest ) {
689+ type RuntimeEvent = <Rococo as Chain >:: RuntimeEvent ;
690+ Rococo :: assert_xcm_pallet_attempted_complete ( None ) ;
691+ assert_expected_events ! (
692+ Rococo ,
693+ vec![
694+ // Amount to teleport is withdrawn from Sender
695+ RuntimeEvent :: Balances ( pallet_balances:: Event :: Burned { who, amount } ) => {
696+ who: * who == t. sender. account_id,
697+ amount: * amount == t. args. amount,
698+ } ,
699+ // Amount to teleport is deposited in Relay's `CheckAccount`
700+ RuntimeEvent :: Balances ( pallet_balances:: Event :: Minted { who, amount } ) => {
701+ who: * who == <Rococo as RococoPallet >:: XcmPallet :: check_account( ) ,
702+ amount: * amount == t. args. amount,
703+ } ,
704+ ]
705+ ) ;
706+ }
707+ fn asset_hub_assertions ( _: RelayToParaThroughAHTest ) {
708+ type RuntimeEvent = <AssetHubRococo as Chain >:: RuntimeEvent ;
709+ let sov_penpal_on_ah = AssetHubRococo :: sovereign_account_id_of (
710+ AssetHubRococo :: sibling_location_of ( PenpalA :: para_id ( ) ) ,
711+ ) ;
712+ assert_expected_events ! (
713+ AssetHubRococo ,
714+ vec![
715+ // Deposited to receiver parachain SA
716+ RuntimeEvent :: Balances (
717+ pallet_balances:: Event :: Minted { who, .. }
718+ ) => {
719+ who: * who == sov_penpal_on_ah,
720+ } ,
721+ RuntimeEvent :: MessageQueue (
722+ pallet_message_queue:: Event :: Processed { success: true , .. }
723+ ) => { } ,
724+ ]
725+ ) ;
726+ }
727+ fn penpal_assertions ( t : RelayToParaThroughAHTest ) {
728+ type RuntimeEvent = <PenpalA as Chain >:: RuntimeEvent ;
729+ let expected_id =
730+ t. args . assets . into_inner ( ) . first ( ) . unwrap ( ) . id . 0 . clone ( ) . try_into ( ) . unwrap ( ) ;
731+ assert_expected_events ! (
732+ PenpalA ,
733+ vec![
734+ RuntimeEvent :: ForeignAssets ( pallet_assets:: Event :: Issued { asset_id, owner, .. } ) => {
735+ asset_id: * asset_id == expected_id,
736+ owner: * owner == t. receiver. account_id,
737+ } ,
738+ ]
739+ ) ;
740+ }
741+ fn transfer_assets_dispatchable ( t : RelayToParaThroughAHTest ) -> DispatchResult {
742+ let fee_idx = t. args . fee_asset_item as usize ;
743+ let fee: Asset = t. args . assets . inner ( ) . get ( fee_idx) . cloned ( ) . unwrap ( ) ;
744+ let asset_hub_location = Rococo :: child_location_of ( AssetHubRococo :: para_id ( ) ) ;
745+ let context = RococoUniversalLocation :: get ( ) ;
746+
747+ // reanchor fees to the view of destination (Penpal)
748+ let mut remote_fees = fee. clone ( ) . reanchored ( & t. args . dest , & context) . unwrap ( ) ;
749+ if let Fungible ( ref mut amount) = remote_fees. fun {
750+ // we already spent some fees along the way, just use half of what we started with
751+ * amount = * amount / 2 ;
752+ }
753+ let xcm_on_final_dest = Xcm :: < ( ) > ( vec ! [
754+ BuyExecution { fees: remote_fees, weight_limit: t. args. weight_limit. clone( ) } ,
755+ DepositAsset {
756+ assets: Wild ( AllCounted ( t. args. assets. len( ) as u32 ) ) ,
757+ beneficiary: t. args. beneficiary,
758+ } ,
759+ ] ) ;
760+
761+ // reanchor final dest (Penpal) to the view of hop (Asset Hub)
762+ let mut dest = t. args . dest . clone ( ) ;
763+ dest. reanchor ( & asset_hub_location, & context) . unwrap ( ) ;
764+ // on Asset Hub, forward assets to Penpal
765+ let xcm_on_hop = Xcm :: < ( ) > ( vec ! [ DepositReserveAsset {
766+ assets: Wild ( AllCounted ( t. args. assets. len( ) as u32 ) ) ,
767+ dest,
768+ xcm: xcm_on_final_dest,
769+ } ] ) ;
770+
771+ // First leg is a teleport, from there a local-reserve-transfer to final dest
772+ <Rococo as RococoPallet >:: XcmPallet :: transfer_assets_using_type_and_then (
773+ t. signed_origin ,
774+ bx ! ( asset_hub_location. into( ) ) ,
775+ bx ! ( t. args. assets. into( ) ) ,
776+ bx ! ( TransferType :: Teleport ) ,
777+ bx ! ( fee. id. into( ) ) ,
778+ bx ! ( TransferType :: Teleport ) ,
779+ bx ! ( VersionedXcm :: from( xcm_on_hop) ) ,
780+ t. args . weight_limit ,
781+ )
782+ }
783+
784+ // Set assertions and dispatchables
785+ test. set_assertion :: < Rococo > ( relay_assertions) ;
786+ test. set_assertion :: < AssetHubRococo > ( asset_hub_assertions) ;
787+ test. set_assertion :: < PenpalA > ( penpal_assertions) ;
788+ test. set_dispatchable :: < Rococo > ( transfer_assets_dispatchable) ;
789+ test. assert ( ) ;
790+
791+ // Query final balances
792+ let sender_balance_after = test. sender . balance ;
793+ let sov_penpal_on_ah_after = AssetHubRococo :: execute_with ( || {
794+ <AssetHubRococo as AssetHubRococoPallet >:: Balances :: free_balance ( sov_penpal_on_ah)
795+ } ) ;
796+ let receiver_assets_after = PenpalA :: execute_with ( || {
797+ type ForeignAssets = <PenpalA as PenpalAPallet >:: ForeignAssets ;
798+ <ForeignAssets as Inspect < _ > >:: balance ( relay_native_asset_location, & receiver)
799+ } ) ;
800+
801+ // Sender's balance is reduced by amount sent plus delivery fees
802+ assert ! ( sender_balance_after < sender_balance_before - amount_to_send) ;
803+ // SA on AH balance is increased
804+ assert ! ( sov_penpal_on_ah_after > sov_penpal_on_ah_before) ;
805+ // Receiver's asset balance is increased
806+ assert ! ( receiver_assets_after > receiver_assets_before) ;
807+ // Receiver's asset balance increased by `amount_to_send - delivery_fees - bought_execution`;
808+ // `delivery_fees` might be paid from transfer or JIT, also `bought_execution` is unknown but
809+ // should be non-zero
810+ assert ! ( receiver_assets_after < receiver_assets_before + amount_to_send) ;
811+ }
0 commit comments