1
// Copyright 2021 Parity Technologies (UK) Ltd.
2
// This file is part of Polkadot.
3

            
4
// Polkadot 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
// Polkadot 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 Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
//! Relay chain runtime mock.
18

            
19
use frame_support::traits::Disabled;
20
use frame_support::{
21
	construct_runtime, parameter_types,
22
	traits::{AsEnsureOriginWithArg, Contains, ContainsPair, Everything, Get, Nothing},
23
	weights::Weight,
24
};
25
use frame_system::{EnsureRoot, EnsureSigned};
26
use polkadot_core_primitives::BlockNumber as RelayBlockNumber;
27
use sp_core::H256;
28
use sp_runtime::{
29
	traits::{ConstU32, Hash, IdentityLookup},
30
	AccountId32,
31
};
32

            
33
use polkadot_parachain::primitives::Id as ParaId;
34
use polkadot_parachain::primitives::Sibling;
35
use sp_std::convert::TryFrom;
36
use xcm::latest::prelude::*;
37
use xcm::VersionedXcm;
38
use xcm_builder::{
39
	AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
40
	AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex,
41
	ConvertedConcreteId, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, FungibleAdapter,
42
	FungiblesAdapter, IsConcrete, NoChecking, ParentAsSuperuser, ParentIsPreset,
43
	RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
44
	SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
45
};
46
use xcm_executor::{traits::JustTry, Config, XcmExecutor};
47
use xcm_simulator::{
48
	DmpMessageHandlerT as DmpMessageHandler, XcmpMessageFormat,
49
	XcmpMessageHandlerT as XcmpMessageHandler,
50
};
51
pub type AccountId = AccountId32;
52
pub type Balance = u128;
53
pub type AssetId = u128;
54

            
55
parameter_types! {
56
	pub const BlockHashCount: u32 = 250;
57
}
58

            
59
impl frame_system::Config for Runtime {
60
	type RuntimeOrigin = RuntimeOrigin;
61
	type RuntimeCall = RuntimeCall;
62
	type RuntimeTask = RuntimeTask;
63
	type Nonce = u64;
64
	type Block = Block;
65
	type Hash = H256;
66
	type Hashing = ::sp_runtime::traits::BlakeTwo256;
67
	type AccountId = AccountId;
68
	type Lookup = IdentityLookup<Self::AccountId>;
69
	type RuntimeEvent = RuntimeEvent;
70
	type BlockHashCount = BlockHashCount;
71
	type BlockWeights = ();
72
	type BlockLength = ();
73
	type Version = ();
74
	type PalletInfo = PalletInfo;
75
	type AccountData = pallet_balances::AccountData<Balance>;
76
	type OnNewAccount = ();
77
	type OnKilledAccount = ();
78
	type DbWeight = ();
79
	type BaseCallFilter = Everything;
80
	type SystemWeightInfo = ();
81
	type SS58Prefix = ();
82
	type OnSetCode = ();
83
	type MaxConsumers = frame_support::traits::ConstU32<16>;
84
	type SingleBlockMigrations = ();
85
	type MultiBlockMigrator = ();
86
	type PreInherents = ();
87
	type PostInherents = ();
88
	type PostTransactions = ();
89
	type ExtensionsWeightInfo = ();
90
}
91

            
92
parameter_types! {
93
	pub ExistentialDeposit: Balance = 1;
94
	pub const MaxLocks: u32 = 50;
95
	pub const MaxReserves: u32 = 50;
96
}
97

            
98
impl pallet_balances::Config for Runtime {
99
	type MaxLocks = MaxLocks;
100
	type Balance = Balance;
101
	type RuntimeEvent = RuntimeEvent;
102
	type DustRemoval = ();
103
	type ExistentialDeposit = ExistentialDeposit;
104
	type AccountStore = System;
105
	type WeightInfo = ();
106
	type MaxReserves = MaxReserves;
107
	type ReserveIdentifier = [u8; 8];
108
	type RuntimeHoldReason = ();
109
	type FreezeIdentifier = ();
110
	type MaxFreezes = ();
111
	type RuntimeFreezeReason = ();
112
	type DoneSlashHandler = ();
113
}
114

            
115
// Required for runtime benchmarks
116
pallet_assets::runtime_benchmarks_enabled! {
117
	pub struct BenchmarkHelper;
118
	impl<AssetIdParameter> pallet_assets::BenchmarkHelper<AssetIdParameter> for BenchmarkHelper
119
	where
120
		AssetIdParameter: From<u128>,
121
	{
122
		fn create_asset_id_parameter(id: u32) -> AssetIdParameter {
123
			(id as u128).into()
124
		}
125
	}
126
}
127

            
128
parameter_types! {
129
	pub const AssetDeposit: Balance = 0; // 1 UNIT deposit to create asset
130
	pub const ApprovalDeposit: Balance = 0;
131
	pub const AssetsStringLimit: u32 = 50;
132
	/// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1)
133
	// https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271
134
	pub const MetadataDepositBase: Balance = 0;
135
	pub const MetadataDepositPerByte: Balance = 0;
136
	pub const ExecutiveBody: BodyId = BodyId::Executive;
137
	pub const AssetAccountDeposit: Balance = 0;
138
}
139

            
140
impl pallet_assets::Config for Runtime {
141
	type RuntimeEvent = RuntimeEvent;
142
	type Balance = Balance;
143
	type AssetId = AssetId;
144
	type Currency = Balances;
145
	type ForceOrigin = EnsureRoot<AccountId>;
146
	type AssetDeposit = AssetDeposit;
147
	type MetadataDepositBase = MetadataDepositBase;
148
	type MetadataDepositPerByte = MetadataDepositPerByte;
149
	type ApprovalDeposit = ApprovalDeposit;
150
	type StringLimit = AssetsStringLimit;
151
	type Freezer = ();
152
	type Extra = ();
153
	type AssetAccountDeposit = AssetAccountDeposit;
154
	type WeightInfo = ();
155
	type RemoveItemsLimit = ConstU32<656>;
156
	type AssetIdParameter = AssetId;
157
	type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
158
	type CallbackHandle = ();
159
	type Holder = ();
160
	pallet_assets::runtime_benchmarks_enabled! {
161
		type BenchmarkHelper = BenchmarkHelper;
162
	}
163
}
164

            
165
parameter_types! {
166
	pub const KsmLocation: Location = Location::parent();
167
	pub const RelayNetwork: NetworkId = NetworkId::Kusama;
168
	pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
169
	pub UniversalLocation: InteriorLocation =
170
		[GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())].into();
