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