Fix DepositReserveAsset fees payment (#3340)

The `fee` should be calculated with the reanchored asset, otherwise it
could lead to a failure where the set aside fee ends up not being
enough.

@acatangiu

---------

Co-authored-by: Adrian Catangiu <adrian@parity.io>
This commit is contained in:
Ignacio Palacios
2024-02-23 12:54:54 +01:00
committed by GitHub
parent e4b6b8cd79
commit 11b5354fd3
6 changed files with 132 additions and 14 deletions
+42 -12
View File
@@ -16,14 +16,16 @@
use frame_support::{
parameter_types,
traits::{Everything, Nothing},
traits::{Everything, Get, Nothing},
weights::Weight,
};
use frame_system::EnsureRoot;
use polkadot_runtime_parachains::FeeTracker;
use runtime_common::xcm_sender::{ChildParachainRouter, PriceForMessageDelivery};
use xcm::latest::prelude::*;
use xcm_builder::{
AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor,
SignedAccountId32AsNative, SignedToAccountId32,
SignedAccountId32AsNative, SignedToAccountId32, WithUniqueTopic,
};
use xcm_executor::{
traits::{TransactAsset, WeightTrader},
@@ -36,6 +38,8 @@ parameter_types! {
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 16;
pub const UniversalLocation: xcm::latest::InteriorLocation = xcm::latest::Junctions::Here;
pub TokenLocation: Location = Here.into_location();
pub FeeAssetId: AssetId = AssetId(TokenLocation::get());
}
/// Type to convert an `Origin` type value into a `Location` value which represents an interior
@@ -45,17 +49,43 @@ pub type LocalOriginToLocation = (
SignedToAccountId32<crate::RuntimeOrigin, crate::AccountId, AnyNetwork>,
);
pub struct DoNothingRouter;
impl SendXcm for DoNothingRouter {
type Ticket = ();
fn validate(_dest: &mut Option<Location>, _msg: &mut Option<Xcm<()>>) -> SendResult<()> {
Ok(((), Assets::new()))
}
fn deliver(_: ()) -> Result<XcmHash, SendError> {
Ok([0; 32])
/// Implementation of [`PriceForMessageDelivery`], returning a different price
/// based on whether a message contains a reanchored asset or not.
/// This implementation ensures that messages with non-reanchored assets return higher
/// prices than messages with reanchored assets.
/// Useful for `deposit_reserve_asset_works_for_any_xcm_sender` integration test.
pub struct TestDeliveryPrice<A, F>(sp_std::marker::PhantomData<(A, F)>);
impl<A: Get<AssetId>, F: FeeTracker> PriceForMessageDelivery for TestDeliveryPrice<A, F> {
type Id = F::Id;
fn price_for_delivery(_: Self::Id, msg: &Xcm<()>) -> Assets {
let base_fee: super::Balance = 1_000_000;
let parents = msg.iter().find_map(|xcm| match xcm {
ReserveAssetDeposited(assets) => {
let AssetId(location) = &assets.inner().first().unwrap().id;
Some(location.parents)
},
_ => None,
});
// If no asset is found, price defaults to `base_fee`.
let amount = base_fee
.saturating_add(base_fee.saturating_mul(parents.unwrap_or(0) as super::Balance));
(A::get(), amount).into()
}
}
pub type PriceForChildParachainDelivery = TestDeliveryPrice<FeeAssetId, super::Dmp>;
/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our
/// individual routers.
pub type XcmRouter = WithUniqueTopic<
// Only one router so far - use DMP to communicate with child parachains.
ChildParachainRouter<super::Runtime, super::Xcm, PriceForChildParachainDelivery>,
>;
pub type Barrier = AllowUnpaidExecutionFrom<Everything>;
pub struct DummyAssetTransactor;
@@ -99,7 +129,7 @@ type OriginConverter = (
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type RuntimeCall = super::RuntimeCall;
type XcmSender = DoNothingRouter;
type XcmSender = XcmRouter;
type AssetTransactor = DummyAssetTransactor;
type OriginConverter = OriginConverter;
type IsReserve = ();
@@ -133,7 +163,7 @@ impl pallet_xcm::Config for crate::Runtime {
type UniversalLocation = UniversalLocation;
type SendXcmOrigin = EnsureXcmOrigin<crate::RuntimeOrigin, LocalOriginToLocation>;
type Weigher = FixedWeightBounds<BaseXcmWeight, crate::RuntimeCall, MaxInstructions>;
type XcmRouter = DoNothingRouter;
type XcmRouter = XcmRouter;
type XcmExecuteFilter = Everything;
type XcmExecutor = xcm_executor::XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Everything;