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
pub use moonbeam_runtime::xcm_config::AssetType;
29

            
30
use frame_system::{pallet_prelude::BlockNumberFor, EnsureRoot};
31
use moonbeam_runtime_common::{
32
	impl_asset_conversion::AssetRateConverter, impl_multiasset_paymaster::MultiAssetPaymaster,
33
	xcm_origins::AllowSiblingParachains,
34
};
35
use pallet_moonbeam_foreign_assets::{MapSuccessToGovernance, MapSuccessToXcm};
36
use pallet_xcm::{migration::v1::VersionUncheckedMigrateToV1, EnsureXcm};
37
use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
38
use sp_core::{H160, H256};
39
use sp_runtime::{
40
	traits::{BlakeTwo256, Hash, IdentityLookup, MaybeEquivalence, Zero},
41
	Permill,
42
};
43
use sp_std::{
44
	convert::{From, Into, TryFrom},
45
	prelude::*,
46
};
47
use xcm::{latest::prelude::*, Version as XcmVersion, VersionedXcm};
48

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

            
67
#[cfg(feature = "runtime-benchmarks")]
68
use moonbeam_runtime_common::benchmarking::BenchmarkHelper as ArgumentsBenchmarkHelper;
69
use scale_info::TypeInfo;
70
use xcm_simulator::{
71
	DmpMessageHandlerT as DmpMessageHandler, XcmpMessageFormat,
72
	XcmpMessageHandlerT as XcmpMessageHandler,
73
};
74

            
75
pub type AccountId = moonbeam_core_primitives::AccountId;
76
pub type Balance = u128;
77
pub type AssetId = u128;
78
pub type BlockNumber = BlockNumberFor<Runtime>;
79

            
80
parameter_types! {
81
	pub const BlockHashCount: u32 = 250;
82
}
83

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

            
117
parameter_types! {
118
	pub ExistentialDeposit: Balance = 0;
119
	pub const MaxLocks: u32 = 50;
120
	pub const MaxReserves: u32 = 50;
121
}
122

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

            
140
parameter_types! {
141
	pub const AssetDeposit: Balance = 10; // Does not really matter as this will be only called by root
142
	pub const ApprovalDeposit: Balance = 0;
143
	pub const AssetsStringLimit: u32 = 50;
144
	pub const MetadataDepositBase: Balance = 0;
145
	pub const MetadataDepositPerByte: Balance = 0;
146
	pub const AssetAccountDeposit: Balance = 0;
147
}
148

            
149
/// Type for specifying how a `Location` can be converted into an `AccountId`. This is used
150
/// when determining ownership of accounts for asset transacting and when attempting to use XCM
151
/// `Transact` in order to determine the dispatch Origin.
152
pub type LocationToAccountId = (
153
	// The parent (Relay-chain) origin converts to the default `AccountId`.
154
	ParentIsPreset<AccountId>,
155
	// Sibling parachain origins convert to AccountId via the `ParaId::into`.
156
	SiblingParachainConvertsVia<Sibling, AccountId>,
157
	AccountKey20Aliases<RelayNetwork, AccountId>,
158
	// Generate remote accounts according to polkadot standards
159
	xcm_builder::HashedDescription<
160
		AccountId,
161
		xcm_builder::DescribeFamily<xcm_builder::DescribeAllTerminal>,
162
	>,
163
);
164

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

            
187
parameter_types! {
188
	pub const UnitWeightCost: Weight = Weight::from_parts(1u64, 1u64);
189
	pub MaxInstructions: u32 = 100;
190
}
191

            
192
/// The transactor for our own chain currency.
193
pub type LocalAssetTransactor = FungibleAdapter<
194
	// Use this currency:
195
	Balances,
196
	// Use this currency when it is a fungible asset matching any of the locations in
197
	// SelfReserveRepresentations
198
	IsConcrete<SelfReserve>,
199
	// We can convert the Locations with our converter above:
200
	LocationToAccountId,
201
	// Our chain's account ID type (we can't get away without mentioning it explicitly):
202
	AccountId,
203
	// We dont allow teleport
204
	(),
