moonbase_runtime/
lib.rs

1// Copyright 2019-2025 PureStake Inc.
2// This file is part of Moonbeam.
3
4// Moonbeam 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// Moonbeam 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 Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16
17//! The Moonbase Runtime.
18//!
19//! Primary features of this runtime include:
20//! * Ethereum compatibility
21//! * Moonbase tokenomics
22
23#![cfg_attr(not(feature = "std"), no_std)]
24// `construct_runtime!` does a lot of recursion and requires us to increase the limit.
25#![recursion_limit = "512"]
26
27// Make the WASM binary available.
28#[cfg(feature = "std")]
29include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
30
31pub mod asset_config;
32#[cfg(not(feature = "disable-genesis-builder"))]
33pub mod genesis_config_preset;
34pub mod governance;
35pub mod runtime_params;
36pub mod xcm_config;
37
38mod migrations;
39mod precompiles;
40
41extern crate alloc;
42extern crate core;
43
44use alloc::borrow::Cow;
45// Re-export required by get! macro.
46#[cfg(feature = "std")]
47pub use fp_evm::GenesisAccount;
48pub use moonbeam_core_primitives::{
49	AccountId, AccountIndex, Address, AssetId, Balance, BlockNumber, DigestItem, Hash, Header,
50	Index, Signature,
51};
52pub use pallet_author_slot_filter::EligibilityValue;
53pub use pallet_parachain_staking::{weights::WeightInfo, InflationInfo, Range};
54pub use precompiles::{
55	MoonbasePrecompiles, PrecompileName, FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX,
56};
57
58use account::AccountId20;
59use cumulus_pallet_parachain_system::{
60	RelayChainStateProof, RelayStateProof, RelaychainDataProvider, ValidationData,
61};
62use cumulus_primitives_core::{relay_chain, AggregateMessageOrigin};
63use fp_rpc::TransactionStatus;
64use frame_support::{
65	construct_runtime,
66	dispatch::{DispatchClass, GetDispatchInfo, PostDispatchInfo},
67	ensure,
68	pallet_prelude::DispatchResult,
69	parameter_types,
70	traits::{
71		fungible::{Balanced, Credit, HoldConsideration, Inspect, NativeOrWithId},
72		ConstBool, ConstU128, ConstU16, ConstU32, ConstU64, ConstU8, Contains, EitherOf,
73		EitherOfDiverse, EqualPrivilegeOnly, FindAuthor, Get, InstanceFilter, LinearStoragePrice,
74		OnFinalize, OnUnbalanced, VariantCountOf,
75	},
76	weights::{
77		constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, Weight, WeightToFeeCoefficient,
78		WeightToFeeCoefficients, WeightToFeePolynomial,
79	},
80	PalletId,
81};
82use frame_system::{EnsureRoot, EnsureSigned};
83use governance::councils::*;
84use moonbeam_rpc_primitives_txpool::TxPoolResponse;
85use moonbeam_runtime_common::{
86	impl_asset_conversion::AssetRateConverter, impl_multiasset_paymaster::MultiAssetPaymaster,
87};
88use nimbus_primitives::CanAuthor;
89use pallet_ethereum::Call::transact;
90use pallet_ethereum::{PostLogContent, Transaction as EthereumTransaction};
91use pallet_evm::{
92	Account as EVMAccount, EVMFungibleAdapter, EnsureAddressNever, EnsureAddressRoot,
93	FeeCalculator, FrameSystemAccountProvider, GasWeightMapping, IdentityAddressMapping,
94	OnChargeEVMTransaction as OnChargeEVMTransactionT, Runner,
95};
96use pallet_transaction_payment::{FungibleAdapter, Multiplier, TargetedFeeAdjustment};
97use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
98use runtime_params::*;
99use scale_info::TypeInfo;
100use sp_api::impl_runtime_apis;
101use sp_consensus_slots::Slot;
102use sp_core::{OpaqueMetadata, H160, H256, U256};
103use sp_runtime::generic::Preamble;
104use sp_runtime::{
105	generic, impl_opaque_keys,
106	traits::{
107		BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, IdentityLookup,
108		PostDispatchInfoOf, UniqueSaturatedInto, Zero,
109	},
110	transaction_validity::{
111		InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError,
112	},
113	ApplyExtrinsicResult, DispatchErrorWithPostInfo, FixedPointNumber, Perbill, Permill,
114	Perquintill,
115};
116use sp_std::{
117	convert::{From, Into},
118	prelude::*,
119};
120#[cfg(feature = "std")]
121use sp_version::NativeVersion;
122use sp_version::RuntimeVersion;
123use xcm::{
124	Version as XcmVersion, VersionedAssetId, VersionedAssets, VersionedLocation, VersionedXcm,
125};
126use xcm_runtime_apis::{
127	dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects},
128	fees::Error as XcmPaymentApiError,
129};
130
131use smallvec::smallvec;
132use sp_runtime::serde::{Deserialize, Serialize};
133
134#[cfg(any(feature = "std", test))]
135pub use sp_runtime::BuildStorage;
136
137pub type Precompiles = MoonbasePrecompiles<Runtime>;
138
139mod weights;
140
141pub(crate) use weights as moonbase_weights;
142
143pub use weights::xcm as moonbase_xcm_weights;
144
145/// UNIT, the native token, uses 18 decimals of precision.
146pub mod currency {
147	use super::Balance;
148
149	// Provide a common factor between runtimes based on a supply of 10_000_000 tokens.
150	pub const SUPPLY_FACTOR: Balance = 1;
151
152	pub const WEI: Balance = 1;
153	pub const KILOWEI: Balance = 1_000;
154	pub const MEGAWEI: Balance = 1_000_000;
155	pub const GIGAWEI: Balance = 1_000_000_000;
156	pub const MICROUNIT: Balance = 1_000_000_000_000;
157	pub const MILLIUNIT: Balance = 1_000_000_000_000_000;
158	pub const UNIT: Balance = 1_000_000_000_000_000_000;
159	pub const KILOUNIT: Balance = 1_000_000_000_000_000_000_000;
160
161	pub const TRANSACTION_BYTE_FEE: Balance = 1 * GIGAWEI * SUPPLY_FACTOR;
162	pub const STORAGE_BYTE_FEE: Balance = 100 * MICROUNIT * SUPPLY_FACTOR;
163	pub const WEIGHT_FEE: Balance = 50 * KILOWEI * SUPPLY_FACTOR / 4;
164
165	pub const fn deposit(items: u32, bytes: u32) -> Balance {
166		items as Balance * 1 * UNIT * SUPPLY_FACTOR + (bytes as Balance) * STORAGE_BYTE_FEE
167	}
168}
169
170/// Maximum PoV size we support right now.
171// Reference: https://github.com/polkadot-fellows/runtimes/pull/553
172pub const MAX_POV_SIZE: u32 = 10 * 1024 * 1024;
173
174/// Maximum weight per block
175pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(
176	WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2),
177	MAX_POV_SIZE as u64,
178);
179
180pub const MILLISECS_PER_BLOCK: u64 = 6_000;
181pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
182pub const HOURS: BlockNumber = MINUTES * 60;
183pub const DAYS: BlockNumber = HOURS * 24;
184pub const WEEKS: BlockNumber = DAYS * 7;
185/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
186/// the specifics of the runtime. They can then be made to be agnostic over specific formats
187/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
188/// to even the core data structures.
189pub mod opaque {
190	use super::*;
191
192	pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
193	pub type Block = generic::Block<Header, UncheckedExtrinsic>;
194
195	impl_opaque_keys! {
196		pub struct SessionKeys {
197			pub nimbus: AuthorInherent,
198			pub vrf: session_keys_primitives::VrfSessionKey,
199		}
200	}
201}
202
203/// This runtime version.
204/// The spec_version is composed of 2x2 digits. The first 2 digits represent major changes
205/// that can't be skipped, such as data migration upgrades. The last 2 digits represent minor
206/// changes which can be skipped.
207#[sp_version::runtime_version]
208pub const VERSION: RuntimeVersion = RuntimeVersion {
209	spec_name: Cow::Borrowed("moonbase"),
210	impl_name: Cow::Borrowed("moonbase"),
211	authoring_version: 4,
212	spec_version: 4200,
213	impl_version: 0,
214	apis: RUNTIME_API_VERSIONS,
215	transaction_version: 3,
216	system_version: 1,
217};
218
219/// The version information used to identify this runtime when compiled natively.
220#[cfg(feature = "std")]
221pub fn native_version() -> NativeVersion {
222	NativeVersion {
223		runtime_version: VERSION,
224		can_author_with: Default::default(),
225	}
226}
227
228const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
229pub const NORMAL_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_mul(3).saturating_div(4);
230// Here we assume Ethereum's base fee of 21000 gas and convert to weight, but we
231// subtract roughly the cost of a balance transfer from it (about 1/3 the cost)
232// and some cost to account for per-byte-fee.
233// TODO: we should use benchmarking's overhead feature to measure this
234pub const EXTRINSIC_BASE_WEIGHT: Weight = Weight::from_parts(10000 * WEIGHT_PER_GAS, 0);
235
236pub struct RuntimeBlockWeights;
237impl Get<frame_system::limits::BlockWeights> for RuntimeBlockWeights {
238	fn get() -> frame_system::limits::BlockWeights {
239		frame_system::limits::BlockWeights::builder()
240			.for_class(DispatchClass::Normal, |weights| {
241				weights.base_extrinsic = EXTRINSIC_BASE_WEIGHT;
242				weights.max_total = NORMAL_WEIGHT.into();
243			})
244			.for_class(DispatchClass::Operational, |weights| {
245				weights.max_total = MAXIMUM_BLOCK_WEIGHT.into();
246				weights.reserved = (MAXIMUM_BLOCK_WEIGHT - NORMAL_WEIGHT).into();
247			})
248			.avg_block_initialization(Perbill::from_percent(10))
249			.build()
250			.expect("Provided BlockWeight definitions are valid, qed")
251	}
252}
253
254parameter_types! {
255	pub const Version: RuntimeVersion = VERSION;
256	/// TODO: this is left here so that `impl_runtime_apis_plus_common` will find the same type for
257	/// `BlockWeights` in all runtimes. It can probably be removed once the custom
258	/// `RuntimeBlockWeights` has been pushed to each runtime.
259	pub BlockWeights: frame_system::limits::BlockWeights = RuntimeBlockWeights::get();
260	/// We allow for 5 MB blocks.
261	pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength
262		::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
263}
264
265impl frame_system::Config for Runtime {
266	/// The identifier used to distinguish between accounts.
267	type AccountId = AccountId;
268	/// The aggregated dispatch type that is available for extrinsics.
269	type RuntimeCall = RuntimeCall;
270	/// The lookup mechanism to get account ID from whatever is passed in dispatchers.
271	type Lookup = IdentityLookup<AccountId>;
272	/// The index type for storing how many extrinsics an account has signed.
273	type Nonce = Index;
274	/// The index type for blocks.
275	type Block = Block;
276	/// The type for hashing blocks and tries.
277	type Hash = Hash;
278	/// The hashing algorithm used.
279	type Hashing = BlakeTwo256;
280	/// The ubiquitous event type.
281	type RuntimeEvent = RuntimeEvent;
282	/// The ubiquitous origin type.
283	type RuntimeOrigin = RuntimeOrigin;
284	/// The aggregated RuntimeTask type.
285	type RuntimeTask = RuntimeTask;
286	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
287	type BlockHashCount = ConstU32<256>;
288	/// Maximum weight of each block. With a default weight system of 1byte == 1weight, 4mb is ok.
289	type BlockWeights = RuntimeBlockWeights;
290	/// Maximum size of all encoded transactions (in bytes) that are allowed in one block.
291	type BlockLength = BlockLength;
292	/// Runtime version.
293	type Version = Version;
294	type PalletInfo = PalletInfo;
295	type AccountData = pallet_balances::AccountData<Balance>;
296	type OnNewAccount = ();
297	type OnKilledAccount = ();
298	type DbWeight = moonbase_weights::db::rocksdb::constants::RocksDbWeight;
299	type BaseCallFilter = MaintenanceMode;
300	type SystemWeightInfo = moonbase_weights::frame_system::WeightInfo<Runtime>;
301	/// This is used as an identifier of the chain. 42 is the generic substrate prefix.
302	type SS58Prefix = ConstU16<1287>;
303	type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
304	type MaxConsumers = frame_support::traits::ConstU32<16>;
305	type SingleBlockMigrations = migrations::SingleBlockMigrations<Runtime>;
306	type MultiBlockMigrator = MultiBlockMigrations;
307	type PreInherents = ();
308	type PostInherents = (
309		// Validate timestamp provided by the consensus client
310		AsyncBacking,
311	);
312	type PostTransactions = ();
313	type ExtensionsWeightInfo = moonbase_weights::frame_system_extensions::WeightInfo<Runtime>;
314}
315
316impl pallet_utility::Config for Runtime {
317	type RuntimeEvent = RuntimeEvent;
318	type RuntimeCall = RuntimeCall;
319	type PalletsOrigin = OriginCaller;
320	type WeightInfo = moonbase_weights::pallet_utility::WeightInfo<Runtime>;
321}
322
323impl pallet_timestamp::Config for Runtime {
324	/// A timestamp: milliseconds since the unix epoch.
325	type Moment = u64;
326	type OnTimestampSet = ();
327	type MinimumPeriod = ConstU64<{ RELAY_CHAIN_SLOT_DURATION_MILLIS as u64 / 2 }>;
328	type WeightInfo = moonbase_weights::pallet_timestamp::WeightInfo<Runtime>;
329}
330
331#[cfg(not(feature = "runtime-benchmarks"))]
332parameter_types! {
333	pub const ExistentialDeposit: Balance = 0;
334}
335
336#[cfg(feature = "runtime-benchmarks")]
337parameter_types! {
338	pub const ExistentialDeposit: Balance = 1;
339}
340
341impl pallet_balances::Config for Runtime {
342	type MaxReserves = ConstU32<50>;
343	type ReserveIdentifier = [u8; 4];
344	type MaxLocks = ConstU32<50>;
345	/// The type for recording an account's balance.
346	type Balance = Balance;
347	/// The ubiquitous event type.
348	type RuntimeEvent = RuntimeEvent;
349	type DustRemoval = ();
350	type ExistentialDeposit = ExistentialDeposit;
351	type AccountStore = System;
352	type FreezeIdentifier = RuntimeFreezeReason;
353	type MaxFreezes = VariantCountOf<Self::RuntimeFreezeReason>;
354	type RuntimeHoldReason = RuntimeHoldReason;
355	type RuntimeFreezeReason = RuntimeFreezeReason;
356	type WeightInfo = moonbase_weights::pallet_balances::WeightInfo<Runtime>;
357	type DoneSlashHandler = ();
358}
359
360pub struct LengthToFee;
361impl WeightToFeePolynomial for LengthToFee {
362	type Balance = Balance;
363
364	fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
365		smallvec![
366			WeightToFeeCoefficient {
367				degree: 1,
368				coeff_frac: Perbill::zero(),
369				coeff_integer: currency::TRANSACTION_BYTE_FEE,
370				negative: false,
371			},
372			WeightToFeeCoefficient {
373				degree: 3,
374				coeff_frac: Perbill::zero(),
375				coeff_integer: 1 * currency::SUPPLY_FACTOR,
376				negative: false,
377			},
378		]
379	}
380}
381
382impl pallet_transaction_payment::Config for Runtime {
383	type RuntimeEvent = RuntimeEvent;
384	type OnChargeTransaction = FungibleAdapter<
385		Balances,
386		DealWithSubstrateFeesAndTip<
387			Runtime,
388			dynamic_params::runtime_config::FeesTreasuryProportion,
389		>,
390	>;
391	type OperationalFeeMultiplier = ConstU8<5>;
392	type WeightToFee = ConstantMultiplier<Balance, ConstU128<{ currency::WEIGHT_FEE }>>;
393	type LengthToFee = LengthToFee;
394	type FeeMultiplierUpdate = FastAdjustingFeeUpdate<Runtime>;
395	type WeightInfo = weights::pallet_transaction_payment::WeightInfo<Runtime>;
396}
397
398impl pallet_sudo::Config for Runtime {
399	type RuntimeCall = RuntimeCall;
400	type RuntimeEvent = RuntimeEvent;
401	type WeightInfo = moonbase_weights::pallet_sudo::WeightInfo<Runtime>;
402}
403
404impl pallet_evm_chain_id::Config for Runtime {}
405
406/// Current approximation of the gas/s consumption considering
407/// EVM execution over compiled WASM (on 4.4Ghz CPU).
408/// Given the 2 sec Weight, from which 75% only are used for transactions,
409/// the total EVM execution gas limit is: GAS_PER_SECOND * 2 * 0.75 ~= 60_000_000.
410pub const GAS_PER_SECOND: u64 = 40_000_000;
411
412/// Approximate ratio of the amount of Weight per Gas.
413/// u64 works for approximations because Weight is a very small unit compared to gas.
414pub const WEIGHT_PER_GAS: u64 = WEIGHT_REF_TIME_PER_SECOND / GAS_PER_SECOND;
415
416/// The highest amount of new storage that can be created in a block (160KB).
417/// Originally 40KB, then multiplied by 4 when the block deadline was increased from 500ms to 2000ms.
418/// Reference: https://github.com/moonbeam-foundation/moonbeam/blob/master/MBIPS/MBIP-5.md#specification
419pub const BLOCK_STORAGE_LIMIT: u64 = 160 * 1024;
420
421parameter_types! {
422	pub BlockGasLimit: U256
423		= U256::from(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT.ref_time() / WEIGHT_PER_GAS);
424	/// The portion of the `NORMAL_DISPATCH_RATIO` that we adjust the fees with. Blocks filled less
425	/// than this will decrease the weight and more will increase.
426	pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(35);
427	/// The adjustment variable of the runtime. Higher values will cause `TargetBlockFullness` to
428	/// change the fees more rapidly. This fast multiplier responds by doubling/halving in
429	/// approximately one hour at extreme block congestion levels.
430	pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(4, 1_000);
431	/// Minimum amount of the multiplier. This value cannot be too low. A test case should ensure
432	/// that combined with `AdjustmentVariable`, we can recover from the minimum.
433	/// See `multiplier_can_grow_from_zero` in integration_tests.rs.
434	pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 10);
435	/// Maximum multiplier. We pick a value that is expensive but not impossibly so; it should act
436	/// as a safety net.
437	pub MaximumMultiplier: Multiplier = Multiplier::from(100_000u128);
438	pub PrecompilesValue: MoonbasePrecompiles<Runtime> = MoonbasePrecompiles::<_>::new();
439	pub WeightPerGas: Weight = Weight::from_parts(WEIGHT_PER_GAS, 0);
440	/// The amount of gas per pov. A ratio of 8 if we convert ref_time to gas and we compare
441	/// it with the pov_size for a block. E.g.
442	/// ceil(
443	///     (max_extrinsic.ref_time() / max_extrinsic.proof_size()) / WEIGHT_PER_GAS
444	/// )
445	/// We should re-check `xcm_config::Erc20XcmBridgeTransferGasLimit` when changing this value
446	pub const GasLimitPovSizeRatio: u64 = 8;
447	/// The amount of gas per storage (in bytes): BLOCK_GAS_LIMIT / BLOCK_STORAGE_LIMIT
448	/// (60_000_000 / 160 kb)
449	pub GasLimitStorageGrowthRatio: u64 = 366;
450}
451
452pub struct TransactionPaymentAsGasPrice;
453impl FeeCalculator for TransactionPaymentAsGasPrice {
454	fn min_gas_price() -> (U256, Weight) {
455		// TODO: transaction-payment differs from EIP-1559 in that its tip and length fees are not
456		//       scaled by the multiplier, which means its multiplier will be overstated when
457		//       applied to an ethereum transaction
458		// note: transaction-payment uses both a congestion modifier (next_fee_multiplier, which is
459		//       updated once per block in on_finalize) and a 'WeightToFee' implementation. Our
460		//       runtime implements this as a 'ConstantModifier', so we can get away with a simple
461		//       multiplication here.
462		// It is imperative that `saturating_mul_int` be performed as late as possible in the
463		// expression since it involves fixed point multiplication with a division by a fixed
464		// divisor. This leads to truncation and subsequent precision loss if performed too early.
465		// This can lead to min_gas_price being same across blocks even if the multiplier changes.
466		// There's still some precision loss when the final `gas_price` (used_gas * min_gas_price)
467		// is computed in frontier, but that's currently unavoidable.
468		let min_gas_price = TransactionPayment::next_fee_multiplier()
469			.saturating_mul_int((currency::WEIGHT_FEE).saturating_mul(WEIGHT_PER_GAS as u128));
470		(
471			min_gas_price.into(),
472			<Runtime as frame_system::Config>::DbWeight::get().reads(1),
473		)
474	}
475}
476
477/// A "Fast" TargetedFeeAdjustment. Parameters chosen based on model described here:
478/// https://research.web3.foundation/Polkadot/overview/token-economics#1-fast-adjusting-mechanism
479///
480/// The adjustment algorithm boils down to:
481///
482/// diff = (previous_block_weight - target) / maximum_block_weight
483/// next_multiplier = prev_multiplier * (1 + (v * diff) + ((v * diff)^2 / 2))
484/// assert(next_multiplier > min)
485///     where: v is AdjustmentVariable
486///            target is TargetBlockFullness
487///            min is MinimumMultiplier
488pub type FastAdjustingFeeUpdate<R> = TargetedFeeAdjustment<
489	R,
490	TargetBlockFullness,
491	AdjustmentVariable,
492	MinimumMultiplier,
493	MaximumMultiplier,
494>;
495
496/// The author inherent provides an AccountId, but pallet evm needs an H160.
497/// This simple adapter makes the conversion for any types T, U such that T: Into<U>
498pub struct FindAuthorAdapter<T, U, Inner>(sp_std::marker::PhantomData<(T, U, Inner)>);
499
500impl<T, U, Inner> FindAuthor<U> for FindAuthorAdapter<T, U, Inner>
501where
502	T: Into<U>,
503	Inner: FindAuthor<T>,
504{
505	fn find_author<'a, I>(digests: I) -> Option<U>
506	where
507		I: 'a + IntoIterator<Item = (sp_runtime::ConsensusEngineId, &'a [u8])>,
508	{
509		Inner::find_author(digests).map(Into::into)
510	}
511}
512
513moonbeam_runtime_common::impl_on_charge_evm_transaction!();
514
515impl pallet_evm::Config for Runtime {
516	type FeeCalculator = TransactionPaymentAsGasPrice;
517	type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
518	type WeightPerGas = WeightPerGas;
519	type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
520	type CallOrigin = EnsureAddressRoot<AccountId>;
521	type WithdrawOrigin = EnsureAddressNever<AccountId>;
522	type AddressMapping = IdentityAddressMapping;
523	type Currency = Balances;
524	type Runner = pallet_evm::runner::stack::Runner<Self>;
525	type PrecompilesType = MoonbasePrecompiles<Self>;
526	type PrecompilesValue = PrecompilesValue;
527	type ChainId = EthereumChainId;
528	type OnChargeTransaction = OnChargeEVMTransaction<
529		DealWithEthereumBaseFees<Runtime, dynamic_params::runtime_config::FeesTreasuryProportion>,
530		DealWithEthereumPriorityFees<Runtime>,
531	>;
532	type BlockGasLimit = BlockGasLimit;
533	type FindAuthor = FindAuthorAdapter<AccountId20, H160, AuthorInherent>;
534	type OnCreate = ();
535	type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
536	type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
537	type Timestamp = Timestamp;
538	type AccountProvider = FrameSystemAccountProvider<Runtime>;
539
540	type WeightInfo = moonbase_weights::pallet_evm::WeightInfo<Runtime>;
541	type CreateOriginFilter = ();
542	type CreateInnerOriginFilter = ();
543}
544
545parameter_types! {
546	pub MaxServiceWeight: Weight = NORMAL_DISPATCH_RATIO * RuntimeBlockWeights::get().max_block;
547	pub const NoPreimagePostponement: Option<u32> = Some(10);
548}
549
550impl pallet_scheduler::Config for Runtime {
551	type RuntimeEvent = RuntimeEvent;
552	type RuntimeOrigin = RuntimeOrigin;
553	type PalletsOrigin = OriginCaller;
554	type RuntimeCall = RuntimeCall;
555	type MaximumWeight = MaxServiceWeight;
556	type ScheduleOrigin = EnsureRoot<AccountId>;
557	type MaxScheduledPerBlock = ConstU32<50>;
558	type WeightInfo = moonbase_weights::pallet_scheduler::WeightInfo<Runtime>;
559	type OriginPrivilegeCmp = EqualPrivilegeOnly;
560	type Preimages = Preimage;
561	type BlockNumberProvider = System;
562}
563
564parameter_types! {
565	pub const PreimageBaseDeposit: Balance = 5 * currency::UNIT * currency::SUPPLY_FACTOR ;
566	pub const PreimageByteDeposit: Balance = currency::STORAGE_BYTE_FEE;
567	pub const PreimageHoldReason: RuntimeHoldReason =
568		RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage);
569}
570
571impl pallet_preimage::Config for Runtime {
572	type WeightInfo = moonbase_weights::pallet_preimage::WeightInfo<Runtime>;
573	type RuntimeEvent = RuntimeEvent;
574	type Currency = Balances;
575	type ManagerOrigin = EnsureRoot<AccountId>;
576	type Consideration = HoldConsideration<
577		AccountId,
578		Balances,
579		PreimageHoldReason,
580		LinearStoragePrice<PreimageBaseDeposit, PreimageByteDeposit, Balance>,
581	>;
582}
583
584parameter_types! {
585	pub const ProposalBond: Permill = Permill::from_percent(5);
586	pub const TreasuryId: PalletId = PalletId(*b"pc/trsry");
587	pub TreasuryAccount: AccountId = Treasury::account_id();
588	pub const MaxSpendBalance: crate::Balance = crate::Balance::max_value();
589}
590
591type RootOrTreasuryCouncilOrigin = EitherOfDiverse<
592	EnsureRoot<AccountId>,
593	pallet_collective::EnsureProportionMoreThan<AccountId, TreasuryCouncilInstance, 1, 2>,
594>;
595
596impl pallet_treasury::Config for Runtime {
597	type PalletId = TreasuryId;
598	type Currency = Balances;
599	// More than half of the council is required (or root) to reject a proposal
600	type RejectOrigin = RootOrTreasuryCouncilOrigin;
601	type RuntimeEvent = RuntimeEvent;
602	type SpendPeriod = ConstU32<{ 6 * DAYS }>;
603	type Burn = ();
604	type BurnDestination = ();
605	type MaxApprovals = ConstU32<100>;
606	type WeightInfo = moonbase_weights::pallet_treasury::WeightInfo<Runtime>;
607	type SpendFunds = ();
608	type SpendOrigin =
609		frame_system::EnsureWithSuccess<RootOrTreasuryCouncilOrigin, AccountId, MaxSpendBalance>;
610	type AssetKind = NativeOrWithId<AssetId>;
611	type Beneficiary = AccountId;
612	type BeneficiaryLookup = IdentityLookup<AccountId>;
613	type Paymaster = MultiAssetPaymaster<Runtime, TreasuryAccount, Balances>;
614	type BalanceConverter = AssetRateConverter<Runtime, Balances>;
615	type PayoutPeriod = ConstU32<{ 30 * DAYS }>;
616	#[cfg(feature = "runtime-benchmarks")]
617	type BenchmarkHelper = BenchmarkHelper<Runtime>;
618	type BlockNumberProvider = System;
619}
620
621parameter_types! {
622	pub const MaxSubAccounts: u32 = 100;
623	pub const MaxAdditionalFields: u32 = 100;
624	pub const MaxRegistrars: u32 = 20;
625	pub const PendingUsernameExpiration: u32 = 7 * DAYS;
626	pub const MaxSuffixLength: u32 = 7;
627	pub const MaxUsernameLength: u32 = 32;
628}
629
630type IdentityForceOrigin =
631	EitherOfDiverse<EnsureRoot<AccountId>, governance::custom_origins::GeneralAdmin>;
632type IdentityRegistrarOrigin =
633	EitherOfDiverse<EnsureRoot<AccountId>, governance::custom_origins::GeneralAdmin>;
634
635impl pallet_identity::Config for Runtime {
636	type RuntimeEvent = RuntimeEvent;
637	type Currency = Balances;
638	// Add one item in storage and take 258 bytes
639	type BasicDeposit = ConstU128<{ currency::deposit(1, 258) }>;
640	// Does not add any item to the storage but takes 1 bytes
641	type ByteDeposit = ConstU128<{ currency::deposit(0, 1) }>;
642	// Add one item in storage and take 53 bytes
643	type SubAccountDeposit = ConstU128<{ currency::deposit(1, 53) }>;
644	type MaxSubAccounts = MaxSubAccounts;
645	type IdentityInformation = pallet_identity::legacy::IdentityInfo<MaxAdditionalFields>;
646	type MaxRegistrars = MaxRegistrars;
647	type Slashed = Treasury;
648	type ForceOrigin = IdentityForceOrigin;
649	type RegistrarOrigin = IdentityRegistrarOrigin;
650	type OffchainSignature = Signature;
651	type SigningPublicKey = <Signature as sp_runtime::traits::Verify>::Signer;
652	type UsernameAuthorityOrigin = EnsureRoot<AccountId>;
653	type PendingUsernameExpiration = PendingUsernameExpiration;
654	type MaxSuffixLength = MaxSuffixLength;
655	type MaxUsernameLength = MaxUsernameLength;
656	type WeightInfo = moonbase_weights::pallet_identity::WeightInfo<Runtime>;
657	type UsernameDeposit = ConstU128<{ currency::deposit(0, MaxUsernameLength::get()) }>;
658	type UsernameGracePeriod = ConstU32<{ 30 * DAYS }>;
659	#[cfg(feature = "runtime-benchmarks")]
660	type BenchmarkHelper = BenchmarkHelper<Runtime>;
661}
662
663pub struct TransactionConverter;
664
665impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {
666	fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {
667		UncheckedExtrinsic::new_bare(
668			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
669		)
670	}
671}
672
673impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {
674	fn convert_transaction(
675		&self,
676		transaction: pallet_ethereum::Transaction,
677	) -> opaque::UncheckedExtrinsic {
678		let extrinsic = UncheckedExtrinsic::new_bare(
679			pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
680		);
681		let encoded = extrinsic.encode();
682		opaque::UncheckedExtrinsic::decode(&mut &encoded[..])
683			.expect("Encoded extrinsic is always valid")
684	}
685}
686
687parameter_types! {
688	pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes;
689}
690
691impl pallet_ethereum::Config for Runtime {
692	type StateRoot =
693		pallet_ethereum::IntermediateStateRoot<<Runtime as frame_system::Config>::Version>;
694	type PostLogContent = PostBlockAndTxnHashes;
695	type ExtraDataLength = ConstU32<30>;
696}
697
698pub struct EthereumXcmEnsureProxy;
699impl xcm_primitives::EnsureProxy<AccountId> for EthereumXcmEnsureProxy {
700	fn ensure_ok(delegator: AccountId, delegatee: AccountId) -> Result<(), &'static str> {
701		// The EVM implicitely contains an Any proxy, so we only allow for "Any" proxies
702		let def: pallet_proxy::ProxyDefinition<AccountId, ProxyType, BlockNumber> =
703			pallet_proxy::Pallet::<Runtime>::find_proxy(
704				&delegator,
705				&delegatee,
706				Some(ProxyType::Any),
707			)
708			.map_err(|_| "proxy error: expected `ProxyType::Any`")?;
709		// We only allow to use it for delay zero proxies, as the call will immediatly be executed
710		ensure!(def.delay.is_zero(), "proxy delay is Non-zero`");
711		Ok(())
712	}
713}
714
715impl pallet_ethereum_xcm::Config for Runtime {
716	type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper;
717	type ValidatedTransaction = pallet_ethereum::ValidatedTransaction<Self>;
718	type XcmEthereumOrigin = pallet_ethereum_xcm::EnsureXcmEthereumTransaction;
719	type ReservedXcmpWeight = ReservedXcmpWeight;
720	type EnsureProxy = EthereumXcmEnsureProxy;
721	type ControllerOrigin = EnsureRoot<AccountId>;
722	type ForceOrigin = EnsureRoot<AccountId>;
723}
724
725parameter_types! {
726	// Reserved weight is 1/4 of MAXIMUM_BLOCK_WEIGHT
727	pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
728	pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
729	pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent;
730}
731
732/// Relay chain slot duration, in milliseconds.
733const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000;
734/// Maximum number of blocks simultaneously accepted by the Runtime, not yet included
735/// into the relay chain.
736const UNINCLUDED_SEGMENT_CAPACITY: u32 = 3;
737/// Build with an offset of 1 behind the relay chain.
738const RELAY_PARENT_OFFSET: u32 = 1;
739/// How many parachain blocks are processed by the relay chain per parent. Limits the
740/// number of blocks authored per slot.
741const BLOCK_PROCESSING_VELOCITY: u32 = 1;
742
743type ConsensusHook = pallet_async_backing::consensus_hook::FixedVelocityConsensusHook<
744	Runtime,
745	RELAY_CHAIN_SLOT_DURATION_MILLIS,
746	BLOCK_PROCESSING_VELOCITY,
747	UNINCLUDED_SEGMENT_CAPACITY,
748>;
749
750impl cumulus_pallet_parachain_system::Config for Runtime {
751	type RuntimeEvent = RuntimeEvent;
752	type OnSystemEvent = ();
753	type SelfParaId = ParachainInfo;
754	type ReservedDmpWeight = ReservedDmpWeight;
755	type OutboundXcmpMessageSource = XcmpQueue;
756	type XcmpMessageHandler = XcmpQueue;
757	type ReservedXcmpWeight = ReservedXcmpWeight;
758	type CheckAssociatedRelayNumber = EmergencyParaXcm;
759	type ConsensusHook = ConsensusHook;
760	type DmpQueue = frame_support::traits::EnqueueWithOrigin<MessageQueue, RelayOrigin>;
761	type WeightInfo = moonbase_weights::cumulus_pallet_parachain_system::WeightInfo<Runtime>;
762	type SelectCore = cumulus_pallet_parachain_system::DefaultCoreSelector<Runtime>;
763	type RelayParentOffset = ConstU32<0>;
764}
765
766impl parachain_info::Config for Runtime {}
767
768pub struct OnNewRound;
769impl pallet_parachain_staking::OnNewRound for OnNewRound {
770	fn on_new_round(round_index: pallet_parachain_staking::RoundIndex) -> Weight {
771		MoonbeamOrbiters::on_new_round(round_index)
772	}
773}
774pub struct PayoutCollatorOrOrbiterReward;
775impl pallet_parachain_staking::PayoutCollatorReward<Runtime> for PayoutCollatorOrOrbiterReward {
776	fn payout_collator_reward(
777		for_round: pallet_parachain_staking::RoundIndex,
778		collator_id: AccountId,
779		amount: Balance,
780	) -> Weight {
781		let extra_weight =
782			if MoonbeamOrbiters::is_collator_pool_with_active_orbiter(for_round, collator_id) {
783				MoonbeamOrbiters::distribute_rewards(for_round, collator_id, amount)
784			} else {
785				ParachainStaking::mint_collator_reward(for_round, collator_id, amount)
786			};
787
788		<Runtime as frame_system::Config>::DbWeight::get()
789			.reads(1)
790			.saturating_add(extra_weight)
791	}
792}
793
794pub struct OnInactiveCollator;
795impl pallet_parachain_staking::OnInactiveCollator<Runtime> for OnInactiveCollator {
796	fn on_inactive_collator(
797		collator_id: AccountId,
798		round: pallet_parachain_staking::RoundIndex,
799	) -> Result<Weight, DispatchErrorWithPostInfo<PostDispatchInfo>> {
800		let extra_weight = if !MoonbeamOrbiters::is_collator_pool_with_active_orbiter(
801			round,
802			collator_id.clone(),
803		) {
804			ParachainStaking::go_offline_inner(collator_id)?;
805			<Runtime as pallet_parachain_staking::Config>::WeightInfo::go_offline(
806				pallet_parachain_staking::MAX_CANDIDATES,
807			)
808		} else {
809			Weight::zero()
810		};
811
812		Ok(<Runtime as frame_system::Config>::DbWeight::get()
813			.reads(1)
814			.saturating_add(extra_weight))
815	}
816}
817
818type MonetaryGovernanceOrigin =
819	EitherOfDiverse<EnsureRoot<AccountId>, governance::custom_origins::GeneralAdmin>;
820
821pub struct RelayChainSlotProvider;
822impl Get<Slot> for RelayChainSlotProvider {
823	fn get() -> Slot {
824		let slot_info = pallet_async_backing::pallet::Pallet::<Runtime>::slot_info();
825		slot_info.unwrap_or_default().0
826	}
827}
828
829impl pallet_parachain_staking::Config for Runtime {
830	type Currency = Balances;
831	type MonetaryGovernanceOrigin = MonetaryGovernanceOrigin;
832	/// Minimum round length is 2 minutes (10 * 12 second block times)
833	type MinBlocksPerRound = ConstU32<10>;
834	/// If a collator doesn't produce any block on this number of rounds, it is notified as inactive
835	type MaxOfflineRounds = ConstU32<2>;
836	/// Rounds before the collator leaving the candidates request can be executed
837	type LeaveCandidatesDelay = ConstU32<2>;
838	/// Rounds before the candidate bond increase/decrease can be executed
839	type CandidateBondLessDelay = ConstU32<2>;
840	/// Rounds before the delegator exit can be executed
841	type LeaveDelegatorsDelay = ConstU32<2>;
842	/// Rounds before the delegator revocation can be executed
843	type RevokeDelegationDelay = ConstU32<2>;
844	/// Rounds before the delegator bond increase/decrease can be executed
845	type DelegationBondLessDelay = ConstU32<2>;
846	/// Rounds before the reward is paid
847	type RewardPaymentDelay = ConstU32<2>;
848	/// Minimum collators selected per round, default at genesis and minimum forever after
849	type MinSelectedCandidates = ConstU32<8>;
850	/// Maximum top delegations per candidate
851	type MaxTopDelegationsPerCandidate = ConstU32<300>;
852	/// Maximum bottom delegations per candidate
853	type MaxBottomDelegationsPerCandidate = ConstU32<50>;
854	/// Maximum delegations per delegator
855	type MaxDelegationsPerDelegator = ConstU32<100>;
856	/// Maximum scheduled delegation requests per (collator, delegator)
857	type MaxScheduledRequestsPerDelegator = ConstU32<50>;
858	/// Minimum stake required to be reserved to be a candidate
859	type MinCandidateStk = ConstU128<{ 500 * currency::UNIT * currency::SUPPLY_FACTOR }>;
860	/// Minimum stake required to be reserved to be a delegator
861	type MinDelegation = ConstU128<{ 1 * currency::UNIT * currency::SUPPLY_FACTOR }>;
862	type BlockAuthor = AuthorInherent;
863	type OnCollatorPayout = ();
864	type PayoutCollatorReward = PayoutCollatorOrOrbiterReward;
865	type OnInactiveCollator = OnInactiveCollator;
866	type OnNewRound = OnNewRound;
867	type SlotProvider = RelayChainSlotProvider;
868	type WeightInfo = moonbase_weights::pallet_parachain_staking::WeightInfo<Runtime>;
869	type MaxCandidates = ConstU32<200>;
870	type SlotDuration = ConstU64<MILLISECS_PER_BLOCK>;
871	type BlockTime = ConstU64<MILLISECS_PER_BLOCK>;
872	type RuntimeFreezeReason = RuntimeFreezeReason;
873	type LinearInflationThreshold = ();
874}
875
876impl pallet_author_inherent::Config for Runtime {
877	type SlotBeacon = RelaychainDataProvider<Self>;
878	type AccountLookup = MoonbeamOrbiters;
879	type CanAuthor = AuthorFilter;
880	type AuthorId = AccountId;
881	type WeightInfo = moonbase_weights::pallet_author_inherent::WeightInfo<Runtime>;
882}
883
884#[cfg(test)]
885mod mock {
886	use super::*;
887	pub struct MockRandomness;
888	impl frame_support::traits::Randomness<H256, BlockNumber> for MockRandomness {
889		fn random(subject: &[u8]) -> (H256, BlockNumber) {
890			(H256(sp_io::hashing::blake2_256(subject)), 0)
891		}
892	}
893}
894
895impl pallet_author_slot_filter::Config for Runtime {
896	#[cfg(not(test))]
897	type RandomnessSource = Randomness;
898	#[cfg(test)]
899	type RandomnessSource = mock::MockRandomness;
900	type PotentialAuthors = ParachainStaking;
901	type WeightInfo = moonbase_weights::pallet_author_slot_filter::WeightInfo<Runtime>;
902}
903
904impl pallet_async_backing::Config for Runtime {
905	type AllowMultipleBlocksPerSlot = ConstBool<true>;
906	type GetAndVerifySlot = pallet_async_backing::RelaySlot;
907	type SlotDuration = ConstU64<MILLISECS_PER_BLOCK>;
908	type ExpectedBlockTime = ConstU64<MILLISECS_PER_BLOCK>;
909}
910
911parameter_types! {
912	pub const InitializationPayment: Perbill = Perbill::from_percent(30);
913	pub const RelaySignaturesThreshold: Perbill = Perbill::from_percent(100);
914	pub const SignatureNetworkIdentifier:  &'static [u8] = b"moonbase-";
915
916}
917
918impl pallet_crowdloan_rewards::Config for Runtime {
919	type Initialized = ConstBool<false>;
920	type InitializationPayment = InitializationPayment;
921	type MaxInitContributors = ConstU32<500>;
922	// TODO to be revisited
923	type MinimumReward = ConstU128<0>;
924	type RewardCurrency = Balances;
925	type RelayChainAccountId = [u8; 32];
926	type RewardAddressAssociateOrigin = EnsureSigned<Self::AccountId>;
927	type RewardAddressChangeOrigin = EnsureSigned<Self::AccountId>;
928	type RewardAddressRelayVoteThreshold = RelaySignaturesThreshold;
929	type SignatureNetworkIdentifier = SignatureNetworkIdentifier;
930	type VestingBlockNumber = relay_chain::BlockNumber;
931	type VestingBlockProvider = RelaychainDataProvider<Self>;
932	type WeightInfo = moonbase_weights::pallet_crowdloan_rewards::WeightInfo<Runtime>;
933}
934
935// This is a simple session key manager. It should probably either work with, or be replaced
936// entirely by pallet sessions
937impl pallet_author_mapping::Config for Runtime {
938	type DepositCurrency = Balances;
939	type DepositAmount = ConstU128<{ 100 * currency::UNIT * currency::SUPPLY_FACTOR }>;
940	type Keys = session_keys_primitives::VrfId;
941	type WeightInfo = moonbase_weights::pallet_author_mapping::WeightInfo<Runtime>;
942}
943
944/// The type used to represent the kinds of proxying allowed.
945#[derive(
946	Copy,
947	Clone,
948	Eq,
949	PartialEq,
950	Ord,
951	PartialOrd,
952	Encode,
953	Decode,
954	Debug,
955	MaxEncodedLen,
956	TypeInfo,
957	Serialize,
958	Deserialize,
959	DecodeWithMemTracking,
960)]
961pub enum ProxyType {
962	/// All calls can be proxied. This is the trivial/most permissive filter.
963	Any = 0,
964	/// Only extrinsics that do not transfer funds.
965	NonTransfer = 1,
966	/// Only extrinsics related to governance (democracy and collectives).
967	Governance = 2,
968	/// Only extrinsics related to staking.
969	Staking = 3,
970	/// Allow to veto an announced proxy call.
971	CancelProxy = 4,
972	/// Allow extrinsic related to Balances.
973	Balances = 5,
974	/// Allow extrinsic related to AuthorMapping.
975	AuthorMapping = 6,
976	/// Allow extrinsic related to IdentityJudgement.
977	IdentityJudgement = 7,
978}
979
980impl Default for ProxyType {
981	fn default() -> Self {
982		Self::Any
983	}
984}
985
986fn is_governance_precompile(precompile_name: &precompiles::PrecompileName) -> bool {
987	matches!(
988		precompile_name,
989		PrecompileName::TreasuryCouncilInstance
990			| PrecompileName::ReferendaPrecompile
991			| PrecompileName::ConvictionVotingPrecompile
992			| PrecompileName::PreimagePrecompile
993			| PrecompileName::OpenTechCommitteeInstance,
994	)
995}
996
997// Be careful: Each time this filter is modified, the substrate filter must also be modified
998// consistently.
999impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType {
1000	fn is_evm_proxy_call_allowed(
1001		&self,
1002		call: &pallet_evm_precompile_proxy::EvmSubCall,
1003		recipient_has_code: bool,
1004		gas: u64,
1005	) -> precompile_utils::EvmResult<bool> {
1006		Ok(match self {
1007			ProxyType::Any => {
1008				match PrecompileName::from_address(call.to.0) {
1009					// Any precompile that can execute a subcall should be forbidden here,
1010					// to ensure that unauthorized smart contract can't be called
1011					// indirectly.
1012					// To be safe, we only allow the precompiles we need.
1013					Some(
1014						PrecompileName::AuthorMappingPrecompile
1015						| PrecompileName::ParachainStakingPrecompile,
1016					) => true,
1017					Some(ref precompile) if is_governance_precompile(precompile) => true,
1018					// All non-whitelisted precompiles are forbidden
1019					Some(_) => false,
1020					// Allow evm transfer to "simple" account (no code nor precompile)
1021					// For the moment, no smart contract other than precompiles is allowed.
1022					// In the future, we may create a dynamic whitelist to authorize some audited
1023					// smart contracts through governance.
1024					None => {
1025						// If the address is not recognized, allow only evm transfer to "simple"
1026						// accounts (no code nor precompile).
1027						// Note: Checking the presence of the code is not enough because some
1028						// precompiles have no code.
1029						!recipient_has_code
1030							&& !precompile_utils::precompile_set::is_precompile_or_fail::<Runtime>(
1031								call.to.0, gas,
1032							)?
1033					}
1034				}
1035			}
1036			ProxyType::NonTransfer => {
1037				call.value == U256::zero()
1038					&& match PrecompileName::from_address(call.to.0) {
1039						Some(
1040							PrecompileName::AuthorMappingPrecompile
1041							| PrecompileName::ParachainStakingPrecompile,
1042						) => true,
1043						Some(ref precompile) if is_governance_precompile(precompile) => true,
1044						_ => false,
1045					}
1046			}
1047			ProxyType::Governance => {
1048				call.value == U256::zero()
1049					&& matches!(
1050						PrecompileName::from_address(call.to.0),
1051						Some(ref precompile) if is_governance_precompile(precompile)
1052					)
1053			}
1054			ProxyType::Staking => {
1055				call.value == U256::zero()
1056					&& matches!(
1057						PrecompileName::from_address(call.to.0),
1058						Some(
1059							PrecompileName::AuthorMappingPrecompile
1060								| PrecompileName::ParachainStakingPrecompile
1061						)
1062					)
1063			}
1064			// The proxy precompile does not contain method cancel_proxy
1065			ProxyType::CancelProxy => false,
1066			ProxyType::Balances => {
1067				// Allow only "simple" accounts as recipient (no code nor precompile).
1068				// Note: Checking the presence of the code is not enough because some precompiles
1069				// have no code.
1070				!recipient_has_code
1071					&& !precompile_utils::precompile_set::is_precompile_or_fail::<Runtime>(
1072						call.to.0, gas,
1073					)?
1074			}
1075			ProxyType::AuthorMapping => {
1076				call.value == U256::zero()
1077					&& matches!(
1078						PrecompileName::from_address(call.to.0),
1079						Some(PrecompileName::AuthorMappingPrecompile)
1080					)
1081			}
1082			// There is no identity precompile
1083			ProxyType::IdentityJudgement => false,
1084		})
1085	}
1086}
1087
1088// Be careful: Each time this filter is modified, the EVM filter must also be modified consistently.
1089impl InstanceFilter<RuntimeCall> for ProxyType {
1090	fn filter(&self, c: &RuntimeCall) -> bool {
1091		match self {
1092			ProxyType::Any => true,
1093			ProxyType::NonTransfer => match c {
1094				RuntimeCall::Identity(
1095					pallet_identity::Call::add_sub { .. } | pallet_identity::Call::set_subs { .. },
1096				) => false,
1097				call => {
1098					matches!(
1099						call,
1100						RuntimeCall::System(..)
1101							| RuntimeCall::ParachainSystem(..)
1102							| RuntimeCall::Timestamp(..)
1103							| RuntimeCall::ParachainStaking(..)
1104							| RuntimeCall::Referenda(..)
1105							| RuntimeCall::Preimage(..)
1106							| RuntimeCall::ConvictionVoting(..)
1107							| RuntimeCall::TreasuryCouncilCollective(..)
1108							| RuntimeCall::OpenTechCommitteeCollective(..)
1109							| RuntimeCall::Utility(..)
1110							| RuntimeCall::Proxy(..)
1111							| RuntimeCall::Identity(..)
1112							| RuntimeCall::AuthorMapping(..)
1113							| RuntimeCall::CrowdloanRewards(
1114								pallet_crowdloan_rewards::Call::claim { .. }
1115							)
1116					)
1117				}
1118			},
1119			ProxyType::Governance => matches!(
1120				c,
1121				RuntimeCall::Referenda(..)
1122					| RuntimeCall::Preimage(..)
1123					| RuntimeCall::ConvictionVoting(..)
1124					| RuntimeCall::TreasuryCouncilCollective(..)
1125					| RuntimeCall::OpenTechCommitteeCollective(..)
1126					| RuntimeCall::Utility(..)
1127			),
1128			ProxyType::Staking => matches!(
1129				c,
1130				RuntimeCall::ParachainStaking(..)
1131					| RuntimeCall::Utility(..)
1132					| RuntimeCall::AuthorMapping(..)
1133					| RuntimeCall::MoonbeamOrbiters(..)
1134			),
1135			ProxyType::CancelProxy => matches!(
1136				c,
1137				RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. })
1138			),
1139			ProxyType::Balances => {
1140				matches!(c, RuntimeCall::Balances(..) | RuntimeCall::Utility(..))
1141			}
1142			ProxyType::AuthorMapping => matches!(c, RuntimeCall::AuthorMapping(..)),
1143			ProxyType::IdentityJudgement => matches!(
1144				c,
1145				RuntimeCall::Identity(pallet_identity::Call::provide_judgement { .. })
1146					| RuntimeCall::Utility(..)
1147			),
1148		}
1149	}
1150
1151	fn is_superset(&self, o: &Self) -> bool {
1152		match (self, o) {
1153			(x, y) if x == y => true,
1154			(ProxyType::Any, _) => true,
1155			(_, ProxyType::Any) => false,
1156			_ => false,
1157		}
1158	}
1159}
1160
1161impl pallet_proxy::Config for Runtime {
1162	type RuntimeEvent = RuntimeEvent;
1163	type RuntimeCall = RuntimeCall;
1164	type Currency = Balances;
1165	type ProxyType = ProxyType;
1166	// One storage item; key size 32, value size 8
1167	type ProxyDepositBase = ConstU128<{ currency::deposit(1, 8) }>;
1168	// Additional storage item size of 21 bytes (20 bytes AccountId + 1 byte sizeof(ProxyType)).
1169	type ProxyDepositFactor = ConstU128<{ currency::deposit(0, 21) }>;
1170	type MaxProxies = ConstU32<32>;
1171	type WeightInfo = moonbase_weights::pallet_proxy::WeightInfo<Runtime>;
1172	type MaxPending = ConstU32<32>;
1173	type CallHasher = BlakeTwo256;
1174	type AnnouncementDepositBase = ConstU128<{ currency::deposit(1, 8) }>;
1175	// Additional storage item size of 56 bytes:
1176	// - 20 bytes AccountId
1177	// - 32 bytes Hasher (Blake2256)
1178	// - 4 bytes BlockNumber (u32)
1179	type AnnouncementDepositFactor = ConstU128<{ currency::deposit(0, 56) }>;
1180	type BlockNumberProvider = System;
1181}
1182
1183pub type ForeignAssetMigratorOrigin = EitherOfDiverse<
1184	EnsureRoot<AccountId>,
1185	EitherOfDiverse<
1186		pallet_collective::EnsureProportionMoreThan<AccountId, OpenTechCommitteeInstance, 5, 9>,
1187		EitherOf<
1188			governance::custom_origins::GeneralAdmin,
1189			governance::custom_origins::FastGeneralAdmin,
1190		>,
1191	>,
1192>;
1193
1194impl pallet_moonbeam_lazy_migrations::Config for Runtime {
1195	type WeightInfo = moonbase_weights::pallet_moonbeam_lazy_migrations::WeightInfo<Runtime>;
1196}
1197
1198/// Maintenance mode Call filter
1199pub struct MaintenanceFilter;
1200impl Contains<RuntimeCall> for MaintenanceFilter {
1201	fn contains(c: &RuntimeCall) -> bool {
1202		match c {
1203			RuntimeCall::Balances(_) => false,
1204			RuntimeCall::CrowdloanRewards(_) => false,
1205			RuntimeCall::Ethereum(_) => false,
1206			RuntimeCall::EVM(_) => false,
1207			RuntimeCall::Identity(_) => false,
1208			RuntimeCall::ParachainStaking(_) => false,
1209			RuntimeCall::MoonbeamOrbiters(_) => false,
1210			RuntimeCall::PolkadotXcm(_) => false,
1211			RuntimeCall::Treasury(_) => false,
1212			RuntimeCall::XcmTransactor(_) => false,
1213			RuntimeCall::EthereumXcm(_) => false,
1214			_ => true,
1215		}
1216	}
1217}
1218
1219/// Normal Call Filter
1220pub struct NormalFilter;
1221impl Contains<RuntimeCall> for NormalFilter {
1222	fn contains(c: &RuntimeCall) -> bool {
1223		match c {
1224			RuntimeCall::Proxy(method) => match method {
1225				pallet_proxy::Call::proxy { real, .. } => {
1226					!pallet_evm::AccountCodes::<Runtime>::contains_key(H160::from(*real))
1227				}
1228				_ => true,
1229			},
1230			// Filtering the EVM prevents possible re-entrancy from the precompiles which could
1231			// lead to unexpected scenarios.
1232			// See https://github.com/PureStake/sr-moonbeam/issues/30
1233			// Note: It is also assumed that EVM calls are only allowed through `Origin::Root` so
1234			// this can be seen as an additional security
1235			RuntimeCall::EVM(_) => false,
1236			_ => true,
1237		}
1238	}
1239}
1240
1241pub struct XcmExecutionManager;
1242impl moonkit_xcm_primitives::PauseXcmExecution for XcmExecutionManager {
1243	fn suspend_xcm_execution() -> DispatchResult {
1244		XcmpQueue::suspend_xcm_execution(RuntimeOrigin::root())
1245	}
1246	fn resume_xcm_execution() -> DispatchResult {
1247		XcmpQueue::resume_xcm_execution(RuntimeOrigin::root())
1248	}
1249}
1250
1251impl pallet_maintenance_mode::Config for Runtime {
1252	type NormalCallFilter = NormalFilter;
1253	type MaintenanceCallFilter = MaintenanceFilter;
1254	type MaintenanceOrigin =
1255		pallet_collective::EnsureProportionAtLeast<AccountId, OpenTechCommitteeInstance, 5, 9>;
1256	type XcmExecutionManager = XcmExecutionManager;
1257}
1258
1259impl pallet_proxy_genesis_companion::Config for Runtime {
1260	type ProxyType = ProxyType;
1261	type BlockNumberProvider = System;
1262}
1263
1264parameter_types! {
1265	pub OrbiterReserveIdentifier: [u8; 4] = [b'o', b'r', b'b', b'i'];
1266}
1267
1268type AddCollatorOrigin =
1269	EitherOfDiverse<EnsureRoot<AccountId>, governance::custom_origins::GeneralAdmin>;
1270type DelCollatorOrigin =
1271	EitherOfDiverse<EnsureRoot<AccountId>, governance::custom_origins::GeneralAdmin>;
1272
1273impl pallet_moonbeam_orbiters::Config for Runtime {
1274	type AccountLookup = AuthorMapping;
1275	type AddCollatorOrigin = AddCollatorOrigin;
1276	type Currency = Balances;
1277	type DelCollatorOrigin = DelCollatorOrigin;
1278	/// Maximum number of orbiters per collator
1279	type MaxPoolSize = ConstU32<8>;
1280	/// Maximum number of round to keep on storage
1281	type MaxRoundArchive = ConstU32<4>;
1282	type OrbiterReserveIdentifier = OrbiterReserveIdentifier;
1283	type RotatePeriod = ConstU32<3>;
1284	/// Round index type.
1285	type RoundIndex = pallet_parachain_staking::RoundIndex;
1286	type WeightInfo = moonbase_weights::pallet_moonbeam_orbiters::WeightInfo<Runtime>;
1287}
1288
1289/// Only callable after `set_validation_data` is called which forms this proof the same way
1290fn relay_chain_state_proof<Runtime>() -> RelayChainStateProof
1291where
1292	Runtime: cumulus_pallet_parachain_system::Config,
1293{
1294	let relay_storage_root = ValidationData::<Runtime>::get()
1295		.expect("set in `set_validation_data`")
1296		.relay_parent_storage_root;
1297	let relay_chain_state =
1298		RelayStateProof::<Runtime>::get().expect("set in `set_validation_data`");
1299	RelayChainStateProof::new(ParachainInfo::get(), relay_storage_root, relay_chain_state)
1300		.expect("Invalid relay chain state proof, already constructed in `set_validation_data`")
1301}
1302
1303pub struct BabeDataGetter<Runtime>(sp_std::marker::PhantomData<Runtime>);
1304impl<Runtime> pallet_randomness::GetBabeData<u64, Option<Hash>> for BabeDataGetter<Runtime>
1305where
1306	Runtime: cumulus_pallet_parachain_system::Config,
1307{
1308	// Tolerate panic here because only ever called in inherent (so can be omitted)
1309	fn get_epoch_index() -> u64 {
1310		if cfg!(feature = "runtime-benchmarks") {
1311			// storage reads as per actual reads
1312			let _relay_storage_root = ValidationData::<Runtime>::get();
1313			let _relay_chain_state = RelayStateProof::<Runtime>::get();
1314			const BENCHMARKING_NEW_EPOCH: u64 = 10u64;
1315			return BENCHMARKING_NEW_EPOCH;
1316		}
1317		relay_chain_state_proof::<Runtime>()
1318			.read_optional_entry(relay_chain::well_known_keys::EPOCH_INDEX)
1319			.ok()
1320			.flatten()
1321			.expect("expected to be able to read epoch index from relay chain state proof")
1322	}
1323	fn get_epoch_randomness() -> Option<Hash> {
1324		if cfg!(feature = "runtime-benchmarks") {
1325			// storage reads as per actual reads
1326			let _relay_storage_root = ValidationData::<Runtime>::get();
1327			let _relay_chain_state = RelayStateProof::<Runtime>::get();
1328			let benchmarking_babe_output = Hash::default();
1329			return Some(benchmarking_babe_output);
1330		}
1331		relay_chain_state_proof::<Runtime>()
1332			.read_optional_entry(relay_chain::well_known_keys::ONE_EPOCH_AGO_RANDOMNESS)
1333			.ok()
1334			.flatten()
1335	}
1336}
1337
1338impl pallet_randomness::Config for Runtime {
1339	type AddressMapping = sp_runtime::traits::ConvertInto;
1340	type Currency = Balances;
1341	type BabeDataGetter = BabeDataGetter<Runtime>;
1342	type VrfKeyLookup = AuthorMapping;
1343	type Deposit = runtime_params::PalletRandomnessDepositU128;
1344	type MaxRandomWords = ConstU8<100>;
1345	type MinBlockDelay = ConstU32<2>;
1346	type MaxBlockDelay = ConstU32<2_000>;
1347	type BlockExpirationDelay = ConstU32<10_000>;
1348	type EpochExpirationDelay = ConstU64<10_000>;
1349	type WeightInfo = moonbase_weights::pallet_randomness::WeightInfo<Runtime>;
1350}
1351
1352impl pallet_root_testing::Config for Runtime {
1353	type RuntimeEvent = RuntimeEvent;
1354}
1355
1356parameter_types! {
1357	// One storage item; key size is 32 + 20; value is size 4+4+16+20 bytes = 44 bytes.
1358	pub const DepositBase: Balance = currency::deposit(1, 96);
1359	// Additional storage item size of 20 bytes.
1360	pub const DepositFactor: Balance = currency::deposit(0, 20);
1361	pub const MaxSignatories: u32 = 100;
1362}
1363
1364impl pallet_multisig::Config for Runtime {
1365	type RuntimeEvent = RuntimeEvent;
1366	type RuntimeCall = RuntimeCall;
1367	type Currency = Balances;
1368	type DepositBase = DepositBase;
1369	type DepositFactor = DepositFactor;
1370	type MaxSignatories = MaxSignatories;
1371	type WeightInfo = moonbase_weights::pallet_multisig::WeightInfo<Runtime>;
1372	type BlockNumberProvider = System;
1373}
1374
1375impl pallet_relay_storage_roots::Config for Runtime {
1376	type MaxStorageRoots = ConstU32<30>;
1377	type RelaychainStateProvider = cumulus_pallet_parachain_system::RelaychainDataProvider<Self>;
1378	type WeightInfo = moonbase_weights::pallet_relay_storage_roots::WeightInfo<Runtime>;
1379}
1380
1381#[cfg(feature = "runtime-benchmarks")]
1382impl pallet_precompile_benchmarks::Config for Runtime {
1383	type WeightInfo = moonbase_weights::pallet_precompile_benchmarks::WeightInfo<Runtime>;
1384}
1385
1386impl pallet_parameters::Config for Runtime {
1387	type AdminOrigin = EnsureRoot<AccountId>;
1388	type RuntimeEvent = RuntimeEvent;
1389	type RuntimeParameters = RuntimeParameters;
1390	type WeightInfo = moonbase_weights::pallet_parameters::WeightInfo<Runtime>;
1391}
1392
1393impl cumulus_pallet_weight_reclaim::Config for Runtime {
1394	type WeightInfo = moonbase_weights::cumulus_pallet_weight_reclaim::WeightInfo<Runtime>;
1395}
1396
1397impl pallet_migrations::Config for Runtime {
1398	type RuntimeEvent = RuntimeEvent;
1399	#[cfg(not(feature = "runtime-benchmarks"))]
1400	type Migrations = migrations::MultiBlockMigrationList<Runtime>;
1401	#[cfg(feature = "runtime-benchmarks")]
1402	type Migrations = pallet_migrations::mock_helpers::MockedMigrations;
1403	type CursorMaxLen = ConstU32<65_536>;
1404	type IdentifierMaxLen = ConstU32<256>;
1405	type MigrationStatusHandler = ();
1406	type FailedMigrationHandler = MaintenanceMode;
1407	type MaxServiceWeight = MaxServiceWeight;
1408	type WeightInfo = weights::pallet_migrations::WeightInfo<Runtime>;
1409}
1410
1411construct_runtime! {
1412	pub enum Runtime
1413	{
1414		System: frame_system::{Pallet, Call, Storage, Config<T>, Event<T>} = 0,
1415		Utility: pallet_utility::{Pallet, Call, Event} = 1,
1416		Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 2,
1417		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 3,
1418		Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>} = 4,
1419		// Previously 5: pallet_randomness_collective_flip
1420		ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event<T>} = 6,
1421		TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Config<T>, Event<T>} = 7,
1422		ParachainInfo: parachain_info::{Pallet, Storage, Config<T>} = 8,
1423		EthereumChainId: pallet_evm_chain_id::{Pallet, Storage, Config<T>} = 9,
1424		EVM: pallet_evm::{Pallet, Config<T>, Call, Storage, Event<T>} = 10,
1425		Ethereum: pallet_ethereum::{Pallet, Call, Storage, Event, Origin, Config<T>} = 11,
1426		ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Event<T>, Config<T>, FreezeReason} = 12,
1427		Scheduler: pallet_scheduler::{Pallet, Storage, Event<T>, Call} = 13,
1428		// Previously 14: pallet_democracy::{Pallet, Storage, Config<T>, Event<T>, Call} = 14,
1429		// Previously 15: CouncilCollective: pallet_collective::<Instance1>
1430		// Previously 16: TechCommitteeCollective: pallet_collective::<Instance2>
1431		Treasury: pallet_treasury::{Pallet, Storage, Config<T>, Event<T>, Call} = 17,
1432		AuthorInherent: pallet_author_inherent::{Pallet, Call, Storage, Inherent} = 18,
1433		AuthorFilter: pallet_author_slot_filter::{Pallet, Call, Storage, Event, Config<T>} = 19,
1434		CrowdloanRewards: pallet_crowdloan_rewards::{Pallet, Call, Config<T>, Storage, Event<T>} = 20,
1435		AuthorMapping: pallet_author_mapping::{Pallet, Call, Config<T>, Storage, Event<T>} = 21,
1436		Proxy: pallet_proxy::{Pallet, Call, Storage, Event<T>} = 22,
1437		MaintenanceMode: pallet_maintenance_mode::{Pallet, Call, Config<T>, Storage, Event} = 23,
1438		Identity: pallet_identity::{Pallet, Call, Storage, Event<T>} = 24,
1439		XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 25,
1440		CumulusXcm: cumulus_pallet_xcm::{Pallet, Event<T>, Origin} = 26,
1441		// Previously 27: DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>},
1442		PolkadotXcm: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin, Config<T>} = 28,
1443		// [Removed] Assets: pallet_assets::{Pallet, Call, Storage, Event<T>} = 29,
1444		// Previously 30: XTokens
1445		// Previously 31: AssetManager: pallet_asset_manager::{Pallet, Call, Storage, Event<T>}
1446		// [Removed] Migrations: pallet_migrations::{Pallet, Storage, Config<T>, Event<T>} = 32,
1447		XcmTransactor: pallet_xcm_transactor::{Pallet, Call, Config<T>, Storage, Event<T>} = 33,
1448		ProxyGenesisCompanion: pallet_proxy_genesis_companion::{Pallet, Config<T>} = 34,
1449		// Previously 35: BaseFee
1450		// Previously 36: pallet_assets::<Instance1>
1451		MoonbeamOrbiters: pallet_moonbeam_orbiters::{Pallet, Call, Storage, Event<T>, Config<T>} = 37,
1452		EthereumXcm: pallet_ethereum_xcm::{Pallet, Call, Storage, Origin, Event<T>} = 38,
1453		Randomness: pallet_randomness::{Pallet, Call, Storage, Event<T>, Inherent} = 39,
1454		TreasuryCouncilCollective:
1455			pallet_collective::<Instance3>::{Pallet, Call, Storage, Event<T>, Origin<T>, Config<T>} = 40,
1456		ConvictionVoting: pallet_conviction_voting::{Pallet, Call, Storage, Event<T>} = 41,
1457		Referenda: pallet_referenda::{Pallet, Call, Storage, Event<T>} = 42,
1458		Origins: governance::custom_origins::{Origin} = 43,
1459		Preimage: pallet_preimage::{Pallet, Call, Storage, Event<T>, HoldReason} = 44,
1460		Whitelist: pallet_whitelist::{Pallet, Call, Storage, Event<T>} = 45,
1461		OpenTechCommitteeCollective:
1462			pallet_collective::<Instance4>::{Pallet, Call, Storage, Event<T>, Origin<T>, Config<T>} = 46,
1463		RootTesting: pallet_root_testing::{Pallet, Call, Storage, Event<T>} = 47,
1464		Erc20XcmBridge: pallet_erc20_xcm_bridge::{Pallet} = 48,
1465		Multisig: pallet_multisig::{Pallet, Call, Storage, Event<T>} = 49,
1466		AsyncBacking: pallet_async_backing::{Pallet, Storage} = 50,
1467		MoonbeamLazyMigrations: pallet_moonbeam_lazy_migrations::{Pallet, Call, Storage} = 51,
1468		RelayStorageRoots: pallet_relay_storage_roots::{Pallet, Storage} = 52,
1469
1470		#[cfg(feature = "runtime-benchmarks")]
1471		PrecompileBenchmarks: pallet_precompile_benchmarks::{Pallet} = 53,
1472
1473		MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>} = 54,
1474		EmergencyParaXcm: pallet_emergency_para_xcm::{Pallet, Call, Storage, Event} = 55,
1475		EvmForeignAssets: pallet_moonbeam_foreign_assets::{Pallet, Call, Storage, Event<T>} = 56,
1476		Parameters: pallet_parameters = 57,
1477		XcmWeightTrader: pallet_xcm_weight_trader::{Pallet, Call, Storage, Event<T>} = 58,
1478		MultiBlockMigrations: pallet_migrations = 117,
1479		WeightReclaim: cumulus_pallet_weight_reclaim = 118,
1480	}
1481}
1482
1483/// Block type as expected by this runtime.
1484pub type Block = generic::Block<Header, UncheckedExtrinsic>;
1485/// A Block signed with a Justification
1486pub type SignedBlock = generic::SignedBlock<Block>;
1487/// BlockId type as expected by this runtime.
1488pub type BlockId = generic::BlockId<Block>;
1489
1490/// The TransactionExtension to the basic transaction logic.
1491pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
1492	Runtime,
1493	(
1494		frame_system::CheckNonZeroSender<Runtime>,
1495		frame_system::CheckSpecVersion<Runtime>,
1496		frame_system::CheckTxVersion<Runtime>,
1497		frame_system::CheckGenesis<Runtime>,
1498		frame_system::CheckEra<Runtime>,
1499		frame_system::CheckNonce<Runtime>,
1500		frame_system::CheckWeight<Runtime>,
1501		pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
1502		frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
1503	),
1504>;
1505
1506/// Unchecked extrinsic type as expected by this runtime.
1507pub type UncheckedExtrinsic =
1508	fp_self_contained::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
1509/// Extrinsic type that has already been checked.
1510pub type CheckedExtrinsic =
1511	fp_self_contained::CheckedExtrinsic<AccountId, RuntimeCall, TxExtension, H160>;
1512/// Executive: handles dispatch to the various pallets.
1513pub type Executive = frame_executive::Executive<
1514	Runtime,
1515	Block,
1516	frame_system::ChainContext<Runtime>,
1517	Runtime,
1518	AllPalletsWithSystem,
1519>;
1520
1521#[cfg(feature = "runtime-benchmarks")]
1522use moonbeam_runtime_common::benchmarking::BenchmarkHelper;
1523use moonbeam_runtime_common::deal_with_fees::{
1524	DealWithEthereumBaseFees, DealWithEthereumPriorityFees, DealWithSubstrateFeesAndTip,
1525};
1526
1527#[cfg(feature = "runtime-benchmarks")]
1528mod benches {
1529	frame_support::parameter_types! {
1530		pub const MaxBalance: crate::Balance = crate::Balance::max_value();
1531	}
1532
1533	frame_benchmarking::define_benchmarks!(
1534		[frame_system, SystemBench::<Runtime>]
1535		[frame_system_extensions, frame_system_benchmarking::extensions::Pallet::<Runtime>]
1536		[pallet_utility, Utility]
1537		[pallet_timestamp, Timestamp]
1538		[pallet_balances, Balances]
1539		[pallet_sudo, Sudo]
1540		[pallet_evm, EVM]
1541		[pallet_parachain_staking, ParachainStaking]
1542		[pallet_scheduler, Scheduler]
1543		[pallet_treasury, Treasury]
1544		[pallet_author_inherent, AuthorInherent]
1545		[pallet_author_slot_filter, AuthorFilter]
1546		[pallet_crowdloan_rewards, CrowdloanRewards]
1547		[pallet_author_mapping, AuthorMapping]
1548		[pallet_proxy, Proxy]
1549		[pallet_transaction_payment, TransactionPaymentBenchmark::<Runtime>]
1550		[pallet_identity, Identity]
1551		[cumulus_pallet_parachain_system, ParachainSystem]
1552		[cumulus_pallet_xcmp_queue, XcmpQueue]
1553		[pallet_message_queue, MessageQueue]
1554		[pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
1555		[pallet_xcm_transactor, XcmTransactor]
1556		[pallet_moonbeam_foreign_assets, EvmForeignAssets]
1557		[pallet_moonbeam_orbiters, MoonbeamOrbiters]
1558		[pallet_randomness, Randomness]
1559		[pallet_conviction_voting, ConvictionVoting]
1560		[pallet_referenda, Referenda]
1561		[pallet_preimage, Preimage]
1562		[pallet_whitelist, Whitelist]
1563		[pallet_multisig, Multisig]
1564		[pallet_migrations, MultiBlockMigrations]
1565		// Currently there are no extrinsics to benchmark for the Lazy Migrations pallet
1566		// [pallet_moonbeam_lazy_migrations, MoonbeamLazyMigrations]
1567		[pallet_relay_storage_roots, RelayStorageRoots]
1568		[pallet_precompile_benchmarks, PrecompileBenchmarks]
1569		[pallet_parameters, Parameters]
1570		[pallet_xcm_weight_trader, XcmWeightTrader]
1571		[pallet_collective, TreasuryCouncilCollective]
1572		[pallet_collective, OpenTechCommitteeCollective]
1573		[cumulus_pallet_weight_reclaim, WeightReclaim]
1574	);
1575}
1576
1577// All of our runtimes share most of their Runtime API implementations.
1578// We use a macro to implement this common part and add runtime-specific additional implementations.
1579// This macro expands to :
1580// ```
1581// impl_runtime_apis! {
1582//     // All impl blocks shared between all runtimes.
1583//
1584//     // Specific impls provided to the `impl_runtime_apis_plus_common!` macro.
1585// }
1586// ```
1587moonbeam_runtime_common::impl_runtime_apis_plus_common!(
1588	{
1589		impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
1590			fn validate_transaction(
1591				source: TransactionSource,
1592				xt: <Block as BlockT>::Extrinsic,
1593				block_hash: <Block as BlockT>::Hash,
1594			) -> TransactionValidity {
1595				// Filtered calls should not enter the tx pool as they'll fail if inserted.
1596				// If this call is not allowed, we return early.
1597				if !<Runtime as frame_system::Config>::BaseCallFilter::contains(&xt.0.function) {
1598					return InvalidTransaction::Call.into();
1599				}
1600
1601				// This runtime uses Substrate's pallet transaction payment. This
1602				// makes the chain feel like a standard Substrate chain when submitting
1603				// frame transactions and using Substrate ecosystem tools. It has the downside that
1604				// transaction are not prioritized by gas_price. The following code reprioritizes
1605				// transactions to overcome this.
1606				//
1607				// A more elegant, ethereum-first solution is
1608				// a pallet that replaces pallet transaction payment, and allows users
1609				// to directly specify a gas price rather than computing an effective one.
1610				// #HopefullySomeday
1611
1612				// First we pass the transactions to the standard FRAME executive. This calculates all the
1613				// necessary tags, longevity and other properties that we will leave unchanged.
1614				// This also assigns some priority that we don't care about and will overwrite next.
1615				let mut intermediate_valid = Executive::validate_transaction(source, xt.clone(), block_hash)?;
1616
1617				let dispatch_info = xt.get_dispatch_info();
1618
1619				// If this is a pallet ethereum transaction, then its priority is already set
1620				// according to effective priority fee from pallet ethereum. If it is any other kind of
1621				// transaction, we modify its priority. The goal is to arrive at a similar metric used
1622				// by pallet ethereum, which means we derive a fee-per-gas from the txn's tip and
1623				// weight.
1624				Ok(match &xt.0.function {
1625					RuntimeCall::Ethereum(transact { .. }) => intermediate_valid,
1626					_ if dispatch_info.class != DispatchClass::Normal => intermediate_valid,
1627					_ => {
1628						let tip = match &xt.0.preamble {
1629							Preamble::Bare(_) => 0,
1630							Preamble::Signed(_, _, signed_extra) => {
1631								// Yuck, this depends on the index of ChargeTransactionPayment in TxExtension
1632								let charge_transaction_payment = &signed_extra.0.7;
1633								charge_transaction_payment.tip()
1634							},
1635							Preamble::General(_, _) => 0,
1636						};
1637
1638						let effective_gas =
1639							<Runtime as pallet_evm::Config>::GasWeightMapping::weight_to_gas(
1640								dispatch_info.total_weight()
1641							);
1642						let tip_per_gas = if effective_gas > 0 {
1643							tip.saturating_div(effective_gas as u128)
1644						} else {
1645							0
1646						};
1647
1648						// Overwrite the original prioritization with this ethereum one
1649						intermediate_valid.priority = tip_per_gas as u64;
1650						intermediate_valid
1651					}
1652				})
1653			}
1654		}
1655
1656		impl async_backing_primitives::UnincludedSegmentApi<Block> for Runtime {
1657			fn can_build_upon(
1658				included_hash: <Block as BlockT>::Hash,
1659				slot: async_backing_primitives::Slot,
1660			) -> bool {
1661				ConsensusHook::can_build_upon(included_hash, slot)
1662			}
1663		}
1664
1665	}
1666
1667	// Benchmark customizations
1668	{}
1669);
1670
1671// Nimbus's Executive wrapper allows relay validators to verify the seal digest
1672cumulus_pallet_parachain_system::register_validate_block!(
1673	Runtime = Runtime,
1674	BlockExecutor = pallet_author_inherent::BlockExecutor::<Runtime, Executive>,
1675);
1676
1677moonbeam_runtime_common::impl_self_contained_call!();
1678
1679// Shorthand for a Get field of a pallet Config.
1680#[macro_export]
1681macro_rules! get {
1682	($pallet:ident, $name:ident, $type:ty) => {
1683		<<$crate::Runtime as $pallet::Config>::$name as $crate::Get<$type>>::get()
1684	};
1685}
1686
1687#[cfg(test)]
1688mod tests {
1689	use super::{currency::*, *};
1690
1691	#[test]
1692	// Helps us to identify a Pallet Call in case it exceeds the 1kb limit.
1693	// Hint: this should be a rare case. If that happens, one or more of the dispatchable arguments
1694	// need to be Boxed.
1695	fn call_max_size() {
1696		const CALL_ALIGN: u32 = 1024;
1697		assert!(std::mem::size_of::<pallet_evm_chain_id::Call<Runtime>>() <= CALL_ALIGN as usize);
1698		assert!(std::mem::size_of::<pallet_evm::Call<Runtime>>() <= CALL_ALIGN as usize);
1699		assert!(std::mem::size_of::<pallet_ethereum::Call<Runtime>>() <= CALL_ALIGN as usize);
1700		assert!(
1701			std::mem::size_of::<pallet_parachain_staking::Call<Runtime>>() <= CALL_ALIGN as usize
1702		);
1703		assert!(
1704			std::mem::size_of::<pallet_author_inherent::Call<Runtime>>() <= CALL_ALIGN as usize
1705		);
1706		assert!(
1707			std::mem::size_of::<pallet_author_slot_filter::Call<Runtime>>() <= CALL_ALIGN as usize
1708		);
1709		assert!(
1710			std::mem::size_of::<pallet_crowdloan_rewards::Call<Runtime>>() <= CALL_ALIGN as usize
1711		);
1712		assert!(std::mem::size_of::<pallet_author_mapping::Call<Runtime>>() <= CALL_ALIGN as usize);
1713		assert!(
1714			std::mem::size_of::<pallet_maintenance_mode::Call<Runtime>>() <= CALL_ALIGN as usize
1715		);
1716		assert!(std::mem::size_of::<pallet_migrations::Call<Runtime>>() <= CALL_ALIGN as usize);
1717		assert!(
1718			std::mem::size_of::<pallet_moonbeam_lazy_migrations::Call<Runtime>>()
1719				<= CALL_ALIGN as usize
1720		);
1721		assert!(std::mem::size_of::<pallet_xcm_transactor::Call<Runtime>>() <= CALL_ALIGN as usize);
1722		assert!(
1723			std::mem::size_of::<pallet_proxy_genesis_companion::Call<Runtime>>()
1724				<= CALL_ALIGN as usize
1725		);
1726	}
1727
1728	#[test]
1729	fn currency_constants_are_correct() {
1730		assert_eq!(SUPPLY_FACTOR, 1);
1731
1732		// txn fees
1733		assert_eq!(TRANSACTION_BYTE_FEE, Balance::from(1 * GIGAWEI));
1734		assert_eq!(
1735			get!(pallet_transaction_payment, OperationalFeeMultiplier, u8),
1736			5_u8
1737		);
1738		assert_eq!(STORAGE_BYTE_FEE, Balance::from(100 * MICROUNIT));
1739
1740		// pallet_identity deposits
1741		assert_eq!(
1742			get!(pallet_identity, BasicDeposit, u128),
1743			Balance::from(1 * UNIT + 25800 * MICROUNIT)
1744		);
1745		assert_eq!(
1746			get!(pallet_identity, ByteDeposit, u128),
1747			Balance::from(100 * MICROUNIT)
1748		);
1749		assert_eq!(
1750			get!(pallet_identity, SubAccountDeposit, u128),
1751			Balance::from(1 * UNIT + 5300 * MICROUNIT)
1752		);
1753
1754		// staking minimums
1755		assert_eq!(
1756			get!(pallet_parachain_staking, MinCandidateStk, u128),
1757			Balance::from(500 * UNIT)
1758		);
1759		assert_eq!(
1760			get!(pallet_parachain_staking, MinDelegation, u128),
1761			Balance::from(1 * UNIT)
1762		);
1763
1764		// crowdloan min reward
1765		assert_eq!(
1766			get!(pallet_crowdloan_rewards, MinimumReward, u128),
1767			Balance::from(0u128)
1768		);
1769
1770		// deposit for AuthorMapping
1771		assert_eq!(
1772			get!(pallet_author_mapping, DepositAmount, u128),
1773			Balance::from(100 * UNIT)
1774		);
1775
1776		// proxy deposits
1777		assert_eq!(
1778			get!(pallet_proxy, ProxyDepositBase, u128),
1779			Balance::from(1 * UNIT + 800 * MICROUNIT)
1780		);
1781		assert_eq!(
1782			get!(pallet_proxy, ProxyDepositFactor, u128),
1783			Balance::from(2100 * MICROUNIT)
1784		);
1785		assert_eq!(
1786			get!(pallet_proxy, AnnouncementDepositBase, u128),
1787			Balance::from(1 * UNIT + 800 * MICROUNIT)
1788		);
1789		assert_eq!(
1790			get!(pallet_proxy, AnnouncementDepositFactor, u128),
1791			Balance::from(5600 * MICROUNIT)
1792		);
1793	}
1794
1795	#[test]
1796	fn max_offline_rounds_lower_or_eq_than_reward_payment_delay() {
1797		assert!(
1798			get!(pallet_parachain_staking, MaxOfflineRounds, u32)
1799				<= get!(pallet_parachain_staking, RewardPaymentDelay, u32)
1800		);
1801	}
1802
1803	#[test]
1804	// Required migration is
1805	// pallet_parachain_staking::migrations::IncreaseMaxTopDelegationsPerCandidate
1806	// Purpose of this test is to remind of required migration if constant is ever changed
1807	fn updating_maximum_delegators_per_candidate_requires_configuring_required_migration() {
1808		assert_eq!(
1809			get!(pallet_parachain_staking, MaxTopDelegationsPerCandidate, u32),
1810			300
1811		);
1812		assert_eq!(
1813			get!(
1814				pallet_parachain_staking,
1815				MaxBottomDelegationsPerCandidate,
1816				u32
1817			),
1818			50
1819		);
1820	}
1821
1822	#[test]
1823	fn test_proxy_type_can_be_decoded_from_valid_values() {
1824		let test_cases = vec![
1825			// (input, expected)
1826			(0u8, ProxyType::Any),
1827			(1, ProxyType::NonTransfer),
1828			(2, ProxyType::Governance),
1829			(3, ProxyType::Staking),
1830			(4, ProxyType::CancelProxy),
1831			(5, ProxyType::Balances),
1832			(6, ProxyType::AuthorMapping),
1833			(7, ProxyType::IdentityJudgement),
1834		];
1835
1836		for (input, expected) in test_cases {
1837			let actual = ProxyType::decode(&mut input.to_le_bytes().as_slice());
1838			assert_eq!(
1839				Ok(expected),
1840				actual,
1841				"failed decoding ProxyType for value '{}'",
1842				input
1843			);
1844		}
1845	}
1846
1847	#[test]
1848	fn configured_base_extrinsic_weight_is_evm_compatible() {
1849		let min_ethereum_transaction_weight = WeightPerGas::get() * 21_000;
1850		let base_extrinsic = <Runtime as frame_system::Config>::BlockWeights::get()
1851			.get(frame_support::dispatch::DispatchClass::Normal)
1852			.base_extrinsic;
1853		assert!(base_extrinsic.ref_time() <= min_ethereum_transaction_weight.ref_time());
1854	}
1855
1856	#[test]
1857	fn test_storage_growth_ratio_is_correct() {
1858		let expected_storage_growth_ratio = BlockGasLimit::get()
1859			.low_u64()
1860			.saturating_div(BLOCK_STORAGE_LIMIT);
1861		let actual_storage_growth_ratio =
1862			<Runtime as pallet_evm::Config>::GasLimitStorageGrowthRatio::get();
1863		assert_eq!(
1864			expected_storage_growth_ratio, actual_storage_growth_ratio,
1865			"Storage growth ratio is not correct"
1866		);
1867	}
1868}