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, ensure, parameter_types,
21
	traits::{
22
		fungible::NativeOrWithId, ConstU32, EitherOf, Everything, Get, InstanceFilter, Nothing,
23
		PalletInfoAccess,
24
	},
25
	weights::Weight,
26
	PalletId,
27
};
28
use frame_system::{pallet_prelude::BlockNumberFor, EnsureRoot};
29
use moonbeam_runtime_common::{
30
	impl_asset_conversion::AssetRateConverter, impl_multiasset_paymaster::MultiAssetPaymaster,
31
	xcm_origins::AllowSiblingParachains,
32
};
33
use pallet_moonbeam_foreign_assets::{MapSuccessToGovernance, MapSuccessToXcm};
34
use pallet_xcm::{migration::v1::VersionUncheckedMigrateToV1, EnsureXcm};
35
use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
36
use sp_core::{H160, H256};
37
use sp_runtime::{
38
	traits::{BlakeTwo256, Hash, IdentityLookup, MaybeEquivalence, Zero},
39
	Permill,
40
};
41
use sp_std::{convert::TryFrom, prelude::*};
42
use xcm::{latest::prelude::*, Version as XcmVersion, VersionedXcm};
43

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

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

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

            
76
parameter_types! {
77
	pub const BlockHashCount: u32 = 250;
78
}
79

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

            
113
parameter_types! {
114
	pub ExistentialDeposit: Balance = 0;
115
	pub const MaxLocks: u32 = 50;
116
	pub const MaxReserves: u32 = 50;
117
}
118

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

            
136
/// Type for specifying how a `Location` can be converted into an `AccountId`. This is used
137
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
138
/// `Transact` in order to determine the dispatch Origin.
139
pub type LocationToAccountId = (
140
	// The parent (Relay-chain) origin converts to the default `AccountId`.
141
	ParentIsPreset<AccountId>,
142
	// Sibling parachain origins convert to AccountId via the `ParaId::into`.
143
	SiblingParachainConvertsVia<Sibling, AccountId>,
144
	AccountKey20Aliases<RelayNetwork, AccountId>,
145
	// Generate remote accounts according to polkadot standards
146
	xcm_builder::HashedDescription<
147
		AccountId,
148
		xcm_builder::DescribeFamily<xcm_builder::DescribeAllTerminal>,
149
	>,
150
);
151

            
152
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
153
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
154
/// biases the kind of local `Origin` it will become.
155
pub type XcmOriginToTransactDispatchOrigin = (
156
	// Sovereign account converter; this attempts to derive an `AccountId` from the origin location
157
	// using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
158
	// foreign chains who want to have a local sovereign account on this chain which they control.
159
	SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
160
	// Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
161
	// recognised.
162
	RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
163
	// Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
164
	// recognised.
165
	SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
166
	// Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
167
	// transaction from the Root origin.
168
	ParentAsSuperuser<RuntimeOrigin>,
169
	// Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
170
	pallet_xcm::XcmPassthrough<RuntimeOrigin>,
171
	SignedAccountKey20AsNative<RelayNetwork, RuntimeOrigin>,
172
);
173

            
174
parameter_types! {
175
	pub const UnitWeightCost: Weight = Weight::from_parts(1u64, 1u64);
176
	pub MaxInstructions: u32 = 100;
177
}
178

            
179
pub type LocalAssetTransactor = FungibleAdapter<
180
	// Use this currency:
181
	Balances,
182
	// Use this currency when it is a fungible asset matching any of the locations in
183
	// SelfReserveRepresentations
184
	IsConcrete<SelfReserve>,
185
	// We can convert the Locations with our converter above:
186
	LocationToAccountId,
187
	// Our chain's account ID type (we can't get away without mentioning it explicitly):
188
	AccountId,
189
	// We dont allow teleport
190
	(),
