mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 16:21:02 +00:00
Improve Penpal runtime + emulated tests (#3543)
Issues addressed in this PR: - Improve *Penpal* runtime: - Properly handled received assets. Previously, it treated `(1, Here)` as the local native currency, whereas it should be treated as a `ForeignAsset`. This wasn't a great example of standard Parachain behaviour, as no Parachain treats the system asset as the local currency. - Remove `AllowExplicitUnpaidExecutionFrom` the system. Again, this wasn't a great example of standard Parachain behaviour. - Move duplicated `ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger` to `assets_common` crate. - Improve emulated tests: - Update *Penpal* tests to new runtime. - To simplify tests, register the reserve transferred, teleported, and system assets in *Penpal* and *AssetHub* genesis. This saves us from having to create the assets repeatedly for each test - Add missing test case: `reserve_transfer_assets_from_para_to_system_para`. - Cleanup. - Prevent integration tests crates imports from being re-exported, as they were polluting the `polkadot-sdk` docs. There is still a test case missing for reserve transfers: - Reserve transfer of system asset from *Parachain* to *Parachain* trough *AssetHub*. - This is not yet possible with `pallet-xcm` due to the reasons explained in https://github.com/paritytech/polkadot-sdk/pull/3339 --------- Co-authored-by: command-bot <>
This commit is contained in:
@@ -527,12 +527,12 @@ fn test_foreign_asset_xcm_take_first_trader() {
|
||||
let bought = Weight::from_parts(4_000_000_000u64, 0);
|
||||
|
||||
// Lets calculate amount needed
|
||||
let asset_amount_needed =
|
||||
ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(
|
||||
let asset_amount_needed
|
||||
= ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(
|
||||
foreign_location,
|
||||
bought,
|
||||
bought
|
||||
)
|
||||
.expect("failed to compute");
|
||||
.expect("failed to compute");
|
||||
|
||||
// Lets pay with: asset_amount_needed + asset_amount_extra
|
||||
let asset_amount_extra = 100_u128;
|
||||
|
||||
@@ -527,12 +527,8 @@ fn test_foreign_asset_xcm_take_first_trader() {
|
||||
let bought = Weight::from_parts(4_000_000_000u64, 0);
|
||||
|
||||
// Lets calculate amount needed
|
||||
let asset_amount_needed =
|
||||
ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(
|
||||
foreign_location,
|
||||
bought,
|
||||
)
|
||||
.expect("failed to compute");
|
||||
let asset_amount_needed = ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger::charge_weight_in_fungibles(foreign_location, bought)
|
||||
.expect("failed to compute");
|
||||
|
||||
// Lets pay with: asset_amount_needed + asset_amount_extra
|
||||
let asset_amount_extra = 100_u128;
|
||||
|
||||
@@ -53,7 +53,10 @@ use frame_system::{
|
||||
limits::{BlockLength, BlockWeights},
|
||||
EnsureRoot, EnsureSigned,
|
||||
};
|
||||
use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling};
|
||||
use parachains_common::{
|
||||
impls::{AssetsToBlockAuthor, NonZeroIssuance},
|
||||
message_queue::{NarrowOriginToSibling, ParaIdToSibling},
|
||||
};
|
||||
use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery;
|
||||
use smallvec::smallvec;
|
||||
use sp_api::impl_runtime_apis;
|
||||
@@ -70,7 +73,7 @@ use sp_std::prelude::*;
|
||||
#[cfg(feature = "std")]
|
||||
use sp_version::NativeVersion;
|
||||
use sp_version::RuntimeVersion;
|
||||
use xcm_config::{AssetsToBlockAuthor, XcmOriginToTransactDispatchOrigin};
|
||||
use xcm_config::XcmOriginToTransactDispatchOrigin;
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub use sp_runtime::BuildStorage;
|
||||
@@ -618,7 +621,7 @@ impl pallet_asset_tx_payment::Config for Runtime {
|
||||
ConvertInto,
|
||||
pallet_assets::Instance1,
|
||||
>,
|
||||
AssetsToBlockAuthor<Runtime>,
|
||||
AssetsToBlockAuthor<Runtime, pallet_assets::Instance1>,
|
||||
>;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,41 +23,39 @@
|
||||
//! `ReserveAssetTransferDeposited` message but that will but the intension will be to support this
|
||||
//! soon.
|
||||
use super::{
|
||||
AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances,
|
||||
ForeignAssets, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent,
|
||||
RuntimeOrigin, WeightToFee, XcmpQueue,
|
||||
AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Authorship, Balance,
|
||||
Balances, ForeignAssets, ForeignAssetsInstance, NonZeroIssuance, ParachainInfo,
|
||||
ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee,
|
||||
XcmpQueue,
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
use frame_support::{
|
||||
parameter_types,
|
||||
traits::{
|
||||
fungibles::{self, Balanced, Credit},
|
||||
ConstU32, Contains, ContainsPair, Everything, Get, Nothing,
|
||||
},
|
||||
traits::{ConstU32, Contains, ContainsPair, Everything, EverythingBut, Get, Nothing},
|
||||
weights::Weight,
|
||||
};
|
||||
use frame_system::EnsureRoot;
|
||||
use pallet_asset_tx_payment::HandleCredit;
|
||||
use pallet_assets::Instance1;
|
||||
use pallet_xcm::XcmPassthrough;
|
||||
use parachains_common::xcm_config::AssetFeeAsExistentialDepositMultiplier;
|
||||
use polkadot_parachain_primitives::primitives::Sibling;
|
||||
use polkadot_runtime_common::impls::ToAuthor;
|
||||
use sp_runtime::traits::Zero;
|
||||
use sp_runtime::traits::ConvertInto;
|
||||
use xcm::latest::prelude::*;
|
||||
use xcm_builder::{
|
||||
AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses,
|
||||
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex,
|
||||
ConvertedConcreteId, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor,
|
||||
FungibleAdapter, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, NoChecking,
|
||||
ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
|
||||
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
|
||||
SovereignSignedViaLocation, StartsWith, TakeWeightCredit, TrailingSetTopicAsId,
|
||||
UsingComponents, WithComputedOrigin, WithUniqueTopic,
|
||||
AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
|
||||
AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, EnsureXcmOrigin,
|
||||
FixedWeightBounds, FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, IsConcrete,
|
||||
LocalMint, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
|
||||
SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
|
||||
SignedToAccountId32, SovereignSignedViaLocation, StartsWith, TakeWeightCredit,
|
||||
TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic,
|
||||
};
|
||||
use xcm_executor::{traits::JustTry, XcmExecutor};
|
||||
|
||||
parameter_types! {
|
||||
pub const RelayLocation: Location = Location::parent();
|
||||
// Local native currency which is stored in `pallet_balances``
|
||||
pub const PenpalNativeCurrency: Location = Location::here();
|
||||
pub const RelayNetwork: Option<NetworkId> = None;
|
||||
pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
|
||||
pub UniversalLocation: InteriorLocation = [Parachain(ParachainInfo::parachain_id().into())].into();
|
||||
@@ -80,7 +78,7 @@ pub type CurrencyTransactor = FungibleAdapter<
|
||||
// Use this currency:
|
||||
Balances,
|
||||
// Use this currency when it is a fungible asset matching the given location or name:
|
||||
IsConcrete<RelayLocation>,
|
||||
IsConcrete<PenpalNativeCurrency>,
|
||||
// Do a simple punn to convert an AccountId32 Location into a native chain account ID:
|
||||
LocationToAccountId,
|
||||
// Our chain's account ID type (we can't get away without mentioning it explicitly):
|
||||
@@ -123,9 +121,16 @@ pub type FungiblesTransactor = FungiblesAdapter<
|
||||
CheckingAccount,
|
||||
>;
|
||||
|
||||
/// `AssetId/Balance` converter for `TrustBackedAssets`
|
||||
pub type ForeignAssetsConvertedConcreteId =
|
||||
assets_common::ForeignAssetsConvertedConcreteId<StartsWith<RelayLocation>, Balance>;
|
||||
pub type ForeignAssetsConvertedConcreteId = assets_common::LocationConvertedConcreteId<
|
||||
EverythingBut<(
|
||||
// Here we rely on fact that something like this works:
|
||||
// assert!(Location::new(1,
|
||||
// [Parachain(100)]).starts_with(&Location::parent()));
|
||||
// assert!([Parachain(100)].into().starts_with(&Here));
|
||||
StartsWith<assets_common::matching::LocalLocationPattern>,
|
||||
)>,
|
||||
Balance,
|
||||
>;
|
||||
|
||||
/// Means for transacting foreign assets from different global consensus.
|
||||
pub type ForeignFungiblesTransactor = FungiblesAdapter<
|
||||
@@ -175,6 +180,7 @@ parameter_types! {
|
||||
pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024);
|
||||
pub const MaxInstructions: u32 = 100;
|
||||
pub const MaxAssetsIntoHolding: u32 = 64;
|
||||
pub XcmAssetFeesReceiver: Option<AccountId> = Authorship::author();
|
||||
}
|
||||
|
||||
pub struct ParentOrParentsExecutivePlurality;
|
||||
@@ -184,13 +190,6 @@ impl Contains<Location> for ParentOrParentsExecutivePlurality {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CommonGoodAssetsParachain;
|
||||
impl Contains<Location> for CommonGoodAssetsParachain {
|
||||
fn contains(location: &Location) -> bool {
|
||||
matches!(location.unpack(), (1, [Parachain(1000)]))
|
||||
}
|
||||
}
|
||||
|
||||
pub type Barrier = TrailingSetTopicAsId<(
|
||||
TakeWeightCredit,
|
||||
// Expected responses are OK.
|
||||
@@ -201,12 +200,6 @@ pub type Barrier = TrailingSetTopicAsId<(
|
||||
// If the message is one that immediately attempts to pay for execution, then
|
||||
// allow it.
|
||||
AllowTopLevelPaidExecutionFrom<Everything>,
|
||||
// System Assets parachain, parent and its exec plurality get free
|
||||
// execution
|
||||
AllowExplicitUnpaidExecutionFrom<(
|
||||
CommonGoodAssetsParachain,
|
||||
ParentOrParentsExecutivePlurality,
|
||||
)>,
|
||||
// Subscriptions for version tracking are OK.
|
||||
AllowSubscriptionsFrom<Everything>,
|
||||
),
|
||||
@@ -246,53 +239,30 @@ impl<T: Get<Location>> ContainsPair<Asset, Location> for NativeAssetFrom<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow checking in assets that have issuance > 0.
|
||||
pub struct NonZeroIssuance<AccountId, Assets>(PhantomData<(AccountId, Assets)>);
|
||||
impl<AccountId, Assets> Contains<<Assets as fungibles::Inspect<AccountId>>::AssetId>
|
||||
for NonZeroIssuance<AccountId, Assets>
|
||||
where
|
||||
Assets: fungibles::Inspect<AccountId>,
|
||||
{
|
||||
fn contains(id: &<Assets as fungibles::Inspect<AccountId>>::AssetId) -> bool {
|
||||
!Assets::total_issuance(id.clone()).is_zero()
|
||||
}
|
||||
}
|
||||
|
||||
/// A `HandleCredit` implementation that naively transfers the fees to the block author.
|
||||
/// Will drop and burn the assets in case the transfer fails.
|
||||
pub struct AssetsToBlockAuthor<R>(PhantomData<R>);
|
||||
impl<R> HandleCredit<AccountIdOf<R>, pallet_assets::Pallet<R, Instance1>> for AssetsToBlockAuthor<R>
|
||||
where
|
||||
R: pallet_authorship::Config + pallet_assets::Config<Instance1>,
|
||||
AccountIdOf<R>: From<polkadot_primitives::AccountId> + Into<polkadot_primitives::AccountId>,
|
||||
{
|
||||
fn handle_credit(credit: Credit<AccountIdOf<R>, pallet_assets::Pallet<R, Instance1>>) {
|
||||
if let Some(author) = pallet_authorship::Pallet::<R>::author() {
|
||||
// In case of error: Will drop the result triggering the `OnDrop` of the imbalance.
|
||||
let _ = pallet_assets::Pallet::<R, Instance1>::resolve(&author, credit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This asset can be added to AH as Asset and reserved transfer between Penpal and AH
|
||||
pub const RESERVABLE_ASSET_ID: u32 = 1;
|
||||
// This asset can be added to AH as ForeignAsset and teleported between Penpal and AH
|
||||
pub const TELEPORTABLE_ASSET_ID: u32 = 2;
|
||||
|
||||
pub const ASSETS_PALLET_ID: u8 = 50;
|
||||
pub const ASSET_HUB_ID: u32 = 1000;
|
||||
|
||||
parameter_types! {
|
||||
/// The location that this chain recognizes as the Relay network's Asset Hub.
|
||||
pub SystemAssetHubLocation: Location = Location::new(1, [Parachain(1000)]);
|
||||
// ALWAYS ensure that the index in PalletInstance stays up-to-date with
|
||||
pub SystemAssetHubLocation: Location = Location::new(1, [Parachain(ASSET_HUB_ID)]);
|
||||
// the Relay Chain's Asset Hub's Assets pallet index
|
||||
pub SystemAssetHubAssetsPalletLocation: Location =
|
||||
Location::new(1, [Parachain(1000), PalletInstance(50)]);
|
||||
Location::new(1, [Parachain(ASSET_HUB_ID), PalletInstance(ASSETS_PALLET_ID)]);
|
||||
pub AssetsPalletLocation: Location =
|
||||
Location::new(0, [PalletInstance(50)]);
|
||||
Location::new(0, [PalletInstance(ASSETS_PALLET_ID)]);
|
||||
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
|
||||
pub LocalTeleportableToAssetHub: Location = Location::new(
|
||||
0,
|
||||
[PalletInstance(50), GeneralIndex(TELEPORTABLE_ASSET_ID.into())]
|
||||
[PalletInstance(ASSETS_PALLET_ID), GeneralIndex(TELEPORTABLE_ASSET_ID.into())]
|
||||
);
|
||||
pub LocalTeleportableToAssetHubV3: xcm::v3::Location = xcm::v3::Location::new(
|
||||
0,
|
||||
[xcm::v3::Junction::PalletInstance(50), xcm::v3::Junction::GeneralIndex(TELEPORTABLE_ASSET_ID.into())]
|
||||
pub LocalReservableFromAssetHub: Location = Location::new(
|
||||
1,
|
||||
[Parachain(ASSET_HUB_ID), PalletInstance(ASSETS_PALLET_ID), GeneralIndex(RESERVABLE_ASSET_ID.into())]
|
||||
);
|
||||
|
||||
/// The Penpal runtime is utilized for testing with various environment setups.
|
||||
@@ -337,8 +307,22 @@ impl xcm_executor::Config for XcmConfig {
|
||||
type UniversalLocation = UniversalLocation;
|
||||
type Barrier = Barrier;
|
||||
type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
|
||||
type Trader =
|
||||
UsingComponents<WeightToFee, RelayLocation, AccountId, Balances, ToAuthor<Runtime>>;
|
||||
type Trader = (
|
||||
UsingComponents<WeightToFee, RelayLocation, AccountId, Balances, ToAuthor<Runtime>>,
|
||||
// This trader allows to pay with `is_sufficient=true` "Foreign" assets from dedicated
|
||||
// `pallet_assets` instance - `ForeignAssets`.
|
||||
cumulus_primitives_utility::TakeFirstAssetTrader<
|
||||
AccountId,
|
||||
ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger,
|
||||
ForeignAssetsConvertedConcreteId,
|
||||
ForeignAssets,
|
||||
cumulus_primitives_utility::XcmFeesTo32ByteAccount<
|
||||
ForeignFungiblesTransactor,
|
||||
AccountId,
|
||||
XcmAssetFeesReceiver,
|
||||
>,
|
||||
>,
|
||||
);
|
||||
type ResponseHandler = PolkadotXcm;
|
||||
type AssetTrap = PolkadotXcm;
|
||||
type AssetClaims = PolkadotXcm;
|
||||
@@ -356,6 +340,15 @@ impl xcm_executor::Config for XcmConfig {
|
||||
type TransactionalProcessor = FrameTransactionalProcessor;
|
||||
}
|
||||
|
||||
/// Multiplier used for dedicated `TakeFirstAssetTrader` with `ForeignAssets` instance.
|
||||
pub type ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger =
|
||||
AssetFeeAsExistentialDepositMultiplier<
|
||||
Runtime,
|
||||
WeightToFee,
|
||||
pallet_assets::BalanceToAssetBalance<Balances, Runtime, ConvertInto, ForeignAssetsInstance>,
|
||||
ForeignAssetsInstance,
|
||||
>;
|
||||
|
||||
/// No local origins on this chain are allowed to dispatch XCM sends/executions.
|
||||
pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user