1use super::{
17 AccountId, AllPalletsWithSystem, Assets, Balance, Balances, BaseDeliveryFee, CollatorSelection,
18 FeeAssetId, ForeignAssets, ParachainInfo, ParachainSystem, PolkadotXcm, PoolAssets, Runtime,
19 RuntimeCall, RuntimeEvent, RuntimeHoldReason, RuntimeOrigin, ToWestendXcmRouter,
20 TransactionByteFee, Uniques, WeightToFee, XcmpQueue,
21};
22use assets_common::{
23 matching::{
24 FromNetwork, IsForeignConcreteAsset, NonTeleportableAssetFromTrustedReserve,
25 ParentLocation, TeleportableAssetWithTrustedReserve,
26 },
27 TrustBackedAssetsAsLocation,
28};
29use frame_support::{
30 parameter_types,
31 traits::{
32 fungible::HoldConsideration,
33 tokens::imbalance::{ResolveAssetTo, ResolveTo},
34 ConstU32, Contains, Equals, Everything, LinearStoragePrice, PalletInfoAccess,
35 },
36};
37use frame_system::EnsureRoot;
38use pallet_xcm::{AuthorizedAliasers, XcmPassthrough};
39use parachains_common::{
40 xcm_config::{
41 AllSiblingSystemParachains, ConcreteAssetFromSystem, ParentRelayOrSiblingParachains,
42 RelayOrOtherSystemParachains,
43 },
44 TREASURY_PALLET_ID,
45};
46use polkadot_parachain_primitives::primitives::Sibling;
47use polkadot_runtime_common::xcm_sender::ExponentialPrice;
48use rococo_runtime_constants::system_parachain::ASSET_HUB_ID;
49use sp_runtime::traits::{AccountIdConversion, TryConvertInto};
50use testnet_parachains_constants::rococo::snowbridge::{
51 EthereumNetwork, INBOUND_QUEUE_PALLET_INDEX,
52};
53use xcm::latest::{prelude::*, ROCOCO_GENESIS_HASH, WESTEND_GENESIS_HASH};
54use xcm_builder::{
55 unique_instances::UniqueInstancesAdapter, AccountId32Aliases, AliasChildLocation,
56 AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
57 AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
58 DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal,
59 DescribeFamily, EnsureXcmOrigin, ExternalConsensusLocationsConverterFor,
60 FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, HashedDescription, IsConcrete,
61 LocalMint, MatchInClassInstances, MatchedConvertedConcreteId, NetworkExportTableItem,
62 NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SendXcmFeeToAccount,
63 SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
64 SignedToAccountId32, SingleAssetExchangeAdapter, SovereignPaidRemoteExporter,
65 SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus, TakeWeightCredit,
66 TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin,
67 WithLatestLocationConverter, WithUniqueTopic, XcmFeeManagerFromComponents,
68};
69use xcm_executor::XcmExecutor;
70
71parameter_types! {
72 pub const RootLocation: Location = Location::here();
73 pub const TokenLocation: Location = Location::parent();
74 pub const RelayNetwork: NetworkId = NetworkId::ByGenesis(ROCOCO_GENESIS_HASH);
75 pub const AssetHubParaId: crate::ParaId = crate::ParaId::new(ASSET_HUB_ID);
76 pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
77 pub UniversalLocation: InteriorLocation =
78 [GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into())].into();
79 pub UniversalLocationNetworkId: NetworkId = UniversalLocation::get().global_consensus().unwrap();
80 pub TrustBackedAssetsPalletLocation: Location =
81 PalletInstance(TrustBackedAssetsPalletIndex::get()).into();
82 pub TrustBackedAssetsPalletIndex: u8 = <Assets as PalletInfoAccess>::index() as u8;
83 pub TrustBackedAssetsPalletLocationV3: xcm::v3::Location =
84 xcm::v3::Junction::PalletInstance(<Assets as PalletInfoAccess>::index() as u8).into();
85 pub PoolAssetsPalletLocationV3: xcm::v3::Location =
86 xcm::v3::Junction::PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
87 pub ForeignAssetsPalletLocation: Location =
88 PalletInstance(<ForeignAssets as PalletInfoAccess>::index() as u8).into();
89 pub PoolAssetsPalletLocation: Location =
90 PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
91 pub UniquesPalletLocation: Location =
92 PalletInstance(<Uniques as PalletInfoAccess>::index() as u8).into();
93 pub CheckingAccount: AccountId = PolkadotXcm::check_account();
94 pub const GovernanceLocation: Location = Location::parent();
95 pub StakingPot: AccountId = CollatorSelection::account_id();
96 pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
97 pub RelayTreasuryLocation: Location = (Parent, PalletInstance(rococo_runtime_constants::TREASURY_PALLET_ID)).into();
98}
99
100pub type LocationToAccountId = (
104 ParentIsPreset<AccountId>,
106 SiblingParachainConvertsVia<Sibling, AccountId>,
108 AccountId32Aliases<RelayNetwork, AccountId>,
110 HashedDescription<AccountId, DescribeFamily<DescribeAllTerminal>>,
112 ExternalConsensusLocationsConverterFor<UniversalLocation, AccountId>,
114);
115
116pub type FungibleTransactor = FungibleAdapter<
118 Balances,
120 IsConcrete<TokenLocation>,
122 LocationToAccountId,
124 AccountId,
126 (),
128>;
129
130pub type TrustBackedAssetsConvertedConcreteId =
132 assets_common::TrustBackedAssetsConvertedConcreteId<TrustBackedAssetsPalletLocation, Balance>;
133
134pub type FungiblesTransactor = FungiblesAdapter<
136 Assets,
138 TrustBackedAssetsConvertedConcreteId,
140 LocationToAccountId,
142 AccountId,
144 LocalMint<parachains_common::impls::NonZeroIssuance<AccountId, Assets>>,
147 CheckingAccount,
149>;
150
151pub type UniquesConvertedConcreteId =
153 assets_common::UniquesConvertedConcreteId<UniquesPalletLocation>;
154
155pub type UniquesTransactor = UniqueInstancesAdapter<
157 AccountId,
158 LocationToAccountId,
159 MatchInClassInstances<UniquesConvertedConcreteId>,
160 pallet_uniques::asset_ops::Item<Uniques>,
161>;
162
163pub type ForeignAssetsConvertedConcreteId = assets_common::ForeignAssetsConvertedConcreteId<
165 (
166 StartsWith<TrustBackedAssetsPalletLocation>,
168 StartsWithExplicitGlobalConsensus<UniversalLocationNetworkId>,
174 ),
175 Balance,
176 xcm::v5::Location,
177>;
178
179pub type ForeignFungiblesTransactor = FungiblesAdapter<
181 ForeignAssets,
183 ForeignAssetsConvertedConcreteId,
185 LocationToAccountId,
187 AccountId,
189 NoChecking,
191 CheckingAccount,
193>;
194
195pub type PoolAssetsConvertedConcreteId =
197 assets_common::PoolAssetsConvertedConcreteId<PoolAssetsPalletLocation, Balance>;
198
199pub type PoolFungiblesTransactor = FungiblesAdapter<
201 PoolAssets,
203 PoolAssetsConvertedConcreteId,
205 LocationToAccountId,
207 AccountId,
209 LocalMint<parachains_common::impls::NonZeroIssuance<AccountId, PoolAssets>>,
212 CheckingAccount,
214>;
215
216pub type AssetTransactors = (
218 FungibleTransactor,
219 FungiblesTransactor,
220 ForeignFungiblesTransactor,
221 PoolFungiblesTransactor,
222 UniquesTransactor,
223);
224
225pub type XcmOriginToTransactDispatchOrigin = (
229 SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
233 RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
236 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
239 ParentAsSuperuser<RuntimeOrigin>,
242 SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
245 XcmPassthrough<RuntimeOrigin>,
247);
248
249parameter_types! {
250 pub const MaxInstructions: u32 = 100;
251 pub const MaxAssetsIntoHolding: u32 = 64;
252}
253
254pub struct ParentOrParentsPlurality;
255impl Contains<Location> for ParentOrParentsPlurality {
256 fn contains(location: &Location) -> bool {
257 matches!(location.unpack(), (1, []) | (1, [Plurality { .. }]))
258 }
259}
260
261pub type Barrier = TrailingSetTopicAsId<
262 DenyThenTry<
263 DenyRecursively<DenyReserveTransferToRelayChain>,
264 (
265 TakeWeightCredit,
266 AllowKnownQueryResponses<PolkadotXcm>,
268 WithComputedOrigin<
270 (
271 AllowTopLevelPaidExecutionFrom<Everything>,
274 AllowExplicitUnpaidExecutionFrom<(
277 ParentOrParentsPlurality,
278 Equals<RelayTreasuryLocation>,
279 Equals<bridging::SiblingBridgeHub>,
280 )>,
281 AllowSubscriptionsFrom<ParentRelayOrSiblingParachains>,
283 AllowHrmpNotificationsFromRelayChain,
285 ),
286 UniversalLocation,
287 ConstU32<8>,
288 >,
289 ),
290 >,
291>;
292
293pub type WaivedLocations = (
297 Equals<RootLocation>,
298 RelayOrOtherSystemParachains<AllSiblingSystemParachains, Runtime>,
299 Equals<RelayTreasuryLocation>,
300);
301
302pub type TrustedReserves = (
308 bridging::to_westend::WestendOrEthereumAssetFromAssetHubWestend,
309 bridging::to_ethereum::EthereumAssetFromEthereum,
310 IsForeignConcreteAsset<
311 NonTeleportableAssetFromTrustedReserve<AssetHubParaId, crate::ForeignAssets>,
312 >,
313);
314
315pub type TrustedTeleporters = (
320 ConcreteAssetFromSystem<TokenLocation>,
321 IsForeignConcreteAsset<
322 TeleportableAssetWithTrustedReserve<AssetHubParaId, crate::ForeignAssets>,
323 >,
324);
325
326pub type TrustedAliasers = (AliasChildLocation, AuthorizedAliasers<Runtime>);
331
332pub type PoolAssetsExchanger = SingleAssetExchangeAdapter<
337 crate::AssetConversion,
338 crate::NativeAndNonPoolAssets,
339 (
340 TrustBackedAssetsAsLocation<TrustBackedAssetsPalletLocation, Balance, xcm::v5::Location>,
341 ForeignAssetsConvertedConcreteId,
342 MatchedConvertedConcreteId<
344 xcm::v5::Location,
345 Balance,
346 Equals<ParentLocation>,
347 WithLatestLocationConverter<xcm::v5::Location>,
348 TryConvertInto,
349 >,
350 ),
351 AccountId,
352>;
353
354pub struct XcmConfig;
355impl xcm_executor::Config for XcmConfig {
356 type RuntimeCall = RuntimeCall;
357 type XcmSender = XcmRouter;
358 type XcmEventEmitter = PolkadotXcm;
359 type AssetTransactor = AssetTransactors;
360 type OriginConverter = XcmOriginToTransactDispatchOrigin;
361 type IsReserve = TrustedReserves;
362 type IsTeleporter = TrustedTeleporters;
363 type UniversalLocation = UniversalLocation;
364 type Barrier = Barrier;
365 type Weigher = WeightInfoBounds<
366 crate::weights::xcm::AssetHubRococoXcmWeight<RuntimeCall>,
367 RuntimeCall,
368 MaxInstructions,
369 >;
370 type Trader = (
371 UsingComponents<
372 WeightToFee,
373 TokenLocation,
374 AccountId,
375 Balances,
376 ResolveTo<StakingPot, Balances>,
377 >,
378 cumulus_primitives_utility::SwapFirstAssetTrader<
379 TokenLocation,
380 crate::AssetConversion,
381 WeightToFee,
382 crate::NativeAndNonPoolAssets,
383 (
384 TrustBackedAssetsAsLocation<
385 TrustBackedAssetsPalletLocation,
386 Balance,
387 xcm::v5::Location,
388 >,
389 ForeignAssetsConvertedConcreteId,
390 ),
391 ResolveAssetTo<StakingPot, crate::NativeAndNonPoolAssets>,
392 AccountId,
393 >,
394 );
395 type ResponseHandler = PolkadotXcm;
396 type AssetTrap = PolkadotXcm;
397 type AssetClaims = PolkadotXcm;
398 type SubscriptionService = PolkadotXcm;
399 type PalletInstancesInfo = AllPalletsWithSystem;
400 type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
401 type AssetLocker = ();
402 type AssetExchanger = PoolAssetsExchanger;
403 type FeeManager = XcmFeeManagerFromComponents<
404 WaivedLocations,
405 SendXcmFeeToAccount<Self::AssetTransactor, TreasuryAccount>,
406 >;
407 type MessageExporter = ();
408 type UniversalAliases =
409 (bridging::to_westend::UniversalAliases, bridging::to_ethereum::UniversalAliases);
410 type CallDispatcher = RuntimeCall;
411 type SafeCallFilter = Everything;
412 type Aliasers = TrustedAliasers;
414 type TransactionalProcessor = FrameTransactionalProcessor;
415 type HrmpNewChannelOpenRequestHandler = ();
416 type HrmpChannelAcceptedHandler = ();
417 type HrmpChannelClosingHandler = ();
418 type XcmRecorder = PolkadotXcm;
419}
420
421pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
424
425pub type PriceForParentDelivery =
426 ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, ParachainSystem>;
427
428type LocalXcmRouter = (
430 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, PolkadotXcm, PriceForParentDelivery>,
432 XcmpQueue,
434);
435
436pub type XcmRouter = WithUniqueTopic<(
439 LocalXcmRouter,
440 ToWestendXcmRouter,
443 SovereignPaidRemoteExporter<bridging::EthereumNetworkExportTable, XcmpQueue, UniversalLocation>,
446)>;
447
448parameter_types! {
449 pub const DepositPerItem: Balance = crate::deposit(1, 0);
450 pub const DepositPerByte: Balance = crate::deposit(0, 1);
451 pub const AuthorizeAliasHoldReason: RuntimeHoldReason = RuntimeHoldReason::PolkadotXcm(pallet_xcm::HoldReason::AuthorizeAlias);
452}
453
454impl pallet_xcm::Config for Runtime {
455 type RuntimeEvent = RuntimeEvent;
456 type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, ()>;
458 type XcmRouter = XcmRouter;
459 type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
461 type XcmExecuteFilter = Everything;
462 type XcmExecutor = XcmExecutor<XcmConfig>;
463 type XcmTeleportFilter = Everything;
464 type XcmReserveTransferFilter = Everything;
465 type Weigher = WeightInfoBounds<
466 crate::weights::xcm::AssetHubRococoXcmWeight<RuntimeCall>,
467 RuntimeCall,
468 MaxInstructions,
469 >;
470 type UniversalLocation = UniversalLocation;
471 type RuntimeOrigin = RuntimeOrigin;
472 type RuntimeCall = RuntimeCall;
473 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
474 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
475 type Currency = Balances;
476 type CurrencyMatcher = ();
477 type TrustedLockers = ();
478 type SovereignAccountOf = LocationToAccountId;
479 type MaxLockers = ConstU32<8>;
480 type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
481 type AdminOrigin = EnsureRoot<AccountId>;
482 type MaxRemoteLockConsumers = ConstU32<0>;
483 type RemoteLockConsumerIdentifier = ();
484 type AuthorizedAliasConsideration = HoldConsideration<
486 AccountId,
487 Balances,
488 AuthorizeAliasHoldReason,
489 LinearStoragePrice<DepositPerItem, DepositPerByte, Balance>,
490 >;
491}
492
493impl cumulus_pallet_xcm::Config for Runtime {
494 type RuntimeEvent = RuntimeEvent;
495 type XcmExecutor = XcmExecutor<XcmConfig>;
496}
497
498pub mod bridging {
500 use super::*;
501 use alloc::collections::btree_set::BTreeSet;
502 use assets_common::matching;
503
504 parameter_types! {
506 pub storage XcmBridgeHubRouterBaseFee: Balance =
518 bp_bridge_hub_rococo::BridgeHubRococoBaseXcmFeeInRocs::get()
519 .saturating_add(bp_bridge_hub_westend::BridgeHubWestendBaseDeliveryFeeInWnds::get())
520 .saturating_add(bp_bridge_hub_rococo::BridgeHubRococoBaseConfirmationFeeInRocs::get());
521 pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get();
524
525 pub SiblingBridgeHubParaId: u32 = bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID;
526 pub SiblingBridgeHub: Location = Location::new(1, [Parachain(SiblingBridgeHubParaId::get())]);
527 pub XcmBridgeHubRouterFeeAssetId: AssetId = TokenLocation::get().into();
530
531 pub BridgeTable: alloc::vec::Vec<NetworkExportTableItem> =
532 alloc::vec::Vec::new().into_iter()
533 .chain(to_westend::BridgeTable::get())
534 .collect();
535
536 pub EthereumBridgeTable: alloc::vec::Vec<NetworkExportTableItem> =
537 alloc::vec::Vec::new().into_iter()
538 .chain(to_ethereum::BridgeTable::get())
539 .collect();
540 }
541
542 pub type NetworkExportTable = xcm_builder::NetworkExportTable<BridgeTable>;
543
544 pub type EthereumNetworkExportTable = xcm_builder::NetworkExportTable<EthereumBridgeTable>;
545
546 pub mod to_westend {
547 use super::*;
548
549 parameter_types! {
550 pub SiblingBridgeHubWithBridgeHubWestendInstance: Location = Location::new(
551 1,
552 [
553 Parachain(SiblingBridgeHubParaId::get()),
554 PalletInstance(bp_bridge_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX)
555 ]
556 );
557
558 pub const WestendNetwork: NetworkId = NetworkId::ByGenesis(WESTEND_GENESIS_HASH);
559 pub const EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 11155111 };
560 pub WestendEcosystem: Location = Location::new(2, [GlobalConsensus(WestendNetwork::get())]);
561 pub EthereumEcosystem: Location = Location::new(2, [GlobalConsensus(EthereumNetwork::get())]);
562 pub WndLocation: Location = Location::new(2, [GlobalConsensus(WestendNetwork::get())]);
563 pub AssetHubWestend: Location = Location::new(2, [
564 GlobalConsensus(WestendNetwork::get()),
565 Parachain(bp_asset_hub_westend::ASSET_HUB_WESTEND_PARACHAIN_ID)
566 ]);
567
568 pub BridgeTable: alloc::vec::Vec<NetworkExportTableItem> = alloc::vec![
571 NetworkExportTableItem::new(
572 WestendNetwork::get(),
573 Some(alloc::vec![
574 AssetHubWestend::get().interior.split_global().expect("invalid configuration for AssetHubWestend").1,
575 ]),
576 SiblingBridgeHub::get(),
577 Some((
579 XcmBridgeHubRouterFeeAssetId::get(),
580 XcmBridgeHubRouterBaseFee::get(),
581 ).into())
582 )
583 ];
584
585 pub UniversalAliases: BTreeSet<(Location, Junction)> = BTreeSet::from_iter(
587 alloc::vec![
588 (SiblingBridgeHubWithBridgeHubWestendInstance::get(), GlobalConsensus(WestendNetwork::get()))
589 ]
590 );
591 }
592
593 impl Contains<(Location, Junction)> for UniversalAliases {
594 fn contains(alias: &(Location, Junction)) -> bool {
595 UniversalAliases::get().contains(alias)
596 }
597 }
598
599 pub type WestendOrEthereumAssetFromAssetHubWestend = matching::RemoteAssetFromLocation<
602 (StartsWith<WestendEcosystem>, StartsWith<EthereumEcosystem>),
603 AssetHubWestend,
604 >;
605 }
606
607 pub mod to_ethereum {
608 use super::*;
609
610 parameter_types! {
611 pub const DefaultBridgeHubEthereumBaseFee: Balance = 3_833_568_200_000;
616 pub storage BridgeHubEthereumBaseFee: Balance = DefaultBridgeHubEthereumBaseFee::get();
617 pub SiblingBridgeHubWithEthereumInboundQueueInstance: Location = Location::new(
618 1,
619 [
620 Parachain(SiblingBridgeHubParaId::get()),
621 PalletInstance(INBOUND_QUEUE_PALLET_INDEX)
622 ]
623 );
624
625 pub BridgeTable: alloc::vec::Vec<NetworkExportTableItem> = alloc::vec![
628 NetworkExportTableItem::new(
629 EthereumNetwork::get().into(),
630 Some(alloc::vec![Junctions::Here]),
631 SiblingBridgeHub::get(),
632 Some((
633 XcmBridgeHubRouterFeeAssetId::get(),
634 BridgeHubEthereumBaseFee::get(),
635 ).into())
636 ),
637 ];
638
639 pub UniversalAliases: BTreeSet<(Location, Junction)> = BTreeSet::from_iter(
641 alloc::vec![
642 (SiblingBridgeHubWithEthereumInboundQueueInstance::get(), GlobalConsensus(EthereumNetwork::get().into())),
643 ]
644 );
645 }
646
647 pub type EthereumAssetFromEthereum =
648 IsForeignConcreteAsset<FromNetwork<UniversalLocation, EthereumNetwork>>;
649
650 impl Contains<(Location, Junction)> for UniversalAliases {
651 fn contains(alias: &(Location, Junction)) -> bool {
652 UniversalAliases::get().contains(alias)
653 }
654 }
655 }
656
657 #[cfg(feature = "runtime-benchmarks")]
659 pub struct BridgingBenchmarksHelper;
660
661 #[cfg(feature = "runtime-benchmarks")]
662 impl BridgingBenchmarksHelper {
663 pub fn prepare_universal_alias() -> Option<(Location, Junction)> {
664 let alias =
665 to_westend::UniversalAliases::get()
666 .into_iter()
667 .find_map(|(location, junction)| {
668 match to_westend::SiblingBridgeHubWithBridgeHubWestendInstance::get()
669 .eq(&location)
670 {
671 true => Some((location, junction)),
672 false => None,
673 }
674 });
675 Some(alias.expect("we expect here BridgeHubRococo to Westend mapping at least"))
676 }
677 }
678}