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