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
//! Parachain runtime mock.
18

            
19
use frame_support::{
20
	construct_runtime,
21
	dispatch::GetDispatchInfo,
22
	ensure, parameter_types,
23
	traits::{
24
		AsEnsureOriginWithArg, ConstU32, Everything, Get, InstanceFilter, Nothing, PalletInfoAccess,
25
	},
26
	weights::Weight,
27
	PalletId,
28
};
29
pub use moonbeam_runtime::xcm_config::AssetType;
30

            
31
use frame_system::{pallet_prelude::BlockNumberFor, EnsureNever, EnsureRoot};
32
use pallet_xcm::migration::v1::VersionUncheckedMigrateToV1;
33
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
34
use sp_core::H256;
35
use sp_runtime::{
36
	traits::{BlakeTwo256, Hash, IdentityLookup, MaybeEquivalence, Zero},
37
	Permill,
38
};
39
use sp_std::{convert::TryFrom, prelude::*};
40
use xcm::{latest::prelude::*, Version as XcmVersion, VersionedXcm};
41

            
42
use cumulus_primitives_core::relay_chain::HrmpChannelId;
43
use pallet_ethereum::PostLogContent;
44
use polkadot_core_primitives::BlockNumber as RelayBlockNumber;
45
use polkadot_parachain::primitives::{Id as ParaId, Sibling};
46
use xcm::latest::{
47
	Error as XcmError, ExecuteXcm,
48
	Junction::{PalletInstance, Parachain},
49
	Location, NetworkId, Outcome, Xcm,
50
};
51
use xcm_builder::{
52
	AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
53
	AllowTopLevelPaidExecutionFrom, Case, ConvertedConcreteId, EnsureXcmOrigin, FixedWeightBounds,
54
	FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, IsConcrete, NoChecking,
55
	ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
56
	SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation,
57
	TakeWeightCredit, WithComputedOrigin,
58
};
59
use xcm_executor::{traits::JustTry, Config, XcmExecutor};
60

            
61
#[cfg(feature = "runtime-benchmarks")]
62
use moonbeam_runtime_common::benchmarking::BenchmarkHelper as ArgumentsBenchmarkHelper;
63
use scale_info::TypeInfo;
64
use xcm_simulator::{
65
	DmpMessageHandlerT as DmpMessageHandler, XcmpMessageFormat,
66
	XcmpMessageHandlerT as XcmpMessageHandler,
67
};
68

            
69
pub type AccountId = moonbeam_core_primitives::AccountId;
70
pub type Balance = u128;
71
pub type AssetId = u128;
72
pub type BlockNumber = BlockNumberFor<Runtime>;
73

            
74
parameter_types! {
75
	pub const BlockHashCount: u32 = 250;
76
}
77

            
78
impl frame_system::Config for Runtime {
79
	type RuntimeOrigin = RuntimeOrigin;
80
	type RuntimeCall = RuntimeCall;
81
	type RuntimeTask = RuntimeTask;
82
	type Nonce = u64;
83
	type Block = Block;
84
	type Hash = H256;
85
	type Hashing = ::sp_runtime::traits::BlakeTwo256;
86
	type AccountId = AccountId;
87
	type Lookup = IdentityLookup<AccountId>;
88
	type RuntimeEvent = RuntimeEvent;
89
	type BlockHashCount = BlockHashCount;
90
	type BlockWeights = ();
91
	type BlockLength = ();
92
	type Version = ();
93
	type PalletInfo = PalletInfo;
94
	type AccountData = pallet_balances::AccountData<Balance>;
95
	type OnNewAccount = ();
96
	type OnKilledAccount = ();
97
	type DbWeight = ();
98
	type BaseCallFilter = Everything;
99
	type SystemWeightInfo = ();
100
	type SS58Prefix = ();
101
	type OnSetCode = ();
102
	type MaxConsumers = frame_support::traits::ConstU32<16>;
103
	type SingleBlockMigrations = ();
104
	type MultiBlockMigrator = ();
105
	type PreInherents = ();
106
	type PostInherents = ();
107
	type PostTransactions = ();
108
}
109

            
110
parameter_types! {
111
	pub ExistentialDeposit: Balance = 0;
112
	pub const MaxLocks: u32 = 50;
113
	pub const MaxReserves: u32 = 50;
114
}
115

            
116
impl pallet_balances::Config for Runtime {
117
	type MaxLocks = MaxLocks;
118
	type Balance = Balance;
119
	type RuntimeEvent = RuntimeEvent;
120
	type DustRemoval = ();
121
	type ExistentialDeposit = ExistentialDeposit;
122
	type AccountStore = System;
123
	type WeightInfo = ();
124
	type MaxReserves = MaxReserves;
125
	type ReserveIdentifier = [u8; 8];
126
	type RuntimeHoldReason = ();
127
	type FreezeIdentifier = ();
128
	type MaxFreezes = ();
129
	type RuntimeFreezeReason = ();
130
}
131

            
132
pub type ForeignAssetInstance = ();
133

            
134
// Required for runtime benchmarks
135
pallet_assets::runtime_benchmarks_enabled! {
136
	pub struct BenchmarkHelper;
137
	impl<AssetIdParameter> pallet_assets::BenchmarkHelper<AssetIdParameter> for BenchmarkHelper
138
	where
139
		AssetIdParameter: From<u128>,
140
	{
141
		fn create_asset_id_parameter(id: u32) -> AssetIdParameter {
142
			(id as u128).into()
143
		}
144
	}
145
}
146

            
147
parameter_types! {
148
	pub const AssetDeposit: Balance = 1; // Does not really matter as this will be only called by root
149
	pub const ApprovalDeposit: Balance = 0;
150
	pub const AssetsStringLimit: u32 = 50;
151
	pub const MetadataDepositBase: Balance = 0;
152
	pub const MetadataDepositPerByte: Balance = 0;
153
	pub const AssetAccountDeposit: Balance = 0;
154
}
155

            
156
impl pallet_assets::Config<ForeignAssetInstance> for Runtime {
157
	type RuntimeEvent = RuntimeEvent;
158
	type Balance = Balance;
159
	type AssetId = AssetId;
160
	type Currency = Balances;
161
	type ForceOrigin = EnsureRoot<AccountId>;
162
	type AssetDeposit = AssetDeposit;
163
	type MetadataDepositBase = MetadataDepositBase;
164
	type MetadataDepositPerByte = MetadataDepositPerByte;
165
	type ApprovalDeposit = ApprovalDeposit;
166
	type StringLimit = AssetsStringLimit;
167
	type Freezer = ();
168
	type Extra = ();
169
	type AssetAccountDeposit = AssetAccountDeposit;
170
	type WeightInfo = pallet_assets::weights::SubstrateWeight<Runtime>;
171
	type RemoveItemsLimit = ConstU32<656>;
172
	type AssetIdParameter = AssetId;
173
	type CreateOrigin = AsEnsureOriginWithArg<EnsureNever<AccountId>>;
174
	type CallbackHandle = ();
175
	pallet_assets::runtime_benchmarks_enabled! {
176
		type BenchmarkHelper = BenchmarkHelper;
177
	}
178
}
179

            
180
/// Type for specifying how a `Location` can be converted into an `AccountId`. This is used
181
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
182
/// `Transact` in order to determine the dispatch Origin.
183
pub type LocationToAccountId = (
184
	// The parent (Relay-chain) origin converts to the default `AccountId`.
185
	ParentIsPreset<AccountId>,
186
	// Sibling parachain origins convert to AccountId via the `ParaId::into`.
187
	SiblingParachainConvertsVia<Sibling, AccountId>,
188
	AccountKey20Aliases<RelayNetwork, AccountId>,
189
	// Generate remote accounts according to polkadot standards
190
	xcm_builder::HashedDescription<
191
		AccountId,
192
		xcm_builder::DescribeFamily<xcm_builder::DescribeAllTerminal>,
193
	>,
194
);
195

            
196
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
197
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
198
/// biases the kind of local `Origin` it will become.
199
pub type XcmOriginToTransactDispatchOrigin = (
200
	// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
201
	// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
202
	// foreign chains who want to have a local sovereign account on this chain which they control.
203
	SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
204
	// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
205
	// recognised.
206
	RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
207
	// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
208
	// recognised.
209
	SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
210
	// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
211
	// transaction from the Root origin.
212
	ParentAsSuperuser<RuntimeOrigin>,
213
	// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
214
	pallet_xcm::XcmPassthrough<RuntimeOrigin>,
215
	SignedAccountKey20AsNative<RelayNetwork, RuntimeOrigin>,
216
);
217

            
218
parameter_types! {
219
	pub const UnitWeightCost: Weight = Weight::from_parts(1u64, 1u64);
220
	pub MaxInstructions: u32 = 100;
221
}
222

            
223
// Instructing how incoming xcm assets will be handled
224
pub type ForeignFungiblesTransactor = FungiblesAdapter<
225
	// Use this fungibles implementation:
226
	Assets,
227
	// Use this currency when it is a fungible asset matching the given location or name:
228
	(
229
		ConvertedConcreteId<
230
			AssetId,
231
			Balance,
232
			xcm_primitives::AsAssetType<AssetId, AssetType, AssetManager>,
233
			JustTry,
234
		>,
235
	),
236
	// Do a simple punn to convert an AccountId32 Location into a native chain account ID:
237
	LocationToAccountId,
238
	// Our chain's account ID type (we can't get away without mentioning it explicitly):
239
	AccountId,
240
	// We dont allow teleports.
241
	NoChecking,
242
	// We dont track any teleports
243
	(),
244
>;
245

            
246
pub type LocalAssetTransactor = XcmCurrencyAdapter<
247
	// Use this currency:
248
	Balances,
249
	// Use this currency when it is a fungible asset matching any of the locations in
250
	// SelfReserveRepresentations
251
	IsConcrete<SelfReserve>,
252
	// We can convert the Locations with our converter above:
253
	LocationToAccountId,
254
	// Our chain's account ID type (we can't get away without mentioning it explicitly):
255
	AccountId,
256
	// We dont allow teleport
257
	(),
258
>;
259

            
260
// We use all transactors
261
pub type AssetTransactors = (LocalAssetTransactor, ForeignFungiblesTransactor);
262
pub type XcmRouter = super::ParachainXcmRouter<MsgQueue>;
263

            
264
pub type XcmBarrier = (
265
	// Weight that is paid for may be consumed.
266
	TakeWeightCredit,
267
	// Expected responses are OK.
268
	AllowKnownQueryResponses<PolkadotXcm>,
269
	WithComputedOrigin<
270
		(
271
			// If the message is one that immediately attemps to pay for execution, then allow it.
272
			AllowTopLevelPaidExecutionFrom<Everything>,
273
			// Subscriptions for version tracking are OK.
274
			AllowSubscriptionsFrom<Everything>,
275
		),
276
		UniversalLocation,
277
		ConstU32<8>,
278
	>,
279
);
280

            
281
parameter_types! {
282
	/// Xcm fees will go to the treasury account
283
	pub XcmFeesAccount: AccountId = Treasury::account_id();
284
	/// Parachain token units per second of execution
285
	pub ParaTokensPerSecond: u128 = WEIGHT_REF_TIME_PER_SECOND as u128;
286
}
287

            
288
pub struct WeightToFee;
289
impl sp_weights::WeightToFee for WeightToFee {
290
	type Balance = Balance;
291

            
292
46
	fn weight_to_fee(weight: &Weight) -> Self::Balance {
293
46
		use sp_runtime::SaturatedConversion as _;
294
46
		Self::Balance::saturated_from(weight.ref_time())
295
46
			.saturating_mul(ParaTokensPerSecond::get())
296
46
			.saturating_div(frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND as u128)
297
46
	}
298
}
299

            
300
parameter_types! {
301
	pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
302
	pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
303
	pub UniversalLocation: InteriorLocation =
304
		[GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())].into();