191
>;
192

            
193
// We use both transactors
194
pub type AssetTransactors = (LocalAssetTransactor, EvmForeignAssets);
195

            
196
pub type XcmRouter = super::ParachainXcmRouter<MsgQueue>;
197

            
198
pub type XcmBarrier = (
199
	// Weight that is paid for may be consumed.
200
	TakeWeightCredit,
201
	// Expected responses are OK.
202
	AllowKnownQueryResponses<PolkadotXcm>,
203
	WithComputedOrigin<
204
		(
205
			// If the message is one that immediately attemps to pay for execution, then allow it.
206
			AllowTopLevelPaidExecutionFrom<Everything>,
207
			// Subscriptions for version tracking are OK.
208
			AllowSubscriptionsFrom<Everything>,
209
		),
210
		UniversalLocation,
211
		ConstU32<8>,
212
	>,
213
);
214

            
215
parameter_types! {
216
	/// Xcm fees will go to the treasury account
217
	pub XcmFeesAccount: AccountId = Treasury::account_id();
218
	/// Parachain token units per second of execution
219
	pub ParaTokensPerSecond: u128 = 1000000000000;
220
}
221

            
222
pub struct WeightToFee;
223
impl sp_weights::WeightToFee for WeightToFee {
224
	type Balance = Balance;
225

            
226
49
	fn weight_to_fee(weight: &Weight) -> Self::Balance {
227
		use sp_runtime::SaturatedConversion as _;
228
49
		Self::Balance::saturated_from(weight.ref_time())
229
49
			.saturating_mul(ParaTokensPerSecond::get())
230
49
			.saturating_div(frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND as u128)
231
49
	}
232
}
233

            
234
parameter_types! {
235
	pub RelayNetwork: NetworkId = moonriver_runtime::xcm_config::RelayNetwork::get();
236
	pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
237
	pub UniversalLocation: InteriorLocation =
238
		[GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())].into();
239
	pub SelfReserve: Location = Location {
240
		parents:0,
241
		interior: [
242
			PalletInstance(<Balances as PalletInfoAccess>::index() as u8)
243
		].into()
244
	};
245
	pub const MaxAssetsIntoHolding: u32 = 64;
246

            
247
	pub AssetHubLocation: Location = Location::new(1, [Parachain(1000)]);
248
	pub RelayLocationFilter: AssetFilter = Wild(AllOf {
249
		fun: WildFungible,
250
		id: xcm::prelude::AssetId(Location::parent()),
251
	});
252

            
253
	pub RelayChainNativeAssetFromAssetHub: (AssetFilter, Location) = (
254
		RelayLocationFilter::get(),
255
		AssetHubLocation::get()
256
	);
257
}
258

            
259
use frame_system::RawOrigin;
260
use sp_runtime::traits::PostDispatchInfoOf;
261
use sp_runtime::DispatchErrorWithPostInfo;
262
use xcm_executor::traits::CallDispatcher;
263
moonbeam_runtime_common::impl_moonbeam_xcm_call!();
264

            
265
type Reserves = (
266
	// Relaychain (DOT) from Asset Hub
267
	Case<RelayChainNativeAssetFromAssetHub>,
268
	// Assets which the reserve is the same as the origin.
269
	xcm_primitives::MultiNativeAsset<
270
		xcm_primitives::AbsoluteAndRelativeReserve<SelfLocationAbsolute>,
271
	>,
272
);
273

            
274
pub struct XcmConfig;
275
impl Config for XcmConfig {
276
	type RuntimeCall = RuntimeCall;
277
	type XcmSender = XcmRouter;
278
	type AssetTransactor = AssetTransactors;
279
	type OriginConverter = XcmOriginToTransactDispatchOrigin;
280
	type IsReserve = Reserves;
281
	type IsTeleporter = ();
282
	type UniversalLocation = UniversalLocation;
283
	type Barrier = XcmBarrier;
284
	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
285
	type Trader = pallet_xcm_weight_trader::Trader<Runtime>;
286
	type ResponseHandler = PolkadotXcm;
287
	type SubscriptionService = PolkadotXcm;
288
	type AssetTrap = PolkadotXcm;
289
	type AssetClaims = PolkadotXcm;
290
	type CallDispatcher = MoonbeamCall;
291
	type AssetLocker = ();
292
	type AssetExchanger = ();
293
	type PalletInstancesInfo = ();
294
	type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
295
	type FeeManager = ();
296
	type MessageExporter = ();
297
	type UniversalAliases = Nothing;
298
	type SafeCallFilter = Everything;
299
	type Aliasers = Nothing;
300
	type TransactionalProcessor = ();
301
	type HrmpNewChannelOpenRequestHandler = ();
302
	type HrmpChannelAcceptedHandler = ();
303
	type HrmpChannelClosingHandler = ();
304
	type XcmRecorder = PolkadotXcm;
305
	type XcmEventEmitter = PolkadotXcm;
306
}
307

            
308
impl cumulus_pallet_xcm::Config for Runtime {
309
	type RuntimeEvent = RuntimeEvent;
310
	type XcmExecutor = XcmExecutor<XcmConfig>;
311
}
312

            
313
// Our currencyId. We distinguish for now between SelfReserve, and Others, defined by their Id.
314
#[derive(
315
	Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo, DecodeWithMemTracking,
