mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 17:31:05 +00:00
pallet-xcm: use XcmTeleportFilter for teleported fees in reserve transfers (#2322)
Disallow reserve transfers that use teleportable fees if `(origin, fees)` matches `XcmTeleportFilter`. Add regression tests for filtering based on `XcmTeleportFilter` for both `(limited_)reserve_transfer_assets()` and `(limited_)teleport_assets` extrinsics.
This commit is contained in:
@@ -1379,7 +1379,7 @@ impl<T: Config> Pallet<T> {
|
|||||||
TransferType::DestinationReserve =>
|
TransferType::DestinationReserve =>
|
||||||
Self::destination_reserve_fees_instructions(dest, fees, weight_limit)?,
|
Self::destination_reserve_fees_instructions(dest, fees, weight_limit)?,
|
||||||
TransferType::Teleport =>
|
TransferType::Teleport =>
|
||||||
Self::teleport_fees_instructions(dest, fees, weight_limit)?,
|
Self::teleport_fees_instructions(origin_location, dest, fees, weight_limit)?,
|
||||||
TransferType::RemoteReserve(_) =>
|
TransferType::RemoteReserve(_) =>
|
||||||
return Err(Error::<T>::InvalidAssetUnsupportedReserve.into()),
|
return Err(Error::<T>::InvalidAssetUnsupportedReserve.into()),
|
||||||
});
|
});
|
||||||
@@ -1715,10 +1715,14 @@ impl<T: Config> Pallet<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn teleport_fees_instructions(
|
fn teleport_fees_instructions(
|
||||||
|
origin: MultiLocation,
|
||||||
dest: MultiLocation,
|
dest: MultiLocation,
|
||||||
fees: MultiAsset,
|
fees: MultiAsset,
|
||||||
weight_limit: WeightLimit,
|
weight_limit: WeightLimit,
|
||||||
) -> Result<(Xcm<<T as Config>::RuntimeCall>, Xcm<()>), Error<T>> {
|
) -> Result<(Xcm<<T as Config>::RuntimeCall>, Xcm<()>), Error<T>> {
|
||||||
|
let value = (origin, vec![fees.clone()]);
|
||||||
|
ensure!(T::XcmTeleportFilter::contains(&value), Error::<T>::Filtered);
|
||||||
|
|
||||||
let context = T::UniversalLocation::get();
|
let context = T::UniversalLocation::get();
|
||||||
let reanchored_fees = fees
|
let reanchored_fees = fees
|
||||||
.clone()
|
.clone()
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ use codec::Encode;
|
|||||||
use frame_support::{
|
use frame_support::{
|
||||||
construct_runtime, match_types, parameter_types,
|
construct_runtime, match_types, parameter_types,
|
||||||
traits::{
|
traits::{
|
||||||
AsEnsureOriginWithArg, ConstU128, ConstU32, Equals, Everything, EverythingBut, Nothing,
|
AsEnsureOriginWithArg, ConstU128, ConstU32, Contains, Equals, Everything, EverythingBut,
|
||||||
|
Nothing,
|
||||||
},
|
},
|
||||||
weights::Weight,
|
weights::Weight,
|
||||||
};
|
};
|
||||||
@@ -341,6 +342,9 @@ pub const USDT_PARA_ID: u32 = 2003;
|
|||||||
// This child parachain is not configured as trusted reserve or teleport location for any assets.
|
// This child parachain is not configured as trusted reserve or teleport location for any assets.
|
||||||
pub const OTHER_PARA_ID: u32 = 2009;
|
pub const OTHER_PARA_ID: u32 = 2009;
|
||||||
|
|
||||||
|
// This child parachain is used for filtered/disallowed assets.
|
||||||
|
pub const FILTERED_PARA_ID: u32 = 2010;
|
||||||
|
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
pub const RelayLocation: MultiLocation = Here.into_location();
|
pub const RelayLocation: MultiLocation = Here.into_location();
|
||||||
pub const NativeAsset: MultiAsset = MultiAsset {
|
pub const NativeAsset: MultiAsset = MultiAsset {
|
||||||
@@ -384,6 +388,17 @@ parameter_types! {
|
|||||||
interior: X1(Parachain(USDT_PARA_ID)),
|
interior: X1(Parachain(USDT_PARA_ID)),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
pub const FilteredTeleportLocation: MultiLocation = MultiLocation {
|
||||||
|
parents: 0,
|
||||||
|
interior: X1(Parachain(FILTERED_PARA_ID))
|
||||||
|
};
|
||||||
|
pub const FilteredTeleportAsset: MultiAsset = MultiAsset {
|
||||||
|
fun: Fungible(10),
|
||||||
|
id: Concrete(MultiLocation {
|
||||||
|
parents: 0,
|
||||||
|
interior: X1(Parachain(FILTERED_PARA_ID)),
|
||||||
|
}),
|
||||||
|
};
|
||||||
pub const AnyNetwork: Option<NetworkId> = None;
|
pub const AnyNetwork: Option<NetworkId> = None;
|
||||||
pub UniversalLocation: InteriorMultiLocation = Here;
|
pub UniversalLocation: InteriorMultiLocation = Here;
|
||||||
pub UnitWeightCost: u64 = 1_000;
|
pub UnitWeightCost: u64 = 1_000;
|
||||||
@@ -430,6 +445,7 @@ parameter_types! {
|
|||||||
pub TrustedLocal: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into());
|
pub TrustedLocal: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into());
|
||||||
pub TrustedSystemPara: (MultiAssetFilter, MultiLocation) = (NativeAsset::get().into(), SystemParachainLocation::get());
|
pub TrustedSystemPara: (MultiAssetFilter, MultiLocation) = (NativeAsset::get().into(), SystemParachainLocation::get());
|
||||||
pub TrustedUsdt: (MultiAssetFilter, MultiLocation) = (Usdt::get().into(), UsdtTeleportLocation::get());
|
pub TrustedUsdt: (MultiAssetFilter, MultiLocation) = (Usdt::get().into(), UsdtTeleportLocation::get());
|
||||||
|
pub TrustedFilteredTeleport: (MultiAssetFilter, MultiLocation) = (FilteredTeleportAsset::get().into(), FilteredTeleportLocation::get());
|
||||||
pub TeleportUsdtToForeign: (MultiAssetFilter, MultiLocation) = (Usdt::get().into(), ForeignReserveLocation::get());
|
pub TeleportUsdtToForeign: (MultiAssetFilter, MultiLocation) = (Usdt::get().into(), ForeignReserveLocation::get());
|
||||||
pub TrustedForeign: (MultiAssetFilter, MultiLocation) = (ForeignAsset::get().into(), ForeignReserveLocation::get());
|
pub TrustedForeign: (MultiAssetFilter, MultiLocation) = (ForeignAsset::get().into(), ForeignReserveLocation::get());
|
||||||
pub TrustedUsdc: (MultiAssetFilter, MultiLocation) = (Usdc::get().into(), UsdcReserveLocation::get());
|
pub TrustedUsdc: (MultiAssetFilter, MultiLocation) = (Usdc::get().into(), UsdcReserveLocation::get());
|
||||||
@@ -466,6 +482,7 @@ impl xcm_executor::Config for XcmConfig {
|
|||||||
Case<TrustedSystemPara>,
|
Case<TrustedSystemPara>,
|
||||||
Case<TrustedUsdt>,
|
Case<TrustedUsdt>,
|
||||||
Case<TeleportUsdtToForeign>,
|
Case<TeleportUsdtToForeign>,
|
||||||
|
Case<TrustedFilteredTeleport>,
|
||||||
);
|
);
|
||||||
type UniversalLocation = UniversalLocation;
|
type UniversalLocation = UniversalLocation;
|
||||||
type Barrier = Barrier;
|
type Barrier = Barrier;
|
||||||
@@ -496,6 +513,14 @@ parameter_types! {
|
|||||||
pub static AdvertisedXcmVersion: pallet_xcm::XcmVersion = 3;
|
pub static AdvertisedXcmVersion: pallet_xcm::XcmVersion = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct XcmTeleportFiltered;
|
||||||
|
impl Contains<(MultiLocation, Vec<MultiAsset>)> for XcmTeleportFiltered {
|
||||||
|
fn contains(t: &(MultiLocation, Vec<MultiAsset>)) -> bool {
|
||||||
|
let filtered = FilteredTeleportAsset::get();
|
||||||
|
t.1.iter().any(|asset| asset == &filtered)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl pallet_xcm::Config for Test {
|
impl pallet_xcm::Config for Test {
|
||||||
type RuntimeEvent = RuntimeEvent;
|
type RuntimeEvent = RuntimeEvent;
|
||||||
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
|
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
|
||||||
@@ -503,7 +528,7 @@ impl pallet_xcm::Config for Test {
|
|||||||
type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
|
type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
|
||||||
type XcmExecuteFilter = Everything;
|
type XcmExecuteFilter = Everything;
|
||||||
type XcmExecutor = XcmExecutor<XcmConfig>;
|
type XcmExecutor = XcmExecutor<XcmConfig>;
|
||||||
type XcmTeleportFilter = Everything;
|
type XcmTeleportFilter = EverythingBut<XcmTeleportFiltered>;
|
||||||
type XcmReserveTransferFilter = Everything;
|
type XcmReserveTransferFilter = Everything;
|
||||||
type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
|
type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
|
||||||
type UniversalLocation = UniversalLocation;
|
type UniversalLocation = UniversalLocation;
|
||||||
|
|||||||
@@ -117,6 +117,30 @@ fn limited_teleport_assets_works() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `limited_teleport_assets` should fail for filtered assets
|
||||||
|
#[test]
|
||||||
|
fn limited_teleport_filtered_assets_disallowed() {
|
||||||
|
let beneficiary: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into();
|
||||||
|
new_test_ext_with_balances(vec![(ALICE, INITIAL_BALANCE)]).execute_with(|| {
|
||||||
|
let result = XcmPallet::limited_teleport_assets(
|
||||||
|
RuntimeOrigin::signed(ALICE),
|
||||||
|
Box::new(FilteredTeleportLocation::get().into()),
|
||||||
|
Box::new(beneficiary.into()),
|
||||||
|
Box::new(FilteredTeleportAsset::get().into()),
|
||||||
|
0,
|
||||||
|
Unlimited,
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
Err(DispatchError::Module(ModuleError {
|
||||||
|
index: 4,
|
||||||
|
error: [2, 0, 0, 0],
|
||||||
|
message: Some("Filtered")
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Test `reserve_transfer_assets_with_paid_router_works`
|
/// Test `reserve_transfer_assets_with_paid_router_works`
|
||||||
///
|
///
|
||||||
/// Asserts that the sender's balance is decreased and the beneficiary's balance
|
/// Asserts that the sender's balance is decreased and the beneficiary's balance
|
||||||
@@ -1403,3 +1427,33 @@ fn reserve_transfer_assets_with_teleportable_asset_fails() {
|
|||||||
assert_eq!(Assets::active_issuance(usdt_id_multilocation), usdt_initial_local_amount);
|
assert_eq!(Assets::active_issuance(usdt_id_multilocation), usdt_initial_local_amount);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test `reserve_transfer_assets` with teleportable fee that is filtered - should fail.
|
||||||
|
#[test]
|
||||||
|
fn reserve_transfer_assets_with_filtered_teleported_fee_disallowed() {
|
||||||
|
let beneficiary: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into();
|
||||||
|
new_test_ext_with_balances(vec![(ALICE, INITIAL_BALANCE)]).execute_with(|| {
|
||||||
|
let (assets, fee_index, _, _) = into_multiassets_checked(
|
||||||
|
// FilteredTeleportAsset for fees - teleportable but filtered
|
||||||
|
FilteredTeleportAsset::get().into(),
|
||||||
|
// native asset to transfer (not used for fees) - local reserve
|
||||||
|
(MultiLocation::here(), SEND_AMOUNT).into(),
|
||||||
|
);
|
||||||
|
let result = XcmPallet::limited_reserve_transfer_assets(
|
||||||
|
RuntimeOrigin::signed(ALICE),
|
||||||
|
Box::new(FilteredTeleportLocation::get().into()),
|
||||||
|
Box::new(beneficiary.into()),
|
||||||
|
Box::new(assets.into()),
|
||||||
|
fee_index as u32,
|
||||||
|
Unlimited,
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
Err(DispatchError::Module(ModuleError {
|
||||||
|
index: 4,
|
||||||
|
error: [2, 0, 0, 0],
|
||||||
|
message: Some("Filtered")
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user