305
	pub SelfReserve: Location = Location {
306
		parents:0,
307
		interior: [
308
			PalletInstance(<Balances as PalletInfoAccess>::index() as u8)
309
		].into()
310
	};
311
	pub const MaxAssetsIntoHolding: u32 = 64;
312

            
313
	pub AssetHubLocation: Location = Location::new(1, [Parachain(1000)]);
314
	pub RelayLocationFilter: AssetFilter = Wild(AllOf {
315
		fun: WildFungible,
316
		id: xcm::prelude::AssetId(Location::parent()),
317
	});
318

            
319
	pub RelayChainNativeAssetFromAssetHub: (AssetFilter, Location) = (
320
		RelayLocationFilter::get(),
321
		AssetHubLocation::get()
322
	);
323
}
324

            
325
use frame_system::RawOrigin;
326
use sp_runtime::traits::PostDispatchInfoOf;
327
use sp_runtime::DispatchErrorWithPostInfo;
328
use xcm_executor::traits::CallDispatcher;
329
moonbeam_runtime_common::impl_moonbeam_xcm_call!();
330

            
331
type Reserves = (
332
	// Relaychain (DOT) from Asset Hub
333
	Case<RelayChainNativeAssetFromAssetHub>,
334
	// Assets which the reserve is the same as the origin.
335
	xcm_primitives::MultiNativeAsset<
336
		xcm_primitives::AbsoluteAndRelativeReserve<SelfLocationAbsolute>,
337
	>,
338
);
339

            
340
pub struct XcmConfig;
341
impl Config for XcmConfig {
342
	type RuntimeCall = RuntimeCall;
343
	type XcmSender = XcmRouter;
344
	type AssetTransactor = AssetTransactors;
345
	type OriginConverter = XcmOriginToTransactDispatchOrigin;
346
	type IsReserve = Reserves;
347
	type IsTeleporter = ();
348
	type UniversalLocation = UniversalLocation;
349
	type Barrier = XcmBarrier;
350
	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
351
	type Trader = pallet_xcm_weight_trader::Trader<Runtime>;
352
	type ResponseHandler = PolkadotXcm;
353
	type SubscriptionService = PolkadotXcm;
354
	type AssetTrap = PolkadotXcm;
355
	type AssetClaims = PolkadotXcm;
356
	type CallDispatcher = MoonbeamCall;
357
	type AssetLocker = ();
358
	type AssetExchanger = ();
359
	type PalletInstancesInfo = ();
360
	type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
361
	type FeeManager = ();
362
	type MessageExporter = ();
363
	type UniversalAliases = Nothing;
364
	type SafeCallFilter = Everything;
365
	type Aliasers = Nothing;
366
	type TransactionalProcessor = ();
367
	type HrmpNewChannelOpenRequestHandler = ();
368
	type HrmpChannelAcceptedHandler = ();
369
	type HrmpChannelClosingHandler = ();
370
	type XcmRecorder = PolkadotXcm;
371
}
372

            
373
impl cumulus_pallet_xcm::Config for Runtime {
374
	type RuntimeEvent = RuntimeEvent;
375
	type XcmExecutor = XcmExecutor<XcmConfig>;
376
}
377

            
378
// Our currencyId. We distinguish for now between SelfReserve, and Others, defined by their Id.
379
#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
380
pub enum CurrencyId {
381
	SelfReserve,
382
	ForeignAsset(AssetId),
383
}
384

            
385
// How to convert from CurrencyId to Location
386
pub struct CurrencyIdToLocation<AssetXConverter>(sp_std::marker::PhantomData<AssetXConverter>);
387
impl<AssetXConverter> sp_runtime::traits::Convert<CurrencyId, Option<Location>>
388
	for CurrencyIdToLocation<AssetXConverter>
389
where
390
	AssetXConverter: MaybeEquivalence<Location, AssetId>,
391
{
392
23
	fn convert(currency: CurrencyId) -> Option<Location> {
393
23
		match currency {
394
			CurrencyId::SelfReserve => {
395
6
				let multi: Location = SelfReserve::get();
396
6
				Some(multi)
397
			}
398
17
			CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset),
399
		}
400
23
	}
