1
// Copyright 2021 Parity Technologies (UK) Ltd.
2
// This file is part of Polkadot.
3

            
4
// Polkadot is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Polkadot is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
//! Parachain runtime mock.
18

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

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

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

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

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

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

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

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

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

            
134
pub type ForeignAssetInstance = ();
135

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

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

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

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

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

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

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

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

            
264
// These will be our transactors
265
// We use both transactors
266
pub type AssetTransactors = (LocalAssetTransactor, ForeignFungiblesTransactor);
267

            
268
pub type XcmRouter = super::ParachainXcmRouter<MsgQueue>;
269

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

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

            
294
pub struct WeightToFee;
295
impl sp_weights::WeightToFee for WeightToFee {
296
	type Balance = Balance;
297

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

            
306
parameter_types! {
307
	pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
308
	pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
309
	pub UniversalLocation: InteriorLocation =
310
		[GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())].into();
311

            
312
	// New Self Reserve location, defines the multilocation identifiying the self-reserve currency
313
	// This is used to match it also against our Balances pallet when we receive such
314
	// a Location: (Self Balances pallet index)
315
	pub SelfReserve: Location = Location {
316
		parents:0,
317
		interior: [
318
			PalletInstance(<Balances as PalletInfoAccess>::index() as u8)
319
		].into()
320
	};
321
	pub const MaxAssetsIntoHolding: u32 = 64;
322

            
323
	pub AssetHubLocation: Location = Location::new(1, [Parachain(1000)]);
324
	pub RelayLocationFilter: AssetFilter = Wild(AllOf {
325
		fun: WildFungible,
326
		id: xcm::prelude::AssetId(Location::parent()),
327
	});
328

            
329
	pub RelayChainNativeAssetFromAssetHub: (AssetFilter, Location) = (
330
		RelayLocationFilter::get(),
331
		AssetHubLocation::get()
332
	);
333
}
334

            
335
use frame_system::RawOrigin;
336
use sp_runtime::traits::PostDispatchInfoOf;
337
use sp_runtime::DispatchErrorWithPostInfo;
338
use xcm_executor::traits::CallDispatcher;
339
moonbeam_runtime_common::impl_moonbeam_xcm_call!();
340

            
341
type Reserves = (
342
	// Relaychain (DOT) from Asset Hub
343
	Case<RelayChainNativeAssetFromAssetHub>,
344
	// Assets which the reserve is the same as the origin.
345
	xcm_primitives::MultiNativeAsset<
346
		xcm_primitives::AbsoluteAndRelativeReserve<SelfLocationAbsolute>,
347
	>,
348
);
349

            
350
pub struct XcmConfig;
351
impl Config for XcmConfig {
352
	type RuntimeCall = RuntimeCall;
353
	type XcmSender = XcmRouter;
354
	type AssetTransactor = AssetTransactors;
355
	type OriginConverter = XcmOriginToTransactDispatchOrigin;
356
	type IsReserve = Reserves;
357
	type IsTeleporter = ();
358
	type UniversalLocation = UniversalLocation;
359
	type Barrier = XcmBarrier;
360
	type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
361
	type Trader = pallet_xcm_weight_trader::Trader<Runtime>;
362

            
363
	type ResponseHandler = PolkadotXcm;
364
	type SubscriptionService = PolkadotXcm;
365
	type AssetTrap = PolkadotXcm;
366
	type AssetClaims = PolkadotXcm;
367
	type CallDispatcher = MoonbeamCall;
368
	type AssetLocker = ();
369
	type AssetExchanger = ();
370
	type PalletInstancesInfo = ();
371
	type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
372
	type FeeManager = ();
373
	type MessageExporter = ();
374
	type UniversalAliases = Nothing;
375
	type SafeCallFilter = Everything;
376
	type Aliasers = Nothing;
377
	type TransactionalProcessor = ();
378
	type HrmpNewChannelOpenRequestHandler = ();
379
	type HrmpChannelAcceptedHandler = ();
380
	type HrmpChannelClosingHandler = ();
381
	type XcmRecorder = PolkadotXcm;
382
}
383

            
384
impl cumulus_pallet_xcm::Config for Runtime {
385
	type RuntimeEvent = RuntimeEvent;
386
	type XcmExecutor = XcmExecutor<XcmConfig>;
387
}
388

            
389
// Our currencyId. We distinguish for now between SelfReserve, and Others, defined by their Id.
390
#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
391
pub enum CurrencyId {
392
	SelfReserve,
393
	ForeignAsset(AssetId),
394
}
395

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

            
419
parameter_types! {
420
	pub const BaseXcmWeight: Weight = Weight::from_parts(100u64, 100u64);
421
	pub const MaxAssetsForTransfer: usize = 2;
422
	pub SelfLocation: Location = Location::here();
423
	pub SelfLocationAbsolute: Location = Location {
424
		parents:1,
425
		interior: [
426
			Parachain(MsgQueue::parachain_id().into())
427
		].into()
428
	};
429
}
430

            
431
parameter_types! {
432
	pub const ProposalBond: Permill = Permill::from_percent(5);
433
	pub const ProposalBondMinimum: Balance = 0;
434
	pub const SpendPeriod: u32 = 0;
435
	pub const TreasuryId: PalletId = PalletId(*b"pc/trsry");
436
	pub const MaxApprovals: u32 = 100;
437
	pub TreasuryAccount: AccountId = Treasury::account_id();
438
}
439

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

            
463
#[frame_support::pallet]
464
pub mod mock_msg_queue {
465
	use super::*;
466
	use frame_support::pallet_prelude::*;
467

            
468
	#[pallet::config]
469
	pub trait Config: frame_system::Config {
470
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
471
		type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
472
	}
473

            
474
	#[pallet::call]
475
	impl<T: Config> Pallet<T> {}
476

            
477
1
	#[pallet::pallet]
478
	pub struct Pallet<T>(_);
479

            
480
1158
	#[pallet::storage]
481
	#[pallet::getter(fn parachain_id)]
482
	pub(super) type ParachainId<T: Config> = StorageValue<_, ParaId, ValueQuery>;
483

            
484
	impl<T: Config> Get<ParaId> for Pallet<T> {
485
49
		fn get() -> ParaId {
486
49
			Self::parachain_id()
487
49
		}
488
	}
489

            
490
	pub type MessageId = [u8; 32];
491

            
492
	#[pallet::event]
493
53
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
494
	pub enum Event<T: Config> {
495
		// XCMP
496
5
		/// Some XCM was executed OK.
497
		Success(Option<T::Hash>),
498
		/// Some XCM failed.
499
		Fail(Option<T::Hash>, XcmError),
500
		/// Bad XCM version used.
501
		BadVersion(Option<T::Hash>),
502
		/// Bad XCM format used.
503
		BadFormat(Option<T::Hash>),
504

            
505
		// DMP
506
		/// Downward message is invalid XCM.
507
		InvalidFormat(MessageId),
508
		/// Downward message is unsupported version of XCM.
509
		UnsupportedVersion(MessageId),
510
5
		/// Downward message executed with the given outcome.
511
		ExecutedDownward(MessageId, Outcome),
512
	}
513

            
514
	impl<T: Config> Pallet<T> {
515
246
		pub fn set_para_id(para_id: ParaId) {
516
246
			ParachainId::<T>::put(para_id);
517
246
		}
518

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

            
559
	impl<T: Config> XcmpMessageHandler for Pallet<T> {
560
33
		fn handle_xcmp_messages<'a, I: Iterator<Item = (ParaId, RelayBlockNumber, &'a [u8])>>(
561
33
			iter: I,
562
33
			max_weight: Weight,
563
33
		) -> Weight {
564
66
			for (sender, sent_at, data) in iter {
565
33
				let mut data_ref = data;
566
33
				let _ = XcmpMessageFormat::decode(&mut data_ref)
567
33
					.expect("Simulator encodes with versioned xcm format; qed");
568
33

            
569
33
				let mut remaining_fragments = &data_ref[..];
570
66
				while !remaining_fragments.is_empty() {
571
33
					if let Ok(xcm) =
572
33
						VersionedXcm::<T::RuntimeCall>::decode(&mut remaining_fragments)
573
33
					{
574
33
						let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight);
575
33
					} else {
576
						debug_assert!(false, "Invalid incoming XCMP message data");
577
					}
578
				}
579
			}
580
33
			max_weight
581
33
		}
582
	}
