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

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

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

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

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

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

            
133
pub type ForeignAssetInstance = ();
134

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

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

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

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

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

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

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

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

            
261
// We use both transactors
262
pub type AssetTransactors = (LocalAssetTransactor, ForeignFungiblesTransactor);
263

            
264
pub type XcmRouter = super::ParachainXcmRouter<MsgQueue>;
265

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

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

            
290
pub struct WeightToFee;
291
impl sp_weights::WeightToFee for WeightToFee {
292
	type Balance = Balance;
293

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

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

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

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

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

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

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

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

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

            
387
// How to convert from CurrencyId to Location
388
pub struct CurrencyIdToLocation<AssetXConverter>(sp_std::marker::PhantomData<AssetXConverter>);
389
impl<AssetXConverter> sp_runtime::traits::Convert<CurrencyId, Option<Location>>
390
	for CurrencyIdToLocation<AssetXConverter>
391
where
392
	AssetXConverter: MaybeEquivalence<Location, AssetId>,
393
{
394
25
	fn convert(currency: CurrencyId) -> Option<Location> {
395
25
		match currency {
396
			CurrencyId::SelfReserve => {
397
				// For now and until Xtokens is adapted to handle 0.9.16 version we use
398
				// the old anchoring here
399
				// This is not a problem in either cases, since the view of the destination
400
				// chain does not change
401
				// TODO! change this to NewAnchoringSelfReserve once xtokens is adapted for it
402
8
				let multi: Location = SelfReserve::get();
403
8
				Some(multi)
404
			}
405
17
			CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset),
406
		}
407
25
	}
408
}
409

            
410
parameter_types! {
411
	pub const BaseXcmWeight: Weight = Weight::from_parts(100u64, 100u64);
412
	pub const MaxAssetsForTransfer: usize = 2;
413
	pub SelfLocation: Location = Location::here();
414
	pub SelfLocationAbsolute: Location = Location {
415
		parents:1,
416
		interior: [
417
			Parachain(MsgQueue::parachain_id().into())
418
		].into()
419
	};
420
}
421

            
422
parameter_types! {
423
	pub const ProposalBond: Permill = Permill::from_percent(5);
424
	pub const ProposalBondMinimum: Balance = 0;
425
	pub const SpendPeriod: u32 = 0;
426
	pub const TreasuryId: PalletId = PalletId(*b"pc/trsry");
427
	pub const MaxApprovals: u32 = 100;
428
	pub TreasuryAccount: AccountId = Treasury::account_id();
429
}
430

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

            
454
#[frame_support::pallet]
455
pub mod mock_msg_queue {
456
	use super::*;
457
	use frame_support::pallet_prelude::*;
458

            
459
	#[pallet::config]
460
	pub trait Config: frame_system::Config {
461
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
462
		type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
463
	}
464

            
465
	#[pallet::call]
466
	impl<T: Config> Pallet<T> {}
467

            
468
1
	#[pallet::pallet]
469
	pub struct Pallet<T>(_);
470

            
471
1161
	#[pallet::storage]
472
	#[pallet::getter(fn parachain_id)]
473
	pub(super) type ParachainId<T: Config> = StorageValue<_, ParaId, ValueQuery>;
474

            
475
	impl<T: Config> Get<ParaId> for Pallet<T> {
476
50
		fn get() -> ParaId {
477
50
			Self::parachain_id()
478
50
		}
479
	}
480

            
481
	pub type MessageId = [u8; 32];
482

            
483
	#[pallet::event]
484
54
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
485
	pub enum Event<T: Config> {
486
		// XCMP
487
5
		/// Some XCM was executed OK.
488
		Success(Option<T::Hash>),
489
		/// Some XCM failed.
490
		Fail(Option<T::Hash>, XcmError),
491
		/// Bad XCM version used.
492
		BadVersion(Option<T::Hash>),
493
		/// Bad XCM format used.
494
		BadFormat(Option<T::Hash>),
495

            
496
		// DMP
497
		/// Downward message is invalid XCM.
498
		InvalidFormat(MessageId),
499
		/// Downward message is unsupported version of XCM.
500
		UnsupportedVersion(MessageId),
501
4
		/// Downward message executed with the given outcome.
502
		ExecutedDownward(MessageId, Outcome),
503
	}
504

            
505
	impl<T: Config> Pallet<T> {
506
246
		pub fn set_para_id(para_id: ParaId) {
507
246
			ParachainId::<T>::put(para_id);
508
246
		}
509

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

            
550
	impl<T: Config> XcmpMessageHandler for Pallet<T> {
551
34
		fn handle_xcmp_messages<'a, I: Iterator<Item = (ParaId, RelayBlockNumber, &'a [u8])>>(
552
34
			iter: I,
553
34
			max_weight: Weight,
554
34
		) -> Weight {
555
68
			for (sender, sent_at, data) in iter {
556
34
				let mut data_ref = data;
557
34
				let _ = XcmpMessageFormat::decode(&mut data_ref)
558
34
					.expect("Simulator encodes with versioned xcm format; qed");
559
34

            
560
34
				let mut remaining_fragments = &data_ref[..];
561
68
				while !remaining_fragments.is_empty() {
562
34
					if let Ok(xcm) =
563
34
						VersionedXcm::<T::RuntimeCall>::decode(&mut remaining_fragments)
564
34
					{
565
34
						let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight);
566
34
					} else {
567
						debug_assert!(false, "Invalid incoming XCMP message data");
568
					}
569
				}
570
			}
571
34
			max_weight
572
34
		}
573
	}