401
}
402

            
403
parameter_types! {
404
	pub const BaseXcmWeight: Weight = Weight::from_parts(100u64, 100u64);
405
	pub const MaxAssetsForTransfer: usize = 2;
406
	pub SelfLocation: Location = Location::here();
407
	pub SelfLocationAbsolute: Location = Location {
408
		parents:1,
409
		interior: [
410
			Parachain(MsgQueue::parachain_id().into())
411
		].into()
412
	};
413
}
414

            
415
parameter_types! {
416
	pub const ProposalBond: Permill = Permill::from_percent(5);
417
	pub const ProposalBondMinimum: Balance = 0;
418
	pub const SpendPeriod: u32 = 0;
419
	pub const TreasuryId: PalletId = PalletId(*b"pc/trsry");
420
	pub const MaxApprovals: u32 = 100;
421
	pub TreasuryAccount: AccountId = Treasury::account_id();
422
}
423

            
424
impl pallet_treasury::Config for Runtime {
425
	type PalletId = TreasuryId;
426
	type Currency = Balances;
427
	type RejectOrigin = EnsureRoot<AccountId>;
428
	type RuntimeEvent = RuntimeEvent;
429
	type SpendPeriod = SpendPeriod;
430
	type Burn = ();
431
	type BurnDestination = ();
432
	type MaxApprovals = MaxApprovals;
433
	type WeightInfo = ();
434
	type SpendFunds = ();
435
	type SpendOrigin = frame_support::traits::NeverEnsureOrigin<Balance>; // Same as Polkadot
436
	type AssetKind = ();
437
	type Beneficiary = AccountId;
438
	type BeneficiaryLookup = IdentityLookup<AccountId>;
439
	type Paymaster = PayFromAccount<Balances, TreasuryAccount>;
440
	type BalanceConverter = UnityAssetBalanceConversion;
441
	type PayoutPeriod = ConstU32<0>;
442
	#[cfg(feature = "runtime-benchmarks")]
443
	type BenchmarkHelper = ArgumentsBenchmarkHelper;
444
}
445

            
446
#[frame_support::pallet]
447
pub mod mock_msg_queue {
448
	use super::*;
449
	use frame_support::pallet_prelude::*;
450

            
451
	#[pallet::config]
452
	pub trait Config: frame_system::Config {
453
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
454
		type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
455
	}
456

            
457
	#[pallet::call]
458
	impl<T: Config> Pallet<T> {}
459

            
460
1
	#[pallet::pallet]
461
	pub struct Pallet<T>(_);
462

            
463
1053
	#[pallet::storage]
464
	#[pallet::getter(fn parachain_id)]
465
	pub(super) type ParachainId<T: Config> = StorageValue<_, ParaId, ValueQuery>;
466

            
467
	impl<T: Config> Get<ParaId> for Pallet<T> {
468
43
		fn get() -> ParaId {
469
43
			Self::parachain_id()
470
43
		}
471
	}
472

            
473
	pub type MessageId = [u8; 32];
474

            
475
	#[pallet::event]
476
47
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
477
	pub enum Event<T: Config> {
478
		// XCMP
479
		/// Some XCM was executed OK.
480
		Success(Option<T::Hash>),
481
		/// Some XCM failed.
482
		Fail(Option<T::Hash>, XcmError),
483
		/// Bad XCM version used.
484
		BadVersion(Option<T::Hash>),
485
		/// Bad XCM format used.
486
		BadFormat(Option<T::Hash>),
487

            
488
		// DMP
489
		/// Downward message is invalid XCM.
490
		InvalidFormat(MessageId),
491
		/// Downward message is unsupported version of XCM.
492
		UnsupportedVersion(MessageId),
493
4
		/// Downward message executed with the given outcome.
494
		ExecutedDownward(MessageId, Outcome),
495
	}
496

            
497
	impl<T: Config> Pallet<T> {
498
234
		pub fn set_para_id(para_id: ParaId) {
499
234
			ParachainId::<T>::put(para_id);
500
234
		}
501

            
502
27
		fn handle_xcmp_message(
503
27
			sender: ParaId,
504
27
			_sent_at: RelayBlockNumber,
505
27
			xcm: VersionedXcm<T::RuntimeCall>,
506
27
			max_weight: Weight,
507
27
		) -> Result<Weight, XcmError> {
508
27
			let hash = Encode::using_encoded(&xcm, T::Hashing::hash);
509
27
			let (result, event) = match Xcm::<T::RuntimeCall>::try_from(xcm) {
510
27
				Ok(xcm) => {
511
27
					let location = Location::new(1, [Parachain(sender.into())]);
512
27
					let mut id = [0u8; 32];
513
27
					id.copy_from_slice(hash.as_ref());
514
27
					match T::XcmExecutor::prepare_and_execute(
515
27
						location,
516
27
						xcm,
517
27
						&mut id,
518
27
						max_weight,
519
27
						Weight::zero(),
520
27
					) {
521
						Outcome::Error { error } => {
522
							(Err(error.clone()), Event::Fail(Some(hash), error))
523
						}
524
27
						Outcome::Complete { used } => (Ok(used), Event::Success(Some(hash))),
525
						// As far as the caller is concerned, this was dispatched without error, so
526
						// we just report the weight used.
527
						Outcome::Incomplete { used, error } => {
528
							(Ok(used), Event::Fail(Some(hash), error))
529
						}
530
					}
531
				}
532
				Err(()) => (
533
					Err(XcmError::UnhandledXcmVersion),
534
					Event::BadVersion(Some(hash)),
535
				),
536
			};
537
27
			Self::deposit_event(event);
538
27
			result
539
27
		}
540
	}
541

            
542
	impl<T: Config> XcmpMessageHandler for Pallet<T> {
543
27
		fn handle_xcmp_messages<'a, I: Iterator<Item = (ParaId, RelayBlockNumber, &'a [u8])>>(
544
27
			iter: I,
545
27
			max_weight: Weight,
546
27
		) -> Weight {
547
54
			for (sender, sent_at, data) in iter {
548
27
				let mut data_ref = data;
549
27
				let _ = XcmpMessageFormat::decode(&mut data_ref)
550
27
					.expect("Simulator encodes with versioned xcm format; qed");
551
27

            
552
27
				let mut remaining_fragments = &data_ref[..];
553
54
				while !remaining_fragments.is_empty() {
554
27
					if let Ok(xcm) =
555
27
						VersionedXcm::<T::RuntimeCall>::decode(&mut remaining_fragments)
556
27
					{
557
27
						let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight);
558
27
					} else {
559
						debug_assert!(false, "Invalid incoming XCMP message data");
560
					}
561
				}
562
			}
563
27
			max_weight
564
27
		}