583

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

            
609
20
						Self::deposit_event(Event::ExecutedDownward(id, outcome));
610
20
					}
611
				}
612
			}
613
20
			limit
614
20
		}
615
	}
616
}
617

            
618
// Pallet to provide the version, used to test runtime upgrade version changes
619
#[frame_support::pallet]
620
pub mod mock_version_changer {
621
	use super::*;
622
	use frame_support::pallet_prelude::*;
623

            
624
	#[pallet::config]
625
	pub trait Config: frame_system::Config {
626
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
627
	}
628

            
629
	#[pallet::call]
630
	impl<T: Config> Pallet<T> {}
631

            
632
1
	#[pallet::pallet]
633
	pub struct Pallet<T>(_);
634

            
635
22
	#[pallet::storage]
636
	#[pallet::getter(fn current_version)]
637
	pub(super) type CurrentVersion<T: Config> = StorageValue<_, XcmVersion, ValueQuery>;
638

            
639
	impl<T: Config> Get<XcmVersion> for Pallet<T> {
640
4
		fn get() -> XcmVersion {
641
4
			Self::current_version()
642
4
		}
643
	}
644

            
645
	#[pallet::event]
646
5
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
647
	pub enum Event<T: Config> {
648
		// XCMP
649
6
		/// Some XCM was executed OK.
650
		VersionChanged(XcmVersion),
651
	}
652

            
653
	impl<T: Config> Pallet<T> {
654
5
		pub fn set_version(version: XcmVersion) {
655
5
			CurrentVersion::<T>::put(version);
656
5
			Self::deposit_event(Event::VersionChanged(version));
657
5
		}
658
	}
659
}
660

            
661
impl mock_msg_queue::Config for Runtime {
662
	type RuntimeEvent = RuntimeEvent;
663
	type XcmExecutor = XcmExecutor<XcmConfig>;
664
}
665

            
666
impl mock_version_changer::Config for Runtime {
667
	type RuntimeEvent = RuntimeEvent;
668
}
669

            
670
pub type LocalOriginToLocation =
671
	xcm_primitives::SignedToAccountId20<RuntimeOrigin, AccountId, RelayNetwork>;