171
	pub Local: Location = Here.into();
172
	pub CheckingAccount: AccountId = PolkadotXcm::check_account();
173
	pub KsmPerSecond: (xcm::latest::prelude::AssetId, u128, u128) =
174
		(AssetId(KsmLocation::get()), 1, 1);
175
}
176

            
177
/// Type for specifying how a `Location` can be converted into an `AccountId`. This is used
178
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
179
/// `Transact` in order to determine the dispatch Origin.
180
pub type LocationToAccountId = (
181
	// The parent (Relay-chain) origin converts to the default `AccountId`.
182
	ParentIsPreset<AccountId>,
183
	// Sibling parachain origins convert to AccountId via the `ParaId::into`.
184
	SiblingParachainConvertsVia<Sibling, AccountId>,
185
	// Straight up local `AccountId32` origins just alias directly to `AccountId`.
186
	AccountId32Aliases<RelayNetwork, AccountId>,
187
);
188

            
189
/// Means for transacting the native currency on this chain.
190
pub type CurrencyTransactor = FungibleAdapter<
191
	// Use this currency:
192
	Balances,
193
	// Use this currency when it is a fungible asset matching the given location or name:
194
	IsConcrete<KsmLocation>,
195
	// Convert an XCM Location into a local account id:
196
	LocationToAccountId,
197
	// Our chain's account ID type (we can't get away without mentioning it explicitly):
198
	AccountId,
199
	// We don't track any teleports of `Balances`.
200
	(),