205
>;
206

            
207
// These will be our transactors
208
// We use both transactors
209
pub type AssetTransactors = (LocalAssetTransactor, EvmForeignAssets);
210
pub type XcmRouter = super::ParachainXcmRouter<MsgQueue>;
211

            
212
pub type XcmBarrier = (
213
	// Weight that is paid for may be consumed.
214
	TakeWeightCredit,
215
	// Expected responses are OK.
216
	AllowKnownQueryResponses<PolkadotXcm>,
217
	WithComputedOrigin<
218
		(
219
			// If the message is one that immediately attemps to pay for execution, then allow it.
220
			AllowTopLevelPaidExecutionFrom<Everything>,
221
			// Subscriptions for version tracking are OK.
222
			AllowSubscriptionsFrom<Everything>,
223
		),
224
		UniversalLocation,
225
		ConstU32<8>,
226
	>,
227
);
228

            
229
parameter_types! {
230
	/// Xcm fees will go to the treasury account
231
	pub XcmFeesAccount: AccountId = Treasury::account_id();
232
	/// Parachain token units per second of execution
233
	pub ParaTokensPerSecond: u128 = WEIGHT_REF_TIME_PER_SECOND as u128;
234
}
235

            
236
pub struct WeightToFee;
237
impl sp_weights::WeightToFee for WeightToFee {
238
	type Balance = Balance;
239

            
240
46
	fn weight_to_fee(weight: &Weight) -> Self::Balance {
241
		use sp_runtime::SaturatedConversion as _;
242
46
		Self::Balance::saturated_from(weight.ref_time())
243
46
			.saturating_mul(ParaTokensPerSecond::get())
244
46
			.saturating_div(frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND as u128)
245
46
	}
246
}
247

            
248
parameter_types! {
249
	pub RelayNetwork: NetworkId = moonbeam_runtime::xcm_config::RelayNetwork::get();
250
	pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
251
	pub UniversalLocation: InteriorLocation =
252
		[GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())].into();
253
	pub SelfReserve: Location = Location {
254
		parents:0,
255
		interior: [
256
			PalletInstance(<Balances as PalletInfoAccess>::index() as u8)
257
		].into()
258
	};
259
	pub const MaxAssetsIntoHolding: u32 = 64;
260

            
261
	pub AssetHubLocation: Location = Location::new(1, [Parachain(1000)]);
262
	pub RelayLocationFilter: AssetFilter = Wild(AllOf {
263
		fun: WildFungible,
264
		id: xcm::prelude::AssetId(Location::parent()),
265
	});
266

            
267
	pub RelayChainNativeAssetFromAssetHub: (AssetFilter, Location) = (
268
		RelayLocationFilter::get(),
269
		AssetHubLocation::get()
270
	);
271
}
272

            
273
use frame_system::RawOrigin;
274
use sp_runtime::traits::PostDispatchInfoOf;
275
use sp_runtime::DispatchErrorWithPostInfo;
276
use xcm_executor::traits::CallDispatcher;
277
moonbeam_runtime_common::impl_moonbeam_xcm_call!();
278

            
279
type Reserves = (
280
	// Relaychain (DOT) from Asset Hub
281
	Case<RelayChainNativeAssetFromAssetHub>,
282
	// Assets which the reserve is the same as the origin.
283
	xcm_primitives::MultiNativeAsset<
284
		xcm_primitives::AbsoluteAndRelativeReserve<SelfLocationAbsolute>,
285
	>,
286
);
287

            
288
pub struct XcmConfig;
289
impl Config for XcmConfig {
290
	type RuntimeCall = RuntimeCall;
291
	type XcmSender = XcmRouter;
292
	type AssetTransactor = AssetTransactors;
293
	type OriginConverter = XcmOriginToTransactDispatchOrigin;
294
	type IsReserve = Reserves;
295
	type IsTeleporter = ();
296
	type UniversalLocation = UniversalLocation;
297
	type Barrier = XcmBarrier;
298
	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
299
	type Trader = pallet_xcm_weight_trader::Trader<Runtime>;
300
	type ResponseHandler = PolkadotXcm;
301
	type SubscriptionService = PolkadotXcm;
302
	type AssetTrap = PolkadotXcm;
303
	type AssetClaims = PolkadotXcm;
304
	type CallDispatcher = MoonbeamCall;
305
	type AssetLocker = ();
306
	type AssetExchanger = ();
307
	type PalletInstancesInfo = ();
308
	type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
309
	type FeeManager = ();
310
	type MessageExporter = ();
311
	type UniversalAliases = Nothing;
312
	type SafeCallFilter = Everything;
313
	type Aliasers = Nothing;
314
	type TransactionalProcessor = ();
315
	type HrmpNewChannelOpenRequestHandler = ();
316
	type HrmpChannelAcceptedHandler = ();
317
	type HrmpChannelClosingHandler = ();
318
	type XcmRecorder = PolkadotXcm;
319
	type XcmEventEmitter = ();
320
}
321

            
322
impl cumulus_pallet_xcm::Config for Runtime {
323
	type RuntimeEvent = RuntimeEvent;
324
	type XcmExecutor = XcmExecutor<XcmConfig>;
325
}
326

            
327
// Our currencyId. We distinguish for now between SelfReserve, and Others, defined by their Id.
328
#[derive(
329
	Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo, DecodeWithMemTracking,
