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

            
27
use sp_core::H256;
28
use sp_runtime::{
29
	traits::{ConstU32, Hash, IdentityLookup},
30
	AccountId32,
31
};
32

            
33
use polkadot_core_primitives::BlockNumber as RelayBlockNumber;
34

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

            
58
parameter_types! {
59
	pub const BlockHashCount: u32 = 250;
60
}
61

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

            
95
parameter_types! {
96
	pub ExistentialDeposit: Balance = 1;
97
	pub const MaxLocks: u32 = 50;
98
	pub const MaxReserves: u32 = 50;
99
}
100

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

            
118
// Required for runtime benchmarks
119
pallet_assets::runtime_benchmarks_enabled! {
120
	pub struct BenchmarkHelper;
121
	impl<AssetIdParameter, ReserveIdParameter> pallet_assets::BenchmarkHelper<AssetIdParameter, ReserveIdParameter> for BenchmarkHelper
122
	where
123
		AssetIdParameter: From<u128>,
124
		ReserveIdParameter: From<u128>,
125
	{
126
		fn create_asset_id_parameter(id: u32) -> AssetIdParameter {
127
			(id as u128).into()
128
		}
129
		fn create_reserve_id_parameter(id: u32) -> ReserveIdParameter {
130
			(id as u128).into()
131
		}
132
	}
133
}
134

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

            
147
impl pallet_assets::Config for Runtime {
148
	type RuntimeEvent = RuntimeEvent;
149
	type Balance = Balance;
150
	type AssetId = AssetId;
151
	type Currency = Balances;
152
	type ForceOrigin = EnsureRoot<AccountId>;
153
	type AssetDeposit = AssetDeposit;
154
	type MetadataDepositBase = MetadataDepositBase;
155
	type MetadataDepositPerByte = MetadataDepositPerByte;
156
	type ApprovalDeposit = ApprovalDeposit;
157
	type StringLimit = AssetsStringLimit;
158
	type Freezer = ();
159
	type Extra = ();
160
	type AssetAccountDeposit = AssetAccountDeposit;
161
	type WeightInfo = ();
162
	type RemoveItemsLimit = ConstU32<656>;
163
	type AssetIdParameter = AssetId;
164
	type ReserveData = ReserveId;
165
	type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
166
	type CallbackHandle = ();
167
	type Holder = ();
168
	pallet_assets::runtime_benchmarks_enabled! {
169
		type BenchmarkHelper = BenchmarkHelper;
170
	}
171
}
172

            
173
parameter_types! {
174
	pub const KsmLocation: Location = Location::parent();
175
	pub const RelayNetwork: NetworkId = NetworkId::Kusama;
176
	pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
177
	pub UniversalLocation: InteriorLocation =
178
		[GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())].into();
179
	pub Local: Location = Here.into();
180
	pub CheckingAccount: AccountId = PolkadotXcm::check_account();
181
	pub KsmPerSecond: (xcm::latest::prelude::AssetId, u128, u128) =
182
		(AssetId(KsmLocation::get()), 1, 1);