201
>;
202

            
203
/// Means for transacting assets besides the native currency on this chain.
204
pub type FungiblesTransactor = FungiblesAdapter<
205
	// Use this fungibles implementation:
206
	Assets,
207
	// Use this currency when it is a fungible asset matching the given location or name:
208
	ConvertedConcreteId<
209
		AssetId,
210
		Balance,
211
		AsPrefixedGeneralIndex<PrefixChanger, AssetId, JustTry>,
212
		JustTry,
213
	>,
214
	// Convert an XCM Location into a local account id:
215
	LocationToAccountId,
216
	// Our chain's account ID type (we can't get away without mentioning it explicitly):
217
	AccountId,
218
	// We only want to allow teleports of known assets. We use non-zero issuance as an indication
219
	// that this asset is known.
220
	NoChecking,
221
	// The account to use for tracking teleports.
222
	CheckingAccount,
223
>;
224
/// Means for transacting assets on this chain.
225
pub type AssetTransactors = (CurrencyTransactor, FungiblesTransactor);
226

            
227
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
228
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
229
/// biases the kind of local `Origin` it will become.
230
pub type XcmOriginToTransactDispatchOrigin = (
231
	// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
232
	// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
233
	// foreign chains who want to have a local sovereign account on this chain which they control.
234
	SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
235
	// Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when
236
	// recognised.
237
	RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
238
	// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
239
	// recognised.
240
	SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
241
	// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
242
	// transaction from the Root origin.
243
	ParentAsSuperuser<RuntimeOrigin>,
244
	// Native signed account converter; this just converts an `AccountId32` origin into a normal
245
	// `RuntimeOrigin::signed` origin of the same 32-byte value.
246
	SignedAccountId32AsNative<RelayNetwork, RuntimeOrigin>,
247
	// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
248
	pallet_xcm::XcmPassthrough<RuntimeOrigin>,
249
);
250

            
251
parameter_types! {
252
	// One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate.
253
	pub UnitWeightCost: Weight = Weight::from_parts(100u64, 100u64);
254
	pub const MaxInstructions: u32 = 100;
255
}
256

            
257
pub struct ParentOrParentsExecutivePlurality;
258
impl Contains<Location> for ParentOrParentsExecutivePlurality {
259
	fn contains(location: &Location) -> bool {
260
		matches!(
261
			location.unpack(),
262
			(1, [])
263
				| (
264
					1,
265
					[Plurality {
266
						id: BodyId::Executive,
267
						..
268
					}]
269
				)
270
		)
271
	}
272
}
273

            
274
pub struct ParentOrSiblings;
275
impl Contains<Location> for ParentOrSiblings {
276
	fn contains(location: &Location) -> bool {
277
		matches!(location.unpack(), (1, []) | (1, [_]))
278
	}
279
}
280

            
281
pub type Barrier = (
282
	TakeWeightCredit,
283
	AllowTopLevelPaidExecutionFrom<Everything>,
284
	// Parent and its exec plurality get free execution
285
	AllowUnpaidExecutionFrom<ParentOrParentsExecutivePlurality>,
286
	// Expected responses are OK.
287
	AllowKnownQueryResponses<PolkadotXcm>,
288
	// Subscriptions for version tracking are OK.
289
	AllowSubscriptionsFrom<ParentOrSiblings>,
290
);
291

            
292
parameter_types! {
293
	pub MatcherLocation: Location = Location::here();
294
	pub const MaxAssetsIntoHolding: u32 = 64;
295
	pub const RelayTokenLocation: Location = Location::parent();
296
}
297

            
298
// Copied from:
299
//
300
// https://github.com/paritytech/polkadot-sdk/blob/f4eb41773611008040c9d4d8a8e6b7323eccfca1/cumulus
301
// /parachains/common/src/xcm_config.rs#L118
302
//
303
// The difference with the original "ConcreteAssetFromSystem" (which is used by AssetHub),
304
// is that in our tests we only need to check if the asset matches the relay one.
305
pub struct ConcreteAssetFromRelay<AssetLocation>(sp_std::marker::PhantomData<AssetLocation>);
306
impl<AssetLocation: Get<Location>> ContainsPair<Asset, Location>
307
	for ConcreteAssetFromRelay<AssetLocation>