330
)]
331
pub enum CurrencyId {
332
	SelfReserve,
333
	ForeignAsset(AssetId),
334
}
335

            
336
// How to convert from CurrencyId to Location
337
pub struct CurrencyIdToLocation<AssetXConverter>(sp_std::marker::PhantomData<AssetXConverter>);
338
impl<AssetXConverter> sp_runtime::traits::Convert<CurrencyId, Option<Location>>
339
	for CurrencyIdToLocation<AssetXConverter>
340
where
341
	AssetXConverter: MaybeEquivalence<Location, AssetId>,
342
{
343
23
	fn convert(currency: CurrencyId) -> Option<Location> {
344
23
		match currency {
345
			CurrencyId::SelfReserve => {
346
6
				let multi: Location = SelfReserve::get();
347
6
				Some(multi)
348
			}
349
17
			CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset),
350
		}
351
23
	}
352
}
353

            
354
parameter_types! {
355
	pub const BaseXcmWeight: Weight = Weight::from_parts(100u64, 100u64);
356
	pub const MaxAssetsForTransfer: usize = 2;
357
	pub SelfLocation: Location = Location::here();
358
	pub SelfLocationAbsolute: Location = Location {
359
		parents:1,
360
		interior: [
361
			Parachain(MsgQueue::parachain_id().into())
362
		].into()
363
	};
364
}
365

            
366
parameter_types! {
367
	pub const ProposalBond: Permill = Permill::from_percent(5);
368
	pub const ProposalBondMinimum: Balance = 0;
369
	pub const SpendPeriod: u32 = 0;
370
	pub const TreasuryId: PalletId = PalletId(*b"pc/trsry");
371
	pub const MaxApprovals: u32 = 100;
372
	pub TreasuryAccount: AccountId = Treasury::account_id();
373
}
374

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

            
398
#[frame_support::pallet]
399
pub mod mock_msg_queue {
400
	use super::*;
401
	use frame_support::pallet_prelude::*;
402

            
403
	#[pallet::config]
404
	pub trait Config: frame_system::Config {
405
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
406
		type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
407
	}
408

            
409
	#[pallet::call]
410
	impl<T: Config> Pallet<T> {}
411

            
412
3
	#[pallet::pallet]
413
	pub struct Pallet<T>(_);
414

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

            
419
	impl<T: Config> Get<ParaId> for Pallet<T> {
420
43
		fn get() -> ParaId {
421
43
			Self::parachain_id()
422
43
		}
423
	}
424

            
425
	pub type MessageId = [u8; 32];
426

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

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

            
449
	impl<T: Config> Pallet<T> {
450
234
		pub fn set_para_id(para_id: ParaId) {
451
234
			ParachainId::<T>::put(para_id);
452
234
		}
453

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

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

            
504
27
				let mut remaining_fragments = &data_ref[..];
505
54
				while !remaining_fragments.is_empty() {
506
27
					if let Ok(xcm) =
507
27
						VersionedXcm::<T::RuntimeCall>::decode(&mut remaining_fragments)
508
27
					{
509
27
						let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight);
510
27
					} else {
511
						debug_assert!(false, "Invalid incoming XCMP message data");
512
					}
513
				}
514
			}