574

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

            
600
20
						Self::deposit_event(Event::ExecutedDownward(id, outcome));
601
20
					}
602
				}
603
			}
604
20
			limit
605
20
		}
606
	}
607
}
608

            
609
// Pallet to provide the version, used to test runtime upgrade version changes
610
#[frame_support::pallet]
611
pub mod mock_version_changer {
612
	use super::*;
613
	use frame_support::pallet_prelude::*;
614

            
615
	#[pallet::config]
616
	pub trait Config: frame_system::Config {
617
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
618
	}
619

            
620
	#[pallet::call]
621
	impl<T: Config> Pallet<T> {}
622

            
623
1
	#[pallet::pallet]
624
	pub struct Pallet<T>(_);
625

            
626
22
	#[pallet::storage]
627
	#[pallet::getter(fn current_version)]
628
	pub(super) type CurrentVersion<T: Config> = StorageValue<_, XcmVersion, ValueQuery>;
629

            
630
	impl<T: Config> Get<XcmVersion> for Pallet<T> {
631
4
		fn get() -> XcmVersion {
632
4
			Self::current_version()
633
4
		}
634
	}
635

            
636
	#[pallet::event]
637
5
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
638
	pub enum Event<T: Config> {
639
		// XCMP
640
6
		/// Some XCM was executed OK.
641
		VersionChanged(XcmVersion),
642
	}
643

            
644
	impl<T: Config> Pallet<T> {
645
5
		pub fn set_version(version: XcmVersion) {
646
5
			CurrentVersion::<T>::put(version);
647
5
			Self::deposit_event(Event::VersionChanged(version));
648
5
		}
649
	}
650
}
651

            
652
impl mock_msg_queue::Config for Runtime {
653
	type RuntimeEvent = RuntimeEvent;
654
	type XcmExecutor = XcmExecutor<XcmConfig>;
655
}
656

            
657
impl mock_version_changer::Config for Runtime {
658
	type RuntimeEvent = RuntimeEvent;
659
}
660

            
661
pub type LocalOriginToLocation =
662
	xcm_primitives::SignedToAccountId20<RuntimeOrigin, AccountId, RelayNetwork>;