565
	}
566

            
567
	impl<T: Config> DmpMessageHandler for Pallet<T> {
568
20
		fn handle_dmp_messages(
569
20
			iter: impl Iterator<Item = (RelayBlockNumber, Vec<u8>)>,
570
20
			limit: Weight,
571
20
		) -> Weight {
572
20
			for (_i, (_sent_at, data)) in iter.enumerate() {
573
20
				let mut id = sp_io::hashing::blake2_256(&data[..]);
574
20
				let maybe_msg = VersionedXcm::<T::RuntimeCall>::decode(&mut &data[..])
575
20
					.map(Xcm::<T::RuntimeCall>::try_from);
576
20
				match maybe_msg {
577
					Err(_) => {
578
						Self::deposit_event(Event::InvalidFormat(id));
579
					}
580
					Ok(Err(())) => {
581
						Self::deposit_event(Event::UnsupportedVersion(id));
582
					}
583
20
					Ok(Ok(x)) => {
584
20
						let outcome = T::XcmExecutor::prepare_and_execute(
585
20
							Parent,
586
20
							x,
587
20
							&mut id,
588
20
							limit,
589
20
							Weight::zero(),
590
20
						);
591
20

            
592
20
						Self::deposit_event(Event::ExecutedDownward(id, outcome));
593
20
					}
594
				}
595
			}
596
20
			limit
597
20
		}
598
	}
599
}
600

            
601
// Pallet to provide the version, used to test runtime upgrade version changes
602
#[frame_support::pallet]
603
pub mod mock_version_changer {
604
	use super::*;
605
	use frame_support::pallet_prelude::*;
606

            
607
	#[pallet::config]
608
	pub trait Config: frame_system::Config {
609
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
610
	}
611

            
612
	#[pallet::call]
613
	impl<T: Config> Pallet<T> {}
614

            
615
1
	#[pallet::pallet]
616
	pub struct Pallet<T>(_);
617

            
618
10
	#[pallet::storage]
619
	#[pallet::getter(fn current_version)]
620
	pub(super) type CurrentVersion<T: Config> = StorageValue<_, XcmVersion, ValueQuery>;
621

            
622
	impl<T: Config> Get<XcmVersion> for Pallet<T> {
623
2
		fn get() -> XcmVersion {
624
2
			Self::current_version()
625
2
		}
626
	}
627

            
628
	#[pallet::event]
629
2
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
630
	pub enum Event<T: Config> {
631
		// XCMP
632
2
		/// Some XCM was executed OK.
633
		VersionChanged(XcmVersion),
634
	}
635

            
636
	impl<T: Config> Pallet<T> {
637
2
		pub fn set_version(version: XcmVersion) {
638
2
			CurrentVersion::<T>::put(version);
639
2
			Self::deposit_event(Event::VersionChanged(version));
640
2
		}
641
	}
642
}
643

            
644
impl mock_msg_queue::Config for Runtime {
645
	type RuntimeEvent = RuntimeEvent;
646
	type XcmExecutor = XcmExecutor<XcmConfig>;
647
}
648

            
649
impl mock_version_changer::Config for Runtime {
650
	type RuntimeEvent = RuntimeEvent;
651
}
652

            
653
pub type LocalOriginToLocation =
654
	xcm_primitives::SignedToAccountId20<RuntimeOrigin, AccountId, RelayNetwork>;
