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::{
20
	construct_runtime, parameter_types,
21
	traits::{AsEnsureOriginWithArg, Contains, ContainsPair, Everything, Get, Nothing},
22
	weights::Weight,
23
};
24
use frame_system::{EnsureRoot, EnsureSigned};
25
use polkadot_core_primitives::BlockNumber as RelayBlockNumber;
26
use sp_core::H256;
27
use sp_runtime::{
28
	traits::{ConstU32, Hash, IdentityLookup},
29
	AccountId32,
30
};
31

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
288
parameter_types! {
289
	pub MatcherLocation: Location = Location::here();
290
	pub const MaxAssetsIntoHolding: u32 = 64;
291
	pub const RelayTokenLocation: Location = Location::parent();
292
}
293

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

            
316
pub type TrustedTeleporters = (ConcreteAssetFromRelay<RelayTokenLocation>,);
317

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

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

            
354
pub type XcmRouter = super::ParachainXcmRouter<MsgQueue>;
355

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

            
382
impl cumulus_pallet_xcm::Config for Runtime {
383
	type RuntimeEvent = RuntimeEvent;
384
	type XcmExecutor = XcmExecutor<XcmConfig>;
385
}
386

            
387
#[frame_support::pallet]
388
pub mod mock_msg_queue {
389
	use super::*;
390
	use frame_support::pallet_prelude::*;
391

            
392
	#[pallet::config]
393
	pub trait Config: frame_system::Config {
394
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
395
		type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
396
	}
397

            
398
	#[pallet::call]
399
	impl<T: Config> Pallet<T> {}
400

            
401
1
	#[pallet::pallet]
402
	pub struct Pallet<T>(_);
403

            
404
290
	#[pallet::storage]
405
	#[pallet::getter(fn parachain_id)]
406
	pub(super) type ParachainId<T: Config> = StorageValue<_, ParaId, ValueQuery>;
407

            
408
	impl<T: Config> Get<ParaId> for Pallet<T> {
409
14
		fn get() -> ParaId {
410
14
			Self::parachain_id()
411
14
		}
412
	}
413

            
414
	pub type MessageId = [u8; 32];
415

            
416
	#[pallet::event]
417
11
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
418
	pub enum Event<T: Config> {
419
		// XCMP
420
		/// Some XCM was executed OK.
421
		Success(Option<T::Hash>),
422
		/// Some XCM failed.
423
		Fail(Option<T::Hash>, XcmError),
424
		/// Bad XCM version used.
425
		BadVersion(Option<T::Hash>),
426
		/// Bad XCM format used.
427
		BadFormat(Option<T::Hash>),
428

            
429
		// DMP
430
		/// Downward message is invalid XCM.
431
		InvalidFormat(MessageId),
432
		/// Downward message is unsupported version of XCM.
433
		UnsupportedVersion(MessageId),
434
		/// Downward message executed with the given outcome.
435
		ExecutedDownward(MessageId, Outcome),
436
	}
437

            
438
	impl<T: Config> Pallet<T> {
439
82
		pub fn set_para_id(para_id: ParaId) {
440
82
			ParachainId::<T>::put(para_id);
441
82
		}
442

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

            
483
	impl<T: Config> XcmpMessageHandler for Pallet<T> {
484
6
		fn handle_xcmp_messages<'a, I: Iterator<Item = (ParaId, RelayBlockNumber, &'a [u8])>>(
485
6
			iter: I,
486
6
			max_weight: Weight,
487
6
		) -> Weight {
488
12
			for (sender, sent_at, data) in iter {
489
6
				let mut data_ref = data;
490
6
				let _ = XcmpMessageFormat::decode(&mut data_ref)
491
6
					.expect("Simulator encodes with versioned xcm format; qed");
492
6

            
493
6
				let mut remaining_fragments = &data_ref[..];
494
12
				while !remaining_fragments.is_empty() {
495
6
					if let Ok(xcm) =
496
6
						VersionedXcm::<T::RuntimeCall>::decode(&mut remaining_fragments)
497
6
					{
498
6
						let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight);
499
6
					} else {
500
						debug_assert!(false, "Invalid incoming XCMP message data");
501
					}
502
				}
503
			}
504
6
			max_weight
505
6
		}
506
	}
507

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

            
533
5
						Self::deposit_event(Event::ExecutedDownward(id, outcome));
534
5
					}
535
				}
536
			}
537
5
			limit
538
5
		}
539
	}
540
}
541
impl mock_msg_queue::Config for Runtime {
542
	type RuntimeEvent = RuntimeEvent;
543
	type XcmExecutor = XcmExecutor<XcmConfig>;
544
}
545

            
546
// Pallet to cover test cases for change https://github.com/paritytech/cumulus/pull/831
547
#[frame_support::pallet]
548
pub mod mock_statemint_prefix {
549
	use super::*;
550
	use frame_support::pallet_prelude::*;
551

            
552
	#[pallet::config]
553
	pub trait Config: frame_system::Config {
554
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
555
	}
556

            
557
	#[pallet::call]
558
	impl<T: Config> Pallet<T> {}
559

            
560
1
	#[pallet::pallet]
561
	#[pallet::without_storage_info]
562
	pub struct Pallet<T>(_);
563

            
564
53
	#[pallet::storage]
565
	#[pallet::getter(fn current_prefix)]
566
	pub(super) type CurrentPrefix<T: Config> = StorageValue<_, Location, ValueQuery>;
567

            
568
	impl<T: Config> Get<Location> for Pallet<T> {
569
15
		fn get() -> Location {
570
15
			Self::current_prefix()
571
15
		}
572
	}
573

            
574
	#[pallet::event]
575
4
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
576
	pub enum Event<T: Config> {
577
		// Changed Prefix
578
		PrefixChanged(Location),
579
	}
580

            
581
	impl<T: Config> Pallet<T> {
582
4
		pub fn set_prefix(prefix: Location) {
583
4
			CurrentPrefix::<T>::put(&prefix);
584
4
			Self::deposit_event(Event::PrefixChanged(prefix));
585
4
		}
586
	}
587
}
588

            
589
impl mock_statemint_prefix::Config for Runtime {
590
	type RuntimeEvent = RuntimeEvent;
591
}
592

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

            
604
	}
605
4737
);