663

            
664
parameter_types! {
665
	pub MatcherLocation: Location = Location::here();
666
}
667

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

            
696
// We instruct how to register the Assets
697
// In this case, we tell it to Create an Asset in pallet-assets
698
pub struct AssetRegistrar;
699
use frame_support::pallet_prelude::DispatchResult;
700
impl pallet_asset_manager::AssetRegistrar<Runtime> for AssetRegistrar {
701
35
	fn create_foreign_asset(
702
35
		asset: AssetId,
703
35
		min_balance: Balance,
704
35
		metadata: AssetMetadata,
705
35
		is_sufficient: bool,
706
35
	) -> DispatchResult {
707
35
		Assets::force_create(
708
35
			RuntimeOrigin::root(),
709
35
			asset,
710
35
			AssetManager::account_id(),
711
35
			is_sufficient,
712
35
			min_balance,
713
35
		)?;
714

            
715
35
		Assets::force_set_metadata(
716
35
			RuntimeOrigin::root(),
717
35
			asset,
718
35
			metadata.name,
719
35
			metadata.symbol,
720
35
			metadata.decimals,
721
35
			false,
722
35
		)
723
35
	}
724

            
725
	fn destroy_foreign_asset(asset: AssetId) -> DispatchResult {
726
		// Mark the asset as destroying
727
		Assets::start_destroy(RuntimeOrigin::root(), asset.into())?;
728

            
729
		Ok(())
730
	}
731

            
732
	fn destroy_asset_dispatch_info_weight(asset: AssetId) -> Weight {
733
		RuntimeCall::Assets(
734
			pallet_assets::Call::<Runtime, ForeignAssetInstance>::start_destroy {
735
				id: asset.into(),
736
			},
737
		)
738
		.get_dispatch_info()
739
		.total_weight()
740
	}
741
}
742

            
743
#[derive(Clone, Default, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
744
pub struct AssetMetadata {
745
	pub name: Vec<u8>,
746
	pub symbol: Vec<u8>,
747
	pub decimals: u8,
748
}
749

            
750
impl pallet_asset_manager::Config for Runtime {
751
	type RuntimeEvent = RuntimeEvent;
752
	type Balance = Balance;
753
	type AssetId = AssetId;
754
	type AssetRegistrarMetadata = AssetMetadata;
755
	type ForeignAssetType = AssetType;
756
	type AssetRegistrar = AssetRegistrar;
757
	type ForeignAssetModifierOrigin = EnsureRoot<AccountId>;
758
	type WeightInfo = ();
759
}
760

            
761
// 1 KSM should be enough
762
parameter_types! {
763
	pub MaxHrmpRelayFee: Asset = (Location::parent(), 1_000_000_000_000u128).into();
764
}
765

            
766
impl pallet_xcm_transactor::Config for Runtime {
767
	type RuntimeEvent = RuntimeEvent;
768
	type Balance = Balance;
769
	type Transactor = MockTransactors;
770
	type DerivativeAddressRegistrationOrigin = EnsureRoot<AccountId>;
771
	type SovereignAccountDispatcherOrigin = frame_system::EnsureRoot<AccountId>;
772
	type CurrencyId = CurrencyId;
773
	type AccountIdToLocation = xcm_primitives::AccountIdToLocation<AccountId>;
774
	type CurrencyIdToLocation = CurrencyIdToLocation<(
775
		EvmForeignAssets,
776
		AsAssetType<moonbeam_core_primitives::AssetId, AssetType, AssetManager>,
777
	)>;
778
	type SelfLocation = SelfLocation;
779
	type Weigher = xcm_builder::FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
780
	type UniversalLocation = UniversalLocation;
781
	type XcmSender = XcmRouter;
782
	type BaseXcmWeight = BaseXcmWeight;
783
	type AssetTransactor = AssetTransactors;
784
	type ReserveProvider = xcm_primitives::AbsoluteAndRelativeReserve<SelfLocationAbsolute>;
785
	type WeightInfo = ();
786
	type HrmpManipulatorOrigin = EnsureRoot<AccountId>;
787
	type HrmpOpenOrigin = EnsureRoot<AccountId>;
788
	type MaxHrmpFee = xcm_builder::Case<MaxHrmpRelayFee>;
789
}
790

            
791
parameter_types! {
792
	pub RelayLocation: Location = Location::parent();
793
}
794

            
795
impl pallet_xcm_weight_trader::Config for Runtime {
796
	type AccountIdToLocation = xcm_primitives::AccountIdToLocation<AccountId>;
797
	type AddSupportedAssetOrigin = EnsureRoot<AccountId>;
798
	type AssetLocationFilter = Everything;
799
	type AssetTransactor = AssetTransactors;
800
	type Balance = Balance;
801
	type EditSupportedAssetOrigin = EnsureRoot<AccountId>;
802
	type NativeLocation = SelfReserve;
803
	type PauseSupportedAssetOrigin = EnsureRoot<AccountId>;
804
	type RemoveSupportedAssetOrigin = EnsureRoot<AccountId>;
805
	type RuntimeEvent = RuntimeEvent;
806
	type ResumeSupportedAssetOrigin = EnsureRoot<AccountId>;
807
	type WeightInfo = ();
808
	type WeightToFee = WeightToFee;
809
	type XcmFeesAccount = XcmFeesAccount;
810
	#[cfg(feature = "runtime-benchmarks")]
811
	type NotFilteredLocation = RelayLocation;
812
}
813

            
814
parameter_types! {
815
	pub const MinimumPeriod: u64 = 1000;
816
}
817
impl pallet_timestamp::Config for Runtime {
818
	type Moment = u64;
819
	type OnTimestampSet = ();
820
	type MinimumPeriod = MinimumPeriod;
821
	type WeightInfo = ();
822
}
823

            
824
use sp_core::U256;
825

            
826
parameter_types! {
827
	pub BlockGasLimit: U256 = U256::from(u64::MAX);
828
	pub WeightPerGas: Weight = Weight::from_parts(1, 0);
829
	pub GasLimitPovSizeRatio: u64 = {
830
		let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
831
		block_gas_limit.saturating_div(MAX_POV_SIZE as u64)
832
	};
833
	pub GasLimitStorageGrowthRatio: u64 =
834
		BlockGasLimit::get().min(u64::MAX.into()).low_u64().saturating_div(BLOCK_STORAGE_LIMIT);
835
}
836

            
837
impl pallet_evm::Config for Runtime {
838
	type FeeCalculator = ();
839
	type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
840
	type WeightPerGas = WeightPerGas;
841

            
842
	type CallOrigin = pallet_evm::EnsureAddressRoot<AccountId>;
843
	type WithdrawOrigin = pallet_evm::EnsureAddressNever<AccountId>;
844

            
845
	type AddressMapping = pallet_evm::IdentityAddressMapping;
846
	type Currency = Balances;
847
	type Runner = pallet_evm::runner::stack::Runner<Self>;
848

            
849
	type RuntimeEvent = RuntimeEvent;
850
	type PrecompilesType = ();
851
	type PrecompilesValue = ();
852
	type ChainId = ();
853
	type BlockGasLimit = BlockGasLimit;
854
	type OnChargeTransaction = ();
855
	type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping<Self>;
856
	type FindAuthor = ();
857
	type OnCreate = ();
858
	type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
859
	type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
860
	type Timestamp = Timestamp;
861
	type WeightInfo = pallet_evm::weights::SubstrateWeight<Runtime>;
862
	type AccountProvider = FrameSystemAccountProvider<Runtime>;
863
}
864

            
865
#[allow(dead_code)]
866
pub struct NormalFilter;
867

            
868
impl frame_support::traits::Contains<RuntimeCall> for NormalFilter {
869
	fn contains(c: &RuntimeCall) -> bool {
870
		match c {
871
			_ => true,
872
		}
873
	}
874
}
875

            
876
// We need to use the encoding from the relay mock runtime
877
#[derive(Encode, Decode)]
878
pub enum RelayCall {
879
	#[codec(index = 5u8)]
880
	// the index should match the position of the module in `construct_runtime!`
881
	Utility(UtilityCall),
882
	#[codec(index = 6u8)]
883
	// the index should match the position of the module in `construct_runtime!`
884
	Hrmp(HrmpCall),
885
}
886

            
887
#[derive(Encode, Decode)]
888
pub enum UtilityCall {
889
	#[codec(index = 1u8)]
890
	AsDerivative(u16),
891
}
892

            
893
// HRMP call encoding, needed for xcm transactor pallet
894
#[derive(Encode, Decode)]
895
pub enum HrmpCall {
896
	#[codec(index = 0u8)]
897
	InitOpenChannel(ParaId, u32, u32),
898
	#[codec(index = 1u8)]
899
	AcceptOpenChannel(ParaId),
900
	#[codec(index = 2u8)]
901
	CloseChannel(HrmpChannelId),
902
	#[codec(index = 6u8)]
903
	CancelOpenRequest(HrmpChannelId, u32),
904
}
905

            
906
#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
907
pub enum MockTransactors {
908
	Relay,
909
}
910

            
911
impl xcm_primitives::XcmTransact for MockTransactors {
912
3
	fn destination(self) -> Location {
913
3
		match self {
914
3
			MockTransactors::Relay => Location::parent(),
915
3
		}
916
3
	}
917
}
918

            
919
impl xcm_primitives::UtilityEncodeCall for MockTransactors {
920
7
	fn encode_call(self, call: xcm_primitives::UtilityAvailableCalls) -> Vec<u8> {
921
7
		match self {
922
7
			MockTransactors::Relay => match call {
923
7
				xcm_primitives::UtilityAvailableCalls::AsDerivative(a, b) => {
924
7
					let mut call =
925
7
						RelayCall::Utility(UtilityCall::AsDerivative(a.clone())).encode();
926
7
					call.append(&mut b.clone());
927
7
					call
928
7
				}
929
7
			},
930
7
		}
931
7
	}
932
}
933

            
934
#[allow(dead_code)]
935
pub struct MockHrmpEncoder;
936

            
937
impl xcm_primitives::HrmpEncodeCall for MockHrmpEncoder {
938
	fn hrmp_encode_call(
939
		call: xcm_primitives::HrmpAvailableCalls,
940
	) -> Result<Vec<u8>, xcm::latest::Error> {
941
		match call {
942
			xcm_primitives::HrmpAvailableCalls::InitOpenChannel(a, b, c) => Ok(RelayCall::Hrmp(
943
				HrmpCall::InitOpenChannel(a.clone(), b.clone(), c.clone()),
944
			)
945
			.encode()),
946
			xcm_primitives::HrmpAvailableCalls::AcceptOpenChannel(a) => {
947
				Ok(RelayCall::Hrmp(HrmpCall::AcceptOpenChannel(a.clone())).encode())
948
			}
949
			xcm_primitives::HrmpAvailableCalls::CloseChannel(a) => {
950
				Ok(RelayCall::Hrmp(HrmpCall::CloseChannel(a.clone())).encode())
951
			}
952
			xcm_primitives::HrmpAvailableCalls::CancelOpenRequest(a, b) => {
953
				Ok(RelayCall::Hrmp(HrmpCall::CancelOpenRequest(a.clone(), b.clone())).encode())
954
			}
955
		}
956
	}
957
}
958

            
959
parameter_types! {
960
	pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes;
961
}
962

            
963
impl pallet_ethereum::Config for Runtime {
964
	type RuntimeEvent = RuntimeEvent;
965
	type StateRoot =
966
		pallet_ethereum::IntermediateStateRoot<<Runtime as frame_system::Config>::Version>;
967
	type PostLogContent = PostBlockAndTxnHashes;
968
	type ExtraDataLength = ConstU32<30>;
969
}
970

            
971
parameter_types! {
972
	pub ReservedXcmpWeight: Weight = Weight::from_parts(u64::max_value(), 0);
973
}
974

            
975
#[derive(
976
	Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, MaxEncodedLen, TypeInfo,
