bridge_hub_rococo_runtime/
xcm_config.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Cumulus.
3
4// Cumulus is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Cumulus is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Cumulus.  If not, see <http://www.gnu.org/licenses/>.
16
17use super::{
18	AccountId, AllPalletsWithSystem, Balances, BaseDeliveryFee, FeeAssetId, ParachainInfo,
19	ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
20	TransactionByteFee, WeightToFee, XcmOverBridgeHubWestend, XcmOverRococoBulletin, XcmpQueue,
21};
22
23use core::marker::PhantomData;
24use frame_support::{
25	parameter_types,
26	traits::{tokens::imbalance::ResolveTo, ConstU32, Contains, Equals, Everything, Nothing},
27};
28use frame_system::EnsureRoot;
29use pallet_collator_selection::StakingPotAccountId;
30use pallet_xcm::XcmPassthrough;
31use parachains_common::{
32	xcm_config::{
33		AllSiblingSystemParachains, ConcreteAssetFromSystem, ParentRelayOrSiblingParachains,
34		RelayOrOtherSystemParachains,
35	},
36	TREASURY_PALLET_ID,
37};
38use polkadot_parachain_primitives::primitives::Sibling;
39use polkadot_runtime_common::xcm_sender::ExponentialPrice;
40use snowbridge_runtime_common::XcmExportFeeToSibling;
41use sp_runtime::traits::AccountIdConversion;
42use testnet_parachains_constants::rococo::snowbridge::EthereumNetwork;
43use xcm::latest::prelude::*;
44use xcm_builder::{
45	AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
46	AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
47	DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FrameTransactionalProcessor,
48	FungibleAdapter, HandleFee, IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
49	SendXcmFeeToAccount, SiblingParachainAsNative, SiblingParachainConvertsVia,
50	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
51	TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
52};
53use xcm_executor::{
54	traits::{FeeManager, FeeReason, FeeReason::Export},
55	XcmExecutor,
56};
57
58parameter_types! {
59	pub const TokenLocation: Location = Location::parent();
60	pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
61	pub RelayNetwork: NetworkId = NetworkId::Rococo;
62	pub UniversalLocation: InteriorLocation =
63		[GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into())].into();
64	pub const MaxInstructions: u32 = 100;
65	pub const MaxAssetsIntoHolding: u32 = 64;
66	pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
67	pub RelayTreasuryLocation: Location = (Parent, PalletInstance(rococo_runtime_constants::TREASURY_PALLET_ID)).into();
68	pub SiblingPeople: Location = (Parent, Parachain(rococo_runtime_constants::system_parachain::PEOPLE_ID)).into();
69}
70
71/// Type for specifying how a `Location` can be converted into an `AccountId`. This is used
72/// when determining ownership of accounts for asset transacting and when attempting to use XCM
73/// `Transact` in order to determine the dispatch Origin.
74pub type LocationToAccountId = (
75	// The parent (Relay-chain) origin converts to the parent `AccountId`.
76	ParentIsPreset<AccountId>,
77	// Sibling parachain origins convert to AccountId via the `ParaId::into`.
78	SiblingParachainConvertsVia<Sibling, AccountId>,
79	// Straight up local `AccountId32` origins just alias directly to `AccountId`.
80	AccountId32Aliases<RelayNetwork, AccountId>,
81);
82
83/// Means for transacting the native currency on this chain.
84pub type FungibleTransactor = FungibleAdapter<
85	// Use this currency:
86	Balances,
87	// Use this currency when it is a fungible asset matching the given location or name:
88	IsConcrete<TokenLocation>,
89	// Do a simple punn to convert an AccountId32 Location into a native chain account ID:
90	LocationToAccountId,
91	// Our chain's account ID type (we can't get away without mentioning it explicitly):
92	AccountId,
93	// We don't track any teleports of `Balances`.
94	(),
95>;
96
97/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
98/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
99/// biases the kind of local `Origin` it will become.
100pub type XcmOriginToTransactDispatchOrigin = (
101	// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
102	// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
103	// foreign chains who want to have a local sovereign account on this chain which they control.
104	SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
105	// Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when
106	// recognized.
107	RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
108	// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
109	// recognized.
110	SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
111	// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
112	// transaction from the Root origin.
113	ParentAsSuperuser<RuntimeOrigin>,
114	// Native signed account converter; this just converts an `AccountId32` origin into a normal
115	// `RuntimeOrigin::Signed` origin of the same 32-byte value.
116	SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
117	// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
118	XcmPassthrough<RuntimeOrigin>,
119);
120
121pub struct ParentOrParentsPlurality;
122impl Contains<Location> for ParentOrParentsPlurality {
123	fn contains(location: &Location) -> bool {
124		matches!(location.unpack(), (1, []) | (1, [Plurality { .. }]))
125	}
126}
127
128pub type Barrier = TrailingSetTopicAsId<
129	DenyThenTry<
130		DenyReserveTransferToRelayChain,
131		(
132			// Allow local users to buy weight credit.
133			TakeWeightCredit,
134			// Expected responses are OK.
135			AllowKnownQueryResponses<PolkadotXcm>,
136			WithComputedOrigin<
137				(
138					// If the message is one that immediately attempts to pay for execution, then
139					// allow it.
140					AllowTopLevelPaidExecutionFrom<Everything>,
141					// Parent, its pluralities (i.e. governance bodies), relay treasury pallet
142					// and sibling People get free execution.
143					AllowExplicitUnpaidExecutionFrom<(
144						ParentOrParentsPlurality,
145						Equals<RelayTreasuryLocation>,
146						Equals<SiblingPeople>,
147					)>,
148					// Subscriptions for version tracking are OK.
149					AllowSubscriptionsFrom<ParentRelayOrSiblingParachains>,
150					// HRMP notifications from the relay chain are OK.
151					AllowHrmpNotificationsFromRelayChain,
152				),
153				UniversalLocation,
154				ConstU32<8>,
155			>,
156		),
157	>,
158>;
159
160/// Locations that will not be charged fees in the executor,
161/// either execution or delivery.
162/// We only waive fees for system functions, which these locations represent.
163pub type WaivedLocations = (
164	RelayOrOtherSystemParachains<AllSiblingSystemParachains, Runtime>,
165	Equals<RelayTreasuryLocation>,
166);
167
168/// Cases where a remote origin is accepted as trusted Teleporter for a given asset:
169/// - NativeToken with the parent Relay Chain and sibling parachains.
170pub type TrustedTeleporters = ConcreteAssetFromSystem<TokenLocation>;
171
172pub struct XcmConfig;
173impl xcm_executor::Config for XcmConfig {
174	type RuntimeCall = RuntimeCall;
175	type XcmSender = XcmRouter;
176	type AssetTransactor = FungibleTransactor;
177	type OriginConverter = XcmOriginToTransactDispatchOrigin;
178	// BridgeHub does not recognize a reserve location for any asset. Users must teleport Native
179	// token where allowed (e.g. with the Relay Chain).
180	type IsReserve = ();
181	type IsTeleporter = TrustedTeleporters;
182	type UniversalLocation = UniversalLocation;
183	type Barrier = Barrier;
184	type Weigher = WeightInfoBounds<
185		crate::weights::xcm::BridgeHubRococoXcmWeight<RuntimeCall>,
186		RuntimeCall,
187		MaxInstructions,
188	>;
189	type Trader = UsingComponents<
190		WeightToFee,
191		TokenLocation,
192		AccountId,
193		Balances,
194		ResolveTo<StakingPotAccountId<Runtime>, Balances>,
195	>;
196	type ResponseHandler = PolkadotXcm;
197	type AssetTrap = PolkadotXcm;
198	type AssetLocker = ();
199	type AssetExchanger = ();
200	type AssetClaims = PolkadotXcm;
201	type SubscriptionService = PolkadotXcm;
202	type PalletInstancesInfo = AllPalletsWithSystem;
203	type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
204	type FeeManager = XcmFeeManagerFromComponentsBridgeHub<
205		WaivedLocations,
206		(
207			XcmExportFeeToSibling<
208				bp_rococo::Balance,
209				AccountId,
210				TokenLocation,
211				EthereumNetwork,
212				Self::AssetTransactor,
213				crate::EthereumOutboundQueue,
214			>,
215			SendXcmFeeToAccount<Self::AssetTransactor, TreasuryAccount>,
216		),
217	>;
218	type MessageExporter = (
219		XcmOverBridgeHubWestend,
220		XcmOverRococoBulletin,
221		crate::bridge_to_ethereum_config::SnowbridgeExporter,
222	);
223	type UniversalAliases = Nothing;
224	type CallDispatcher = RuntimeCall;
225	type SafeCallFilter = Everything;
226	type Aliasers = Nothing;
227	type TransactionalProcessor = FrameTransactionalProcessor;
228	type HrmpNewChannelOpenRequestHandler = ();
229	type HrmpChannelAcceptedHandler = ();
230	type HrmpChannelClosingHandler = ();
231	type XcmRecorder = PolkadotXcm;
232}
233
234pub type PriceForParentDelivery =
235	ExponentialPrice<FeeAssetId, BaseDeliveryFee, TransactionByteFee, ParachainSystem>;
236
237/// Converts a local signed origin into an XCM location.
238/// Forms the basis for local origins sending/executing XCMs.
239pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
240
241/// The means for routing XCM messages which are not for local execution into the right message
242/// queues.
243pub type XcmRouter = WithUniqueTopic<(
244	// Two routers - use UMP to communicate with the relay chain:
245	cumulus_primitives_utility::ParentAsUmp<ParachainSystem, PolkadotXcm, PriceForParentDelivery>,
246	// ..and XCMP to communicate with the sibling chains.
247	XcmpQueue,
248)>;
249
250impl pallet_xcm::Config for Runtime {
251	type RuntimeEvent = RuntimeEvent;
252	type XcmRouter = XcmRouter;
253	// We want to disallow users sending (arbitrary) XCMs from this chain.
254	type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, ()>;
255	// We support local origins dispatching XCM executions.
256	type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
257	type XcmExecuteFilter = Everything;
258	type XcmExecutor = XcmExecutor<XcmConfig>;
259	type XcmTeleportFilter = Everything;
260	type XcmReserveTransferFilter = Nothing; // This parachain is not meant as a reserve location.
261	type Weigher = WeightInfoBounds<
262		crate::weights::xcm::BridgeHubRococoXcmWeight<RuntimeCall>,
263		RuntimeCall,
264		MaxInstructions,
265	>;
266	type UniversalLocation = UniversalLocation;
267	type RuntimeOrigin = RuntimeOrigin;
268	type RuntimeCall = RuntimeCall;
269	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
270	type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
271	type Currency = Balances;
272	type CurrencyMatcher = ();
273	type TrustedLockers = ();
274	type SovereignAccountOf = LocationToAccountId;
275	type MaxLockers = ConstU32<8>;
276	type WeightInfo = crate::weights::pallet_xcm::WeightInfo<Runtime>;
277	type AdminOrigin = EnsureRoot<AccountId>;
278	type MaxRemoteLockConsumers = ConstU32<0>;
279	type RemoteLockConsumerIdentifier = ();
280}
281
282impl cumulus_pallet_xcm::Config for Runtime {
283	type RuntimeEvent = RuntimeEvent;
284	type XcmExecutor = XcmExecutor<XcmConfig>;
285}
286
287pub struct XcmFeeManagerFromComponentsBridgeHub<WaivedLocations, HandleFee>(
288	PhantomData<(WaivedLocations, HandleFee)>,
289);
290impl<WaivedLocations: Contains<Location>, FeeHandler: HandleFee> FeeManager
291	for XcmFeeManagerFromComponentsBridgeHub<WaivedLocations, FeeHandler>
292{
293	fn is_waived(origin: Option<&Location>, fee_reason: FeeReason) -> bool {
294		let Some(loc) = origin else { return false };
295		if let Export { network, destination: Here } = fee_reason {
296			if network == EthereumNetwork::get() {
297				return false
298			}
299		}
300		WaivedLocations::contains(loc)
301	}
302
303	fn handle_fee(fee: Assets, context: Option<&XcmContext>, reason: FeeReason) {
304		FeeHandler::handle_fee(fee, context, reason);
305	}
306}