1use super::{
38 AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, CollatorSelection,
39 ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent,
40 RuntimeHoldReason, RuntimeOrigin, WeightToFee, XcmpQueue,
41};
42use crate::{BaseDeliveryFee, FeeAssetId, TransactionByteFee};
43use core::marker::PhantomData;
44use frame_support::{
45 parameter_types,
46 traits::{
47 fungible::HoldConsideration, tokens::imbalance::ResolveAssetTo, ConstU32, Contains,
48 ContainsPair, Equals, Everything, EverythingBut, Get, LinearStoragePrice, Nothing,
49 PalletInfoAccess,
50 },
51 weights::Weight,
52};
53use frame_system::EnsureRoot;
54use pallet_xcm::{AuthorizedAliasers, XcmPassthrough};
55use parachains_common::{
56 impls::NonZeroIssuance, xcm_config::ConcreteAssetFromSystem, TREASURY_PALLET_ID,
57};
58use polkadot_parachain_primitives::primitives::Sibling;
59use polkadot_runtime_common::{impls::ToAuthor, xcm_sender::ExponentialPrice};
60use sp_runtime::traits::{AccountIdConversion, Identity, TryConvertInto};
61use testnet_parachains_constants::westend::currency::deposit;
62use xcm::latest::{prelude::*, WESTEND_GENESIS_HASH};
63use xcm_builder::{
64 AccountId32Aliases, AliasChildLocation, AliasOriginRootUsingFilter,
65 AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
66 AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
67 DescribeAllTerminal, DescribeFamily, DescribeTerminus, EnsureXcmOrigin,
68 ExternalConsensusLocationsConverterFor, FixedWeightBounds, FrameTransactionalProcessor,
69 FungibleAdapter, FungiblesAdapter, HashedDescription, IsConcrete, LocalMint, NativeAsset,
70 NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SendXcmFeeToAccount,
71 SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
72 SignedToAccountId32, SingleAssetExchangeAdapter, SovereignSignedViaLocation, StartsWith,
73 TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic,
74 XcmFeeManagerFromComponents,
75};
76use xcm_executor::XcmExecutor;
77
78parameter_types! {
79 pub const RelayLocation: Location = Location::parent();
80 pub const PenpalNativeCurrency: Location = Location::here();
82 pub storage RelayNetworkId: NetworkId = NetworkId::ByGenesis(WESTEND_GENESIS_HASH);
86 pub RelayNetwork: Option<NetworkId> = Some(RelayNetworkId::get());
87 pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
88 pub UniversalLocation: InteriorLocation = [
89 GlobalConsensus(RelayNetworkId::get()),
90 Parachain(ParachainInfo::parachain_id().into())
91 ].into();
92 pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
93 pub StakingPot: AccountId = CollatorSelection::account_id();
94 pub AssetsPalletIndex: u8 = <Assets as PalletInfoAccess>::index() as u8;
95 pub AssetsPalletLocation: Location =
96 PalletInstance(AssetsPalletIndex::get()).into();
97}
98
99pub type LocationToAccountId = (
103 ParentIsPreset<AccountId>,
105 SiblingParachainConvertsVia<Sibling, AccountId>,
107 AccountId32Aliases<RelayNetwork, AccountId>,
109 HashedDescription<AccountId, (DescribeTerminus, DescribeFamily<DescribeAllTerminal>)>,
111 ExternalConsensusLocationsConverterFor<UniversalLocation, AccountId>,
113);
114
115pub type FungibleTransactor = FungibleAdapter<
117 Balances,
119 IsConcrete<PenpalNativeCurrency>,
121 LocationToAccountId,
123 AccountId,
125 (),
127>;
128
129pub type LocalFungiblesTransactor = FungiblesAdapter<
132 Assets,
134 LocalAssetsConvertedConcreteId,
136 LocationToAccountId,
138 AccountId,
140 LocalMint<NonZeroIssuance<AccountId, Assets>>,
143 CheckingAccount,
145>;
146
147pub type AssetsAssetId = Location;
149pub type ForeignAssetsConvertedConcreteId = xcm_builder::MatchedConvertedConcreteId<
150 Location,
151 Balance,
152 EverythingBut<(
153 StartsWith<assets_common::matching::LocalLocationPattern>,
158 )>,
159 Identity,
160 TryConvertInto,
161>;
162
163pub type LocalAssetsConvertedConcreteId = xcm_builder::MatchedConvertedConcreteId<
164 Location,
165 Balance,
166 (
168 StartsWith<assets_common::matching::LocalLocationPattern>,
173 ),
174 Identity,
175 TryConvertInto,
176>;
177
178pub type ForeignFungiblesTransactor = FungiblesAdapter<
180 Assets,
182 ForeignAssetsConvertedConcreteId,
184 LocationToAccountId,
186 AccountId,
188 NoChecking,
190 CheckingAccount,
192>;
193
194pub type AssetTransactors =
196 (FungibleTransactor, ForeignFungiblesTransactor, LocalFungiblesTransactor);
197
198pub type XcmOriginToTransactDispatchOrigin = (
202 SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
206 RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
209 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
212 ParentAsSuperuser<RuntimeOrigin>,
215 SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
218 XcmPassthrough<RuntimeOrigin>,
220);
221
222parameter_types! {
223 pub const RootLocation: Location = Location::here();
224 pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024);
226 pub const MaxInstructions: u32 = 100;
227 pub const MaxAssetsIntoHolding: u32 = 64;
228 pub XcmAssetFeesReceiver: Option<AccountId> = Authorship::author();
229}
230
231pub struct ParentOrParentsExecutivePlurality;
232impl Contains<Location> for ParentOrParentsExecutivePlurality {
233 fn contains(location: &Location) -> bool {
234 matches!(location.unpack(), (1, []) | (1, [Plurality { id: BodyId::Executive, .. }]))
235 }
236}
237
238pub type Barrier = TrailingSetTopicAsId<(
239 TakeWeightCredit,
240 AllowKnownQueryResponses<PolkadotXcm>,
242 WithComputedOrigin<
244 (
245 AllowTopLevelPaidExecutionFrom<Everything>,
248 AllowExplicitUnpaidExecutionFrom<(ParentOrParentsExecutivePlurality,)>,
250 AllowSubscriptionsFrom<Everything>,
252 AllowHrmpNotificationsFromRelayChain,
254 ),
255 UniversalLocation,
256 ConstU32<8>,
257 >,
258)>;
259
260pub type AccountIdOf<R> = <R as frame_system::Config>::AccountId;
262
263pub struct AssetPrefixFrom<Prefix, Origin>(PhantomData<(Prefix, Origin)>);
265impl<Prefix, Origin> ContainsPair<Asset, Location> for AssetPrefixFrom<Prefix, Origin>
266where
267 Prefix: Get<Location>,
268 Origin: Get<Location>,
269{
270 fn contains(asset: &Asset, origin: &Location) -> bool {
271 let loc = Origin::get();
272 &loc == origin &&
273 matches!(asset, Asset { id: AssetId(asset_loc), fun: Fungible(_a) }
274 if asset_loc.starts_with(&Prefix::get()))
275 }
276}
277
278type AssetsFrom<T> = AssetPrefixFrom<T, T>;
279
280pub const RESERVABLE_ASSET_ID: u32 = 1;
282pub const PEN2_TELEPORTABLE_GENERAL_INDEX: u32 = 2;
284
285pub const ASSET_HUB_ASSETS_PALLET_ID: u8 = 50;
286pub const ASSET_HUB_ID: u32 = 1000;
287
288pub const PENPAL_ASSETS_PALLET_ID: u8 = 50;
289
290pub const USDT_ASSET_ID: u128 = 1984;
291
292pub const SEPOLIA_ID: u64 = 11155111;
293pub const ETHER_MIN_BALANCE: u128 = 1000;
295pub const USDT_ED: Balance = 70_000;
296
297parameter_types! {
298 pub SystemAssetHubLocation: Location = Location::new(1, [Parachain(ASSET_HUB_ID)]);
300 pub SystemAssetHubAssetsPalletLocation: Location =
302 Location::new(1, [Parachain(ASSET_HUB_ID), PalletInstance(ASSET_HUB_ASSETS_PALLET_ID)]);
303 pub CheckingAccount: AccountId = PolkadotXcm::check_account();
304 pub LocalReservableFromAssetHub: Location = Location::new(
305 1,
306 [Parachain(ASSET_HUB_ID), PalletInstance(ASSET_HUB_ASSETS_PALLET_ID), GeneralIndex(RESERVABLE_ASSET_ID.into())]
307 );
308 pub UsdtFromAssetHub: Location = Location::new(
309 1,
310 [Parachain(ASSET_HUB_ID), PalletInstance(ASSET_HUB_ASSETS_PALLET_ID), GeneralIndex(USDT_ASSET_ID)],
311 );
312
313 pub EthFromEthereum: Location = Location::new(
314 2,
315 [GlobalConsensus(Ethereum { chain_id: SEPOLIA_ID})],
316 );
317
318 pub LocalPen2Asset: Location = Location::new(0, [PalletInstance(PENPAL_ASSETS_PALLET_ID), GeneralIndex(PEN2_TELEPORTABLE_GENERAL_INDEX.into())]);
320
321 pub storage CustomizableAssetFromSystemAssetHub: Location = SystemAssetHubLocation::get();
327 pub storage LocalTeleportableToAssetHub: Location = LocalPen2Asset::get();
328
329 pub const NativeAssetId: AssetId = AssetId(Location::here());
330 pub const NativeAssetFilter: AssetFilter = Wild(AllOf { fun: WildFungible, id: NativeAssetId::get() });
331 pub AssetHubTrustedTeleporter: (AssetFilter, Location) = (NativeAssetFilter::get(), SystemAssetHubLocation::get());
332}
333
334pub struct AssetFromChain<AssetLocation, Origin>(PhantomData<(AssetLocation, Origin)>);
336impl<AssetLocation: Get<Location>, Origin: Get<Location>> ContainsPair<Asset, Location>
337 for AssetFromChain<AssetLocation, Origin>
338{
339 fn contains(asset: &Asset, origin: &Location) -> bool {
340 tracing::trace!(target: "xcm::contains", ?asset, ?origin, "AssetFromChain");
341 *origin == Origin::get() &&
342 matches!(asset.id.clone(), AssetId(id) if id == AssetLocation::get())
343 }
344}
345
346pub type TrustedReserves = (
347 NativeAsset,
348 ConcreteAssetFromSystem<RelayLocation>,
349 AssetsFrom<SystemAssetHubLocation>,
350 AssetPrefixFrom<CustomizableAssetFromSystemAssetHub, SystemAssetHubLocation>,
351);
352
353pub type TrustedTeleporters = (
354 AssetFromChain<PenpalNativeCurrency, SystemAssetHubLocation>,
355 AssetFromChain<LocalTeleportableToAssetHub, SystemAssetHubLocation>,
356 xcm_builder::Case<AssetHubTrustedTeleporter>,
359);
360
361pub type TrustedAliasers = (
367 AliasChildLocation,
368 AliasOriginRootUsingFilter<SystemAssetHubLocation, Everything>,
369 AuthorizedAliasers<Runtime>,
370);
371
372pub type WaivedLocations = Equals<RootLocation>;
373
374pub type PoolAssetsExchanger = SingleAssetExchangeAdapter<
379 crate::AssetConversion,
380 crate::NativeAndAssets,
381 (LocalAssetsConvertedConcreteId, ForeignAssetsConvertedConcreteId),
382 AccountId,
383>;
384
385pub struct XcmConfig;
386impl xcm_executor::Config for XcmConfig {
387 type RuntimeCall = RuntimeCall;
388 type XcmSender = XcmRouter;
389 type XcmEventEmitter = PolkadotXcm;
390 type AssetTransactor = AssetTransactors;
392 type OriginConverter = XcmOriginToTransactDispatchOrigin;
393 type IsReserve = TrustedReserves;
394 type IsTeleporter = TrustedTeleporters;
396 type UniversalLocation = UniversalLocation;
397 type Barrier = Barrier;
398 type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
399 type Trader = (
400 UsingComponents<WeightToFee, PenpalNativeCurrency, AccountId, Balances, ToAuthor<Runtime>>,
402 cumulus_primitives_utility::SwapFirstAssetTrader<
405 PenpalNativeCurrency,
406 crate::AssetConversion,
407 WeightToFee,
408 crate::NativeAndAssets,
409 (LocalAssetsConvertedConcreteId, ForeignAssetsConvertedConcreteId),
410 ResolveAssetTo<StakingPot, crate::NativeAndAssets>,
411 AccountId,
412 >,
413 );
414 type ResponseHandler = PolkadotXcm;
415 type AssetTrap = PolkadotXcm;
416 type SubscriptionService = PolkadotXcm;
417 type PalletInstancesInfo = AllPalletsWithSystem;
418 type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
419 type AssetLocker = ();
420 type AssetExchanger = PoolAssetsExchanger;
421 type FeeManager = XcmFeeManagerFromComponents<
422 WaivedLocations,
423 SendXcmFeeToAccount<Self::AssetTransactor, TreasuryAccount>,
424 >;
425 type MessageExporter = ();
426 type UniversalAliases = Nothing;
427 type CallDispatcher = RuntimeCall;
428 type SafeCallFilter = Everything;
429 type Aliasers = TrustedAliasers;
430 type TransactionalProcessor = FrameTransactionalProcessor;
431 type HrmpNewChannelOpenRequestHandler = ();
432 type HrmpChannelAcceptedHandler = ();
433 type HrmpChannelClosingHandler = ();
434 type XcmRecorder = PolkadotXcm;
435}
436
437pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
440
441pub type PriceForParentDelivery =
442 ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, ParachainSystem>;
443
444pub type XcmRouter = WithUniqueTopic<(
447 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, PolkadotXcm, PriceForParentDelivery>,
449 XcmpQueue,
451)>;
452
453parameter_types! {
454 pub const DepositPerItem: Balance = deposit(1, 0);
455 pub const DepositPerByte: Balance = deposit(0, 1);
456 pub const AuthorizeAliasHoldReason: RuntimeHoldReason = RuntimeHoldReason::PolkadotXcm(pallet_xcm::HoldReason::AuthorizeAlias);
457}
458
459impl pallet_xcm::Config for Runtime {
460 type RuntimeEvent = RuntimeEvent;
461 type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
462 type XcmRouter = XcmRouter;
463 type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
464 type XcmExecuteFilter = Everything;
465 type XcmExecutor = XcmExecutor<XcmConfig>;
466 type XcmTeleportFilter = Everything;
467 type XcmReserveTransferFilter = Everything;
468 type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
469 type UniversalLocation = UniversalLocation;
470 type RuntimeOrigin = RuntimeOrigin;
471 type RuntimeCall = RuntimeCall;
472
473 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
474 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
476 type Currency = Balances;
477 type CurrencyMatcher = ();
478 type TrustedLockers = ();
479 type SovereignAccountOf = LocationToAccountId;
480 type MaxLockers = ConstU32<8>;
481 type WeightInfo = pallet_xcm::TestWeightInfo;
482 type AdminOrigin = EnsureRoot<AccountId>;
483 type MaxRemoteLockConsumers = ConstU32<0>;
484 type RemoteLockConsumerIdentifier = ();
485 type AuthorizedAliasConsideration = HoldConsideration<
487 AccountId,
488 Balances,
489 AuthorizeAliasHoldReason,
490 LinearStoragePrice<DepositPerItem, DepositPerByte, Balance>,
491 >;
492}
493
494impl cumulus_pallet_xcm::Config for Runtime {
495 type RuntimeEvent = RuntimeEvent;
496 type XcmExecutor = XcmExecutor<XcmConfig>;
497}