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

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

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

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

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

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

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

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

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

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

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

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

            
184
parameter_types! {
185
	pub const UnitWeightCost: Weight = Weight::from_parts(1u64, 1u64);
186
	pub MaxInstructions: u32 = 100;
187
}
188

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

            
204
// These will be our transactors
205
// We use both transactors
206
pub type AssetTransactors = (LocalAssetTransactor, EvmForeignAssets);
207

            
208
pub type XcmRouter = super::ParachainXcmRouter<MsgQueue>;
209

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

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

            
234
pub struct WeightToFee;
235
impl sp_weights::WeightToFee for WeightToFee {
236
	type Balance = Balance;
237

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

            
246
parameter_types! {
247
	pub RelayNetwork: NetworkId = moonbase_runtime::xcm_config::RelayNetwork::get();
248
	pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
249
	pub UniversalLocation: InteriorLocation =
250
		[GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())].into();
251

            
252
	// New Self Reserve location, defines the multilocation identifying the self-reserve currency
253
	// This is used to match it also against our Balances pallet when we receive such
254
	// a Location: (Self Balances pallet index)
255
	pub SelfReserve: Location = Location {
256
		parents:0,
257
		interior: [
258
			PalletInstance(<Balances as PalletInfoAccess>::index() as u8)
259
		].into()
260
	};
261
	pub const MaxAssetsIntoHolding: u32 = 64;
262

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

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

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

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

            
290
pub struct XcmConfig;
291
impl Config for XcmConfig {
292
	type RuntimeCall = RuntimeCall;
293
	type XcmSender = XcmRouter;
294
	type AssetTransactor = AssetTransactors;
295
	type OriginConverter = XcmOriginToTransactDispatchOrigin;
296
	type IsReserve = Reserves;
297
	type IsTeleporter = ();
298
	type UniversalLocation = UniversalLocation;
299
	type Barrier = XcmBarrier;
300
	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
301
	type Trader = pallet_xcm_weight_trader::Trader<Runtime>;
302

            
303
	type ResponseHandler = PolkadotXcm;
304
	type SubscriptionService = PolkadotXcm;
305
	type AssetTrap = PolkadotXcm;
306
	type AssetClaims = PolkadotXcm;
307
	type CallDispatcher = MoonbeamCall;
308
	type AssetLocker = ();
309
	type AssetExchanger = ();
310
	type PalletInstancesInfo = ();
311
	type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
312
	type FeeManager = ();
313
	type MessageExporter = ();
314
	type UniversalAliases = Nothing;
315
	type SafeCallFilter = Everything;
316
	type Aliasers = Nothing;
317
	type TransactionalProcessor = ();
318
	type HrmpNewChannelOpenRequestHandler = ();
319
	type HrmpChannelAcceptedHandler = ();
320
	type HrmpChannelClosingHandler = ();
321
	type XcmRecorder = PolkadotXcm;
322
	type XcmEventEmitter = ();
323
}
324

            
325
impl cumulus_pallet_xcm::Config for Runtime {
326
	type RuntimeEvent = RuntimeEvent;
327
	type XcmExecutor = XcmExecutor<XcmConfig>;
328
}
329

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

            
339
// How to convert from CurrencyId to Location
340
pub struct CurrencyIdToLocation<AssetXConverter>(sp_std::marker::PhantomData<AssetXConverter>);
341
impl<AssetXConverter> sp_runtime::traits::Convert<CurrencyId, Option<Location>>
342
	for CurrencyIdToLocation<AssetXConverter>
343
where
344
	AssetXConverter: MaybeEquivalence<Location, AssetId>,
345
{
346
25
	fn convert(currency: CurrencyId) -> Option<Location> {
347
25
		match currency {
348
			CurrencyId::SelfReserve => {
349
				// For now and until Xtokens is adapted to handle 0.9.16 version we use
350
				// the old anchoring here
351
				// This is not a problem in either cases, since the view of the destination
352
				// chain does not change
353
				// TODO! change this to NewAnchoringSelfReserve once xtokens is adapted for it
354
8
				let multi: Location = SelfReserve::get();
355
8
				Some(multi)
356
			}
357
17
			CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset),
358
		}
359
25
	}
360
}
361

            
362
parameter_types! {
363
	pub const BaseXcmWeight: Weight = Weight::from_parts(100u64, 100u64);
364
	pub const MaxAssetsForTransfer: usize = 2;
365
	pub SelfLocation: Location = Location::here();
366
	pub SelfLocationAbsolute: Location = Location {
367
		parents:1,
368
		interior: [
369
			Parachain(MsgQueue::parachain_id().into())
370
		].into()
371
	};
372
}
373

            
374
parameter_types! {
375
	pub const ProposalBond: Permill = Permill::from_percent(5);
376
	pub const ProposalBondMinimum: Balance = 0;
377
	pub const SpendPeriod: u32 = 0;
378
	pub const TreasuryId: PalletId = PalletId(*b"pc/trsry");
379
	pub const MaxApprovals: u32 = 100;
380
	pub TreasuryAccount: AccountId = Treasury::account_id();
381
}
382

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

            
406
#[frame_support::pallet]
407
pub mod mock_msg_queue {
408
	use super::*;
409
	use frame_support::pallet_prelude::*;
410

            
411
	#[pallet::config]
412
	pub trait Config: frame_system::Config {
413
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
414
		type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
415
	}
416

            
417
	#[pallet::call]
418
	impl<T: Config> Pallet<T> {}
419

            
420
3
	#[pallet::pallet]
421
	pub struct Pallet<T>(_);
422

            
423
1155
	#[pallet::storage]
424
	#[pallet::getter(fn parachain_id)]
425
	pub(super) type ParachainId<T: Config> = StorageValue<_, ParaId, ValueQuery>;
426

            
427
	impl<T: Config> Get<ParaId> for Pallet<T> {
428
49
		fn get() -> ParaId {
429
49
			Self::parachain_id()
430
49
		}
431
	}
432

            
433
	pub type MessageId = [u8; 32];
434

            
435
	#[pallet::event]
436
52
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
437
	pub enum Event<T: Config> {
438
		// XCMP
439
		/// Some XCM was executed OK.
440
		Success(Option<T::Hash>),
441
		/// Some XCM failed.
442
		Fail(Option<T::Hash>, XcmError),
443
		/// Bad XCM version used.
444
		BadVersion(Option<T::Hash>),
445
		/// Bad XCM format used.
446
		BadFormat(Option<T::Hash>),
447

            
448
		// DMP
449
		/// Downward message is invalid XCM.
450
		InvalidFormat(MessageId),
451
		/// Downward message is unsupported version of XCM.
452
		UnsupportedVersion(MessageId),
453
		/// Downward message executed with the given outcome.
454
		ExecutedDownward(MessageId, Outcome),
455
	}
456

            
457
	impl<T: Config> Pallet<T> {
458
246
		pub fn set_para_id(para_id: ParaId) {
459
246
			ParachainId::<T>::put(para_id);
460
246
		}
461

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

            
502
	impl<T: Config> XcmpMessageHandler for Pallet<T> {
503
33
		fn handle_xcmp_messages<'a, I: Iterator<Item = (ParaId, RelayBlockNumber, &'a [u8])>>(
504
33
			iter: I,
505
33
			max_weight: Weight,
506
33
		) -> Weight {
507
66
			for (sender, sent_at, data) in iter {
508
33
				let mut data_ref = data;
509
33
				let _ = XcmpMessageFormat::decode(&mut data_ref)
510
33
					.expect("Simulator encodes with versioned xcm format; qed");
511
33

            
512
33
				let mut remaining_fragments = &data_ref[..];
513
66
				while !remaining_fragments.is_empty() {
514
33
					if let Ok(xcm) =
515
33
						VersionedXcm::<T::RuntimeCall>::decode(&mut remaining_fragments)
516
33
					{
517
33
						let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight);
518
33
					} else {
519
						debug_assert!(false, "Invalid incoming XCMP message data");
520
					}
521
				}
522
			}
523
33
			max_weight
524
33
		}
525
	}