515
27
			max_weight
516
27
		}
517
	}
518

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

            
544
19
						Self::deposit_event(Event::ExecutedDownward(id, outcome));
545
19
					}
546
				}
547
			}
548
19
			limit
549
19
		}
550
	}
551
}
552

            
553
// Pallet to provide the version, used to test runtime upgrade version changes
554
#[frame_support::pallet]
555
pub mod mock_version_changer {
556
	use super::*;
557
	use frame_support::pallet_prelude::*;
558

            
559
	#[pallet::config]
560
	pub trait Config: frame_system::Config {
561
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
562
	}
563

            
564
	#[pallet::call]
565
	impl<T: Config> Pallet<T> {}
566

            
567
3
	#[pallet::pallet]
568
	pub struct Pallet<T>(_);
569

            
570
10
	#[pallet::storage]
571
	#[pallet::getter(fn current_version)]
572
	pub(super) type CurrentVersion<T: Config> = StorageValue<_, XcmVersion, ValueQuery>;
573

            
574
	impl<T: Config> Get<XcmVersion> for Pallet<T> {
575
2
		fn get() -> XcmVersion {
576
2
			Self::current_version()
577
2
		}
578
	}
579

            
580
	#[pallet::event]
581
2
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
582
	pub enum Event<T: Config> {
583
		// XCMP
584
		/// Some XCM was executed OK.
585
		VersionChanged(XcmVersion),
586
	}
587

            
588
	impl<T: Config> Pallet<T> {
589
2
		pub fn set_version(version: XcmVersion) {
590
2
			CurrentVersion::<T>::put(version);
591
2
			Self::deposit_event(Event::VersionChanged(version));
592
2
		}
593
	}
594
}
595

            
596
impl mock_msg_queue::Config for Runtime {
597
	type RuntimeEvent = RuntimeEvent;
598
	type XcmExecutor = XcmExecutor<XcmConfig>;
599
}
600

            
601
impl mock_version_changer::Config for Runtime {
602
	type RuntimeEvent = RuntimeEvent;
603
}
604

            
605
pub type LocalOriginToLocation =
606
	xcm_primitives::SignedToAccountId20<RuntimeOrigin, AccountId, RelayNetwork>;
607

            
608
parameter_types! {
609
	pub MatcherLocation: Location = Location::here();
610
}
611

            
612
impl pallet_xcm::Config for Runtime {
613
	type RuntimeEvent = RuntimeEvent;
614
	type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
615
	type XcmRouter = XcmRouter;
616
	type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
617
	type XcmExecuteFilter = frame_support::traits::Nothing;
618
	type XcmExecutor = XcmExecutor<XcmConfig>;
619
	// Do not allow teleports
620
	type XcmTeleportFilter = Nothing;
621
	type XcmReserveTransferFilter = Everything;
622
	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
623
	type UniversalLocation = UniversalLocation;
624
	type RuntimeOrigin = RuntimeOrigin;
625
	type RuntimeCall = RuntimeCall;
626
	const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
627
	// We use a custom one to test runtime ugprades
628
	type AdvertisedXcmVersion = XcmVersioner;
629
	type Currency = Balances;
630
	type CurrencyMatcher = IsConcrete<MatcherLocation>;
631
	type TrustedLockers = ();
632
	type SovereignAccountOf = ();
633
	type MaxLockers = ConstU32<8>;
634
	type WeightInfo = pallet_xcm::TestWeightInfo;
635
	type MaxRemoteLockConsumers = ConstU32<0>;
636
	type RemoteLockConsumerIdentifier = ();
637
	type AdminOrigin = frame_system::EnsureRoot<AccountId>;
638
	type AuthorizedAliasConsideration = Disabled;
639
	type AssetHubMigrationStarted = ConstBool<false>;
640
}
641

            
642
#[derive(
643
	Clone,
644
	Default,
645
	Eq,
646
	Debug,
647
	PartialEq,
648
	Ord,
649
	PartialOrd,
650
	Encode,
651
	Decode,
652
	TypeInfo,
