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