655

            
656
parameter_types! {
657
	pub MatcherLocation: Location = Location::here();
658
}
659

            
660
impl pallet_xcm::Config for Runtime {
661
	type RuntimeEvent = RuntimeEvent;
662
	type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
663
	type XcmRouter = XcmRouter;
664
	type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
665
	type XcmExecuteFilter = frame_support::traits::Nothing;
666
	type XcmExecutor = XcmExecutor<XcmConfig>;
667
	// Do not allow teleports
668
	type XcmTeleportFilter = Nothing;
669
	type XcmReserveTransferFilter = Everything;
670
	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
671
	type UniversalLocation = UniversalLocation;
672
	type RuntimeOrigin = RuntimeOrigin;
673
	type RuntimeCall = RuntimeCall;
674
	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
675
	// We use a custom one to test runtime ugprades
676
	type AdvertisedXcmVersion = XcmVersioner;
677
	type Currency = Balances;
678
	type CurrencyMatcher = IsConcrete<MatcherLocation>;
679
	type TrustedLockers = ();
680
	type SovereignAccountOf = ();
681
	type MaxLockers = ConstU32<8>;
682
	type WeightInfo = pallet_xcm::TestWeightInfo;
683
	type MaxRemoteLockConsumers = ConstU32<0>;
684
	type RemoteLockConsumerIdentifier = ();
685
	type AdminOrigin = frame_system::EnsureRoot<AccountId>;
686
}
687

            
688
// We instruct how to register the Assets
689
// In this case, we tell it to Create an Asset in pallet-assets
690
pub struct AssetRegistrar;
691
use frame_support::pallet_prelude::DispatchResult;
692
impl pallet_asset_manager::AssetRegistrar<Runtime> for AssetRegistrar {
693
33
	fn create_foreign_asset(
694
33
		asset: AssetId,
695
33
		min_balance: Balance,
696
33
		metadata: AssetMetadata,
697
33
		is_sufficient: bool,
698
33
	) -> DispatchResult {
699
33
		Assets::force_create(
700
33
			RuntimeOrigin::root(),
701
33
			asset,
702
33
			AssetManager::account_id(),
703
33
			is_sufficient,
704
33
			min_balance,
705
33
		)?;
706

            
707
33
		Assets::force_set_metadata(
708
33
			RuntimeOrigin::root(),
709
33
			asset,
710
33
			metadata.name,
711
33
			metadata.symbol,
712
33
			metadata.decimals,
713
33
			false,
714
33
		)
715
33
	}
716

            
717
	fn destroy_foreign_asset(asset: AssetId) -> DispatchResult {
718
		// Mark the asset as destroying
719
		Assets::start_destroy(RuntimeOrigin::root(), asset.into())?;
720

            
721
		Ok(())
722
	}
723

            
724
	fn destroy_asset_dispatch_info_weight(asset: AssetId) -> Weight {
725
		RuntimeCall::Assets(
726
			pallet_assets::Call::<Runtime, ForeignAssetInstance>::start_destroy {
727
				id: asset.into(),
728
			},
729
		)
730
		.get_dispatch_info()
731
		.weight
732
	}
733
}
734

            
735
#[derive(Clone, Default, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
736
pub struct AssetMetadata {
737
	pub name: Vec<u8>,
738
	pub symbol: Vec<u8>,
739
	pub decimals: u8,
740
}
741

            
742
impl pallet_asset_manager::Config for Runtime {
743
	type RuntimeEvent = RuntimeEvent;
744
	type Balance = Balance;
745
	type AssetId = AssetId;
746
	type AssetRegistrarMetadata = AssetMetadata;
747
	type ForeignAssetType = AssetType;
748
	type AssetRegistrar = AssetRegistrar;
749
	type ForeignAssetModifierOrigin = EnsureRoot<AccountId>;
750
	type WeightInfo = ();
751
}
752

            
753
// 1 DOT should be enough
754
parameter_types! {
755
	pub MaxHrmpRelayFee: Asset = (Location::parent(), 1_000_000_000_000u128).into();
756
}
757

            
758
impl pallet_xcm_transactor::Config for Runtime {
759
	type RuntimeEvent = RuntimeEvent;
760
	type Balance = Balance;
761
	type Transactor = MockTransactors;
762
	type DerivativeAddressRegistrationOrigin = EnsureRoot<AccountId>;
763
	type SovereignAccountDispatcherOrigin = frame_system::EnsureRoot<AccountId>;
764
	type CurrencyId = CurrencyId;
765
	type AccountIdToLocation = xcm_primitives::AccountIdToLocation<AccountId>;
766
	type CurrencyIdToLocation =
767
		CurrencyIdToLocation<xcm_primitives::AsAssetType<AssetId, AssetType, AssetManager>>;
768
	type SelfLocation = SelfLocation;
769
	type Weigher = xcm_builder::FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
770
	type UniversalLocation = UniversalLocation;
771
	type XcmSender = XcmRouter;
772
	type BaseXcmWeight = BaseXcmWeight;
773
	type AssetTransactor = AssetTransactors;
774
	type ReserveProvider = xcm_primitives::AbsoluteAndRelativeReserve<SelfLocationAbsolute>;
775
	type WeightInfo = ();
776
	type HrmpManipulatorOrigin = EnsureRoot<AccountId>;
777
	type HrmpOpenOrigin = EnsureRoot<AccountId>;
778
	type MaxHrmpFee = xcm_builder::Case<MaxHrmpRelayFee>;
779
}
780

            
781
parameter_types! {
782
	pub RelayLocation: Location = Location::parent();
783
}
784

            
785
impl pallet_xcm_weight_trader::Config for Runtime {
786
	type AccountIdToLocation = xcm_primitives::AccountIdToLocation<AccountId>;
787
	type AddSupportedAssetOrigin = EnsureRoot<AccountId>;
788
	type AssetLocationFilter = Everything;
789
	type AssetTransactor = AssetTransactors;
790
	type Balance = Balance;
791
	type EditSupportedAssetOrigin = EnsureRoot<AccountId>;
792
	type NativeLocation = SelfReserve;
793
	type PauseSupportedAssetOrigin = EnsureRoot<AccountId>;
794
	type RemoveSupportedAssetOrigin = EnsureRoot<AccountId>;
795
	type RuntimeEvent = RuntimeEvent;
796
	type ResumeSupportedAssetOrigin = EnsureRoot<AccountId>;
797
	type WeightInfo = ();
798
	type WeightToFee = WeightToFee;
799
	type XcmFeesAccount = XcmFeesAccount;
800
	#[cfg(feature = "runtime-benchmarks")]
801
	type NotFilteredLocation = RelayLocation;
802
}
803

            
804
parameter_types! {
805
	pub const MinimumPeriod: u64 = 1000;
806
}
807
impl pallet_timestamp::Config for Runtime {
808
	type Moment = u64;
809
	type OnTimestampSet = ();
810
	type MinimumPeriod = MinimumPeriod;
811
	type WeightInfo = ();
812
}
813

            
814
use sp_core::U256;
815

            
816
const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
817
/// Block storage limit in bytes. Set to 160 KB.
818
const BLOCK_STORAGE_LIMIT: u64 = 160 * 1024;
819

            
820
parameter_types! {
821
	pub BlockGasLimit: U256 = U256::from(u64::MAX);
822
	pub WeightPerGas: Weight = Weight::from_parts(1, 0);
823
	pub GasLimitPovSizeRatio: u64 = {
824
		let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
825
		block_gas_limit.saturating_div(MAX_POV_SIZE)
826
	};
827
	pub GasLimitStorageGrowthRatio: u64 =
828
		BlockGasLimit::get().min(u64::MAX.into()).low_u64().saturating_div(BLOCK_STORAGE_LIMIT);
829
}
830

            
831
impl pallet_evm::Config for Runtime {
832
	type FeeCalculator = ();
833
	type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
834
	type WeightPerGas = WeightPerGas;
835

            
836
	type CallOrigin = pallet_evm::EnsureAddressRoot<AccountId>;
837
	type WithdrawOrigin = pallet_evm::EnsureAddressNever<AccountId>;
838

            
839
	type AddressMapping = pallet_evm::IdentityAddressMapping;
840
	type Currency = Balances;
841
	type Runner = pallet_evm::runner::stack::Runner<Self>;
842

            
843
	type RuntimeEvent = RuntimeEvent;
844
	type PrecompilesType = ();
845
	type PrecompilesValue = ();
846
	type ChainId = ();
847
	type BlockGasLimit = BlockGasLimit;
848
	type OnChargeTransaction = ();
849
	type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping<Self>;
850
	type FindAuthor = ();
851
	type OnCreate = ();
852
	type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
853
	type SuicideQuickClearLimit = ConstU32<0>;
854
	type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
855
	type Timestamp = Timestamp;
856
	type WeightInfo = pallet_evm::weights::SubstrateWeight<Runtime>;
857
}
858

            
859
pub struct NormalFilter;
860
impl frame_support::traits::Contains<RuntimeCall> for NormalFilter {
861
	fn contains(c: &RuntimeCall) -> bool {
862
		match c {
863
			_ => true,
864
		}
865
	}
866
}
867

            
868
// We need to use the encoding from the relay mock runtime
869
#[derive(Encode, Decode)]
870
pub enum RelayCall {
871
	#[codec(index = 5u8)]
872
	// the index should match the position of the module in `construct_runtime!`
873
	Utility(UtilityCall),
874
	#[codec(index = 6u8)]
875
	// the index should match the position of the module in `construct_runtime!`
876
	Hrmp(HrmpCall),
877
}
878

            
879
#[derive(Encode, Decode)]
880
pub enum UtilityCall {
881
	#[codec(index = 1u8)]
882
	AsDerivative(u16),
883
}
884

            
885
// HRMP call encoding, needed for xcm transactor pallet
886
#[derive(Encode, Decode)]
887
pub enum HrmpCall {
888
	#[codec(index = 0u8)]
889
	InitOpenChannel(ParaId, u32, u32),
890
	#[codec(index = 1u8)]
891
	AcceptOpenChannel(ParaId),
892
	#[codec(index = 2u8)]
893
	CloseChannel(HrmpChannelId),
894
	#[codec(index = 6u8)]
895
	CancelOpenRequest(HrmpChannelId, u32),
896
}
897

            
898
#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
899
pub enum MockTransactors {
900
	Relay,
901
}
902

            
903
impl xcm_primitives::XcmTransact for MockTransactors {
904
3
	fn destination(self) -> Location {
905
3
		match self {
906
3
			MockTransactors::Relay => Location::parent(),
907
3
		}
908
3
	}
909
}
910

            
911
impl xcm_primitives::UtilityEncodeCall for MockTransactors {
912
7
	fn encode_call(self, call: xcm_primitives::UtilityAvailableCalls) -> Vec<u8> {
913
7
		match self {
914
7
			MockTransactors::Relay => match call {
915
7
				xcm_primitives::UtilityAvailableCalls::AsDerivative(a, b) => {
916
7
					let mut call =
917
7
						RelayCall::Utility(UtilityCall::AsDerivative(a.clone())).encode();
918
7
					call.append(&mut b.clone());
919
7
					call
920
7
				}
921
7
			},
922
7
		}
923
7
	}
924
}
925

            
926
pub struct MockHrmpEncoder;
927
impl xcm_primitives::HrmpEncodeCall for MockHrmpEncoder {
928
	fn hrmp_encode_call(
929
		call: xcm_primitives::HrmpAvailableCalls,
930
	) -> Result<Vec<u8>, xcm::latest::Error> {
931
		match call {
932
			xcm_primitives::HrmpAvailableCalls::InitOpenChannel(a, b, c) => Ok(RelayCall::Hrmp(
933
				HrmpCall::InitOpenChannel(a.clone(), b.clone(), c.clone()),
934
			)
935
			.encode()),
936
			xcm_primitives::HrmpAvailableCalls::AcceptOpenChannel(a) => {
937
				Ok(RelayCall::Hrmp(HrmpCall::AcceptOpenChannel(a.clone())).encode())
938
			}
939
			xcm_primitives::HrmpAvailableCalls::CloseChannel(a) => {
940
				Ok(RelayCall::Hrmp(HrmpCall::CloseChannel(a.clone())).encode())
941
			}
942
			xcm_primitives::HrmpAvailableCalls::CancelOpenRequest(a, b) => {
943
				Ok(RelayCall::Hrmp(HrmpCall::CancelOpenRequest(a.clone(), b.clone())).encode())
944
			}
945
		}
946
	}
947
}
948

            
949
parameter_types! {
950
	pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes;
951
}
952

            
953
impl pallet_ethereum::Config for Runtime {
954
	type RuntimeEvent = RuntimeEvent;
955
	type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;
956
	type PostLogContent = PostBlockAndTxnHashes;
957
	type ExtraDataLength = ConstU32<30>;
958
}
959
parameter_types! {
960
	pub ReservedXcmpWeight: Weight = Weight::from_parts(u64::max_value(), 0);
961
}
962

            
963
#[derive(
964
	Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, MaxEncodedLen, TypeInfo,
