XCM: Fix issue with RequestUnlock (#7278)

* XCM: Fix issue with RequestUnlock

* Leave API changes for v4

* Fix clippy errors

* Fix tests

---------

Co-authored-by: parity-processbot <>
This commit is contained in:
Francisco Aguirre
2023-05-26 16:41:10 -03:00
committed by GitHub
parent 9450970927
commit aac5b1e364
4 changed files with 67 additions and 11 deletions
@@ -136,6 +136,8 @@ fn remote_unlock_roundtrip_should_work() {
set_send_price((Parent, 10u128));
// We have been told by Parachain #1 that Account #3 has locked funds which we can unlock.
// Previously, we must have sent a LockAsset instruction to Parachain #1.
// This caused Parachain #1 to send us the NoteUnlockable instruction.
let message =
Xcm(vec![NoteUnlockable { asset: (Parent, 100u128).into(), owner: (3u64,).into() }]);
let hash = fake_message_hash(&message);
@@ -169,8 +171,10 @@ fn remote_unlock_roundtrip_should_work() {
assert_eq!(r, Outcome::Complete(Weight::from_parts(40, 40)));
assert_eq!(asset_list((3u64,)), vec![(Parent, 990u128).into()]);
let expected_msg =
Xcm::<()>(vec![UnlockAsset { target: (3u64,).into(), asset: (Parent, 100u128).into() }]);
let expected_msg = Xcm::<()>(vec![UnlockAsset {
target: (Parent, Parachain(42), 3u64).into(),
asset: (Parent, 100u128).into(),
}]);
let expected_hash = fake_message_hash(&expected_msg);
assert_eq!(sent_xcm(), vec![((Parent, Parachain(1)).into(), expected_msg, expected_hash)]);
assert_eq!(
+14 -1
View File
@@ -876,9 +876,11 @@ impl<Config: config::Config> XcmExecutor<Config> {
RequestUnlock { asset, locker } => {
let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?;
let remote_asset = Self::try_reanchor(asset.clone(), &locker)?.0;
let remote_target = Self::try_reanchor_multilocation(origin, &locker)?.0;
let reduce_ticket =
Config::AssetLocker::prepare_reduce_unlockable(locker, asset, origin)?;
let msg = Xcm::<()>(vec![UnlockAsset { asset: remote_asset, target: origin }]);
let msg =
Xcm::<()>(vec![UnlockAsset { asset: remote_asset, target: remote_target }]);
let (ticket, price) = validate_send::<Config::XcmSender>(locker, msg)?;
self.take_fee(price, FeeReason::RequestUnlock)?;
reduce_ticket.enact()?;
@@ -990,6 +992,17 @@ impl<Config: config::Config> XcmExecutor<Config> {
Ok((asset, reanchor_context))
}
fn try_reanchor_multilocation(
location: MultiLocation,
destination: &MultiLocation,
) -> Result<(MultiLocation, InteriorMultiLocation), XcmError> {
let reanchor_context = Config::UniversalLocation::get();
let location = location
.reanchored(&destination, reanchor_context)
.map_err(|_| XcmError::ReanchorFailed)?;
Ok((location, reanchor_context))
}
/// NOTE: Any assets which were unable to be reanchored are introduced into `failed_bin`.
fn reanchored(
mut assets: Assets,
+24 -2
View File
@@ -272,7 +272,7 @@ mod tests {
}
#[test]
fn remote_locking() {
fn remote_locking_and_unlocking() {
MockNet::reset();
let locked_amount = 100;
@@ -280,7 +280,7 @@ mod tests {
ParaB::execute_with(|| {
let message = Xcm(vec![LockAsset {
asset: (Here, locked_amount).into(),
unlocker: (Parachain(1),).into(),
unlocker: Parachain(1).into(),
}]);
assert_ok!(ParachainPalletXcm::send_xcm(Here, Parent, message.clone()));
});
@@ -306,6 +306,28 @@ mod tests {
}])]
);
});
ParaB::execute_with(|| {
// Request unlocking part of the funds on the relay chain
let message = Xcm(vec![RequestUnlock {
asset: (Parent, locked_amount - 50).into(),
locker: Parent.into(),
}]);
assert_ok!(ParachainPalletXcm::send_xcm(Here, (Parent, Parachain(1)), message));
});
Relay::execute_with(|| {
use pallet_balances::{BalanceLock, Reasons};
// Lock is reduced
assert_eq!(
relay_chain::Balances::locks(&child_account_id(2)),
vec![BalanceLock {
id: *b"py/xcmlk",
amount: locked_amount - 50,
reasons: Reasons::All
}]
);
});
}
/// Scenario:
@@ -17,9 +17,10 @@
//! Parachain runtime mock.
use codec::{Decode, Encode};
use core::marker::PhantomData;
use frame_support::{
construct_runtime, parameter_types,
traits::{EnsureOrigin, EnsureOriginWithArg, Everything, EverythingBut, Nothing},
traits::{ContainsPair, EnsureOrigin, EnsureOriginWithArg, Everything, EverythingBut, Nothing},
weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight},
};
@@ -27,7 +28,7 @@ use frame_system::EnsureRoot;
use sp_core::{ConstU32, H256};
use sp_runtime::{
testing::Header,
traits::{Hash, IdentityLookup},
traits::{Get, Hash, IdentityLookup},
AccountId32,
};
use sp_std::prelude::*;
@@ -238,7 +239,7 @@ impl Config for XcmConfig {
type Trader = FixedRateOfFungible<KsmPerSecondPerByte, ()>;
type ResponseHandler = ();
type AssetTrap = ();
type AssetLocker = ();
type AssetLocker = PolkadotXcm;
type AssetExchanger = ();
type AssetClaims = ();
type SubscriptionService = ();
@@ -325,7 +326,7 @@ pub mod mock_msg_queue {
Ok(xcm) => {
let location = (Parent, Parachain(sender.into()));
match T::XcmExecutor::execute_xcm(location, xcm, message_hash, max_weight) {
Outcome::Error(e) => (Err(e.clone()), Event::Fail(Some(hash), e)),
Outcome::Error(e) => (Err(e), Event::Fail(Some(hash), e)),
Outcome::Complete(w) => (Ok(w), Event::Success(Some(hash))),
// As far as the caller is concerned, this was dispatched without error, so
// we just report the weight used.
@@ -349,7 +350,7 @@ pub mod mock_msg_queue {
let _ = XcmpMessageFormat::decode(&mut data_ref)
.expect("Simulator encodes with versioned xcm format; qed");
let mut remaining_fragments = &data_ref[..];
let mut remaining_fragments = data_ref;
while !remaining_fragments.is_empty() {
if let Ok(xcm) =
VersionedXcm::<T::RuntimeCall>::decode(&mut remaining_fragments)
@@ -403,6 +404,22 @@ parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parent.into());
}
pub struct TrustedLockerCase<T>(PhantomData<T>);
impl<T: Get<(MultiLocation, MultiAssetFilter)>> ContainsPair<MultiLocation, MultiAsset>
for TrustedLockerCase<T>
{
fn contains(origin: &MultiLocation, asset: &MultiAsset) -> bool {
let (o, a) = T::get();
a.matches(asset) && &o == origin
}
}
parameter_types! {
pub RelayTokenForRelay: (MultiLocation, MultiAssetFilter) = (Parent.into(), Wild(AllOf { id: Concrete(Parent.into()), fun: WildFungible }));
}
pub type TrustedLockers = TrustedLockerCase<RelayTokenForRelay>;
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
@@ -420,7 +437,7 @@ impl pallet_xcm::Config for Runtime {
type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
type Currency = Balances;
type CurrencyMatcher = ();
type TrustedLockers = ();
type TrustedLockers = TrustedLockers;
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockConsumers = ConstU32<0>;