316
)]
317
pub enum CurrencyId {
318
	SelfReserve,
319
	ForeignAsset(AssetId),
320
}
321

            
322
// How to convert from CurrencyId to Location
323
pub struct CurrencyIdToLocation<AssetXConverter>(sp_std::marker::PhantomData<AssetXConverter>);
324
impl<AssetXConverter> sp_runtime::traits::Convert<CurrencyId, Option<Location>>
325
	for CurrencyIdToLocation<AssetXConverter>
326
where
327
	AssetXConverter: MaybeEquivalence<Location, AssetId>,
328
{
329
25
	fn convert(currency: CurrencyId) -> Option<Location> {
330
25
		match currency {
331
			CurrencyId::SelfReserve => {
332
				// For now and until Xtokens is adapted to handle 0.9.16 version we use
333
				// the old anchoring here
334
				// This is not a problem in either cases, since the view of the destination
335
				// chain does not change
336
				// TODO! change this to NewAnchoringSelfReserve once xtokens is adapted for it
337
8
				let multi: Location = SelfReserve::get();
338
8
				Some(multi)
339
			}
340
17
			CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset),
341
		}
342
25
	}
343
}
344

            
345
parameter_types! {
346
	pub const BaseXcmWeight: Weight = Weight::from_parts(100u64, 100u64);
347
	pub const MaxAssetsForTransfer: usize = 2;
348
	pub SelfLocation: Location = Location::here();
349
	pub SelfLocationAbsolute: Location = Location {
350
		parents:1,
351
		interior: [
352
			Parachain(MsgQueue::parachain_id().into())
353
		].into()
354
	};
355
}
356

            
357
parameter_types! {
358
	pub const ProposalBond: Permill = Permill::from_percent(5);
359
	pub const ProposalBondMinimum: Balance = 0;
360
	pub const SpendPeriod: u32 = 0;
361
	pub const TreasuryId: PalletId = PalletId(*b"pc/trsry");
362
	pub const MaxApprovals: u32 = 100;
363
	pub TreasuryAccount: AccountId = Treasury::account_id();
364
}
365

            
366
impl pallet_treasury::Config for Runtime {
367
	type PalletId = TreasuryId;
368
	type Currency = Balances;
369
	type RejectOrigin = EnsureRoot<AccountId>;
370
	type RuntimeEvent = RuntimeEvent;
371
	type SpendPeriod = SpendPeriod;
372
	type Burn = ();
373
	type BurnDestination = ();
374
	type MaxApprovals = MaxApprovals;
375
	type WeightInfo = ();
376
	type SpendFunds = ();
377
	type SpendOrigin = frame_support::traits::NeverEnsureOrigin<Balance>; // Same as Polkadot
378
	type AssetKind = NativeOrWithId<AssetId>;
379
	type Beneficiary = AccountId;
380
	type BeneficiaryLookup = IdentityLookup<AccountId>;
381
	type Paymaster = MultiAssetPaymaster<Runtime, TreasuryAccount, Balances>;
382
	type BalanceConverter = AssetRateConverter<Runtime, Balances>;
383
	type PayoutPeriod = ConstU32<0>;
384
	#[cfg(feature = "runtime-benchmarks")]
385
	type BenchmarkHelper = ArgumentsBenchmarkHelper<Runtime>;
386
	type BlockNumberProvider = System;
387
}
388

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

            
394
	#[pallet::config]
