1use super::{
26 AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Authorship, Balance,
27 Balances, CollatorSelection, ForeignAssets, ForeignAssetsInstance, NonZeroIssuance,
28 ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
29 WeightToFee, XcmpQueue,
30};
31use crate::{BaseDeliveryFee, FeeAssetId, TransactionByteFee};
32use assets_common::TrustBackedAssetsAsLocation;
33use core::marker::PhantomData;
34use frame_support::{
35 parameter_types,
36 traits::{
37 tokens::imbalance::ResolveAssetTo, ConstU32, Contains, ContainsPair, Everything,
38 EverythingBut, Get, Nothing, PalletInfoAccess,
39 },
40 weights::Weight,
41};
42use frame_system::EnsureRoot;
43use pallet_xcm::XcmPassthrough;
44use parachains_common::{xcm_config::AssetFeeAsExistentialDepositMultiplier, TREASURY_PALLET_ID};
45use polkadot_parachain_primitives::primitives::Sibling;
46use polkadot_runtime_common::{impls::ToAuthor, xcm_sender::ExponentialPrice};
47use snowbridge_router_primitives::inbound::EthereumLocationsConverterFor;
48use sp_runtime::traits::{AccountIdConversion, ConvertInto, Identity, TryConvertInto};
49use xcm::latest::{prelude::*, WESTEND_GENESIS_HASH};
50use xcm_builder::{
51 AccountId32Aliases, AliasOriginRootUsingFilter, AllowHrmpNotificationsFromRelayChain,
52 AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
53 AsPrefixedGeneralIndex, ConvertedConcreteId, DescribeAllTerminal, DescribeFamily,
54 EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, FungibleAdapter,
55 FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete,
56 LocalMint, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
57 SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
58 SignedAccountId32AsNative, SignedToAccountId32, SingleAssetExchangeAdapter,
59 SovereignSignedViaLocation, StartsWith, TakeWeightCredit, TrailingSetTopicAsId,
60 UsingComponents, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
61};
62use xcm_executor::{traits::JustTry, XcmExecutor};
63
64parameter_types! {
65 pub const RelayLocation: Location = Location::parent();
66 pub const PenpalNativeCurrency: Location = Location::here();
68 pub storage RelayNetworkId: NetworkId = NetworkId::ByGenesis(WESTEND_GENESIS_HASH);
72 pub RelayNetwork: Option<NetworkId> = Some(RelayNetworkId::get());
73 pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
74 pub UniversalLocation: InteriorLocation = [
75 GlobalConsensus(RelayNetworkId::get()),
76 Parachain(ParachainInfo::parachain_id().into())
77 ].into();
78 pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
79 pub StakingPot: AccountId = CollatorSelection::account_id();
80 pub TrustBackedAssetsPalletIndex: u8 = <Assets as PalletInfoAccess>::index() as u8;
81 pub TrustBackedAssetsPalletLocation: Location =
82 PalletInstance(TrustBackedAssetsPalletIndex::get()).into();
83}
84
85pub type LocationToAccountId = (
89 ParentIsPreset<AccountId>,
91 SiblingParachainConvertsVia<Sibling, AccountId>,
93 AccountId32Aliases<RelayNetwork, AccountId>,
95 HashedDescription<AccountId, DescribeFamily<DescribeAllTerminal>>,
97 GlobalConsensusParachainConvertsFor<UniversalLocation, AccountId>,
100 EthereumLocationsConverterFor<AccountId>,
103);
104
105pub type FungibleTransactor = FungibleAdapter<
107 Balances,
109 IsConcrete<PenpalNativeCurrency>,
111 LocationToAccountId,
113 AccountId,
115 (),
117>;
118
119pub type FungiblesTransactor = FungiblesAdapter<
121 Assets,
123 (
125 ConvertedConcreteId<
126 AssetIdPalletAssets,
127 Balance,
128 AsPrefixedGeneralIndex<AssetsPalletLocation, AssetIdPalletAssets, JustTry>,
129 JustTry,
130 >,
131 ConvertedConcreteId<
132 AssetIdPalletAssets,
133 Balance,
134 AsPrefixedGeneralIndex<
135 SystemAssetHubAssetsPalletLocation,
136 AssetIdPalletAssets,
137 JustTry,
138 >,
139 JustTry,
140 >,
141 ),
142 LocationToAccountId,
144 AccountId,
146 LocalMint<NonZeroIssuance<AccountId, Assets>>,
149 CheckingAccount,
151>;
152
153pub type ForeignAssetsAssetId = Location;
155pub type ForeignAssetsConvertedConcreteId = xcm_builder::MatchedConvertedConcreteId<
156 Location,
157 Balance,
158 EverythingBut<(
159 StartsWith<assets_common::matching::LocalLocationPattern>,
164 )>,
165 Identity,
166 TryConvertInto,
167>;
168
169pub type ForeignFungiblesTransactor = FungiblesAdapter<
171 ForeignAssets,
173 ForeignAssetsConvertedConcreteId,
175 LocationToAccountId,
177 AccountId,
179 NoChecking,
181 CheckingAccount,
183>;
184
185pub type AssetTransactors = (FungibleTransactor, ForeignFungiblesTransactor, FungiblesTransactor);
187
188pub type XcmOriginToTransactDispatchOrigin = (
192 SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
196 RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
199 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
202 ParentAsSuperuser<RuntimeOrigin>,
205 SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
208 XcmPassthrough<RuntimeOrigin>,
210);
211
212parameter_types! {
213 pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024);
215 pub const MaxInstructions: u32 = 100;
216 pub const MaxAssetsIntoHolding: u32 = 64;
217 pub XcmAssetFeesReceiver: Option<AccountId> = Authorship::author();
218}
219
220pub struct ParentOrParentsExecutivePlurality;
221impl Contains<Location> for ParentOrParentsExecutivePlurality {
222 fn contains(location: &Location) -> bool {
223 matches!(location.unpack(), (1, []) | (1, [Plurality { id: BodyId::Executive, .. }]))
224 }
225}
226
227pub type Barrier = TrailingSetTopicAsId<(
228 TakeWeightCredit,
229 AllowKnownQueryResponses<PolkadotXcm>,
231 WithComputedOrigin<
233 (
234 AllowTopLevelPaidExecutionFrom<Everything>,
237 AllowSubscriptionsFrom<Everything>,
239 AllowHrmpNotificationsFromRelayChain,
241 ),
242 UniversalLocation,
243 ConstU32<8>,
244 >,
245)>;
246
247pub type AccountIdOf<R> = <R as frame_system::Config>::AccountId;
249
250pub struct AssetPrefixFrom<Prefix, Origin>(PhantomData<(Prefix, Origin)>);
252impl<Prefix, Origin> ContainsPair<Asset, Location> for AssetPrefixFrom<Prefix, Origin>
253where
254 Prefix: Get<Location>,
255 Origin: Get<Location>,
256{
257 fn contains(asset: &Asset, origin: &Location) -> bool {
258 let loc = Origin::get();
259 &loc == origin &&
260 matches!(asset, Asset { id: AssetId(asset_loc), fun: Fungible(_a) }
261 if asset_loc.starts_with(&Prefix::get()))
262 }
263}
264
265type AssetsFrom<T> = AssetPrefixFrom<T, T>;
266
267pub struct NativeAssetFrom<T>(PhantomData<T>);
269impl<T: Get<Location>> ContainsPair<Asset, Location> for NativeAssetFrom<T> {
270 fn contains(asset: &Asset, origin: &Location) -> bool {
271 let loc = T::get();
272 &loc == origin &&
273 matches!(asset, Asset { id: AssetId(asset_loc), fun: Fungible(_a) }
274 if *asset_loc == Location::from(Parent))
275 }
276}
277
278pub const RESERVABLE_ASSET_ID: u32 = 1;
280pub const TELEPORTABLE_ASSET_ID: u32 = 2;
282
283pub const ASSETS_PALLET_ID: u8 = 50;
284pub const ASSET_HUB_ID: u32 = 1000;
285
286pub const USDT_ASSET_ID: u128 = 1984;
287
288parameter_types! {
289 pub SystemAssetHubLocation: Location = Location::new(1, [Parachain(ASSET_HUB_ID)]);
291 pub SystemAssetHubAssetsPalletLocation: Location =
293 Location::new(1, [Parachain(ASSET_HUB_ID), PalletInstance(ASSETS_PALLET_ID)]);
294 pub AssetsPalletLocation: Location =
295 Location::new(0, [PalletInstance(ASSETS_PALLET_ID)]);
296 pub CheckingAccount: AccountId = PolkadotXcm::check_account();
297 pub LocalTeleportableToAssetHub: Location = Location::new(
298 0,
299 [PalletInstance(ASSETS_PALLET_ID), GeneralIndex(TELEPORTABLE_ASSET_ID.into())]
300 );
301 pub LocalReservableFromAssetHub: Location = Location::new(
302 1,
303 [Parachain(ASSET_HUB_ID), PalletInstance(ASSETS_PALLET_ID), GeneralIndex(RESERVABLE_ASSET_ID.into())]
304 );
305 pub UsdtFromAssetHub: Location = Location::new(
306 1,
307 [Parachain(ASSET_HUB_ID), PalletInstance(ASSETS_PALLET_ID), GeneralIndex(USDT_ASSET_ID)],
308 );
309
310 pub storage CustomizableAssetFromSystemAssetHub: Location = SystemAssetHubLocation::get();
316}
317
318pub struct AssetFromChain<AssetLocation, Origin>(PhantomData<(AssetLocation, Origin)>);
320impl<AssetLocation: Get<Location>, Origin: Get<Location>> ContainsPair<Asset, Location>
321 for AssetFromChain<AssetLocation, Origin>
322{
323 fn contains(asset: &Asset, origin: &Location) -> bool {
324 log::trace!(target: "xcm::contains", "AssetFromChain asset: {:?}, origin: {:?}", asset, origin);
325 *origin == Origin::get() &&
326 matches!(asset.id.clone(), AssetId(id) if id == AssetLocation::get())
327 }
328}
329
330pub type TrustedReserves = (
331 NativeAsset,
332 AssetsFrom<SystemAssetHubLocation>,
333 NativeAssetFrom<SystemAssetHubLocation>,
334 AssetPrefixFrom<CustomizableAssetFromSystemAssetHub, SystemAssetHubLocation>,
335);
336pub type TrustedTeleporters =
337 (AssetFromChain<LocalTeleportableToAssetHub, SystemAssetHubLocation>,);
338
339pub type TrustBackedAssetsConvertedConcreteId =
341 assets_common::TrustBackedAssetsConvertedConcreteId<AssetsPalletLocation, Balance>;
342
343pub type PoolAssetsExchanger = SingleAssetExchangeAdapter<
348 crate::AssetConversion,
349 crate::NativeAndAssets,
350 (
351 TrustBackedAssetsAsLocation<
352 TrustBackedAssetsPalletLocation,
353 Balance,
354 xcm::latest::Location,
355 >,
356 ForeignAssetsConvertedConcreteId,
357 ),
358 AccountId,
359>;
360
361pub struct XcmConfig;
362impl xcm_executor::Config for XcmConfig {
363 type RuntimeCall = RuntimeCall;
364 type XcmSender = XcmRouter;
365 type AssetTransactor = AssetTransactors;
367 type OriginConverter = XcmOriginToTransactDispatchOrigin;
368 type IsReserve = TrustedReserves;
369 type IsTeleporter = TrustedTeleporters;
371 type UniversalLocation = UniversalLocation;
372 type Barrier = Barrier;
373 type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
374 type Trader = (
375 UsingComponents<WeightToFee, RelayLocation, AccountId, Balances, ToAuthor<Runtime>>,
376 cumulus_primitives_utility::SwapFirstAssetTrader<
377 RelayLocation,
378 crate::AssetConversion,
379 WeightToFee,
380 crate::NativeAndAssets,
381 (
382 TrustBackedAssetsAsLocation<
383 TrustBackedAssetsPalletLocation,
384 Balance,
385 xcm::latest::Location,
386 >,
387 ForeignAssetsConvertedConcreteId,
388 ),
389 ResolveAssetTo<StakingPot, crate::NativeAndAssets>,
390 AccountId,
391 >,
392 );
393 type ResponseHandler = PolkadotXcm;
394 type AssetTrap = PolkadotXcm;
395 type AssetClaims = PolkadotXcm;
396 type SubscriptionService = PolkadotXcm;
397 type PalletInstancesInfo = AllPalletsWithSystem;
398 type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
399 type AssetLocker = ();
400 type AssetExchanger = PoolAssetsExchanger;
401 type FeeManager = XcmFeeManagerFromComponents<
402 (),
403 SendXcmFeeToAccount<Self::AssetTransactor, TreasuryAccount>,
404 >;
405 type MessageExporter = ();
406 type UniversalAliases = Nothing;
407 type CallDispatcher = RuntimeCall;
408 type SafeCallFilter = Everything;
409 type Aliasers = AliasOriginRootUsingFilter<SystemAssetHubLocation, Everything>;
411 type TransactionalProcessor = FrameTransactionalProcessor;
412 type HrmpNewChannelOpenRequestHandler = ();
413 type HrmpChannelAcceptedHandler = ();
414 type HrmpChannelClosingHandler = ();
415 type XcmRecorder = PolkadotXcm;
416}
417
418pub type ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger =
420 AssetFeeAsExistentialDepositMultiplier<
421 Runtime,
422 WeightToFee,
423 pallet_assets::BalanceToAssetBalance<Balances, Runtime, ConvertInto, ForeignAssetsInstance>,
424 ForeignAssetsInstance,
425 >;
426
427pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
429
430pub type PriceForParentDelivery =
431 ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, ParachainSystem>;
432
433pub type XcmRouter = WithUniqueTopic<(
436 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, PolkadotXcm, PriceForParentDelivery>,
438 XcmpQueue,
440)>;
441
442impl pallet_xcm::Config for Runtime {
443 type RuntimeEvent = RuntimeEvent;
444 type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
445 type XcmRouter = XcmRouter;
446 type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
447 type XcmExecuteFilter = Everything;
448 type XcmExecutor = XcmExecutor<XcmConfig>;
449 type XcmTeleportFilter = Everything;
450 type XcmReserveTransferFilter = Everything;
451 type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
452 type UniversalLocation = UniversalLocation;
453 type RuntimeOrigin = RuntimeOrigin;
454 type RuntimeCall = RuntimeCall;
455
456 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
457 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
459 type Currency = Balances;
460 type CurrencyMatcher = ();
461 type TrustedLockers = ();
462 type SovereignAccountOf = LocationToAccountId;
463 type MaxLockers = ConstU32<8>;
464 type WeightInfo = pallet_xcm::TestWeightInfo;
465 type AdminOrigin = EnsureRoot<AccountId>;
466 type MaxRemoteLockConsumers = ConstU32<0>;
467 type RemoteLockConsumerIdentifier = ();
468}
469
470impl cumulus_pallet_xcm::Config for Runtime {
471 type RuntimeEvent = RuntimeEvent;
472 type XcmExecutor = XcmExecutor<XcmConfig>;
473}
474
475pub struct XcmBenchmarkHelper;
477#[cfg(feature = "runtime-benchmarks")]
478impl pallet_assets::BenchmarkHelper<ForeignAssetsAssetId> for XcmBenchmarkHelper {
479 fn create_asset_id_parameter(id: u32) -> ForeignAssetsAssetId {
480 Location::new(1, [Parachain(id)])
481 }
482}