977
)]
978
pub enum ProxyType {
979
	NotAllowed = 0,
980
1
	Any = 1,
981
}
982

            
983
impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType {}
984

            
985
impl InstanceFilter<RuntimeCall> for ProxyType {
986
	fn filter(&self, _c: &RuntimeCall) -> bool {
987
		match self {
988
			ProxyType::NotAllowed => false,
989
			ProxyType::Any => true,
990
		}
991
	}
992
	fn is_superset(&self, _o: &Self) -> bool {
993
		false
994
	}
995
}
996

            
997
impl Default for ProxyType {
998
	fn default() -> Self {
999
		Self::NotAllowed
	}
}
parameter_types! {
	pub const ProxyCost: u64 = 1;
}
impl pallet_proxy::Config for Runtime {
	type RuntimeEvent = RuntimeEvent;
	type RuntimeCall = RuntimeCall;
	type Currency = Balances;
	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>;
10081
construct_runtime!(
1896
	pub enum Runtime	{
1896
		System: frame_system,
1896
		Balances: pallet_balances,
1896
		MsgQueue: mock_msg_queue,
1896
		XcmVersioner: mock_version_changer,
1896

            
1896
		PolkadotXcm: pallet_xcm,
1896
		Assets: pallet_assets,
1896
		CumulusXcm: cumulus_pallet_xcm,
1896
		AssetManager: pallet_asset_manager,
1896
		XcmTransactor: pallet_xcm_transactor,
1896
		XcmWeightTrader: pallet_xcm_weight_trader,
1896
		Treasury: pallet_treasury,
1896
		Proxy: pallet_proxy,
1896

            
1896
		Timestamp: pallet_timestamp,
1896
		EVM: pallet_evm,
1896
		Ethereum: pallet_ethereum,
1896
		EthereumXcm: pallet_ethereum_xcm,
1896
	}
10273
);
6
pub(crate) fn para_events() -> Vec<RuntimeEvent> {
6
	System::events()
6
		.into_iter()
62
		.map(|r| r.event)
62
		.filter_map(|e| Some(e))
6
		.collect::<Vec<_>>()
6
}
use frame_support::traits::tokens::{PayFromAccount, UnityAssetBalanceConversion};
use frame_support::traits::{OnFinalize, OnInitialize, UncheckedOnRuntimeUpgrade};
use moonriver_runtime::{EvmForeignAssets, BLOCK_STORAGE_LIMIT, MAX_POV_SIZE};
use pallet_evm::FrameSystemAccountProvider;
use xcm_primitives::AsAssetType;
2
pub(crate) fn on_runtime_upgrade() {
2
	VersionUncheckedMigrateToV1::<Runtime>::on_runtime_upgrade();
2
}
3
pub(crate) fn para_roll_to(n: BlockNumber) {
6
	while System::block_number() < n {
3
		PolkadotXcm::on_finalize(System::block_number());
3
		Balances::on_finalize(System::block_number());
3
		System::on_finalize(System::block_number());
3
		System::set_block_number(System::block_number() + 1);
3
		System::on_initialize(System::block_number());
3
		Balances::on_initialize(System::block_number());
3
		PolkadotXcm::on_initialize(System::block_number());
3
	}
3
}