965
)]
966
pub enum ProxyType {
967
	NotAllowed = 0,
968
1
	Any = 1,
969
}
970

            
971
impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType {}
972

            
973
impl InstanceFilter<RuntimeCall> for ProxyType {
974
	fn filter(&self, _c: &RuntimeCall) -> bool {
975
		match self {
976
			ProxyType::NotAllowed => false,
977
			ProxyType::Any => true,
978
		}
979
	}
980
	fn is_superset(&self, _o: &Self) -> bool {
981
		false
982
	}
983
}
984

            
985
impl Default for ProxyType {
986
	fn default() -> Self {
987
		Self::NotAllowed
988
	}
989
}
990

            
991
parameter_types! {
992
	pub const ProxyCost: u64 = 1;
993
}
994

            
995
impl pallet_proxy::Config for Runtime {
996
	type RuntimeEvent = RuntimeEvent;
997
	type RuntimeCall = RuntimeCall;
998
	type Currency = Balances;
999
	type ProxyType = ProxyType;
	type ProxyDepositBase = ProxyCost;
	type ProxyDepositFactor = ProxyCost;
	type MaxProxies = ConstU32<32>;
	type WeightInfo = pallet_proxy::weights::SubstrateWeight<Runtime>;
	type MaxPending = ConstU32<32>;
	type CallHasher = BlakeTwo256;
	type AnnouncementDepositBase = ProxyCost;
	type AnnouncementDepositFactor = ProxyCost;
}
pub struct EthereumXcmEnsureProxy;
impl xcm_primitives::EnsureProxy<AccountId> for EthereumXcmEnsureProxy {
2
	fn ensure_ok(delegator: AccountId, delegatee: AccountId) -> Result<(), &'static str> {
		// The EVM implicitely contains an Any proxy, so we only allow for "Any" proxies
1
		let def: pallet_proxy::ProxyDefinition<AccountId, ProxyType, BlockNumber> =
2
			pallet_proxy::Pallet::<Runtime>::find_proxy(
2
				&delegator,
2
				&delegatee,
2
				Some(ProxyType::Any),
2
			)
2
			.map_err(|_| "proxy error: expected `ProxyType::Any`")?;
		// We only allow to use it for delay zero proxies, as the call will iMmediatly be executed
1
		ensure!(def.delay.is_zero(), "proxy delay is Non-zero`");
1
		Ok(())
2
	}
}
impl pallet_ethereum_xcm::Config for Runtime {
	type RuntimeEvent = RuntimeEvent;
	type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper;
	type ValidatedTransaction = pallet_ethereum::ValidatedTransaction<Self>;
	type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction;
	type ReservedXcmpWeight = ReservedXcmpWeight;
	type EnsureProxy = EthereumXcmEnsureProxy;
	type ControllerOrigin = EnsureRoot<AccountId>;
	type ForceOrigin = EnsureRoot<AccountId>;
}
type Block = frame_system::mocking::MockBlockU32<Runtime>;
9969
construct_runtime!(
	pub enum Runtime	{
1
		System: frame_system,
		Balances: pallet_balances,
		MsgQueue: mock_msg_queue,
		XcmVersioner: mock_version_changer,
		PolkadotXcm: pallet_xcm,
		Assets: pallet_assets,
		CumulusXcm: cumulus_pallet_xcm,
		AssetManager: pallet_asset_manager,
		XcmTransactor: pallet_xcm_transactor,
		XcmWeightTrader: pallet_xcm_weight_trader,
		Treasury: pallet_treasury,
		Proxy: pallet_proxy,
		Timestamp: pallet_timestamp,
		EVM: pallet_evm,
		Ethereum: pallet_ethereum,
		EthereumXcm: pallet_ethereum_xcm,
	}
33390
);
4
pub(crate) fn para_events() -> Vec<RuntimeEvent> {
4
	System::events()
4
		.into_iter()
44
		.map(|r| r.event)
44
		.filter_map(|e| Some(e))
4
		.collect::<Vec<_>>()
4
}
use frame_support::traits::tokens::{PayFromAccount, UnityAssetBalanceConversion};
use frame_support::traits::{OnFinalize, OnInitialize, UncheckedOnRuntimeUpgrade};
use sp_weights::constants::WEIGHT_REF_TIME_PER_SECOND;
1
pub(crate) fn on_runtime_upgrade() {
1
	VersionUncheckedMigrateToV1::<Runtime>::on_runtime_upgrade();
1
}
1
pub(crate) fn para_roll_to(n: BlockNumber) {
2
	while System::block_number() < n {
1
		PolkadotXcm::on_finalize(System::block_number());
1
		Balances::on_finalize(System::block_number());
1
		System::on_finalize(System::block_number());
1
		System::set_block_number(System::block_number() + 1);
1
		System::on_initialize(System::block_number());
1
		Balances::on_initialize(System::block_number());
1
		PolkadotXcm::on_initialize(System::block_number());
1
	}
1
}