672

            
673
parameter_types! {
674
	pub MatcherLocation: Location = Location::here();
675
}
676

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

            
705
// We instruct how to register the Assets
706
// In this case, we tell it to Create an Asset in pallet-assets
707
pub struct AssetRegistrar;
708
use frame_support::pallet_prelude::DispatchResult;
709
impl pallet_asset_manager::AssetRegistrar<Runtime> for AssetRegistrar {
710
35
	fn create_foreign_asset(
711
35
		asset: AssetId,
712
35
		min_balance: Balance,
713
35
		metadata: AssetMetadata,
714
35
		is_sufficient: bool,
715
35
	) -> DispatchResult {
716
35
		Assets::force_create(
717
35
			RuntimeOrigin::root(),
718
35
			asset,
719
35
			AssetManager::account_id(),
720
35
			is_sufficient,
721
35
			min_balance,
722
35
		)?;
723

            
724
35
		Assets::force_set_metadata(
725
35
			RuntimeOrigin::root(),
726
35
			asset,
727
35
			metadata.name,
728
35
			metadata.symbol,
729
35
			metadata.decimals,
730
35
			false,
731
35
		)
732
35
	}
733

            
734
	fn destroy_foreign_asset(asset: AssetId) -> DispatchResult {
735
		// Mark the asset as destroying
736
		Assets::start_destroy(RuntimeOrigin::root(), asset.into())?;
737

            
738
		Ok(())
739
	}
740

            
741
	fn destroy_asset_dispatch_info_weight(asset: AssetId) -> Weight {
742
		RuntimeCall::Assets(
743
			pallet_assets::Call::<Runtime, ForeignAssetInstance>::start_destroy {
744
				id: asset.into(),
745
			},
746
		)
747
		.get_dispatch_info()
748
		.total_weight()
749
	}
750
}
751

            
752
#[derive(Clone, Default, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
753
pub struct AssetMetadata {
754
	pub name: Vec<u8>,
755
	pub symbol: Vec<u8>,
756
	pub decimals: u8,
757
}
758

            
759
impl pallet_asset_manager::Config for Runtime {
760
	type RuntimeEvent = RuntimeEvent;
761
	type Balance = Balance;
762
	type AssetId = AssetId;
763
	type AssetRegistrarMetadata = AssetMetadata;
764
	type ForeignAssetType = AssetType;
765
	type AssetRegistrar = AssetRegistrar;
766
	type ForeignAssetModifierOrigin = EnsureRoot<AccountId>;
767
	type WeightInfo = ();
768
}
769

            
770
// 1 ROC/WND should be enough
771
parameter_types! {
772
	pub MaxHrmpRelayFee: Asset = (Location::parent(), 1_000_000_000_000u128).into();
773
}
774

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

            
800
parameter_types! {
801
	pub RelayLocation: Location = Location::parent();
802
}
803

            
804
impl pallet_xcm_weight_trader::Config for Runtime {
805
	type AccountIdToLocation = xcm_primitives::AccountIdToLocation<AccountId>;
806
	type AddSupportedAssetOrigin = EnsureRoot<AccountId>;
807
	type AssetLocationFilter = Everything;
808
	type AssetTransactor = AssetTransactors;
809
	type Balance = Balance;
810
	type EditSupportedAssetOrigin = EnsureRoot<AccountId>;
811
	type NativeLocation = SelfReserve;
812
	type PauseSupportedAssetOrigin = EnsureRoot<AccountId>;
813
	type RemoveSupportedAssetOrigin = EnsureRoot<AccountId>;
814
	type RuntimeEvent = RuntimeEvent;
815
	type ResumeSupportedAssetOrigin = EnsureRoot<AccountId>;
816
	type WeightInfo = ();
817
	type WeightToFee = WeightToFee;
818
	type XcmFeesAccount = XcmFeesAccount;
819
	#[cfg(feature = "runtime-benchmarks")]
820
	type NotFilteredLocation = RelayLocation;
821
}
822

            
823
parameter_types! {
824
	pub const MinimumPeriod: u64 = 1000;
825
}
826
impl pallet_timestamp::Config for Runtime {
827
	type Moment = u64;
828
	type OnTimestampSet = ();
829
	type MinimumPeriod = MinimumPeriod;
830
	type WeightInfo = ();
831
}
832

            
833
use sp_core::U256;
834

            
835
parameter_types! {
836
	pub BlockGasLimit: U256 = U256::from(u64::MAX);
837
	pub WeightPerGas: Weight = Weight::from_parts(1, 0);
838
	pub GasLimitPovSizeRatio: u64 = {
839
		let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
840
		block_gas_limit.saturating_div(MAX_POV_SIZE as u64)
841
	};
842
	pub GasLimitStorageGrowthRatio: u64 =
843
		BlockGasLimit::get().min(u64::MAX.into()).low_u64().saturating_div(BLOCK_STORAGE_LIMIT);
844
}
845

            
846
impl pallet_evm::Config for Runtime {
847
	type FeeCalculator = ();
848
	type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
849
	type WeightPerGas = WeightPerGas;
850

            
851
	type CallOrigin = pallet_evm::EnsureAddressRoot<AccountId>;
852
	type WithdrawOrigin = pallet_evm::EnsureAddressNever<AccountId>;
853

            
854
	type AddressMapping = pallet_evm::IdentityAddressMapping;
855
	type Currency = Balances;
856
	type Runner = pallet_evm::runner::stack::Runner<Self>;
857

            
858
	type RuntimeEvent = RuntimeEvent;
859
	type PrecompilesType = ();
860
	type PrecompilesValue = ();
861
	type ChainId = ();
862
	type BlockGasLimit = BlockGasLimit;
863
	type OnChargeTransaction = ();
864
	type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping<Self>;
865
	type FindAuthor = ();
866
	type OnCreate = ();
867
	type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
868
	type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
869
	type Timestamp = Timestamp;
870
	type WeightInfo = pallet_evm::weights::SubstrateWeight<Runtime>;
871
	type AccountProvider = FrameSystemAccountProvider<Runtime>;
872
}
873

            
874
#[allow(dead_code)]
875
pub struct NormalFilter;
876

            
877
impl frame_support::traits::Contains<RuntimeCall> for NormalFilter {
878
	fn contains(c: &RuntimeCall) -> bool {
879
		match c {
880
			_ => true,
881
		}
882
	}
883
}
884

            
885
// We need to use the encoding from the relay mock runtime
886
#[derive(Encode, Decode)]
887
pub enum RelayCall {
888
	#[codec(index = 5u8)]
889
	// the index should match the position of the module in `construct_runtime!`
890
	Utility(UtilityCall),
891
	#[codec(index = 6u8)]
892
	// the index should match the position of the module in `construct_runtime!`
893
	Hrmp(HrmpCall),
894
}
895

            
896
#[derive(Encode, Decode)]
897
pub enum UtilityCall {
898
	#[codec(index = 1u8)]
899
	AsDerivative(u16),
900
}
901

            
902
// HRMP call encoding, needed for xcm transactor pallet
903
#[derive(Encode, Decode)]
904
pub enum HrmpCall {
905
	#[codec(index = 0u8)]
906
	InitOpenChannel(ParaId, u32, u32),
907
	#[codec(index = 1u8)]
908
	AcceptOpenChannel(ParaId),
909
	#[codec(index = 2u8)]
910
	CloseChannel(HrmpChannelId),
911
	#[codec(index = 6u8)]
912
	CancelOpenRequest(HrmpChannelId, u32),
913
}
914

            
915
#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
916
pub enum MockTransactors {
917
	Relay,
918
}
919

            
920
impl xcm_primitives::XcmTransact for MockTransactors {
921
3
	fn destination(self) -> Location {
922
3
		match self {
923
3
			MockTransactors::Relay => Location::parent(),
924
3
		}
925
3
	}
926
}
927

            
928
impl xcm_primitives::UtilityEncodeCall for MockTransactors {
929
7
	fn encode_call(self, call: xcm_primitives::UtilityAvailableCalls) -> Vec<u8> {
930
7
		match self {
931
7
			MockTransactors::Relay => match call {
932
7
				xcm_primitives::UtilityAvailableCalls::AsDerivative(a, b) => {
933
7
					let mut call =
934
7
						RelayCall::Utility(UtilityCall::AsDerivative(a.clone())).encode();
935
7
					call.append(&mut b.clone());
936
7
					call
937
7
				}
938
7
			},
939
7
		}
940
7
	}
941
}
942

            
943
#[allow(dead_code)]
944
pub struct MockHrmpEncoder;
945

            
946
impl xcm_primitives::HrmpEncodeCall for MockHrmpEncoder {
947
	fn hrmp_encode_call(
948
		call: xcm_primitives::HrmpAvailableCalls,
949
	) -> Result<Vec<u8>, xcm::latest::Error> {
950
		match call {
951
			xcm_primitives::HrmpAvailableCalls::InitOpenChannel(a, b, c) => Ok(RelayCall::Hrmp(
952
				HrmpCall::InitOpenChannel(a.clone(), b.clone(), c.clone()),
953
			)
954
			.encode()),
955
			xcm_primitives::HrmpAvailableCalls::AcceptOpenChannel(a) => {
956
				Ok(RelayCall::Hrmp(HrmpCall::AcceptOpenChannel(a.clone())).encode())
957
			}
958
			xcm_primitives::HrmpAvailableCalls::CloseChannel(a) => {
959
				Ok(RelayCall::Hrmp(HrmpCall::CloseChannel(a.clone())).encode())
960
			}
961
			xcm_primitives::HrmpAvailableCalls::CancelOpenRequest(a, b) => {
962
				Ok(RelayCall::Hrmp(HrmpCall::CancelOpenRequest(a.clone(), b.clone())).encode())
963
			}
964
		}
965
	}
966
}
967

            
968
parameter_types! {
969
	pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes;
970
}
971

            
972
impl pallet_ethereum::Config for Runtime {
973
	type RuntimeEvent = RuntimeEvent;
974
	type StateRoot =
975
		pallet_ethereum::IntermediateStateRoot<<Runtime as frame_system::Config>::Version>;
976
	type PostLogContent = PostBlockAndTxnHashes;
977
	type ExtraDataLength = ConstU32<30>;
978
}
979
parameter_types! {
980
	pub ReservedXcmpWeight: Weight = Weight::from_parts(u64::max_value(), 0);
981
}
982

            
983
#[derive(
984
	Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, MaxEncodedLen, TypeInfo,
