referrerpolicy=no-referrer-when-downgrade

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