653
	DecodeWithMemTracking,
654
)]
655
pub struct AssetMetadata {
656
	pub name: Vec<u8>,
657
	pub symbol: Vec<u8>,
658
	pub decimals: u8,
659
}
660

            
661
pub struct AccountIdToH160;
662
impl sp_runtime::traits::Convert<AccountId, H160> for AccountIdToH160 {
663
238
	fn convert(account_id: AccountId) -> H160 {
664
238
		account_id.into()
665
238
	}
666
}
667

            
668
pub type ForeignAssetManagerOrigin = EitherOf<
669
	MapSuccessToXcm<EnsureXcm<AllowSiblingParachains>>,
670
	MapSuccessToGovernance<EnsureRoot<AccountId>>,
671
>;
672

            
673
moonbeam_runtime_common::impl_evm_runner_precompile_or_eth_xcm!();
674

            
675
parameter_types! {
676
	pub ForeignAssetCreationDeposit: u128 = 100 * currency::GLMR;
677
}
678

            
679
impl pallet_moonbeam_foreign_assets::Config for Runtime {
680
	type AccountIdToH160 = AccountIdToH160;
681
	type AssetIdFilter = Everything;
682
	type EvmRunner = EvmRunnerPrecompileOrEthXcm<MoonbeamCall, Self>;
683
	type ConvertLocation =
684
		SiblingParachainConvertsVia<polkadot_parachain::primitives::Sibling, AccountId>;
685
	type ForeignAssetCreatorOrigin = ForeignAssetManagerOrigin;
686
	type ForeignAssetFreezerOrigin = ForeignAssetManagerOrigin;
687
	type ForeignAssetModifierOrigin = ForeignAssetManagerOrigin;
688
	type ForeignAssetUnfreezerOrigin = ForeignAssetManagerOrigin;
689
	type OnForeignAssetCreated = ();
690
	type MaxForeignAssets = ConstU32<256>;
691
	type RuntimeEvent = RuntimeEvent;
692
	type WeightInfo = ();
693
	type XcmLocationToH160 = LocationToH160;
694
	type ForeignAssetCreationDeposit = ForeignAssetCreationDeposit;
695
	type Balance = Balance;
696
	type Currency = Balances;
697
}
698

            
699
// 1 DOT should be enough
700
parameter_types! {
701
	pub MaxHrmpRelayFee: Asset = (Location::parent(), 1_000_000_000_000u128).into();
702
}
703

            
704
impl pallet_xcm_transactor::Config for Runtime {
705
	type RuntimeEvent = RuntimeEvent;
706
	type Balance = Balance;
707
	type Transactor = MockTransactors;
708
	type DerivativeAddressRegistrationOrigin = EnsureRoot<AccountId>;
709
	type SovereignAccountDispatcherOrigin = frame_system::EnsureRoot<AccountId>;
710
	type CurrencyId = CurrencyId;
711
	type AccountIdToLocation = xcm_primitives::AccountIdToLocation<AccountId>;
712
	type CurrencyIdToLocation = CurrencyIdToLocation<EvmForeignAssets>;
713
	type SelfLocation = SelfLocation;
714
	type Weigher = xcm_builder::FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
715
	type UniversalLocation = UniversalLocation;
716
	type XcmSender = XcmRouter;
717
	type BaseXcmWeight = BaseXcmWeight;
718
	type AssetTransactor = AssetTransactors;
719
	type ReserveProvider = xcm_primitives::AbsoluteAndRelativeReserve<SelfLocationAbsolute>;
720
	type WeightInfo = ();
721
	type HrmpManipulatorOrigin = EnsureRoot<AccountId>;
722
	type HrmpOpenOrigin = EnsureRoot<AccountId>;
723
	type MaxHrmpFee = xcm_builder::Case<MaxHrmpRelayFee>;
724
}
725

            
726
parameter_types! {
727
	pub RelayLocation: Location = Location::parent();
728
}
729

            
730
impl pallet_xcm_weight_trader::Config for Runtime {
731
	type AccountIdToLocation = xcm_primitives::AccountIdToLocation<AccountId>;
732
	type AddSupportedAssetOrigin = EnsureRoot<AccountId>;
733
	type AssetLocationFilter = Everything;
734
	type AssetTransactor = AssetTransactors;
735
	type Balance = Balance;
736
	type EditSupportedAssetOrigin = EnsureRoot<AccountId>;
737
	type NativeLocation = SelfReserve;
738
	type PauseSupportedAssetOrigin = EnsureRoot<AccountId>;
739
	type RemoveSupportedAssetOrigin = EnsureRoot<AccountId>;
740
	type RuntimeEvent = RuntimeEvent;
741
	type ResumeSupportedAssetOrigin = EnsureRoot<AccountId>;
742
	type WeightInfo = ();
743
	type WeightToFee = WeightToFee;
744
	type XcmFeesAccount = XcmFeesAccount;
745
	#[cfg(feature = "runtime-benchmarks")]
746
	type NotFilteredLocation = RelayLocation;
747
}
748

            
749
parameter_types! {
750
	pub const MinimumPeriod: u64 = 1000;
751
}
752
impl pallet_timestamp::Config for Runtime {
753
	type Moment = u64;
754
	type OnTimestampSet = ();
755
	type MinimumPeriod = MinimumPeriod;
756
	type WeightInfo = ();
757
}
758

            
759
parameter_types! {
760
	pub BlockGasLimit: U256 = moonbeam_runtime::BlockGasLimit::get();
761
	pub WeightPerGas: Weight = moonbeam_runtime::WeightPerGas::get();
762
	pub const GasLimitPovSizeRatio: u64 = moonbeam_runtime::GasLimitPovSizeRatio::get();
763
	pub GasLimitStorageGrowthRatio: u64 = moonbeam_runtime::GasLimitStorageGrowthRatio::get();
764
}
765

            
766
impl pallet_evm::Config for Runtime {
767
	type FeeCalculator = ();
768
	type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
769
	type WeightPerGas = WeightPerGas;
770

            
771
	type CallOrigin = pallet_evm::EnsureAddressRoot<AccountId>;
772
	type WithdrawOrigin = pallet_evm::EnsureAddressNever<AccountId>;
773

            
774
	type AddressMapping = pallet_evm::IdentityAddressMapping;
775
	type Currency = Balances;
776
	type Runner = pallet_evm::runner::stack::Runner<Self>;
777

            
778
	type RuntimeEvent = RuntimeEvent;
779
	type PrecompilesType = ();
780
	type PrecompilesValue = ();
781
	type ChainId = ();
782
	type BlockGasLimit = BlockGasLimit;
783
	type OnChargeTransaction = ();
784
	type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping<Self>;
785
	type FindAuthor = ();
786
	type OnCreate = ();
787
	type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
788
	type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
789
	type Timestamp = Timestamp;
790
	type WeightInfo = pallet_evm::weights::SubstrateWeight<Runtime>;
791
	type AccountProvider = FrameSystemAccountProvider<Runtime>;
792
	type CreateOriginFilter = ();
793
	type CreateInnerOriginFilter = ();
794
}
795

            
796
#[allow(dead_code)]
797
pub struct NormalFilter;
798

            
799
impl frame_support::traits::Contains<RuntimeCall> for NormalFilter {
800
	fn contains(c: &RuntimeCall) -> bool {
801
		match c {
802
			_ => true,
803
		}
804
	}
805
}
806

            
807
// We need to use the encoding from the relay mock runtime
808
#[derive(Encode, Decode)]
809
pub enum RelayCall {
810
	#[codec(index = 5u8)]
811
	// the index should match the position of the module in `construct_runtime!`
812
	Utility(UtilityCall),
813
	#[codec(index = 6u8)]
814
	// the index should match the position of the module in `construct_runtime!`
815
	Hrmp(HrmpCall),
816
}
817

            
818
#[derive(Encode, Decode)]
819
pub enum UtilityCall {
820
	#[codec(index = 1u8)]
821
	AsDerivative(u16),
822
}
823

            
824
// HRMP call encoding, needed for xcm transactor pallet
825
#[derive(Encode, Decode)]
826
pub enum HrmpCall {
827
	#[codec(index = 0u8)]
828
	InitOpenChannel(ParaId, u32, u32),
829
	#[codec(index = 1u8)]
830
	AcceptOpenChannel(ParaId),
831
	#[codec(index = 2u8)]
832
	CloseChannel(HrmpChannelId),
833
	#[codec(index = 6u8)]
834
	CancelOpenRequest(HrmpChannelId, u32),
835
}
836

            
837
#[derive(
838
	Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo, DecodeWithMemTracking,