985
)]
986
pub enum ProxyType {
987
	NotAllowed = 0,
988
1
	Any = 1,
989
}
990

            
991
impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType {}
992

            
993
impl InstanceFilter<RuntimeCall> for ProxyType {
994
	fn filter(&self, _c: &RuntimeCall) -> bool {
995
		match self {
996
			ProxyType::NotAllowed => false,
997
			ProxyType::Any => true,
998
		}
999
	}
	fn is_superset(&self, _o: &Self) -> bool {
		false
	}
}
impl Default for ProxyType {
	fn default() -> Self {
		Self::NotAllowed
	}
}
parameter_types! {
	pub const ProxyCost: u64 = 1;
}
impl pallet_proxy::Config for Runtime {
	type RuntimeEvent = RuntimeEvent;
	type RuntimeCall = RuntimeCall;
	type Currency = Balances;
	type ProxyType = ProxyType;
	type ProxyDepositBase = ProxyCost;
	type ProxyDepositFactor = ProxyCost;
	type MaxProxies = ConstU32<32>;
	type WeightInfo = pallet_proxy::weights::SubstrateWeight<Runtime>;
	type MaxPending = ConstU32<32>;
	type CallHasher = BlakeTwo256;
	type AnnouncementDepositBase = ProxyCost;
	type AnnouncementDepositFactor = ProxyCost;
}
pub struct EthereumXcmEnsureProxy;
impl xcm_primitives::EnsureProxy<AccountId> for EthereumXcmEnsureProxy {
2
	fn ensure_ok(delegator: AccountId, delegatee: AccountId) -> Result<(), &'static str> {
		// The EVM implicitely contains an Any proxy, so we only allow for "Any" proxies
1
		let def: pallet_proxy::ProxyDefinition<AccountId, ProxyType, BlockNumber> =
2
			pallet_proxy::Pallet::<Runtime>::find_proxy(
2
				&delegator,
2
				&delegatee,
2
				Some(ProxyType::Any),
2
			)
2
			.map_err(|_| "proxy error: expected `ProxyType::Any`")?;
		// We only allow to use it for delay zero proxies, as the call will iMmediatly be executed
1
		ensure!(def.delay.is_zero(), "proxy delay is Non-zero`");
1
		Ok(())
2
	}
}
impl pallet_ethereum_xcm::Config for Runtime {
	type RuntimeEvent = RuntimeEvent;
	type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper;
	type ValidatedTransaction = pallet_ethereum::ValidatedTransaction<Self>;
	type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction;
	type ReservedXcmpWeight = ReservedXcmpWeight;
	type EnsureProxy = EthereumXcmEnsureProxy;
	type ControllerOrigin = EnsureRoot<AccountId>;
	type ForceOrigin = EnsureRoot<AccountId>;
}
type Block = frame_system::mocking::MockBlockU32<Runtime>;
10080
construct_runtime!(
1882
	pub enum Runtime	{
1882
		System: frame_system,
1882
		Balances: pallet_balances,
1882
		MsgQueue: mock_msg_queue,
1882
		XcmVersioner: mock_version_changer,
1882

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

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