526

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

            
552
19
						Self::deposit_event(Event::ExecutedDownward(id, outcome));
553
19
					}
554
				}
555
			}
556
19
			limit
557
19
		}
558
	}
559
}
560

            
561
// Pallet to provide the version, used to test runtime upgrade version changes
562
#[frame_support::pallet]
563
pub mod mock_version_changer {
564
	use super::*;
565
	use frame_support::pallet_prelude::*;
566

            
567
	#[pallet::config]
568
	pub trait Config: frame_system::Config {
569
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
570
	}
571

            
572
	#[pallet::call]
573
	impl<T: Config> Pallet<T> {}
574

            
575
3
	#[pallet::pallet]
576
	pub struct Pallet<T>(_);
577

            
578
22
	#[pallet::storage]
579
	#[pallet::getter(fn current_version)]
580
	pub(super) type CurrentVersion<T: Config> = StorageValue<_, XcmVersion, ValueQuery>;
581

            
582
	impl<T: Config> Get<XcmVersion> for Pallet<T> {
583
4
		fn get() -> XcmVersion {
584
4
			Self::current_version()
585
4
		}
586
	}
587

            
588
	#[pallet::event]
589
5
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
590
	pub enum Event<T: Config> {
591
		// XCMP
592
		/// Some XCM was executed OK.
593
		VersionChanged(XcmVersion),
594
	}
595

            
596
	impl<T: Config> Pallet<T> {
597
5
		pub fn set_version(version: XcmVersion) {
598
5
			CurrentVersion::<T>::put(version);
599
5
			Self::deposit_event(Event::VersionChanged(version));
600
5
		}
601
	}
602
}
603

            
604
impl mock_msg_queue::Config for Runtime {
605
	type RuntimeEvent = RuntimeEvent;
606
	type XcmExecutor = XcmExecutor<XcmConfig>;
607
}
608

            
609
impl mock_version_changer::Config for Runtime {
610
	type RuntimeEvent = RuntimeEvent;
611
}
612

            
613
pub type LocalOriginToLocation =
614
	xcm_primitives::SignedToAccountId20<RuntimeOrigin, AccountId, RelayNetwork>;