839
)]
840
pub enum MockTransactors {
841
	Relay,
842
}
843

            
844
impl xcm_primitives::XcmTransact for MockTransactors {
845
3
	fn destination(self) -> Location {
846
3
		match self {
847
3
			MockTransactors::Relay => Location::parent(),
848
3
		}
849
3
	}
850
}
851

            
852
impl xcm_primitives::UtilityEncodeCall for MockTransactors {
853
7
	fn encode_call(self, call: xcm_primitives::UtilityAvailableCalls) -> Vec<u8> {
854
7
		match self {
855
7
			MockTransactors::Relay => match call {
856
7
				xcm_primitives::UtilityAvailableCalls::AsDerivative(a, b) => {
857
7
					let mut call =
858
7
						RelayCall::Utility(UtilityCall::AsDerivative(a.clone())).encode();
859
7
					call.append(&mut b.clone());
860
7
					call
861
7
				}
862
7
			},
863
7
		}
864
7
	}
865
}
866

            
867
#[allow(dead_code)]
868
pub struct MockHrmpEncoder;
869

            
870
impl xcm_primitives::HrmpEncodeCall for MockHrmpEncoder {
871
	fn hrmp_encode_call(
872
		call: xcm_primitives::HrmpAvailableCalls,
873
	) -> Result<Vec<u8>, xcm::latest::Error> {
874
		match call {
875
			xcm_primitives::HrmpAvailableCalls::InitOpenChannel(a, b, c) => Ok(RelayCall::Hrmp(
876
				HrmpCall::InitOpenChannel(a.clone(), b.clone(), c.clone()),
877
			)
878
			.encode()),
879
			xcm_primitives::HrmpAvailableCalls::AcceptOpenChannel(a) => {
880
				Ok(RelayCall::Hrmp(HrmpCall::AcceptOpenChannel(a.clone())).encode())
881
			}
882
			xcm_primitives::HrmpAvailableCalls::CloseChannel(a) => {
883
				Ok(RelayCall::Hrmp(HrmpCall::CloseChannel(a.clone())).encode())
884
			}
885
			xcm_primitives::HrmpAvailableCalls::CancelOpenRequest(a, b) => {
886
				Ok(RelayCall::Hrmp(HrmpCall::CancelOpenRequest(a.clone(), b.clone())).encode())
887
			}
888
		}
889
	}
890
}
891

            
892
parameter_types! {
893
	pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes;
894
}
895

            
896
impl pallet_ethereum::Config for Runtime {
897
	type RuntimeEvent = RuntimeEvent;
898
	type StateRoot =
899
		pallet_ethereum::IntermediateStateRoot<<Runtime as frame_system::Config>::Version>;
900
	type PostLogContent = PostBlockAndTxnHashes;
901
	type ExtraDataLength = ConstU32<30>;
902
}
903
parameter_types! {
904
	pub ReservedXcmpWeight: Weight = Weight::from_parts(u64::max_value(), 0);
905
}
906

            
907
#[derive(
908
	Copy,