395
	pub trait Config: frame_system::Config {
396
		type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
397
	}
398

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

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

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

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

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

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

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

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

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

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

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

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

            
537
19
						Self::deposit_event(Event::ExecutedDownward(id, outcome));
538
19
					}
539
				}
540
			}
541
19
			limit
542
19
		}
543
	}
544
}
545

            
546
// Pallet to provide the version, used to test runtime upgrade version changes
547
#[frame_support::pallet]
548
pub mod mock_version_changer {
549
	use super::*;
550
	use frame_support::pallet_prelude::*;
551

            
552
	#[pallet::config]
553
	pub trait Config: frame_system::Config {}
554

            
555
	#[pallet::call]
556
	impl<T: Config> Pallet<T> {}
557

            
558
	#[pallet::pallet]
559
	pub struct Pallet<T>(_);
560

            
561
	#[pallet::storage]
562
	#[pallet::getter(fn current_version)]
563
	pub(super) type CurrentVersion<T: Config> = StorageValue<_, XcmVersion, ValueQuery>;
564

            
565
	impl<T: Config> Get<XcmVersion> for Pallet<T> {
566
4
		fn get() -> XcmVersion {
567
4
			Self::current_version()
568
4
		}
569
	}
570

            
571
	#[pallet::event]
572
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
573
	pub enum Event<T: Config> {
574
		// XCMP
575
		/// Some XCM was executed OK.
576
		VersionChanged(XcmVersion),
577
	}
578

            
579
	impl<T: Config> Pallet<T> {
580
5
		pub fn set_version(version: XcmVersion) {
581
5
			CurrentVersion::<T>::put(version);
582
5
			Self::deposit_event(Event::VersionChanged(version));
583
5
		}
584
	}
585
}
586

            
587
impl mock_msg_queue::Config for Runtime {
588
	type XcmExecutor = XcmExecutor<XcmConfig>;
589
}
590

            
591
impl mock_version_changer::Config for Runtime {}
592

            
593
pub type LocalOriginToLocation =
594
	xcm_primitives::SignedToAccountId20<RuntimeOrigin, AccountId, RelayNetwork>;
595

            
596
parameter_types! {
597
	pub MatcherLocation: Location = Location::here();
598
}
599

            
600
impl pallet_xcm::Config for Runtime {
601
	type RuntimeEvent = RuntimeEvent;
602
	type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
603
	type XcmRouter = XcmRouter;
604
	type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
605
	type XcmExecuteFilter = frame_support::traits::Nothing;
606
	type XcmExecutor = XcmExecutor<XcmConfig>;
607
	// Do not allow teleports
608
	type XcmTeleportFilter = Nothing;
609
	type XcmReserveTransferFilter = Everything;
610
	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
611
	type UniversalLocation = UniversalLocation;
612
	type RuntimeOrigin = RuntimeOrigin;
613
	type RuntimeCall = RuntimeCall;
614
	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
615
	// We use a custom one to test runtime upgrades
616
	type AdvertisedXcmVersion = XcmVersioner;
617
	type Currency = Balances;
618
	type CurrencyMatcher = IsConcrete<MatcherLocation>;
619
	type TrustedLockers = ();
620
	type SovereignAccountOf = ();
621
	type MaxLockers = ConstU32<8>;
622
	type WeightInfo = pallet_xcm::TestWeightInfo;
623
	type MaxRemoteLockConsumers = ConstU32<0>;
624
	type RemoteLockConsumerIdentifier = ();
625
	type AdminOrigin = frame_system::EnsureRoot<AccountId>;
626
	type AuthorizedAliasConsideration = Disabled;
627
}
628

            
629
#[derive(
630
	Clone,
631
	Default,
632
	Eq,
633
	Debug,
634
	PartialEq,
635
	Ord,
636
	PartialOrd,
637
	Encode,
638
	Decode,