308
{
309
5
	fn contains(asset: &Asset, origin: &Location) -> bool {
310
5
		let is_relay = match origin.unpack() {
311
			// The Relay Chain
312
5
			(1, []) => true,
313
			// Others
314
			_ => false,
315
		};
316
5
		asset.id.0 == AssetLocation::get() && is_relay
317
5
	}
318
}
319

            
320
pub type TrustedTeleporters = (ConcreteAssetFromRelay<RelayTokenLocation>,);
321

            
322
pub struct XcmConfig;
323
impl Config for XcmConfig {
324
	type RuntimeCall = RuntimeCall;
325
	type XcmSender = XcmRouter;
326
	type AssetTransactor = AssetTransactors;
327
	type OriginConverter = XcmOriginToTransactDispatchOrigin;
328
	type IsReserve = xcm_primitives::MultiNativeAsset<xcm_primitives::RelativeReserveProvider>;
329
	type IsTeleporter = TrustedTeleporters;
330
	type UniversalLocation = UniversalLocation;
331
	type Barrier = Barrier;
332
	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
333
	type Trader = FixedRateOfFungible<KsmPerSecond, ()>;
334
	type ResponseHandler = PolkadotXcm;
335
	type AssetTrap = PolkadotXcm;
336
	type AssetClaims = PolkadotXcm;
337
	type SubscriptionService = PolkadotXcm;
338
	type CallDispatcher = RuntimeCall;
339
	type AssetLocker = ();
340
	type AssetExchanger = ();
341
	type PalletInstancesInfo = ();
342
	type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
343
	type FeeManager = ();
344
	type MessageExporter = ();
345
	type UniversalAliases = Nothing;
346
	type SafeCallFilter = Everything;
347
	type Aliasers = Nothing;
348
	type TransactionalProcessor = ();
349
	type HrmpNewChannelOpenRequestHandler = ();
350
	type HrmpChannelAcceptedHandler = ();
351
	type HrmpChannelClosingHandler = ();
352
	type XcmRecorder = PolkadotXcm;
353
	type XcmEventEmitter = PolkadotXcm;
354
}
355

            
356
/// No local origins on this chain are allowed to dispatch XCM sends/executions.
357
pub type LocalOriginToLocation = SignedToAccountId32<RuntimeOrigin, AccountId, RelayNetwork>;
358

            
359
pub type XcmRouter = super::ParachainXcmRouter<MsgQueue>;
360

            
361
impl pallet_xcm::Config for Runtime {
362
	type RuntimeEvent = RuntimeEvent;
363
	type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
364
	type XcmRouter = XcmRouter;
365
	type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
366
	type XcmExecuteFilter = Nothing;
367
	type XcmExecutor = XcmExecutor<XcmConfig>;
368
	type XcmTeleportFilter = Everything;
369
	type XcmReserveTransferFilter = Everything;
370
	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
371
	type UniversalLocation = UniversalLocation;
372
	type RuntimeOrigin = RuntimeOrigin;
373
	type RuntimeCall = RuntimeCall;
374
	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
375
	type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
376
	type Currency = Balances;
377
	type CurrencyMatcher = IsConcrete<MatcherLocation>;
378
	type TrustedLockers = ();
379
	type SovereignAccountOf = ();
380
	type MaxLockers = ConstU32<8>;
381
	type WeightInfo = pallet_xcm::TestWeightInfo;
382
	type MaxRemoteLockConsumers = ConstU32<0>;
383
	type RemoteLockConsumerIdentifier = ();
384
	type AdminOrigin = frame_system::EnsureRoot<AccountId>;
385
	type AuthorizedAliasConsideration = Disabled;
386
}
387

            
388
impl cumulus_pallet_xcm::Config for Runtime {
389
	type RuntimeEvent = RuntimeEvent;
390
	type XcmExecutor = XcmExecutor<XcmConfig>;
391
}
392

            
393
#[frame_support::pallet]
394
pub mod mock_msg_queue {
395
	use super::*;
396
	use frame_support::pallet_prelude::*;
397

            
398
	#[pallet::config]
399
	pub trait Config: frame_system::Config {
400
		type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
401
	}
402

            
403
	#[pallet::call]
404
	impl<T: Config> Pallet<T> {}
405

            
406
	#[pallet::pallet]
407
	pub struct Pallet<T>(_);
408

            
409
	#[pallet::storage]
410
	#[pallet::getter(fn parachain_id)]
411
	pub(super) type ParachainId<T: Config> = StorageValue<_, ParaId, ValueQuery>;
412

            
413
	impl<T: Config> Get<ParaId> for Pallet<T> {
414
14
		fn get() -> ParaId {
415
14
			Self::parachain_id()
416
14
		}
417
	}
418

            
419
	pub type MessageId = [u8; 32];
420

            
421
	#[pallet::event]
422
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
423
	pub enum Event<T: Config> {
424
		// XCMP
425
		/// Some XCM was executed OK.
426
		Success(Option<T::Hash>),
427
		/// Some XCM failed.
428
		Fail(Option<T::Hash>, InstructionError),
429
		/// Bad XCM version used.
430
		BadVersion(Option<T::Hash>),
431
		/// Bad XCM format used.
432
		BadFormat(Option<T::Hash>),
433

            
434
		// DMP
435
		/// Downward message is invalid XCM.
436
		InvalidFormat(MessageId),
437
		/// Downward message is unsupported version of XCM.
438
		UnsupportedVersion(MessageId),
439
		/// Downward message executed with the given outcome.
440
		ExecutedDownward(MessageId, Outcome),
441
	}
442

            
443
	impl<T: Config> Pallet<T> {
444
82
		pub fn set_para_id(para_id: ParaId) {
445
82
			ParachainId::<T>::put(para_id);
446
82
		}
447

            
448
6
		fn handle_xcmp_message(
449
6
			sender: ParaId,
450
6
			_sent_at: RelayBlockNumber,
451
6
			xcm: VersionedXcm<T::RuntimeCall>,
452
6
			max_weight: Weight,
453
6
		) -> Result<Weight, InstructionError> {
454
6
			let hash = Encode::using_encoded(&xcm, T::Hashing::hash);
455
6
			let (result, event) = match Xcm::<T::RuntimeCall>::try_from(xcm) {
456
6
				Ok(xcm) => {
457
6
					let location = Location::new(1, [Parachain(sender.into())]);
458
6
					let mut id = [0u8; 32];
459
6
					id.copy_from_slice(hash.as_ref());
460
6
					match T::XcmExecutor::prepare_and_execute(
461
6
						location,
462
6
						xcm,
463
6
						&mut id,
464
6
						max_weight,
465
6
						Weight::zero(),
466
6
					) {
467
						Outcome::Error(error) => {
468
							(Err(error.clone()), Event::Fail(Some(hash), error))
469
						}
470
6
						Outcome::Complete { used } => (Ok(used), Event::Success(Some(hash))),
471
						// As far as the caller is concerned, this was dispatched without error, so
472
						// we just report the weight used.
473
						Outcome::Incomplete { used, error } => {
474
							(Ok(used), Event::Fail(Some(hash), error))
475
						}
476
					}
477
				}
478
				Err(()) => (
479
					Err(InstructionError {
480
						error: XcmError::UnhandledXcmVersion,
481
						index: 0,
482
					}),
483
					Event::BadVersion(Some(hash)),
484
				),
485
			};
486
6
			Self::deposit_event(event);
487
6
			result
488
6
		}
489
	}
490

            
491
	impl<T: Config> XcmpMessageHandler for Pallet<T> {
492
6
		fn handle_xcmp_messages<'a, I: Iterator<Item = (ParaId, RelayBlockNumber, &'a [u8])>>(
493
6
			iter: I,
494
6
			max_weight: Weight,
495
6
		) -> Weight {
496
12
			for (sender, sent_at, data) in iter {
497
6
				let mut data_ref = data;
498
6
				let _ = XcmpMessageFormat::decode(&mut data_ref)
499
6
					.expect("Simulator encodes with versioned xcm format; qed");
500

            
501
6
				let mut remaining_fragments = &data_ref[..];
502
12
				while !remaining_fragments.is_empty() {
503
6
					if let Ok(xcm) =
504
6
						VersionedXcm::<T::RuntimeCall>::decode(&mut remaining_fragments)
505
6
					{
506
6
						let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight);
507
6
					} else {
508
						debug_assert!(false, "Invalid incoming XCMP message data");
509
					}
510
				}
511
			}
512
6
			max_weight
513
6
		}