909
	Clone,
910
	Eq,
911
	PartialEq,
912
	Ord,
913
	PartialOrd,
914
	Encode,
915
	Decode,
916
	Debug,
917
	MaxEncodedLen,
918
	TypeInfo,
919
	DecodeWithMemTracking,
920
)]
921
pub enum ProxyType {
922
	NotAllowed = 0,
923
1
	Any = 1,
924
}
925

            
926
impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType {}
927

            
928
impl InstanceFilter<RuntimeCall> for ProxyType {
929
	fn filter(&self, _c: &RuntimeCall) -> bool {
930
		match self {
931
			ProxyType::NotAllowed => false,
932
			ProxyType::Any => true,
933
		}
934
	}
935
	fn is_superset(&self, _o: &Self) -> bool {
936
		false
937
	}
938
}
939

            
940
impl Default for ProxyType {
941
	fn default() -> Self {
942
		Self::NotAllowed
943
	}
944
}
945

            
946
parameter_types! {
947
	pub const ProxyCost: u64 = 1;
948
}
949

            
950
impl pallet_proxy::Config for Runtime {
951
	type RuntimeEvent = RuntimeEvent;
952
	type RuntimeCall = RuntimeCall;
953
	type Currency = Balances;
954
	type ProxyType = ProxyType;
955
	type ProxyDepositBase = ProxyCost;
956
	type ProxyDepositFactor = ProxyCost;
957
	type MaxProxies = ConstU32<32>;
958
	type WeightInfo = pallet_proxy::weights::SubstrateWeight<Runtime>;
959
	type MaxPending = ConstU32<32>;
960
	type CallHasher = BlakeTwo256;
961
	type AnnouncementDepositBase = ProxyCost;
962
	type AnnouncementDepositFactor = ProxyCost;
963
	type BlockNumberProvider = System;
964
}
965

            
966
pub struct EthereumXcmEnsureProxy;
967
impl xcm_primitives::EnsureProxy<AccountId> for EthereumXcmEnsureProxy {
968
2
	fn ensure_ok(delegator: AccountId, delegatee: AccountId) -> Result<(), &'static str> {
969
		// The EVM implicitely contains an Any proxy, so we only allow for "Any" proxies
970
1
		let def: pallet_proxy::ProxyDefinition<AccountId, ProxyType, BlockNumber> =
971
2
			pallet_proxy::Pallet::<Runtime>::find_proxy(
972
2
				&delegator,
973
2
				&delegatee,
974
2
				Some(ProxyType::Any),
975
2
			)
976
2
			.map_err(|_| "proxy error: expected `ProxyType::Any`")?;
977
		// We only allow to use it for delay zero proxies, as the call will iMmediatly be executed
978
1
		ensure!(def.delay.is_zero(), "proxy delay is Non-zero`");
979
1
		Ok(())
980
2
	}