639
	TypeInfo,
640
	DecodeWithMemTracking,
641
)]
642
pub struct AssetMetadata {
643
	pub name: Vec<u8>,
644
	pub symbol: Vec<u8>,
645
	pub decimals: u8,
646
}
647

            
648
pub struct AccountIdToH160;
649
impl sp_runtime::traits::Convert<AccountId, H160> for AccountIdToH160 {
650
250
	fn convert(account_id: AccountId) -> H160 {
651
250
		account_id.into()
652
250
	}
653
}
654

            
655
pub struct EvmForeignAssetIdFilter;
656
impl frame_support::traits::Contains<AssetId> for EvmForeignAssetIdFilter {
657
35
	fn contains(_asset_id: &AssetId) -> bool {
658
35
		true
659
35
	}
660
}
661

            
662
pub type ForeignAssetManagerOrigin = EitherOf<
663
	MapSuccessToXcm<EnsureXcm<AllowSiblingParachains>>,
664
	MapSuccessToGovernance<EnsureRoot<AccountId>>,
665
>;
666

            
667
moonbeam_runtime_common::impl_evm_runner_precompile_or_eth_xcm!();
668

            
669
parameter_types! {
670
	pub ForeignAssetCreationDeposit: u128 = 100 * currency::MOVR;
671
}
672

            
673
impl pallet_moonbeam_foreign_assets::Config for Runtime {
674
	type AccountIdToH160 = AccountIdToH160;
675
	type AssetIdFilter = EvmForeignAssetIdFilter;
676
	type EvmRunner = EvmRunnerPrecompileOrEthXcm<MoonbeamCall, Self>;
677
	type ConvertLocation =
678
		SiblingParachainConvertsVia<polkadot_parachain::primitives::Sibling, AccountId>;
679
	type ForeignAssetCreatorOrigin = ForeignAssetManagerOrigin;
680
	type ForeignAssetFreezerOrigin = ForeignAssetManagerOrigin;
681
	type ForeignAssetModifierOrigin = ForeignAssetManagerOrigin;
682
	type ForeignAssetUnfreezerOrigin = ForeignAssetManagerOrigin;
683
	type OnForeignAssetCreated = ();
684
	type MaxForeignAssets = ConstU32<256>;
685
	type WeightInfo = ();
686
	type XcmLocationToH160 = LocationToH160;
687
	type ForeignAssetCreationDeposit = ForeignAssetCreationDeposit;
688
	type Balance = Balance;
689
	type Currency = Balances;
690
}
691

            
692
// 1 KSM should be enough
693
parameter_types! {
694
	pub MaxHrmpRelayFee: Asset = (Location::parent(), 1_000_000_000_000u128).into();
695
}
696

            
697
impl pallet_xcm_transactor::Config for Runtime {
698
	type Balance = Balance;
699
	type Transactor = moonriver_runtime::xcm_config::Transactors;
700
	type DerivativeAddressRegistrationOrigin = EnsureRoot<AccountId>;
701
	type SovereignAccountDispatcherOrigin = frame_system::EnsureRoot<AccountId>;
702
	type CurrencyId = CurrencyId;
703
	type AccountIdToLocation = xcm_primitives::AccountIdToLocation<AccountId>;
704
	type CurrencyIdToLocation = CurrencyIdToLocation<EvmForeignAssets>;
705
	type SelfLocation = SelfLocation;
706
	type Weigher = xcm_builder::FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
707
	type UniversalLocation = UniversalLocation;
708
	type XcmSender = XcmRouter;
709
	type BaseXcmWeight = BaseXcmWeight;
710
	type AssetTransactor = AssetTransactors;
711
	type ReserveProvider = xcm_primitives::AbsoluteAndRelativeReserve<SelfLocationAbsolute>;
712
	type WeightInfo = ();
713
	type HrmpManipulatorOrigin = EnsureRoot<AccountId>;
714
	type HrmpOpenOrigin = EnsureRoot<AccountId>;
715
	type MaxHrmpFee = xcm_builder::Case<MaxHrmpRelayFee>;
716
}
717

            
718
parameter_types! {
719
	pub RelayLocation: Location = Location::parent();
720
}
721

            
722
impl pallet_xcm_weight_trader::Config for Runtime {
723
	type AccountIdToLocation = xcm_primitives::AccountIdToLocation<AccountId>;
724
	type AddSupportedAssetOrigin = EnsureRoot<AccountId>;
725
	type AssetLocationFilter = Everything;
726
	type AssetTransactor = AssetTransactors;
727
	type Balance = Balance;
728
	type EditSupportedAssetOrigin = EnsureRoot<AccountId>;
729
	type NativeLocation = SelfReserve;
730
	type PauseSupportedAssetOrigin = EnsureRoot<AccountId>;
731
	type RemoveSupportedAssetOrigin = EnsureRoot<AccountId>;
732
	type ResumeSupportedAssetOrigin = EnsureRoot<AccountId>;
733
	type WeightInfo = ();
734
	type WeightToFee = WeightToFee;
735
	type XcmFeesAccount = XcmFeesAccount;
736
	#[cfg(feature = "runtime-benchmarks")]
737
	type NotFilteredLocation = RelayLocation;
738
}
739

            
740
parameter_types! {
741
	pub const MinimumPeriod: u64 = 1000;
742
}
743
impl pallet_timestamp::Config for Runtime {
744
	type Moment = u64;
745
	type OnTimestampSet = ();
746
	type MinimumPeriod = MinimumPeriod;
747
	type WeightInfo = ();
748
}
749

            
750
parameter_types! {
751
	pub BlockGasLimit: U256 = moonriver_runtime::BlockGasLimit::get();
752
	pub WeightPerGas: Weight = moonriver_runtime::WeightPerGas::get();
753
	pub const GasLimitPovSizeRatio: u64 = moonriver_runtime::GasLimitPovSizeRatio::get();
754
	pub GasLimitStorageGrowthRatio: u64 = moonriver_runtime::GasLimitStorageGrowthRatio::get();
755
}
756

            
757
impl pallet_evm::Config for Runtime {
758
	type FeeCalculator = ();
759
	type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
760
	type WeightPerGas = WeightPerGas;
761

            
762
	type CallOrigin = pallet_evm::EnsureAddressRoot<AccountId>;
763
	type WithdrawOrigin = pallet_evm::EnsureAddressNever<AccountId>;
764

            
765
	type AddressMapping = pallet_evm::IdentityAddressMapping;
766
	type Currency = Balances;
767
	type Runner = pallet_evm::runner::stack::Runner<Self>;
768

            
769
	type PrecompilesType = ();
770
	type PrecompilesValue = ();
771
	type ChainId = ();
772
	type BlockGasLimit = BlockGasLimit;
773
	type OnChargeTransaction = ();
774
	type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping<Self>;
775
	type FindAuthor = ();
776
	type OnCreate = ();
777
	type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
778
	type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
779
	type Timestamp = Timestamp;
780
	type WeightInfo = pallet_evm::weights::SubstrateWeight<Runtime>;
781
	type AccountProvider = FrameSystemAccountProvider<Runtime>;
782
	type CreateOriginFilter = ();
783
	type CreateInnerOriginFilter = ();
784
}
785

            
786
#[allow(dead_code)]
787
pub struct NormalFilter;
788

            
789
impl frame_support::traits::Contains<RuntimeCall> for NormalFilter {
790
	fn contains(c: &RuntimeCall) -> bool {
791
		match c {
792
			_ => true,
793
		}
794
	}
795
}
796

            
797
// We need to use the encoding from the relay mock runtime
798
#[derive(Encode, Decode)]
799
pub enum RelayCall {
800
	#[codec(index = 5u8)]
801
	// the index should match the position of the module in `construct_runtime!`
802
	Utility(UtilityCall),
803
	#[codec(index = 6u8)]
804
	// the index should match the position of the module in `construct_runtime!`
805
	Hrmp(HrmpCall),
806
}
807

            
808
#[derive(Encode, Decode)]
809
pub enum UtilityCall {
810
	#[codec(index = 1u8)]
811
	AsDerivative(u16),
812
}
813

            
814
// HRMP call encoding, needed for xcm transactor pallet
815
#[derive(Encode, Decode)]
816
pub enum HrmpCall {
817
	#[codec(index = 0u8)]
818
	InitOpenChannel(ParaId, u32, u32),
819
	#[codec(index = 1u8)]
820
	AcceptOpenChannel(ParaId),
821
	#[codec(index = 2u8)]
822
	CloseChannel(HrmpChannelId),
823
	#[codec(index = 6u8)]
824
	CancelOpenRequest(HrmpChannelId, u32),
825
}
826

            
827
#[allow(dead_code)]
828
pub struct MockHrmpEncoder;
829

            
830
impl xcm_primitives::HrmpEncodeCall for MockHrmpEncoder {
831
	fn hrmp_encode_call(
832
		call: xcm_primitives::HrmpAvailableCalls,
833
	) -> Result<Vec<u8>, xcm::latest::Error> {
834
		match call {
835
			xcm_primitives::HrmpAvailableCalls::InitOpenChannel(a, b, c) => Ok(RelayCall::Hrmp(
836
				HrmpCall::InitOpenChannel(a.clone(), b.clone(), c.clone()),
837
			)
838
			.encode()),
839
			xcm_primitives::HrmpAvailableCalls::AcceptOpenChannel(a) => {
840
				Ok(RelayCall::Hrmp(HrmpCall::AcceptOpenChannel(a.clone())).encode())
841
			}
842
			xcm_primitives::HrmpAvailableCalls::CloseChannel(a) => {
843
				Ok(RelayCall::Hrmp(HrmpCall::CloseChannel(a.clone())).encode())
844
			}
845
			xcm_primitives::HrmpAvailableCalls::CancelOpenRequest(a, b) => {
846
				Ok(RelayCall::Hrmp(HrmpCall::CancelOpenRequest(a.clone(), b.clone())).encode())
847
			}
848
		}
849
	}
850
}
851

            
852
parameter_types! {
853
	pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes;
854
}
855

            
856
impl pallet_ethereum::Config for Runtime {
857
	type StateRoot =
858
		pallet_ethereum::IntermediateStateRoot<<Runtime as frame_system::Config>::Version>;
859
	type PostLogContent = PostBlockAndTxnHashes;
860
	type ExtraDataLength = ConstU32<30>;
861
}
862

            
863
parameter_types! {
864
	pub ReservedXcmpWeight: Weight = Weight::from_parts(u64::max_value(), 0);
865
}
866

            
867
#[derive(
868
	Copy,