514
	}
515

            
516
	impl<T: Config> DmpMessageHandler for Pallet<T> {
517
5
		fn handle_dmp_messages(
518
5
			iter: impl Iterator<Item = (RelayBlockNumber, Vec<u8>)>,
519
5
			limit: Weight,
520
5
		) -> Weight {
521
5
			for (_i, (_sent_at, data)) in iter.enumerate() {
522
5
				let mut id = sp_io::hashing::blake2_256(&data[..]);
523
5
				let maybe_msg = VersionedXcm::<T::RuntimeCall>::decode(&mut &data[..])
524
5
					.map(Xcm::<T::RuntimeCall>::try_from);
525
5
				match maybe_msg {
526
					Err(_) => {
527
						Self::deposit_event(Event::InvalidFormat(id));
528
					}
529
					Ok(Err(())) => {
530
						Self::deposit_event(Event::UnsupportedVersion(id));
531
					}
532
5
					Ok(Ok(x)) => {
533
5
						let outcome = T::XcmExecutor::prepare_and_execute(
534
5
							Parent,
535
5
							x,
536
5
							&mut id,
537
5
							limit,
538
5
							Weight::zero(),
539
5
						);
540
5

            
541
5
						Self::deposit_event(Event::ExecutedDownward(id, outcome));
542
5
					}
543
				}
544
			}
545
5
			limit
546
5
		}
547
	}