183
}
184

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

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

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

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

            
259
parameter_types! {
260
	// One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate.
261
	pub UnitWeightCost: Weight = Weight::from_parts(100u64, 100u64);
262
	pub const MaxInstructions: u32 = 100;
263
}
264

            
265
pub struct ParentOrParentsExecutivePlurality;
266
impl Contains<Location> for ParentOrParentsExecutivePlurality {
267
	fn contains(location: &Location) -> bool {
268
		matches!(
269
			location.unpack(),
270
			(1, [])
271
				| (
272
					1,
273
					[Plurality {
274
						id: BodyId::Executive,
275
						..
276
					}]
277
				)
278
		)
279
	}
280
}
281

            
282
pub struct ParentOrSiblings;
283
impl Contains<Location> for ParentOrSiblings {
284
	fn contains(location: &Location) -> bool {
285
		matches!(location.unpack(), (1, []) | (1, [_]))
286
	}
287
}
288

            
289
pub type Barrier = (
290
	TakeWeightCredit,
291
	AllowTopLevelPaidExecutionFrom<Everything>,
292
	// Parent and its exec plurality get free execution
293
	AllowUnpaidExecutionFrom<ParentOrParentsExecutivePlurality>,
294
	// Expected responses are OK.
295
	AllowKnownQueryResponses<PolkadotXcm>,
296
	// Subscriptions for version tracking are OK.
297
	AllowSubscriptionsFrom<ParentOrSiblings>,
298
);
299

            
300
parameter_types! {
301
	pub MatcherLocation: Location = Location::here();
302
	pub const MaxAssetsIntoHolding: u32 = 64;
303
	pub const RelayTokenLocation: Location = Location::parent();
304
}
305

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

            
328
pub type TrustedTeleporters = (ConcreteAssetFromRelay<RelayTokenLocation>,);
329

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

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

            
367
pub type XcmRouter = super::ParachainXcmRouter<MsgQueue>;
368

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

            
396
impl cumulus_pallet_xcm::Config for Runtime {
397
	type RuntimeEvent = RuntimeEvent;
398
	type XcmExecutor = XcmExecutor<XcmConfig>;
399
}
400

            
401
#[frame_support::pallet]
402
pub mod mock_msg_queue {
403
	use super::*;
404
	use frame_support::pallet_prelude::*;
405

            
406
	#[pallet::config]
407
	pub trait Config: frame_system::Config {
408
		type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
409
	}
410

            
411
	#[pallet::call]
412
	impl<T: Config> Pallet<T> {}
413

            
414
	#[pallet::pallet]
415
	pub struct Pallet<T>(_);
416

            
417
	#[pallet::storage]
418
	#[pallet::getter(fn parachain_id)]
419
	pub(super) type ParachainId<T: Config> = StorageValue<_, ParaId, ValueQuery>;
420

            
421
	impl<T: Config> Get<ParaId> for Pallet<T> {
422
14
		fn get() -> ParaId {
423
14
			Self::parachain_id()
424
14
		}
425
	}
426

            
427
	pub type MessageId = [u8; 32];
428

            
429
	#[pallet::event]
430
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
431
	pub enum Event<T: Config> {
432
		// XCMP
433
		/// Some XCM was executed OK.
434
		Success(Option<T::Hash>),
435
		/// Some XCM failed.
436
		Fail(Option<T::Hash>, InstructionError),
437
		/// Bad XCM version used.
438
		BadVersion(Option<T::Hash>),
439
		/// Bad XCM format used.
440
		BadFormat(Option<T::Hash>),
441

            
442
		// DMP
443
		/// Downward message is invalid XCM.
444
		InvalidFormat(MessageId),
445
		/// Downward message is unsupported version of XCM.
446
		UnsupportedVersion(MessageId),
447
		/// Downward message executed with the given outcome.
448
		ExecutedDownward(MessageId, Outcome),
449
	}
450

            
451
	impl<T: Config> Pallet<T> {
452
78
		pub fn set_para_id(para_id: ParaId) {
453
78
			ParachainId::<T>::put(para_id);
454
78
		}
455

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

            
499
	impl<T: Config> XcmpMessageHandler for Pallet<T> {
500
6
		fn handle_xcmp_messages<'a, I: Iterator<Item = (ParaId, RelayBlockNumber, &'a [u8])>>(
501
6
			iter: I,
502
6
			max_weight: Weight,
503
6
		) -> Weight {
504
12
			for (sender, sent_at, data) in iter {
505
6
				let mut data_ref = data;
506
6
				let _ = XcmpMessageFormat::decode(&mut data_ref)
507
6
					.expect("Simulator encodes with versioned xcm format; qed");
508

            
509
6
				let mut remaining_fragments = &data_ref[..];
510
12
				while !remaining_fragments.is_empty() {
511
6
					if let Ok(xcm) =
512
6
						VersionedXcm::<T::RuntimeCall>::decode(&mut remaining_fragments)
513
6
					{
514
6
						let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight);
515
6
					} else {
516
						debug_assert!(false, "Invalid incoming XCMP message data");
517
					}
518
				}
519
			}
520
6
			max_weight
521
6
		}
522
	}
523

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

            
549
5
						Self::deposit_event(Event::ExecutedDownward(id, outcome));
550
5
					}
551
				}
552
			}
553
5
			limit
554
5
		}
555
	}
556
}
557
impl mock_msg_queue::Config for Runtime {
558
	type XcmExecutor = XcmExecutor<XcmConfig>;
559
}
560

            
561
// Pallet to cover test cases for change https://github.com/paritytech/cumulus/pull/831
562
#[frame_support::pallet]
563
pub mod mock_statemint_prefix {
564
	use super::*;
565
	use frame_support::pallet_prelude::*;
566

            
567
	#[pallet::config]
568
	pub trait Config: frame_system::Config {}
569

            
570
	#[pallet::call]
571
	impl<T: Config> Pallet<T> {}
572

            
573
	#[pallet::pallet]
574
	#[pallet::without_storage_info]
575
	pub struct Pallet<T>(_);
576

            
577
	#[pallet::storage]
578
	#[pallet::getter(fn current_prefix)]
579
	pub(super) type CurrentPrefix<T: Config> = StorageValue<_, Location, ValueQuery>;
580

            
581
	impl<T: Config> Get<Location> for Pallet<T> {
582
15
		fn get() -> Location {
583
15
			Self::current_prefix()
584
15
		}
585
	}
586

            
587
	#[pallet::event]
588
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
589
	pub enum Event<T: Config> {
590
		// Changed Prefix
591
		PrefixChanged(Location),
592
	}
593

            
594
	impl<T: Config> Pallet<T> {
595
4
		pub fn set_prefix(prefix: Location) {
596
4
			CurrentPrefix::<T>::put(&prefix);
597
4
			Self::deposit_event(Event::PrefixChanged(prefix));
598
4
		}
599
	}
600
}
601

            
602
impl mock_statemint_prefix::Config for Runtime {}
603

            
604
type Block = frame_system::mocking::MockBlockU32<Runtime>;
605
construct_runtime!(
606
	pub enum Runtime	{
607
		System: frame_system,
608
		Balances: pallet_balances,
609
		PolkadotXcm: pallet_xcm,
610
		CumulusXcm: cumulus_pallet_xcm,
611
		MsgQueue: mock_msg_queue,
612
		Assets: pallet_assets,
613
		PrefixChanger: mock_statemint_prefix,
614

            
615
	}
616
);