615

            
616
parameter_types! {
617
	pub MatcherLocation: Location = Location::here();
618
}
619

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

            
650
#[derive(
651
	Clone,
652
	Default,
653
	Eq,
654
	Debug,
655
	PartialEq,
656
	Ord,
657
	PartialOrd,
658
	Encode,
659
	Decode,
660
	TypeInfo,
661
	DecodeWithMemTracking,
662
)]
663
pub struct AssetMetadata {
664
	pub name: Vec<u8>,
665
	pub symbol: Vec<u8>,
666
	pub decimals: u8,
667
}
668

            
669
pub struct AccountIdToH160;
670
impl sp_runtime::traits::Convert<AccountId, H160> for AccountIdToH160 {
671
250
	fn convert(account_id: AccountId) -> H160 {
672
250
		account_id.into()
673
250
	}
674
}
675

            
676
pub type ForeignAssetManagerOrigin = EitherOf<
677
	MapSuccessToXcm<EnsureXcm<AllowSiblingParachains>>,
678
	MapSuccessToGovernance<EnsureRoot<AccountId>>,
679
>;
680

            
681
moonbeam_runtime_common::impl_evm_runner_precompile_or_eth_xcm!();
682

            
683
parameter_types! {
684
	pub ForeignAssetCreationDeposit: u128 = 100 * currency::UNIT;
685
}
686

            
687
impl pallet_moonbeam_foreign_assets::Config for Runtime {
688
	type AccountIdToH160 = AccountIdToH160;
689
	type AssetIdFilter = Everything;
690
	type EvmRunner = EvmRunnerPrecompileOrEthXcm<MoonbeamCall, Self>;
691
	type ConvertLocation =
692
		SiblingParachainConvertsVia<polkadot_parachain::primitives::Sibling, AccountId>;
693
	type ForeignAssetCreatorOrigin = ForeignAssetManagerOrigin;
694
	type ForeignAssetFreezerOrigin = ForeignAssetManagerOrigin;
695
	type ForeignAssetModifierOrigin = ForeignAssetManagerOrigin;
696
	type ForeignAssetUnfreezerOrigin = ForeignAssetManagerOrigin;
697
	type OnForeignAssetCreated = ();
698
	type MaxForeignAssets = ConstU32<256>;
699
	type RuntimeEvent = RuntimeEvent;
700
	type WeightInfo = ();
701
	type XcmLocationToH160 = LocationToH160;
702
	type ForeignAssetCreationDeposit = ForeignAssetCreationDeposit;
703
	type Balance = Balance;
704
	type Currency = Balances;
705
}
706

            
707
// 1 ROC/WND should be enough
708
parameter_types! {
709
	pub MaxHrmpRelayFee: Asset = (Location::parent(), 1_000_000_000_000u128).into();
710
}
711

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

            
734
parameter_types! {
735
	pub RelayLocation: Location = Location::parent();
736
}
737

            
738
impl pallet_xcm_weight_trader::Config for Runtime {
739
	type AccountIdToLocation = xcm_primitives::AccountIdToLocation<AccountId>;
740
	type AddSupportedAssetOrigin = EnsureRoot<AccountId>;
741
	type AssetLocationFilter = Everything;
742
	type AssetTransactor = AssetTransactors;
743
	type Balance = Balance;
744
	type EditSupportedAssetOrigin = EnsureRoot<AccountId>;
745
	type NativeLocation = SelfReserve;
746
	type PauseSupportedAssetOrigin = EnsureRoot<AccountId>;
747
	type RemoveSupportedAssetOrigin = EnsureRoot<AccountId>;
748
	type RuntimeEvent = RuntimeEvent;
749
	type ResumeSupportedAssetOrigin = EnsureRoot<AccountId>;
750
	type WeightInfo = ();
751
	type WeightToFee = WeightToFee;
752
	type XcmFeesAccount = XcmFeesAccount;
753
	#[cfg(feature = "runtime-benchmarks")]
754
	type NotFilteredLocation = RelayLocation;
755
}
756

            
757
parameter_types! {
758
	pub const MinimumPeriod: u64 = 1000;
759
}
760
impl pallet_timestamp::Config for Runtime {
761
	type Moment = u64;
762
	type OnTimestampSet = ();
763
	type MinimumPeriod = MinimumPeriod;
764
	type WeightInfo = ();
765
}
766

            
767
parameter_types! {
768
	pub BlockGasLimit: U256 = moonbase_runtime::BlockGasLimit::get();
769
	pub WeightPerGas: Weight = moonbase_runtime::WeightPerGas::get();
770
	pub const GasLimitPovSizeRatio: u64 = moonbase_runtime::GasLimitPovSizeRatio::get();
771
	pub GasLimitStorageGrowthRatio: u64 = moonbase_runtime::GasLimitStorageGrowthRatio::get();
772
}
773

            
774
impl pallet_evm::Config for Runtime {
775
	type FeeCalculator = ();
776
	type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
777
	type WeightPerGas = WeightPerGas;
778

            
779
	type CallOrigin = pallet_evm::EnsureAddressRoot<AccountId>;
780
	type WithdrawOrigin = pallet_evm::EnsureAddressNever<AccountId>;
781

            
782
	type AddressMapping = pallet_evm::IdentityAddressMapping;
783
	type Currency = Balances;
784
	type Runner = pallet_evm::runner::stack::Runner<Self>;
785

            
786
	type RuntimeEvent = RuntimeEvent;
787
	type PrecompilesType = ();
788
	type PrecompilesValue = ();
789
	type ChainId = ();
790
	type BlockGasLimit = BlockGasLimit;
791
	type OnChargeTransaction = ();
792
	type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping<Self>;
793
	type FindAuthor = ();
794
	type OnCreate = ();
795
	type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
796
	type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
797
	type Timestamp = Timestamp;
798
	type WeightInfo = pallet_evm::weights::SubstrateWeight<Runtime>;
799
	type AccountProvider = FrameSystemAccountProvider<Runtime>;
800
	type CreateOriginFilter = ();
801
	type CreateInnerOriginFilter = ();
802
}
803

            
804
#[allow(dead_code)]
805
pub struct NormalFilter;
806

            
807
impl frame_support::traits::Contains<RuntimeCall> for NormalFilter {
808
	fn contains(c: &RuntimeCall) -> bool {
809
		match c {
810
			_ => true,
811
		}
812
	}
813
}
814

            
815
// We need to use the encoding from the relay mock runtime
816
#[derive(Encode, Decode)]
817
pub enum RelayCall {
818
	#[codec(index = 5u8)]
819
	// the index should match the position of the module in `construct_runtime!`
820
	Utility(UtilityCall),
821
	#[codec(index = 6u8)]
822
	// the index should match the position of the module in `construct_runtime!`
823
	Hrmp(HrmpCall),
824
}
825

            
826
#[derive(Encode, Decode)]
827
pub enum UtilityCall {
828
	#[codec(index = 1u8)]
829
	AsDerivative(u16),
830
}
831

            
832
// HRMP call encoding, needed for xcm transactor pallet
833
#[derive(Encode, Decode)]
834
pub enum HrmpCall {
835
	#[codec(index = 0u8)]
836
	InitOpenChannel(ParaId, u32, u32),
837
	#[codec(index = 1u8)]
838
	AcceptOpenChannel(ParaId),
839
	#[codec(index = 2u8)]
840
	CloseChannel(HrmpChannelId),
841
	#[codec(index = 6u8)]
842
	CancelOpenRequest(HrmpChannelId, u32),
843
}
844

            
845
#[derive(
846
	Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo, DecodeWithMemTracking,
