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::{FromNetwork, FromSiblingParachain, IsForeignConcreteAsset, ParentLocation},
24 TrustBackedAssetsAsLocation,
25};
26use frame_support::{
27 parameter_types,
28 traits::{
29 fungible::HoldConsideration,
30 tokens::imbalance::{ResolveAssetTo, ResolveTo},
31 ConstU32, Contains, Equals, Everything, LinearStoragePrice, PalletInfoAccess,
32 },
33};
34use frame_system::EnsureRoot;
35use pallet_xcm::{AuthorizedAliasers, XcmPassthrough};
36use parachains_common::{
37 xcm_config::{
38 AllSiblingSystemParachains, ConcreteAssetFromSystem, ParentRelayOrSiblingParachains,
39 RelayOrOtherSystemParachains,
40 },
41 TREASURY_PALLET_ID,
42};
43use polkadot_parachain_primitives::primitives::Sibling;
44use polkadot_runtime_common::xcm_sender::ExponentialPrice;
45use sp_runtime::traits::{AccountIdConversion, TryConvertInto};
46use testnet_parachains_constants::rococo::snowbridge::{
47 EthereumNetwork, INBOUND_QUEUE_PALLET_INDEX,
48};
49use xcm::latest::{prelude::*, ROCOCO_GENESIS_HASH, WESTEND_GENESIS_HASH};
50use xcm_builder::{
51 unique_instances::UniqueInstancesAdapter, AccountId32Aliases, AliasChildLocation,
52 AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
53 AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
54 DenyRecursively, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal,
55 DescribeFamily, EnsureXcmOrigin, ExternalConsensusLocationsConverterFor,
56 FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, HashedDescription, IsConcrete,
57 LocalMint, MatchInClassInstances, MatchedConvertedConcreteId, NetworkExportTableItem,
58 NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SendXcmFeeToAccount,
59 SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
60 SignedToAccountId32, SingleAssetExchangeAdapter, SovereignPaidRemoteExporter,
61 SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus, TakeWeightCredit,
62 TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin,
63 WithLatestLocationConverter, WithUniqueTopic, XcmFeeManagerFromComponents,
64};
65use xcm_executor::XcmExecutor;
66
67parameter_types! {
68 pub const RootLocation: Location = Location::here();
69 pub const TokenLocation: Location = Location::parent();
70 pub const RelayNetwork: NetworkId = NetworkId::ByGenesis(ROCOCO_GENESIS_HASH);
71 pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
72 pub UniversalLocation: InteriorLocation =
73 [GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into())].into();
74 pub UniversalLocationNetworkId: NetworkId = UniversalLocation::get().global_consensus().unwrap();
75 pub TrustBackedAssetsPalletLocation: Location =
76 PalletInstance(TrustBackedAssetsPalletIndex::get()).into();
77 pub TrustBackedAssetsPalletIndex: u8 = <Assets as PalletInfoAccess>::index() as u8;
78 pub TrustBackedAssetsPalletLocationV3: xcm::v3::Location =
79 xcm::v3::Junction::PalletInstance(<Assets as PalletInfoAccess>::index() as u8).into();
80 pub PoolAssetsPalletLocationV3: xcm::v3::Location =
81 xcm::v3::Junction::PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
82 pub ForeignAssetsPalletLocation: Location =
83 PalletInstance(<ForeignAssets as PalletInfoAccess>::index() as u8).into();
84 pub PoolAssetsPalletLocation: Location =
85 PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
86 pub UniquesPalletLocation: Location =
87 PalletInstance(<Uniques as PalletInfoAccess>::index() as u8).into();
88 pub CheckingAccount: AccountId = PolkadotXcm::check_account();
89 pub const GovernanceLocation: Location = Location::parent();
90 pub StakingPot: AccountId = CollatorSelection::account_id();
91 pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
92 pub RelayTreasuryLocation: Location = (Parent, PalletInstance(rococo_runtime_constants::TREASURY_PALLET_ID)).into();
93}
94
95pub type LocationToAccountId = (
99 ParentIsPreset<AccountId>,
101 SiblingParachainConvertsVia<Sibling, AccountId>,
103 AccountId32Aliases<RelayNetwork, AccountId>,
105 HashedDescription<AccountId, DescribeFamily<DescribeAllTerminal>>,
107 ExternalConsensusLocationsConverterFor<UniversalLocation, AccountId>,
109);
110
111pub type FungibleTransactor = FungibleAdapter<
113 Balances,
115 IsConcrete<TokenLocation>,
117 LocationToAccountId,
119 AccountId,
121 (),
123>;
124
125pub type TrustBackedAssetsConvertedConcreteId =
127 assets_common::TrustBackedAssetsConvertedConcreteId<TrustBackedAssetsPalletLocation, Balance>;
128
129pub type FungiblesTransactor = FungiblesAdapter<
131 Assets,
133 TrustBackedAssetsConvertedConcreteId,
135 LocationToAccountId,
137 AccountId,
139 LocalMint<parachains_common::impls::NonZeroIssuance<AccountId, Assets>>,
142 CheckingAccount,
144>;
145
146pub type UniquesConvertedConcreteId =
148 assets_common::UniquesConvertedConcreteId<UniquesPalletLocation>;
149
150pub type UniquesTransactor = UniqueInstancesAdapter<
152 AccountId,
153 LocationToAccountId,
154 MatchInClassInstances<UniquesConvertedConcreteId>,
155 pallet_uniques::asset_ops::Item<Uniques>,
156>;
157
158pub type ForeignAssetsConvertedConcreteId = assets_common::ForeignAssetsConvertedConcreteId<
160 (
161 StartsWith<TrustBackedAssetsPalletLocation>,
163 StartsWithExplicitGlobalConsensus<UniversalLocationNetworkId>,
169 ),
170 Balance,
171 xcm::v5::Location,
172>;
173
174pub type ForeignFungiblesTransactor = FungiblesAdapter<
176 ForeignAssets,
178 ForeignAssetsConvertedConcreteId,
180 LocationToAccountId,
182 AccountId,
184 NoChecking,
186 CheckingAccount,
188>;
189
190pub type PoolAssetsConvertedConcreteId =
192 assets_common::PoolAssetsConvertedConcreteId<PoolAssetsPalletLocation, Balance>;
193
194pub type PoolFungiblesTransactor = FungiblesAdapter<
196 PoolAssets,
198 PoolAssetsConvertedConcreteId,
200 LocationToAccountId,
202 AccountId,
204 LocalMint<parachains_common::impls::NonZeroIssuance<AccountId, PoolAssets>>,
207 CheckingAccount,
209>;
210
211pub type AssetTransactors = (
213 FungibleTransactor,
214 FungiblesTransactor,
215 ForeignFungiblesTransactor,
216 PoolFungiblesTransactor,
217 UniquesTransactor,
218);
219
220pub type XcmOriginToTransactDispatchOrigin = (
224 SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
228 RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
231 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
234 ParentAsSuperuser<RuntimeOrigin>,
237 SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
240 XcmPassthrough<RuntimeOrigin>,
242);
243
244parameter_types! {
245 pub const MaxInstructions: u32 = 100;
246 pub const MaxAssetsIntoHolding: u32 = 64;
247}
248
249pub struct ParentOrParentsPlurality;
250impl Contains<Location> for ParentOrParentsPlurality {
251 fn contains(location: &Location) -> bool {
252 matches!(location.unpack(), (1, []) | (1, [Plurality { .. }]))
253 }
254}
255
256pub type Barrier = TrailingSetTopicAsId<
257 DenyThenTry<
258 DenyRecursively<DenyReserveTransferToRelayChain>,
259 (
260 TakeWeightCredit,
261 AllowKnownQueryResponses<PolkadotXcm>,
263 WithComputedOrigin<
265 (
266 AllowTopLevelPaidExecutionFrom<Everything>,
269 AllowExplicitUnpaidExecutionFrom<(
272 ParentOrParentsPlurality,
273 Equals<RelayTreasuryLocation>,
274 Equals<bridging::SiblingBridgeHub>,
275 )>,
276 AllowSubscriptionsFrom<ParentRelayOrSiblingParachains>,
278 AllowHrmpNotificationsFromRelayChain,
280 ),
281 UniversalLocation,
282 ConstU32<8>,
283 >,
284 ),
285 >,
286>;
287
288pub type WaivedLocations = (
292 Equals<RootLocation>,
293 RelayOrOtherSystemParachains<AllSiblingSystemParachains, Runtime>,
294 Equals<RelayTreasuryLocation>,
295);
296
297pub type TrustedTeleporters = (
302 ConcreteAssetFromSystem<TokenLocation>,
303 IsForeignConcreteAsset<FromSiblingParachain<parachain_info::Pallet<Runtime>>>,
304);
305
306pub type TrustedAliasers = (AliasChildLocation, AuthorizedAliasers<Runtime>);
311
312pub type PoolAssetsExchanger = SingleAssetExchangeAdapter<
317 crate::AssetConversion,
318 crate::NativeAndNonPoolAssets,
319 (
320 TrustBackedAssetsAsLocation<TrustBackedAssetsPalletLocation, Balance, xcm::v5::Location>,
321 ForeignAssetsConvertedConcreteId,
322 MatchedConvertedConcreteId<
324 xcm::v5::Location,
325 Balance,
326 Equals<ParentLocation>,
327 WithLatestLocationConverter<xcm::v5::Location>,
328 TryConvertInto,
329 >,
330 ),
331 AccountId,
332>;
333
334pub struct XcmConfig;
335impl xcm_executor::Config for XcmConfig {
336 type RuntimeCall = RuntimeCall;
337 type XcmSender = XcmRouter;
338 type XcmEventEmitter = PolkadotXcm;
339 type AssetTransactor = AssetTransactors;
340 type OriginConverter = XcmOriginToTransactDispatchOrigin;
341 type IsReserve = (
347 bridging::to_westend::WestendOrEthereumAssetFromAssetHubWestend,
348 bridging::to_ethereum::EthereumAssetFromEthereum,
349 );
350 type IsTeleporter = TrustedTeleporters;
351 type UniversalLocation = UniversalLocation;
352 type Barrier = Barrier;
353 type Weigher = WeightInfoBounds<
354 crate::weights::xcm::AssetHubRococoXcmWeight<RuntimeCall>,
355 RuntimeCall,
356 MaxInstructions,
357 >;
358 type Trader = (
359 UsingComponents<
360 WeightToFee,
361 TokenLocation,
362 AccountId,
363 Balances,
364 ResolveTo<StakingPot, Balances>,
365 >,
366 cumulus_primitives_utility::SwapFirstAssetTrader<
367 TokenLocation,
368 crate::AssetConversion,
369 WeightToFee,
370 crate::NativeAndNonPoolAssets,
371 (
372 TrustBackedAssetsAsLocation<
373 TrustBackedAssetsPalletLocation,
374 Balance,
375 xcm::v5::Location,
376 >,
377 ForeignAssetsConvertedConcreteId,
378 ),
379 ResolveAssetTo<StakingPot, crate::NativeAndNonPoolAssets>,
380 AccountId,
381 >,
382 );
383 type ResponseHandler = PolkadotXcm;
384 type AssetTrap = PolkadotXcm;
385 type AssetClaims = PolkadotXcm;
386 type SubscriptionService = PolkadotXcm;
387 type PalletInstancesInfo = AllPalletsWithSystem;
388 type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
389 type AssetLocker = ();
390 type AssetExchanger = PoolAssetsExchanger;
391 type FeeManager = XcmFeeManagerFromComponents<
392 WaivedLocations,
393 SendXcmFeeToAccount<Self::AssetTransactor, TreasuryAccount>,
394 >;
395 type MessageExporter = ();
396 type UniversalAliases =
397 (bridging::to_westend::UniversalAliases, bridging::to_ethereum::UniversalAliases);
398 type CallDispatcher = RuntimeCall;
399 type SafeCallFilter = Everything;
400 type Aliasers = TrustedAliasers;
402 type TransactionalProcessor = FrameTransactionalProcessor;
403 type HrmpNewChannelOpenRequestHandler = ();
404 type HrmpChannelAcceptedHandler = ();
405 type HrmpChannelClosingHandler = ();
406 type XcmRecorder = PolkadotXcm;
407}
408
409pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
412
413pub type PriceForParentDelivery =
414 ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, ParachainSystem>;
415
416type LocalXcmRouter = (
418 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, PolkadotXcm, PriceForParentDelivery>,
420 XcmpQueue,
422);
423
424pub type XcmRouter = WithUniqueTopic<(
427 LocalXcmRouter,
428 ToWestendXcmRouter,
431 SovereignPaidRemoteExporter<bridging::EthereumNetworkExportTable, XcmpQueue, UniversalLocation>,
434)>;
435
436parameter_types! {
437 pub const DepositPerItem: Balance = crate::deposit(1, 0);
438 pub const DepositPerByte: Balance = crate::deposit(0, 1);
439 pub const AuthorizeAliasHoldReason: RuntimeHoldReason = RuntimeHoldReason::PolkadotXcm(pallet_xcm::HoldReason::AuthorizeAlias);
440}
441
442impl pallet_xcm::Config for Runtime {
443 type RuntimeEvent = RuntimeEvent;
444 type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, ()>;
446 type XcmRouter = XcmRouter;
447 type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
449 type XcmExecuteFilter = Everything;
450 type XcmExecutor = XcmExecutor<XcmConfig>;
451 type XcmTeleportFilter = Everything;
452 type XcmReserveTransferFilter = Everything;
453 type Weigher = WeightInfoBounds<
454 crate::weights::xcm::AssetHubRococoXcmWeight<RuntimeCall>,
455 RuntimeCall,
456 MaxInstructions,
457 >;
458 type UniversalLocation = UniversalLocation;
459 type RuntimeOrigin = RuntimeOrigin;
460 type RuntimeCall = RuntimeCall;
461 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
462 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
463 type Currency = Balances;
464 type CurrencyMatcher = ();
465 type TrustedLockers = ();
466 type SovereignAccountOf = LocationToAccountId;
467 type MaxLockers = ConstU32<8>;
468 type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
469 type AdminOrigin = EnsureRoot<AccountId>;
470 type MaxRemoteLockConsumers = ConstU32<0>;
471 type RemoteLockConsumerIdentifier = ();
472 type AuthorizedAliasConsideration = HoldConsideration<
474 AccountId,
475 Balances,
476 AuthorizeAliasHoldReason,
477 LinearStoragePrice<DepositPerItem, DepositPerByte, Balance>,
478 >;
479}
480
481impl cumulus_pallet_xcm::Config for Runtime {
482 type RuntimeEvent = RuntimeEvent;
483 type XcmExecutor = XcmExecutor<XcmConfig>;
484}
485
486pub struct XcmBenchmarkHelper;
488#[cfg(feature = "runtime-benchmarks")]
489impl pallet_assets::BenchmarkHelper<xcm::v5::Location> for XcmBenchmarkHelper {
490 fn create_asset_id_parameter(id: u32) -> xcm::v5::Location {
491 xcm::v5::Location::new(1, [xcm::v5::Junction::Parachain(id)])
492 }
493}
494
495pub mod bridging {
497 use super::*;
498 use alloc::collections::btree_set::BTreeSet;
499 use assets_common::matching;
500
501 parameter_types! {
503 pub storage XcmBridgeHubRouterBaseFee: Balance =
515 bp_bridge_hub_rococo::BridgeHubRococoBaseXcmFeeInRocs::get()
516 .saturating_add(bp_bridge_hub_westend::BridgeHubWestendBaseDeliveryFeeInWnds::get())
517 .saturating_add(bp_bridge_hub_rococo::BridgeHubRococoBaseConfirmationFeeInRocs::get());
518 pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get();
521
522 pub SiblingBridgeHubParaId: u32 = bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID;
523 pub SiblingBridgeHub: Location = Location::new(1, [Parachain(SiblingBridgeHubParaId::get())]);
524 pub XcmBridgeHubRouterFeeAssetId: AssetId = TokenLocation::get().into();
527
528 pub BridgeTable: alloc::vec::Vec<NetworkExportTableItem> =
529 alloc::vec::Vec::new().into_iter()
530 .chain(to_westend::BridgeTable::get())
531 .collect();
532
533 pub EthereumBridgeTable: alloc::vec::Vec<NetworkExportTableItem> =
534 alloc::vec::Vec::new().into_iter()
535 .chain(to_ethereum::BridgeTable::get())
536 .collect();
537 }
538
539 pub type NetworkExportTable = xcm_builder::NetworkExportTable<BridgeTable>;
540
541 pub type EthereumNetworkExportTable = xcm_builder::NetworkExportTable<EthereumBridgeTable>;
542
543 pub mod to_westend {
544 use super::*;
545
546 parameter_types! {
547 pub SiblingBridgeHubWithBridgeHubWestendInstance: Location = Location::new(
548 1,
549 [
550 Parachain(SiblingBridgeHubParaId::get()),
551 PalletInstance(bp_bridge_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX)
552 ]
553 );
554
555 pub const WestendNetwork: NetworkId = NetworkId::ByGenesis(WESTEND_GENESIS_HASH);
556 pub const EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 11155111 };
557 pub WestendEcosystem: Location = Location::new(2, [GlobalConsensus(WestendNetwork::get())]);
558 pub EthereumEcosystem: Location = Location::new(2, [GlobalConsensus(EthereumNetwork::get())]);
559 pub WndLocation: Location = Location::new(2, [GlobalConsensus(WestendNetwork::get())]);
560 pub AssetHubWestend: Location = Location::new(2, [
561 GlobalConsensus(WestendNetwork::get()),
562 Parachain(bp_asset_hub_westend::ASSET_HUB_WESTEND_PARACHAIN_ID)
563 ]);
564
565 pub BridgeTable: alloc::vec::Vec<NetworkExportTableItem> = alloc::vec![
568 NetworkExportTableItem::new(
569 WestendNetwork::get(),
570 Some(alloc::vec![
571 AssetHubWestend::get().interior.split_global().expect("invalid configuration for AssetHubWestend").1,
572 ]),
573 SiblingBridgeHub::get(),
574 Some((
576 XcmBridgeHubRouterFeeAssetId::get(),
577 XcmBridgeHubRouterBaseFee::get(),
578 ).into())
579 )
580 ];
581
582 pub UniversalAliases: BTreeSet<(Location, Junction)> = BTreeSet::from_iter(
584 alloc::vec![
585 (SiblingBridgeHubWithBridgeHubWestendInstance::get(), GlobalConsensus(WestendNetwork::get()))
586 ]
587 );
588 }
589
590 impl Contains<(Location, Junction)> for UniversalAliases {
591 fn contains(alias: &(Location, Junction)) -> bool {
592 UniversalAliases::get().contains(alias)
593 }
594 }
595
596 pub type WestendOrEthereumAssetFromAssetHubWestend = matching::RemoteAssetFromLocation<
599 (StartsWith<WestendEcosystem>, StartsWith<EthereumEcosystem>),
600 AssetHubWestend,
601 >;
602 }
603
604 pub mod to_ethereum {
605 use super::*;
606
607 parameter_types! {
608 pub const DefaultBridgeHubEthereumBaseFee: Balance = 3_833_568_200_000;
613 pub storage BridgeHubEthereumBaseFee: Balance = DefaultBridgeHubEthereumBaseFee::get();
614 pub SiblingBridgeHubWithEthereumInboundQueueInstance: Location = Location::new(
615 1,
616 [
617 Parachain(SiblingBridgeHubParaId::get()),
618 PalletInstance(INBOUND_QUEUE_PALLET_INDEX)
619 ]
620 );
621
622 pub BridgeTable: alloc::vec::Vec<NetworkExportTableItem> = alloc::vec![
625 NetworkExportTableItem::new(
626 EthereumNetwork::get().into(),
627 Some(alloc::vec![Junctions::Here]),
628 SiblingBridgeHub::get(),
629 Some((
630 XcmBridgeHubRouterFeeAssetId::get(),
631 BridgeHubEthereumBaseFee::get(),
632 ).into())
633 ),
634 ];
635
636 pub UniversalAliases: BTreeSet<(Location, Junction)> = BTreeSet::from_iter(
638 alloc::vec![
639 (SiblingBridgeHubWithEthereumInboundQueueInstance::get(), GlobalConsensus(EthereumNetwork::get().into())),
640 ]
641 );
642 }
643
644 pub type EthereumAssetFromEthereum =
645 IsForeignConcreteAsset<FromNetwork<UniversalLocation, EthereumNetwork>>;
646
647 impl Contains<(Location, Junction)> for UniversalAliases {
648 fn contains(alias: &(Location, Junction)) -> bool {
649 UniversalAliases::get().contains(alias)
650 }
651 }
652 }
653
654 #[cfg(feature = "runtime-benchmarks")]
656 pub struct BridgingBenchmarksHelper;
657
658 #[cfg(feature = "runtime-benchmarks")]
659 impl BridgingBenchmarksHelper {
660 pub fn prepare_universal_alias() -> Option<(Location, Junction)> {
661 let alias =
662 to_westend::UniversalAliases::get()
663 .into_iter()
664 .find_map(|(location, junction)| {
665 match to_westend::SiblingBridgeHubWithBridgeHubWestendInstance::get()
666 .eq(&location)
667 {
668 true => Some((location, junction)),
669 false => None,
670 }
671 });
672 Some(alias.expect("we expect here BridgeHubRococo to Westend mapping at least"))
673 }
674 }
675}