548
}
549
impl mock_msg_queue::Config for Runtime {
550
	type XcmExecutor = XcmExecutor<XcmConfig>;
551
}
552

            
553
// Pallet to cover test cases for change https://github.com/paritytech/cumulus/pull/831
554
#[frame_support::pallet]
555
pub mod mock_statemint_prefix {
556
	use super::*;
557
	use frame_support::pallet_prelude::*;
558

            
559
	#[pallet::config]
560
	pub trait Config: frame_system::Config {}
561

            
562
	#[pallet::call]
563
	impl<T: Config> Pallet<T> {}
564

            
565
	#[pallet::pallet]
566
	#[pallet::without_storage_info]
567
	pub struct Pallet<T>(_);
568

            
569
	#[pallet::storage]
570
	#[pallet::getter(fn current_prefix)]
571
	pub(super) type CurrentPrefix<T: Config> = StorageValue<_, Location, ValueQuery>;
572

            
573
	impl<T: Config> Get<Location> for Pallet<T> {
574
15
		fn get() -> Location {
575
15
			Self::current_prefix()
576
15
		}
577
	}
578

            
579
	#[pallet::event]
580
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
581
	pub enum Event<T: Config> {
582
		// Changed Prefix
583
		PrefixChanged(Location),
584
	}
585

            
586
	impl<T: Config> Pallet<T> {
587
4
		pub fn set_prefix(prefix: Location) {
588
4
			CurrentPrefix::<T>::put(&prefix);
589
4
			Self::deposit_event(Event::PrefixChanged(prefix));
590
4
		}
591
	}
592
}
593

            
594
impl mock_statemint_prefix::Config for Runtime {}
595

            
596
type Block = frame_system::mocking::MockBlockU32<Runtime>;
597
construct_runtime!(
598
	pub enum Runtime	{
599
		System: frame_system,
600
		Balances: pallet_balances,
601
		PolkadotXcm: pallet_xcm,
602
		CumulusXcm: cumulus_pallet_xcm,
603
		MsgQueue: mock_msg_queue,
604
		Assets: pallet_assets,
605
		PrefixChanger: mock_statemint_prefix,
606

            
607
	}
608
);