869
	Clone,
870
	Eq,
871
	PartialEq,
872
	Ord,
873
	PartialOrd,
874
	Encode,
875
	Decode,
876
	Debug,
877
	MaxEncodedLen,
878
	TypeInfo,
879
	DecodeWithMemTracking,
880
)]
881
pub enum ProxyType {
882
	NotAllowed = 0,
883
	Any = 1,
884
}
885

            
886
impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType {}
887

            
888
impl InstanceFilter<RuntimeCall> for ProxyType {
889
	fn filter(&self, _c: &RuntimeCall) -> bool {
890
		match self {
891
			ProxyType::NotAllowed => false,
892
			ProxyType::Any => true,
893
		}
894
	}
895
	fn is_superset(&self, _o: &Self) -> bool {
896
		false
897
	}
898
}
899

            
900
impl Default for ProxyType {
901
	fn default() -> Self {
902
		Self::NotAllowed
903
	}
904
}
905

            
906
parameter_types! {
907
	pub const ProxyCost: u64 = 1;
908
}
909

            
910
impl pallet_proxy::Config for Runtime {
911
	type RuntimeEvent = RuntimeEvent;
912
	type RuntimeCall = RuntimeCall;
913
	type Currency = Balances;
914
	type ProxyType = ProxyType;
915
	type ProxyDepositBase = ProxyCost;
916
	type ProxyDepositFactor = ProxyCost;
917
	type MaxProxies = ConstU32<32>;
918
	type WeightInfo = pallet_proxy::weights::SubstrateWeight<Runtime>;
919
	type MaxPending = ConstU32<32>;
920
	type CallHasher = BlakeTwo256;
921
	type AnnouncementDepositBase = ProxyCost;
922
	type AnnouncementDepositFactor = ProxyCost;
923
	type BlockNumberProvider = System;
924
}
925

            
926
pub struct EthereumXcmEnsureProxy;
927
impl xcm_primitives::EnsureProxy<AccountId> for EthereumXcmEnsureProxy {
928
2
	fn ensure_ok(delegator: AccountId, delegatee: AccountId) -> Result<(), &'static str> {
929
		// The EVM implicitly contains an Any proxy, so we only allow for "Any" proxies
930
1
		let def: pallet_proxy::ProxyDefinition<AccountId, ProxyType, BlockNumber> =
931
2
			pallet_proxy::Pallet::<Runtime>::find_proxy(
932
2
				&delegator,
933
2
				&delegatee,
934
2
				Some(ProxyType::Any),
935
			)
936
2
			.map_err(|_| "proxy error: expected `ProxyType::Any`")?;
937
		// We only allow to use it for delay zero proxies, as the call will immediately be executed
938
1
		ensure!(def.delay.is_zero(), "proxy delay is Non-zero`");
939
1
		Ok(())
940
2
	}