847
)]
848
pub enum MockTransactors {
849
	Relay,
850
}
851

            
852
impl xcm_primitives::XcmTransact for MockTransactors {
853
3
	fn destination(self) -> Location {
854
3
		match self {
855
3
			MockTransactors::Relay => Location::parent(),
856
3
		}
857
3
	}
858
}
859

            
860
impl xcm_primitives::UtilityEncodeCall for MockTransactors {
861
7
	fn encode_call(self, call: xcm_primitives::UtilityAvailableCalls) -> Vec<u8> {
862
7
		match self {
863
7
			MockTransactors::Relay => match call {
864
7
				xcm_primitives::UtilityAvailableCalls::AsDerivative(a, b) => {
865
7
					let mut call =
866
7
						RelayCall::Utility(UtilityCall::AsDerivative(a.clone())).encode();
867
7
					call.append(&mut b.clone());
868
7
					call
869
7
				}
870
7
			},
871
7
		}
872
7
	}
873
}
874

            
875
#[allow(dead_code)]
876
pub struct MockHrmpEncoder;
877

            
878
impl xcm_primitives::HrmpEncodeCall for MockHrmpEncoder {
879
	fn hrmp_encode_call(
880
		call: xcm_primitives::HrmpAvailableCalls,
881
	) -> Result<Vec<u8>, xcm::latest::Error> {
882
		match call {
883
			xcm_primitives::HrmpAvailableCalls::InitOpenChannel(a, b, c) => Ok(RelayCall::Hrmp(
884
				HrmpCall::InitOpenChannel(a.clone(), b.clone(), c.clone()),
885
			)
886
			.encode()),
887
			xcm_primitives::HrmpAvailableCalls::AcceptOpenChannel(a) => {
888
				Ok(RelayCall::Hrmp(HrmpCall::AcceptOpenChannel(a.clone())).encode())
889
			}
890
			xcm_primitives::HrmpAvailableCalls::CloseChannel(a) => {
891
				Ok(RelayCall::Hrmp(HrmpCall::CloseChannel(a.clone())).encode())
892
			}
893
			xcm_primitives::HrmpAvailableCalls::CancelOpenRequest(a, b) => {
894
				Ok(RelayCall::Hrmp(HrmpCall::CancelOpenRequest(a.clone(), b.clone())).encode())
895
			}
896
		}
897
	}
898
}
899

            
900
parameter_types! {
901
	pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes;
902
}
903

            
904
impl pallet_ethereum::Config for Runtime {
905
	type RuntimeEvent = RuntimeEvent;
906
	type StateRoot =
907
		pallet_ethereum::IntermediateStateRoot<<Runtime as frame_system::Config>::Version>;
908
	type PostLogContent = PostBlockAndTxnHashes;
909
	type ExtraDataLength = ConstU32<30>;
910
}
911
parameter_types! {
912
	pub ReservedXcmpWeight: Weight = Weight::from_parts(u64::max_value(), 0);
913
}
914

            
915
#[derive(
916
	Copy,
