asset_hub_rococo_runtime/
xcm_config.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// SPDX-License-Identifier: Apache-2.0
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// 	http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use 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
100/// Type for specifying how a `Location` can be converted into an `AccountId`. This is used
101/// when determining ownership of accounts for asset transacting and when attempting to use XCM
102/// `Transact` in order to determine the dispatch Origin.
103pub type LocationToAccountId = (
104	// The parent (Relay-chain) origin converts to the parent `AccountId`.
105	ParentIsPreset<AccountId>,
106	// Sibling parachain origins convert to AccountId via the `ParaId::into`.
107	SiblingParachainConvertsVia<Sibling, AccountId>,
108	// Straight up local `AccountId32` origins just alias directly to `AccountId`.
109	AccountId32Aliases<RelayNetwork, AccountId>,
110	// Foreign locations alias into accounts according to a hash of their standard description.
111	HashedDescription<AccountId, DescribeFamily<DescribeAllTerminal>>,
112	// Different global consensus locations sovereign accounts.
113	ExternalConsensusLocationsConverterFor<UniversalLocation, AccountId>,
114);
115
116/// Means for transacting the native currency on this chain.
117pub type FungibleTransactor = FungibleAdapter<
118	// Use this currency:
119	Balances,
120	// Use this currency when it is a fungible asset matching the given location or name:
121	IsConcrete<TokenLocation>,
122	// Convert an XCM Location into a local account id:
123	LocationToAccountId,
124	// Our chain's account ID type (we can't get away without mentioning it explicitly):
125	AccountId,
126	// We don't track any teleports of `Balances`.
127	(),
128>;
129
130/// `AssetId`/`Balance` converter for `TrustBackedAssets`.
131pub type TrustBackedAssetsConvertedConcreteId =
132	assets_common::TrustBackedAssetsConvertedConcreteId<TrustBackedAssetsPalletLocation, Balance>;
133
134/// Means for transacting assets besides the native currency on this chain.
135pub type FungiblesTransactor = FungiblesAdapter<
136	// Use this fungibles implementation:
137	Assets,
138	// Use this currency when it is a fungible asset matching the given location or name:
139	TrustBackedAssetsConvertedConcreteId,
140	// Convert an XCM Location into a local account id:
141	LocationToAccountId,
142	// Our chain's account ID type (we can't get away without mentioning it explicitly):
143	AccountId,
144	// We only want to allow teleports of known assets. We use non-zero issuance as an indication
145	// that this asset is known.
146	LocalMint<parachains_common::impls::NonZeroIssuance<AccountId, Assets>>,
147	// The account to use for tracking teleports.
148	CheckingAccount,
149>;
150
151/// Matcher for converting `ClassId`/`InstanceId` into a uniques asset.
152pub type UniquesConvertedConcreteId =
153	assets_common::UniquesConvertedConcreteId<UniquesPalletLocation>;
154
155/// Means for transacting unique assets.
156pub type UniquesTransactor = UniqueInstancesAdapter<
157	AccountId,
158	LocationToAccountId,
159	MatchInClassInstances<UniquesConvertedConcreteId>,
160	pallet_uniques::asset_ops::Item<Uniques>,
161>;
162
163/// `AssetId`/`Balance` converter for `ForeignAssets`.
164pub type ForeignAssetsConvertedConcreteId = assets_common::ForeignAssetsConvertedConcreteId<
165	(
166		// Ignore `TrustBackedAssets` explicitly
167		StartsWith<TrustBackedAssetsPalletLocation>,
168		// Ignore assets that start explicitly with our `GlobalConsensus(NetworkId)`, means:
169		// - foreign assets from our consensus should be: `Location {parents: 1, X*(Parachain(xyz),
170		//   ..)}`
171		// - foreign assets outside our consensus with the same `GlobalConsensus(NetworkId)` won't
172		//   be accepted here
173		StartsWithExplicitGlobalConsensus<UniversalLocationNetworkId>,
174	),
175	Balance,
176	xcm::v5::Location,
177>;
178
179/// Means for transacting foreign assets from different global consensus.
180pub type ForeignFungiblesTransactor = FungiblesAdapter<
181	// Use this fungibles implementation:
182	ForeignAssets,
183	// Use this currency when it is a fungible asset matching the given location or name:
184	ForeignAssetsConvertedConcreteId,
185	// Convert an XCM Location into a local account id:
186	LocationToAccountId,
187	// Our chain's account ID type (we can't get away without mentioning it explicitly):
188	AccountId,
189	// We don't need to check teleports here.
190	NoChecking,
191	// The account to use for tracking teleports.
192	CheckingAccount,
193>;
194
195/// `AssetId`/`Balance` converter for `PoolAssets`.
196pub type PoolAssetsConvertedConcreteId =
197	assets_common::PoolAssetsConvertedConcreteId<PoolAssetsPalletLocation, Balance>;
198
199/// Means for transacting asset conversion pool assets on this chain.
200pub type PoolFungiblesTransactor = FungiblesAdapter<
201	// Use this fungibles implementation:
202	PoolAssets,
203	// Use this currency when it is a fungible asset matching the given location or name:
204	PoolAssetsConvertedConcreteId,
205	// Convert an XCM Location into a local account id:
206	LocationToAccountId,
207	// Our chain's account ID type (we can't get away without mentioning it explicitly):
208	AccountId,
209	// We only want to allow teleports of known assets. We use non-zero issuance as an indication
210	// that this asset is known.
211	LocalMint<parachains_common::impls::NonZeroIssuance<AccountId, PoolAssets>>,
212	// The account to use for tracking teleports.
213	CheckingAccount,
214>;
215
216/// Means for transacting assets on this chain.
217pub type AssetTransactors = (
218	FungibleTransactor,
219	FungiblesTransactor,
220	ForeignFungiblesTransactor,
221	PoolFungiblesTransactor,
222	UniquesTransactor,
223);
224
225/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
226/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
227/// biases the kind of local `Origin` it will become.
228pub type XcmOriginToTransactDispatchOrigin = (
229	// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
230	// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
231	// foreign chains who want to have a local sovereign account on this chain which they control.
232	SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
233	// Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when
234	// recognised.
235	RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
236	// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
237	// recognised.
238	SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
239	// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
240	// transaction from the Root origin.
241	ParentAsSuperuser<RuntimeOrigin>,
242	// Native signed account converter; this just converts an `AccountId32` origin into a normal
243	// `RuntimeOrigin::Signed` origin of the same 32-byte value.
244	SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
245	// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
246	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			// Expected responses are OK.
267			AllowKnownQueryResponses<PolkadotXcm>,
268			// Allow XCMs with some computed origins to pass through.
269			WithComputedOrigin<
270				(
271					// If the message is one that immediately attempts to pay for execution, then
272					// allow it.
273					AllowTopLevelPaidExecutionFrom<Everything>,
274					// Parent, its pluralities (i.e. governance bodies), relay treasury pallet and
275					// BridgeHub get free execution.
276					AllowExplicitUnpaidExecutionFrom<(
277						ParentOrParentsPlurality,
278						Equals<RelayTreasuryLocation>,
279						Equals<bridging::SiblingBridgeHub>,
280					)>,
281					// Subscriptions for version tracking are OK.
282					AllowSubscriptionsFrom<ParentRelayOrSiblingParachains>,
283					// HRMP notifications from the relay chain are OK.
284					AllowHrmpNotificationsFromRelayChain,
285				),
286				UniversalLocation,
287				ConstU32<8>,
288			>,
289		),
290	>,
291>;
292
293/// Locations that will not be charged fees in the executor,
294/// either execution or delivery.
295/// We only waive fees for system functions, which these locations represent.
296pub type WaivedLocations = (
297	Equals<RootLocation>,
298	RelayOrOtherSystemParachains<AllSiblingSystemParachains, Runtime>,
299	Equals<RelayTreasuryLocation>,
300);
301
302// Asset Hub trusts only particular, pre-configured bridged locations from a different consensus
303// as reserve locations (we trust the Bridge Hub to relay the message that a reserve is being
304// held). On Rococo Asset Hub, we allow Westend Asset Hub to act as reserve for any asset native
305// to the Westend ecosystem. We also allow Ethereum contracts to act as reserves for the foreign
306// assets identified by the same respective contracts locations.
307pub type TrustedReserves = (
308	bridging::to_westend::WestendOrEthereumAssetFromAssetHubWestend,
309	bridging::to_ethereum::EthereumAssetFromEthereum,
310	IsForeignConcreteAsset<
311		NonTeleportableAssetFromTrustedReserve<AssetHubParaId, crate::ForeignAssets>,
312	>,
313);
314
315/// Cases where a remote origin is accepted as trusted Teleporter for a given asset:
316///
317/// - ROC with the parent Relay Chain and sibling system parachains; and
318/// - Sibling parachains' assets from where they originate (as `ForeignCreators`).
319pub type TrustedTeleporters = (
320	ConcreteAssetFromSystem<TokenLocation>,
321	IsForeignConcreteAsset<
322		TeleportableAssetWithTrustedReserve<AssetHubParaId, crate::ForeignAssets>,
323	>,
324);
325
326/// Defines origin aliasing rules for this chain.
327///
328/// - Allow any origin to alias into a child sub-location (equivalent to DescendOrigin),
329/// - Allow origins explicitly authorized by the alias target location.
330pub type TrustedAliasers = (AliasChildLocation, AuthorizedAliasers<Runtime>);
331
332/// Asset converter for pool assets.
333/// Used to convert one asset to another, when there is a pool available between the two.
334/// This type thus allows paying fees with any asset as long as there is a pool between said
335/// asset and the asset required for fee payment.
336pub type PoolAssetsExchanger = SingleAssetExchangeAdapter<
337	crate::AssetConversion,
338	crate::NativeAndNonPoolAssets,
339	(
340		TrustBackedAssetsAsLocation<TrustBackedAssetsPalletLocation, Balance, xcm::v5::Location>,
341		ForeignAssetsConvertedConcreteId,
342		// `ForeignAssetsConvertedConcreteId` excludes the relay token, so we add it back here.
343		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	// We allow any origin to alias into a child sub-location (equivalent to DescendOrigin).
413	type Aliasers = TrustedAliasers;
414	type TransactionalProcessor = FrameTransactionalProcessor;
415	type HrmpNewChannelOpenRequestHandler = ();
416	type HrmpChannelAcceptedHandler = ();
417	type HrmpChannelClosingHandler = ();
418	type XcmRecorder = PolkadotXcm;
419}
420
421/// Converts a local signed origin into an XCM location. Forms the basis for local origins
422/// sending/executing XCMs.
423pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
424
425pub type PriceForParentDelivery =
426	ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, ParachainSystem>;
427
428/// For routing XCM messages which do not cross local consensus boundary.
429type LocalXcmRouter = (
430	// Two routers - use UMP to communicate with the relay chain:
431	cumulus_primitives_utility::ParentAsUmp<ParachainSystem, PolkadotXcm, PriceForParentDelivery>,
432	// ..and XCMP to communicate with the sibling chains.
433	XcmpQueue,
434);
435
436/// The means for routing XCM messages which are not for local execution into the right message
437/// queues.
438pub type XcmRouter = WithUniqueTopic<(
439	LocalXcmRouter,
440	// Router which wraps and sends xcm to BridgeHub to be delivered to the Westend
441	// GlobalConsensus
442	ToWestendXcmRouter,
443	// Router which wraps and sends xcm to BridgeHub to be delivered to the Ethereum
444	// GlobalConsensus
445	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	// We want to disallow users sending (arbitrary) XCMs from this chain.
457	type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, ()>;
458	type XcmRouter = XcmRouter;
459	// We support local origins dispatching XCM executions.
460	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	// xcm_executor::Config::Aliasers also uses pallet_xcm::AuthorizedAliasers.
485	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
498/// All configuration related to bridging
499pub mod bridging {
500	use super::*;
501	use alloc::collections::btree_set::BTreeSet;
502	use assets_common::matching;
503
504	// common/shared parameters
505	parameter_types! {
506		/// Base price of every byte of the Rococo -> Westend message. Can be adjusted via
507		/// governance `set_storage` call.
508		///
509		/// Default value is our estimation of the:
510		///
511		/// 1) an approximate cost of XCM execution (`ExportMessage` and surroundings) at Rococo bridge hub;
512		///
513		/// 2) the approximate cost of Rococo -> Westend message delivery transaction on Westend Bridge Hub,
514		///    converted into ROCs using 1:1 conversion rate;
515		///
516		/// 3) the approximate cost of Rococo -> Westend message confirmation transaction on Rococo Bridge Hub.
517		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		/// Price of every byte of the Rococo -> Westend message. Can be adjusted via
522		/// governance `set_storage` call.
523		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		/// Router expects payment with this `AssetId`.
528		/// (`AssetId` has to be aligned with `BridgeTable`)
529		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			/// Set up exporters configuration.
569			/// `Option<Asset>` represents static "base fee" which is used for total delivery fee calculation.
570			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					// base delivery fee to local `BridgeHub`
578					Some((
579						XcmBridgeHubRouterFeeAssetId::get(),
580						XcmBridgeHubRouterBaseFee::get(),
581					).into())
582				)
583			];
584
585			/// Universal aliases
586			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		/// Allow any asset native to the Westend or Ethereum ecosystems if it comes from Westend
600		/// Asset Hub.
601		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			/// User fee for ERC20 token transfer back to Ethereum.
612			/// (initially was calculated by test `OutboundQueue::calculate_fees` - ETH/ROC 1/400 and fee_per_gas 20 GWEI = 2200698000000 + *25%)
613			/// Needs to be more than fee calculated from DefaultFeeConfig FeeConfigRecord in snowbridge:parachain/pallets/outbound-queue/src/lib.rs
614			/// Polkadot uses 10 decimals, Kusama and Rococo 12 decimals.
615			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			/// Set up exporters configuration.
626			/// `Option<Asset>` represents static "base fee" which is used for total delivery fee calculation.
627			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			/// Universal aliases
640			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	/// Benchmarks helper for bridging configuration.
658	#[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}