941
}
942

            
943
impl pallet_ethereum_xcm::Config for Runtime {
944
	type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper;
945
	type ValidatedTransaction = pallet_ethereum::ValidatedTransaction<Self>;
946
	type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction;
947
	type ReservedXcmpWeight = ReservedXcmpWeight;
948
	type EnsureProxy = EthereumXcmEnsureProxy;
949
	type ControllerOrigin = EnsureRoot<AccountId>;
950
	type ForceOrigin = EnsureRoot<AccountId>;
951
}
952

            
953
type Block = frame_system::mocking::MockBlockU32<Runtime>;
954

            
955
construct_runtime!(
956
	pub enum Runtime	{
957
		System: frame_system,
958
		Balances: pallet_balances,
959
		MsgQueue: mock_msg_queue,
960
		XcmVersioner: mock_version_changer,
961

            
962
		PolkadotXcm: pallet_xcm,
963
		CumulusXcm: cumulus_pallet_xcm,
964
		XcmTransactor: pallet_xcm_transactor,
965
		XcmWeightTrader: pallet_xcm_weight_trader,
966
		Treasury: pallet_treasury,
967
		Proxy: pallet_proxy,
968

            
969
		Timestamp: pallet_timestamp,
970
		EVM: pallet_evm,
971
		Ethereum: pallet_ethereum,
972
		EthereumXcm: pallet_ethereum_xcm,
973
		EvmForeignAssets: pallet_moonbeam_foreign_assets,
974
	}
975
);
976

            
977
6
pub(crate) fn para_events() -> Vec<RuntimeEvent> {
978
6
	System::events()
979
6
		.into_iter()
980
6
		.map(|r| r.event)
981
79
		.filter_map(|e| Some(e))
982
6
		.collect::<Vec<_>>()
983
6
}
984

            
985
use frame_support::traits::{Disabled, OnFinalize, OnInitialize, UncheckedOnRuntimeUpgrade};
986
use moonriver_runtime::{currency, xcm_config::LocationToH160};
987
use pallet_evm::FrameSystemAccountProvider;
988

            
989
2
pub(crate) fn on_runtime_upgrade() {
990
2
	VersionUncheckedMigrateToV1::<Runtime>::on_runtime_upgrade();
991
2
}
992

            
993
3
pub(crate) fn para_roll_to(n: BlockNumber) {
994
6
	while System::block_number() < n {
995
3
		PolkadotXcm::on_finalize(System::block_number());
996
3
		Balances::on_finalize(System::block_number());
997
3
		System::on_finalize(System::block_number());
998
3
		System::set_block_number(System::block_number() + 1);
999
3
		System::on_initialize(System::block_number());
3
		Balances::on_initialize(System::block_number());
3
		PolkadotXcm::on_initialize(System::block_number());
3
	}
3
}