981
}
982

            
983
impl pallet_ethereum_xcm::Config for Runtime {
984
	type RuntimeEvent = RuntimeEvent;
985
	type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper;
986
	type ValidatedTransaction = pallet_ethereum::ValidatedTransaction<Self>;
987
	type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction;
988
	type ReservedXcmpWeight = ReservedXcmpWeight;
989
	type EnsureProxy = EthereumXcmEnsureProxy;
990
	type ControllerOrigin = EnsureRoot<AccountId>;
991
	type ForceOrigin = EnsureRoot<AccountId>;
992
}
993

            
994
type Block = frame_system::mocking::MockBlockU32<Runtime>;
995

            
996
2270
construct_runtime!(
997
2270
	pub enum Runtime	{
998
2270
		System: frame_system,
999
2270
		Balances: pallet_balances,
2270
		MsgQueue: mock_msg_queue,
2270
		XcmVersioner: mock_version_changer,
2270

            
2270
		PolkadotXcm: pallet_xcm,
2270
		CumulusXcm: cumulus_pallet_xcm,
2270
		XcmTransactor: pallet_xcm_transactor,
2270
		XcmWeightTrader: pallet_xcm_weight_trader,
2270
		Treasury: pallet_treasury,
2270
		Proxy: pallet_proxy,
2270

            
2270
		Timestamp: pallet_timestamp,
2270
		EVM: pallet_evm,
2270
		Ethereum: pallet_ethereum,
2270
		EthereumXcm: pallet_ethereum_xcm,
2270
		EvmForeignAssets: pallet_moonbeam_foreign_assets,
2270
	}
2270
);
4
pub(crate) fn para_events() -> Vec<RuntimeEvent> {
4
	System::events()
4
		.into_iter()
56
		.map(|r| r.event)
56
		.filter_map(|e| Some(e))
4
		.collect::<Vec<_>>()
4
}
use frame_support::traits::{
	ConstBool, Disabled, OnFinalize, OnInitialize, UncheckedOnRuntimeUpgrade,
};
use moonbeam_runtime::{currency, xcm_config::LocationToH160};
use pallet_evm::FrameSystemAccountProvider;
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
}