917
	Clone,
918
	Eq,
919
	PartialEq,
920
	Ord,
921
	PartialOrd,
922
	Encode,
923
	Decode,
924
	Debug,
925
	MaxEncodedLen,
926
	TypeInfo,
927
	DecodeWithMemTracking,
928
)]
929
pub enum ProxyType {
930
	NotAllowed = 0,
931
1
	Any = 1,
932
}
933

            
934
impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType {}
935

            
936
impl InstanceFilter<RuntimeCall> for ProxyType {
937
	fn filter(&self, _c: &RuntimeCall) -> bool {
938
		match self {
939
			ProxyType::NotAllowed => false,
940
			ProxyType::Any => true,
941
		}
942
	}
943
	fn is_superset(&self, _o: &Self) -> bool {
944
		false
945
	}
946
}
947

            
948
impl Default for ProxyType {
949
	fn default() -> Self {
950
		Self::NotAllowed
951
	}
952
}
953

            
954
parameter_types! {
955
	pub const ProxyCost: u64 = 1;
956
}
957

            
958
impl pallet_proxy::Config for Runtime {
959
	type RuntimeEvent = RuntimeEvent;
960
	type RuntimeCall = RuntimeCall;
961
	type Currency = Balances;
962
	type ProxyType = ProxyType;
963
	type ProxyDepositBase = ProxyCost;
964
	type ProxyDepositFactor = ProxyCost;
965
	type MaxProxies = ConstU32<32>;
966
	type WeightInfo = pallet_proxy::weights::SubstrateWeight<Runtime>;
967
	type MaxPending = ConstU32<32>;
968
	type CallHasher = BlakeTwo256;
969
	type AnnouncementDepositBase = ProxyCost;
970
	type AnnouncementDepositFactor = ProxyCost;
971
	type BlockNumberProvider = ();
972
}
973

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

            
991
impl pallet_ethereum_xcm::Config for Runtime {
992
	type RuntimeEvent = RuntimeEvent;
993
	type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper;
994
	type ValidatedTransaction = pallet_ethereum::ValidatedTransaction<Self>;
995
	type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction;
996
	type ReservedXcmpWeight = ReservedXcmpWeight;
997
	type EnsureProxy = EthereumXcmEnsureProxy;
998
	type ControllerOrigin = EnsureRoot<AccountId>;
999
	type ForceOrigin = EnsureRoot<AccountId>;
}
type Block = frame_system::mocking::MockBlockU32<Runtime>;
2412
construct_runtime!(
2412
	pub enum Runtime	{
2412
		System: frame_system,
2412
		Balances: pallet_balances,
2412
		MsgQueue: mock_msg_queue,
2412
		XcmVersioner: mock_version_changer,
2412

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

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