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 SubscriptionService = PolkadotXcm;
398 type PalletInstancesInfo = AllPalletsWithSystem;
399 type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
400 type AssetLocker = ();
401 type AssetExchanger = PoolAssetsExchanger;
402 type FeeManager = XcmFeeManagerFromComponents<
403 WaivedLocations,
404 SendXcmFeeToAccount<Self::AssetTransactor, TreasuryAccount>,
405 >;
406 type MessageExporter = ();
407 type UniversalAliases =
408 (bridging::to_westend::UniversalAliases, bridging::to_ethereum::UniversalAliases);
409 type CallDispatcher = RuntimeCall;
410 type SafeCallFilter = Everything;
411 type Aliasers = TrustedAliasers;
413 type TransactionalProcessor = FrameTransactionalProcessor;
414 type HrmpNewChannelOpenRequestHandler = ();
415 type HrmpChannelAcceptedHandler = ();
416 type HrmpChannelClosingHandler = ();
417 type XcmRecorder = PolkadotXcm;
418}
419
420pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
423
424pub type PriceForParentDelivery =
425 ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, ParachainSystem>;
426
427type LocalXcmRouter = (
429 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, PolkadotXcm, PriceForParentDelivery>,
431 XcmpQueue,
433);
434
435pub type XcmRouter = WithUniqueTopic<(
438 LocalXcmRouter,
439 ToWestendXcmRouter,
442 SovereignPaidRemoteExporter<bridging::EthereumNetworkExportTable, XcmpQueue, UniversalLocation>,
445)>;
446
447parameter_types! {
448 pub const DepositPerItem: Balance = crate::deposit(1, 0);
449 pub const DepositPerByte: Balance = crate::deposit(0, 1);
450 pub const AuthorizeAliasHoldReason: RuntimeHoldReason = RuntimeHoldReason::PolkadotXcm(pallet_xcm::HoldReason::AuthorizeAlias);
451}
452
453impl pallet_xcm::Config for Runtime {
454 type RuntimeEvent = RuntimeEvent;
455 type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, ()>;
457 type XcmRouter = XcmRouter;
458 type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
460 type XcmExecuteFilter = Everything;
461 type XcmExecutor = XcmExecutor<XcmConfig>;
462 type XcmTeleportFilter = Everything;
463 type XcmReserveTransferFilter = Everything;
464 type Weigher = WeightInfoBounds<
465 crate::weights::xcm::AssetHubRococoXcmWeight<RuntimeCall>,
466 RuntimeCall,
467 MaxInstructions,
468 >;
469 type UniversalLocation = UniversalLocation;
470 type RuntimeOrigin = RuntimeOrigin;
471 type RuntimeCall = RuntimeCall;
472 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
473 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
474 type Currency = Balances;
475 type CurrencyMatcher = ();
476 type TrustedLockers = ();
477 type SovereignAccountOf = LocationToAccountId;
478 type MaxLockers = ConstU32<8>;
479 type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
480 type AdminOrigin = EnsureRoot<AccountId>;
481 type MaxRemoteLockConsumers = ConstU32<0>;
482 type RemoteLockConsumerIdentifier = ();
483 type AuthorizedAliasConsideration = HoldConsideration<
485 AccountId,
486 Balances,
487 AuthorizeAliasHoldReason,
488 LinearStoragePrice<DepositPerItem, DepositPerByte, Balance>,
489 >;
490}
491
492impl cumulus_pallet_xcm::Config for Runtime {
493 type RuntimeEvent = RuntimeEvent;
494 type XcmExecutor = XcmExecutor<XcmConfig>;
495}
496
497pub mod bridging {
499 use super::*;
500 use alloc::collections::btree_set::BTreeSet;
501 use assets_common::matching;
502
503 parameter_types! {
505 pub storage XcmBridgeHubRouterBaseFee: Balance =
517 bp_bridge_hub_rococo::BridgeHubRococoBaseXcmFeeInRocs::get()
518 .saturating_add(bp_bridge_hub_westend::BridgeHubWestendBaseDeliveryFeeInWnds::get())
519 .saturating_add(bp_bridge_hub_rococo::BridgeHubRococoBaseConfirmationFeeInRocs::get());
520 pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get();
523
524 pub SiblingBridgeHubParaId: u32 = bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID;
525 pub SiblingBridgeHub: Location = Location::new(1, [Parachain(SiblingBridgeHubParaId::get())]);
526 pub XcmBridgeHubRouterFeeAssetId: AssetId = TokenLocation::get().into();
529
530 pub BridgeTable: alloc::vec::Vec<NetworkExportTableItem> =
531 alloc::vec::Vec::new().into_iter()
532 .chain(to_westend::BridgeTable::get())
533 .collect();
534
535 pub EthereumBridgeTable: alloc::vec::Vec<NetworkExportTableItem> =
536 alloc::vec::Vec::new().into_iter()
537 .chain(to_ethereum::BridgeTable::get())
538 .collect();
539 }
540
541 pub type NetworkExportTable = xcm_builder::NetworkExportTable<BridgeTable>;
542
543 pub type EthereumNetworkExportTable = xcm_builder::NetworkExportTable<EthereumBridgeTable>;
544
545 pub mod to_westend {
546 use super::*;
547
548 parameter_types! {
549 pub SiblingBridgeHubWithBridgeHubWestendInstance: Location = Location::new(
550 1,
551 [
552 Parachain(SiblingBridgeHubParaId::get()),
553 PalletInstance(bp_bridge_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX)
554 ]
555 );
556
557 pub const WestendNetwork: NetworkId = NetworkId::ByGenesis(WESTEND_GENESIS_HASH);
558 pub const EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 11155111 };
559 pub WestendEcosystem: Location = Location::new(2, [GlobalConsensus(WestendNetwork::get())]);
560 pub EthereumEcosystem: Location = Location::new(2, [GlobalConsensus(EthereumNetwork::get())]);
561 pub WndLocation: Location = Location::new(2, [GlobalConsensus(WestendNetwork::get())]);
562 pub AssetHubWestend: Location = Location::new(2, [
563 GlobalConsensus(WestendNetwork::get()),
564 Parachain(bp_asset_hub_westend::ASSET_HUB_WESTEND_PARACHAIN_ID)
565 ]);
566
567 pub BridgeTable: alloc::vec::Vec<NetworkExportTableItem> = alloc::vec![
570 NetworkExportTableItem::new(
571 WestendNetwork::get(),
572 Some(alloc::vec![
573 AssetHubWestend::get().interior.split_global().expect("invalid configuration for AssetHubWestend").1,
574 ]),
575 SiblingBridgeHub::get(),
576 Some((
578 XcmBridgeHubRouterFeeAssetId::get(),
579 XcmBridgeHubRouterBaseFee::get(),
580 ).into())
581 )
582 ];
583
584 pub UniversalAliases: BTreeSet<(Location, Junction)> = BTreeSet::from_iter(
586 alloc::vec![
587 (SiblingBridgeHubWithBridgeHubWestendInstance::get(), GlobalConsensus(WestendNetwork::get()))
588 ]
589 );
590 }
591
592 impl Contains<(Location, Junction)> for UniversalAliases {
593 fn contains(alias: &(Location, Junction)) -> bool {
594 UniversalAliases::get().contains(alias)
595 }
596 }
597
598 pub type WestendOrEthereumAssetFromAssetHubWestend = matching::RemoteAssetFromLocation<
601 (StartsWith<WestendEcosystem>, StartsWith<EthereumEcosystem>),
602 AssetHubWestend,
603 >;
604 }
605
606 pub mod to_ethereum {
607 use super::*;
608
609 parameter_types! {
610 pub const DefaultBridgeHubEthereumBaseFee: Balance = 3_833_568_200_000;
615 pub storage BridgeHubEthereumBaseFee: Balance = DefaultBridgeHubEthereumBaseFee::get();
616 pub SiblingBridgeHubWithEthereumInboundQueueInstance: Location = Location::new(
617 1,
618 [
619 Parachain(SiblingBridgeHubParaId::get()),
620 PalletInstance(INBOUND_QUEUE_PALLET_INDEX)
621 ]
622 );
623
624 pub BridgeTable: alloc::vec::Vec<NetworkExportTableItem> = alloc::vec![
627 NetworkExportTableItem::new(
628 EthereumNetwork::get().into(),
629 Some(alloc::vec![Junctions::Here]),
630 SiblingBridgeHub::get(),
631 Some((
632 XcmBridgeHubRouterFeeAssetId::get(),
633 BridgeHubEthereumBaseFee::get(),
634 ).into())
635 ),
636 ];
637
638 pub UniversalAliases: BTreeSet<(Location, Junction)> = BTreeSet::from_iter(
640 alloc::vec![
641 (SiblingBridgeHubWithEthereumInboundQueueInstance::get(), GlobalConsensus(EthereumNetwork::get().into())),
642 ]
643 );
644 }
645
646 pub type EthereumAssetFromEthereum =
647 IsForeignConcreteAsset<FromNetwork<UniversalLocation, EthereumNetwork>>;
648
649 impl Contains<(Location, Junction)> for UniversalAliases {
650 fn contains(alias: &(Location, Junction)) -> bool {
651 UniversalAliases::get().contains(alias)
652 }
653 }
654 }
655
656 #[cfg(feature = "runtime-benchmarks")]
658 pub struct BridgingBenchmarksHelper;
659
660 #[cfg(feature = "runtime-benchmarks")]
661 impl BridgingBenchmarksHelper {
662 pub fn prepare_universal_alias() -> Option<(Location, Junction)> {
663 let alias =
664 to_westend::UniversalAliases::get()
665 .into_iter()
666 .find_map(|(location, junction)| {
667 match to_westend::SiblingBridgeHubWithBridgeHubWestendInstance::get()
668 .eq(&location)
669 {
670 true => Some((location, junction)),
671 false => None,
672 }
673 });
674 Some(alias.expect("we expect here BridgeHubRococo to Westend mapping at least"))
675 }
676 }
677}