diff --git a/pallet-rings/src/lib.rs b/pallet-rings/src/lib.rs index 62b7af89..30d92e95 100644 --- a/pallet-rings/src/lib.rs +++ b/pallet-rings/src/lib.rs @@ -117,7 +117,7 @@ pub mod pallet { origin_chain_asset: <::Chains as ChainList>::ChainAssets, amount: u128, from: ::CoreId, - to: ::AccountId, + to: Option<::AccountId>, }, /// A Chain's maintenance status changed. @@ -201,7 +201,7 @@ pub mod pallet { let fee_asset_location = fee_asset.get_asset_location(); - let beneficiary: MultiLocation = MultiLocation { + let mut core_multilocation: MultiLocation = MultiLocation { parents: 1, interior: Junctions::X2( Junction::Parachain(::ParaId::get()), @@ -209,6 +209,8 @@ pub mod pallet { ), }; + mutate_if_relay(&mut core_multilocation, &dest); + let fee_multiasset = MultiAsset { id: AssetId::Concrete(fee_asset_location), fun: Fungibility::Fungible(fee), @@ -228,7 +230,7 @@ pub mod pallet { Instruction::RefundSurplus, Instruction::DepositAsset { assets: MultiAssetFilter::Wild(WildMultiAsset::AllCounted(1)), - beneficiary, + beneficiary: core_multilocation, }, ]); @@ -298,7 +300,7 @@ pub mod pallet { }), }; - let core_multilocation: MultiLocation = MultiLocation { + let mut core_multilocation: MultiLocation = MultiLocation { parents: 1, interior: Junctions::X2( Junction::Parachain(::ParaId::get()), @@ -306,6 +308,8 @@ pub mod pallet { ), }; + mutate_if_relay(&mut core_multilocation, &dest); + let fee_multiasset = MultiAsset { id: AssetId::Concrete(fee_asset.get_asset_location()), fun: Fungibility::Fungible(fee), @@ -367,7 +371,6 @@ pub mod pallet { let core = ensure_multisig::>(origin)?; let core_id = core.id.into(); - let core_account = core.to_account_id(); let from_chain = asset.get_chain(); let from_chain_location = from_chain.get_location(); @@ -421,7 +424,7 @@ pub mod pallet { }) .map_err(|_| Error::::FailedToReanchorAsset)?; - let core_multilocation: MultiLocation = MultiLocation { + let mut core_multilocation: MultiLocation = MultiLocation { parents: 1, interior: Junctions::X2( Junction::Parachain(::ParaId::get()), @@ -437,9 +440,17 @@ pub mod pallet { id: to_inner.into(), }), }, - None => core_multilocation, + None => { + let mut dest_core_multilocation = core_multilocation; + + mutate_if_relay(&mut dest_core_multilocation, &dest); + + dest_core_multilocation + } }; + mutate_if_relay(&mut core_multilocation, &dest); + // If the asset originates from the destination chain, we need to reverse the reserve-transfer. let message = if asset_location.starts_with(&dest) { Xcm(vec![ @@ -516,10 +527,16 @@ pub mod pallet { origin_chain_asset: asset, from: core.id, amount, - to: to.unwrap_or(core_account), + to, }); Ok(()) } } + + pub fn mutate_if_relay(origin: &mut MultiLocation, dest: &MultiLocation) { + if dest.contains_parents_only(1) { + origin.dec_parent(); + } + } } diff --git a/pallet-rings/src/tests/mock.rs b/pallet-rings/src/tests/mock.rs index 2a109cf5..f8c346e1 100644 --- a/pallet-rings/src/tests/mock.rs +++ b/pallet-rings/src/tests/mock.rs @@ -476,6 +476,7 @@ impl pallet::Config for Test { #[derive(Encode, Decode, Clone, Eq, PartialEq, MaxEncodedLen, Debug, TypeInfo)] pub enum Chains { + Relay, ChainA, ChainB, } @@ -488,6 +489,7 @@ pub enum Assets { #[derive(Encode, Decode, Clone, Eq, PartialEq, MaxEncodedLen, Debug, TypeInfo)] pub enum ChainAssets { + Relay(Assets), ChainA(Assets), ChainB(Assets), } @@ -499,6 +501,7 @@ impl ChainAssetsList for ChainAssets { match self { Self::ChainA(_) => Chains::ChainA, Self::ChainB(_) => Chains::ChainB, + Self::Relay(_) => Chains::Relay, } } @@ -507,6 +510,7 @@ impl ChainAssetsList for ChainAssets { match self { Self::ChainA(asset) => asset, Self::ChainB(asset) => asset, + Self::Relay(asset) => asset, } } { Assets::AssetA => MultiLocation { @@ -536,6 +540,10 @@ impl ChainList for Chains { parents: 1, interior: Junctions::X1(Junction::Parachain(2345)), }, + Self::Relay => MultiLocation { + parents: 1, + interior: Junctions::Here, + }, } } @@ -543,6 +551,7 @@ impl ChainList for Chains { match self { Self::ChainA => ChainAssets::ChainA(Assets::AssetA), Self::ChainB => ChainAssets::ChainB(Assets::AssetB), + Self::Relay => ChainAssets::Relay(Assets::AssetA), } } } diff --git a/pallet-rings/src/tests/mod.rs b/pallet-rings/src/tests/mod.rs index a15ec3a2..3ebcfdd0 100644 --- a/pallet-rings/src/tests/mod.rs +++ b/pallet-rings/src/tests/mod.rs @@ -6,7 +6,7 @@ use frame_system::RawOrigin; use mock::*; use pallet_inv4::{origin::MultisigInternalOrigin, Origin}; use sp_std::vec; -use xcm::latest::Weight; +use xcm::latest::{BodyId, BodyPart, Junction, Junctions, MultiLocation, Weight}; #[test] fn set_maintenance_status() { @@ -239,3 +239,52 @@ fn bridge_assets_fails() { ); }) } + +#[test] +fn mutate_location_if_dest_is_relay() { + let relay_dest = Chains::Relay.get_location(); + let para_dest = Chains::ChainA.get_location(); + + let mut core_multilocation = MultiLocation { + parents: 1, + interior: Junctions::X2( + Junction::Parachain(2125), + Junction::Plurality { + id: BodyId::Index(0), + part: BodyPart::Voice, + }, + ), + }; + + crate::pallet::mutate_if_relay(&mut core_multilocation, ¶_dest); + + assert_eq!( + core_multilocation, + MultiLocation { + parents: 1, + interior: Junctions::X2( + Junction::Parachain(2125), + Junction::Plurality { + id: BodyId::Index(0), + part: BodyPart::Voice, + } + ) + } + ); + + crate::pallet::mutate_if_relay(&mut core_multilocation, &relay_dest); + + assert_eq!( + core_multilocation, + MultiLocation { + parents: 0, + interior: Junctions::X2( + Junction::Parachain(2125), + Junction::Plurality { + id: BodyId::Index(0), + part: BodyPart::Voice, + } + ) + } + ); +}