shiden_runtime/
lib.rs

1// This file is part of Astar.
2
3// Copyright (C) Stake Technologies Pte.Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later
5
6// Astar is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// Astar is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with Astar. If not, see <http://www.gnu.org/licenses/>.
18
19//! The Shiden Network runtime. This can be compiled with ``#[no_std]`, ready for Wasm.
20
21#![cfg_attr(not(feature = "std"), no_std)]
22// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
23#![recursion_limit = "256"]
24
25extern crate alloc;
26extern crate core;
27
28#[cfg(feature = "runtime-benchmarks")]
29#[macro_use]
30extern crate frame_benchmarking;
31use alloc::{borrow::Cow, collections::btree_map::BTreeMap, vec, vec::Vec};
32use core::marker::PhantomData;
33
34use cumulus_primitives_core::AggregateMessageOrigin;
35use ethereum::AuthorizationList;
36use frame_support::{
37    dispatch::DispatchClass,
38    genesis_builder_helper, parameter_types,
39    traits::{
40        fungible::{Balanced, Credit},
41        AsEnsureOriginWithArg, ConstBool, ConstU32, ConstU64, ConstU8, Contains, FindAuthor, Get,
42        Imbalance, InstanceFilter, OnFinalize, OnUnbalanced, WithdrawReasons,
43    },
44    weights::{
45        constants::{RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND},
46        ConstantMultiplier, Weight, WeightToFee as WeightToFeeT, WeightToFeeCoefficient,
47        WeightToFeeCoefficients, WeightToFeePolynomial,
48    },
49    ConsensusEngineId, PalletId,
50};
51use frame_system::{
52    limits::{BlockLength, BlockWeights},
53    EnsureRoot, EnsureSigned,
54};
55use pallet_ethereum::PostLogContent;
56use pallet_evm::{FeeCalculator, GasWeightMapping, Runner};
57use pallet_identity::legacy::IdentityInfo;
58use pallet_transaction_payment::{
59    FeeDetails, Multiplier, RuntimeDispatchInfo, TargetedFeeAdjustment,
60};
61use parity_scale_codec::{Compact, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
62use polkadot_runtime_common::BlockHashCount;
63use sp_api::impl_runtime_apis;
64use sp_core::{sr25519, OpaqueMetadata, H160, H256, U256};
65use sp_inherents::{CheckInherentsResult, InherentData};
66use sp_runtime::{
67    generic, impl_opaque_keys,
68    traits::{
69        AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto,
70        DispatchInfoOf, Dispatchable, OpaqueKeys, PostDispatchInfoOf, UniqueSaturatedInto,
71    },
72    transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError},
73    ApplyExtrinsicResult, FixedPointNumber, Perbill, Permill, Perquintill, RuntimeDebug,
74};
75use xcm::{
76    v5::{AssetId as XcmAssetId, Location as XcmLocation},
77    IntoVersion, Version as XcmVersion, VersionedAsset, VersionedAssetId, VersionedAssets,
78    VersionedLocation, VersionedXcm,
79};
80use xcm_runtime_apis::{
81    dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects},
82    fees::Error as XcmPaymentApiError,
83};
84
85use astar_primitives::{
86    dapp_staking::{
87        AccountCheck as DappStakingAccountCheck, CycleConfiguration, DAppId, EraNumber,
88        PeriodNumber, RankedTier, SmartContract, FIXED_NUMBER_OF_TIER_SLOTS,
89    },
90    evm::{EVMFungibleAdapterWrapper, EvmRevertCodeHandler, TX_MAX_GAS_LIMIT},
91    xcm::AssetLocationIdConverter,
92    Address, AssetId, BlockNumber, Hash, Header, Nonce, UnfreezeChainOnFailedMigration,
93};
94pub use astar_primitives::{AccountId, Balance, Signature};
95
96pub use pallet_dapp_staking::TierThreshold;
97pub use pallet_inflation::InflationParameters;
98
99pub use crate::precompiles::WhitelistedCalls;
100use pallet_evm_precompile_assets_erc20::AddressToAssetId;
101
102#[cfg(any(feature = "std", test))]
103use sp_version::NativeVersion;
104use sp_version::RuntimeVersion;
105
106pub use frame_system::Call as SystemCall;
107pub use pallet_balances::Call as BalancesCall;
108use parachains_common::message_queue::NarrowOriginToSibling;
109pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
110#[cfg(any(feature = "std", test))]
111pub use sp_runtime::BuildStorage;
112
113pub mod genesis_config;
114mod precompiles;
115pub mod xcm_config;
116
117mod weights;
118use weights::{BlockExecutionWeight, ExtrinsicBaseWeight};
119
120pub type ShidenAssetLocationIdConverter = AssetLocationIdConverter<AssetId, XcAssetConfig>;
121
122pub use precompiles::{ShidenPrecompiles, ASSET_PRECOMPILE_ADDRESS_PREFIX};
123pub type Precompiles = ShidenPrecompiles<Runtime, ShidenAssetLocationIdConverter>;
124
125/// Constant values used within the runtime.
126pub const NANOSDN: Balance = 1_000_000_000;
127pub const MICROSDN: Balance = 1_000 * NANOSDN;
128pub const MILLISDN: Balance = 1_000 * MICROSDN;
129pub const SDN: Balance = 1_000 * MILLISDN;
130
131pub const STORAGE_BYTE_FEE: Balance = 200 * NANOSDN;
132
133/// Charge fee for stored bytes and items.
134pub const fn deposit(items: u32, bytes: u32) -> Balance {
135    items as Balance * MILLISDN + (bytes as Balance) * STORAGE_BYTE_FEE
136}
137
138/// Change this to adjust the block time.
139pub const MILLISECS_PER_BLOCK: u64 = 6000;
140pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
141
142// Time is measured by number of blocks.
143pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
144pub const HOURS: BlockNumber = MINUTES * 60;
145pub const DAYS: BlockNumber = HOURS * 24;
146
147/// Maximum number of blocks simultaneously accepted by the Runtime, not yet included into the
148/// relay chain.
149pub const UNINCLUDED_SEGMENT_CAPACITY: u32 =
150    (2 + RELAY_PARENT_OFFSET) * BLOCK_PROCESSING_VELOCITY + 1;
151/// How many parachain blocks are processed by the relay chain per parent. Limits the number of
152/// blocks authored per slot.
153pub const BLOCK_PROCESSING_VELOCITY: u32 = 1;
154/// Relay chain slot duration, in milliseconds.
155pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000;
156/// Relay chain best block offset to build blocks on.
157const RELAY_PARENT_OFFSET: u32 = 0;
158
159// Make the WASM binary available.
160#[cfg(feature = "std")]
161include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
162
163#[cfg(feature = "std")]
164/// Wasm binary unwrapped. If built with `BUILD_DUMMY_WASM_BINARY`, the function panics.
165pub fn wasm_binary_unwrap() -> &'static [u8] {
166    WASM_BINARY.expect(
167        "Development wasm binary is not available. This means the client is \
168                        built with `BUILD_DUMMY_WASM_BINARY` flag and it is only usable for \
169                        production chains. Please rebuild with the flag disabled.",
170    )
171}
172
173/// Runtime version.
174#[sp_version::runtime_version]
175pub const VERSION: RuntimeVersion = RuntimeVersion {
176    spec_name: Cow::Borrowed("shiden"),
177    impl_name: Cow::Borrowed("shiden"),
178    authoring_version: 1,
179    spec_version: 2400,
180    impl_version: 0,
181    apis: RUNTIME_API_VERSIONS,
182    transaction_version: 3,
183    system_version: 1,
184};
185
186/// Native version.
187#[cfg(any(feature = "std", test))]
188pub fn native_version() -> NativeVersion {
189    NativeVersion {
190        runtime_version: VERSION,
191        can_author_with: Default::default(),
192    }
193}
194
195impl_opaque_keys! {
196    pub struct SessionKeys {
197        pub aura: Aura,
198    }
199}
200
201/// We assume that ~10% of the block weight is consumed by `on_initalize` handlers.
202/// This is used to limit the maximal weight of a single extrinsic.
203const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
204/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used
205/// by  Operational  extrinsics.
206const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
207/// We allow for 2 seconds of compute with a 6 second average block time.
208const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(
209    WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2),
210    polkadot_primitives::MAX_POV_SIZE as u64,
211);
212
213parameter_types! {
214    pub const Version: RuntimeVersion = VERSION;
215    pub RuntimeBlockLength: BlockLength =
216        BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
217    pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
218        .base_block(BlockExecutionWeight::get())
219        .for_class(DispatchClass::all(), |weights| {
220            weights.base_extrinsic = ExtrinsicBaseWeight::get();
221        })
222        .for_class(DispatchClass::Normal, |weights| {
223            weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
224        })
225        .for_class(DispatchClass::Operational, |weights| {
226            weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
227            // Operational transactions have some extra reserved space, so that they
228            // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
229            weights.reserved = Some(
230                MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
231            );
232        })
233        .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
234        .build_or_panic();
235    pub SS58Prefix: u8 = 5;
236}
237
238pub struct BaseFilter;
239impl Contains<RuntimeCall> for BaseFilter {
240    fn contains(call: &RuntimeCall) -> bool {
241        match call {
242            // Filter permission-less assets creation/destroying.
243            // Custom asset's `id` should fit in `u32` as not to mix with service assets.
244            RuntimeCall::Assets(method) => match method {
245                pallet_assets::Call::create { id, .. } => *id < (u32::MAX as AssetId).into(),
246
247                _ => true,
248            },
249            // These modules are not allowed to be called by transactions:
250            // To leave collator just shutdown it, next session funds will be released
251            // Other modules should works:
252            _ => true,
253        }
254    }
255}
256
257impl frame_system::Config for Runtime {
258    /// The identifier used to distinguish between accounts.
259    type AccountId = AccountId;
260    /// The aggregated dispatch type that is available for extrinsics.
261    type RuntimeCall = RuntimeCall;
262    /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
263    type Lookup = AccountIdLookup<AccountId, ()>;
264    /// The nonce type for storing how many extrinsics an account has signed.
265    type Nonce = Nonce;
266    /// The type for blocks.
267    type Block = Block;
268    /// The type for hashing blocks and tries.
269    type Hash = Hash;
270    /// The hashing algorithm used.
271    type Hashing = BlakeTwo256;
272    /// The ubiquitous event type.
273    type RuntimeEvent = RuntimeEvent;
274    /// The ubiquitous origin type.
275    type RuntimeOrigin = RuntimeOrigin;
276    /// The aggregated RuntimeTask type.
277    type RuntimeTask = RuntimeTask;
278    /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
279    type BlockHashCount = BlockHashCount;
280    /// Runtime version.
281    type Version = Version;
282    /// Converts a module to an index of this module in the runtime.
283    type PalletInfo = PalletInfo;
284    type AccountData = pallet_balances::AccountData<Balance>;
285    type OnNewAccount = ();
286    type OnKilledAccount = ();
287    type DbWeight = RocksDbWeight;
288    type BaseCallFilter = BaseFilter;
289    type SystemWeightInfo = frame_system::weights::SubstrateWeight<Runtime>;
290    type BlockWeights = RuntimeBlockWeights;
291    type BlockLength = RuntimeBlockLength;
292    type SS58Prefix = SS58Prefix;
293    type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
294    type MaxConsumers = frame_support::traits::ConstU32<16>;
295    type SingleBlockMigrations = ();
296    type MultiBlockMigrator = MultiBlockMigrations;
297    type PreInherents = ();
298    type PostInherents = ();
299    type PostTransactions = ();
300    type ExtensionsWeightInfo = weights::frame_system_extensions::SubstrateWeight<Runtime>;
301}
302
303impl pallet_timestamp::Config for Runtime {
304    type Moment = u64;
305    type OnTimestampSet = Aura;
306    type MinimumPeriod = ConstU64<0>;
307    type WeightInfo = pallet_timestamp::weights::SubstrateWeight<Runtime>;
308}
309
310parameter_types! {
311    pub MessageQueueServiceWeight: Weight =
312        Perbill::from_percent(25) * RuntimeBlockWeights::get().max_block;
313}
314
315impl pallet_message_queue::Config for Runtime {
316    type RuntimeEvent = RuntimeEvent;
317    type WeightInfo = pallet_message_queue::weights::SubstrateWeight<Runtime>;
318    #[cfg(feature = "runtime-benchmarks")]
319    type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor<
320        cumulus_primitives_core::AggregateMessageOrigin,
321    >;
322    #[cfg(not(feature = "runtime-benchmarks"))]
323    type MessageProcessor = xcm_builder::ProcessXcmMessage<
324        AggregateMessageOrigin,
325        xcm_executor::XcmExecutor<xcm_config::XcmConfig>,
326        RuntimeCall,
327    >;
328    type Size = u32;
329    type QueueChangeHandler = NarrowOriginToSibling<XcmpQueue>;
330    type QueuePausedQuery = NarrowOriginToSibling<XcmpQueue>;
331    type HeapSize = ConstU32<{ 128 * 1048 }>;
332    type MaxStale = ConstU32<8>;
333    type ServiceWeight = MessageQueueServiceWeight;
334    type IdleMaxServiceWeight = MessageQueueServiceWeight;
335}
336
337parameter_types! {
338    pub const BasicDeposit: Balance = deposit(1, 258);  // 258 bytes on-chain
339    pub const ByteDeposit: Balance = deposit(0, 1);
340    pub const SubAccountDeposit: Balance = deposit(1, 53);  // 53 bytes on-chain
341    pub const UsernameDeposit: Balance = deposit(0, 32);
342    pub const MaxSubAccounts: u32 = 100;
343    pub const MaxAdditionalFields: u32 = 100;
344    pub const MaxRegistrars: u32 = 20;
345}
346
347impl pallet_identity::Config for Runtime {
348    type RuntimeEvent = RuntimeEvent;
349    type Currency = Balances;
350    type BasicDeposit = BasicDeposit;
351    type ByteDeposit = ByteDeposit;
352    type SubAccountDeposit = SubAccountDeposit;
353    type MaxSubAccounts = MaxSubAccounts;
354    type IdentityInformation = IdentityInfo<MaxAdditionalFields>;
355    type MaxRegistrars = MaxRegistrars;
356    type Slashed = ();
357    type ForceOrigin = EnsureRoot<<Self as frame_system::Config>::AccountId>;
358    type RegistrarOrigin = EnsureRoot<<Self as frame_system::Config>::AccountId>;
359    type OffchainSignature = Signature;
360    type SigningPublicKey = <Signature as sp_runtime::traits::Verify>::Signer;
361    type UsernameAuthorityOrigin = EnsureRoot<<Self as frame_system::Config>::AccountId>;
362    type PendingUsernameExpiration = ConstU32<{ 7 * DAYS }>;
363    type MaxSuffixLength = ConstU32<7>;
364    type MaxUsernameLength = ConstU32<32>;
365    type WeightInfo = pallet_identity::weights::SubstrateWeight<Runtime>;
366    type UsernameDeposit = UsernameDeposit;
367    type UsernameGracePeriod = ConstU32<{ 7 * DAYS }>;
368    #[cfg(feature = "runtime-benchmarks")]
369    type BenchmarkHelper = ();
370}
371
372parameter_types! {
373    // One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes.
374    pub const DepositBase: Balance = deposit(1, 88);
375    // Additional storage item size of 32 bytes.
376    pub const DepositFactor: Balance = deposit(0, 32);
377}
378
379impl pallet_multisig::Config for Runtime {
380    type RuntimeEvent = RuntimeEvent;
381    type RuntimeCall = RuntimeCall;
382    type Currency = Balances;
383    type DepositBase = DepositBase;
384    type DepositFactor = DepositFactor;
385    type MaxSignatories = ConstU32<100>;
386    type BlockNumberProvider = System;
387    type WeightInfo = pallet_multisig::weights::SubstrateWeight<Runtime>;
388}
389
390#[cfg(feature = "runtime-benchmarks")]
391pub struct DAppStakingBenchmarkHelper<SC, ACC>(sp_std::marker::PhantomData<(SC, ACC)>);
392#[cfg(feature = "runtime-benchmarks")]
393impl pallet_dapp_staking::BenchmarkHelper<SmartContract<AccountId>, AccountId>
394    for DAppStakingBenchmarkHelper<SmartContract<AccountId>, AccountId>
395{
396    fn get_smart_contract(id: u32) -> SmartContract<AccountId> {
397        // Wasm smart contracts are no longer supported, only EVM ones can be registered.
398        let id_bytes = id.to_le_bytes();
399        let mut address = [0u8; 20];
400        address[..id_bytes.len()].copy_from_slice(&id_bytes);
401
402        SmartContract::Evm(H160::from(address))
403    }
404
405    fn set_balance(account: &AccountId, amount: Balance) {
406        use frame_support::traits::fungible::Unbalanced as FunUnbalanced;
407        Balances::write_balance(account, amount)
408            .expect("Must succeed in test/benchmark environment.");
409    }
410}
411
412pub struct AccountCheck;
413impl DappStakingAccountCheck<AccountId> for AccountCheck {
414    fn allowed_to_stake(account: &AccountId) -> bool {
415        !CollatorSelection::is_account_candidate(account)
416    }
417}
418
419parameter_types! {
420    pub const MinimumStakingAmount: Balance = 50 * SDN;
421}
422
423impl pallet_dapp_staking::Config for Runtime {
424    type RuntimeEvent = RuntimeEvent;
425    type RuntimeFreezeReason = RuntimeFreezeReason;
426    type Currency = Balances;
427    type SmartContract = SmartContract<AccountId>;
428    type ContractRegisterOrigin = frame_system::EnsureRoot<AccountId>;
429    type ContractUnregisterOrigin = frame_system::EnsureRoot<AccountId>;
430    type ManagerOrigin = frame_system::EnsureRoot<AccountId>;
431    type StakingRewardHandler = Inflation;
432    type CycleConfiguration = InflationCycleConfig;
433    type Observers = Inflation;
434    type AccountCheck = AccountCheck;
435    type EraRewardSpanLength = ConstU32<16>;
436    type RewardRetentionInPeriods = ConstU32<3>;
437    type MaxNumberOfContracts = ConstU32<{ FIXED_NUMBER_OF_TIER_SLOTS as u32 }>;
438    type MaxUnlockingChunks = ConstU32<8>;
439    type MinimumLockedAmount = MinimumStakingAmount;
440    type UnlockingPeriod = ConstU32<4>;
441    type MaxNumberOfStakedContracts = ConstU32<16>;
442    type MinimumStakeAmount = MinimumStakingAmount;
443    type NumberOfTiers = ConstU32<4>;
444    type RankingEnabled = ConstBool<true>;
445    type MaxBonusSafeMovesPerPeriod = ConstU8<2>;
446    type WeightInfo = weights::pallet_dapp_staking::SubstrateWeight<Runtime>;
447    #[cfg(feature = "runtime-benchmarks")]
448    type BenchmarkHelper = DAppStakingBenchmarkHelper<SmartContract<AccountId>, AccountId>;
449}
450
451pub struct InflationPayoutPerBlock;
452impl pallet_inflation::PayoutPerBlock<Credit<AccountId, Balances>> for InflationPayoutPerBlock {
453    fn treasury(reward: Credit<AccountId, Balances>) {
454        let _ = Balances::resolve(&TreasuryPalletId::get().into_account_truncating(), reward);
455    }
456
457    fn collators(reward: Credit<AccountId, Balances>) {
458        CollatorRewardPot::on_unbalanced(reward);
459    }
460}
461
462pub struct InflationCycleConfig;
463impl CycleConfiguration for InflationCycleConfig {
464    fn periods_per_cycle() -> u32 {
465        2
466    }
467
468    fn eras_per_voting_subperiod() -> u32 {
469        1
470    }
471
472    fn eras_per_build_and_earn_subperiod() -> u32 {
473        182
474    }
475
476    fn blocks_per_era() -> BlockNumber {
477        24 * HOURS
478    }
479}
480
481impl pallet_inflation::Config for Runtime {
482    type Currency = Balances;
483    type PayoutPerBlock = InflationPayoutPerBlock;
484    type CycleConfiguration = InflationCycleConfig;
485    type WeightInfo = weights::pallet_inflation::SubstrateWeight<Runtime>;
486}
487
488impl pallet_utility::Config for Runtime {
489    type RuntimeEvent = RuntimeEvent;
490    type RuntimeCall = RuntimeCall;
491    type PalletsOrigin = OriginCaller;
492    type WeightInfo = pallet_utility::weights::SubstrateWeight<Runtime>;
493}
494
495parameter_types! {
496    pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
497    pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
498    pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent;
499    pub const RelayParentOffset: u32 = RELAY_PARENT_OFFSET;
500}
501
502impl cumulus_pallet_parachain_system::Config for Runtime {
503    type RuntimeEvent = RuntimeEvent;
504    type OnSystemEvent = ();
505    type SelfParaId = parachain_info::Pallet<Runtime>;
506    type OutboundXcmpMessageSource = XcmpQueue;
507    type DmpQueue = frame_support::traits::EnqueueWithOrigin<MessageQueue, RelayOrigin>;
508    type ReservedDmpWeight = ReservedDmpWeight;
509    type XcmpMessageHandler = XcmpQueue;
510    type ReservedXcmpWeight = ReservedXcmpWeight;
511    type CheckAssociatedRelayNumber =
512        cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
513    type ConsensusHook = ConsensusHook;
514    type WeightInfo = cumulus_pallet_parachain_system::weights::SubstrateWeight<Runtime>;
515    type RelayParentOffset = RelayParentOffset;
516}
517
518type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook<
519    Runtime,
520    RELAY_CHAIN_SLOT_DURATION_MILLIS,
521    BLOCK_PROCESSING_VELOCITY,
522    UNINCLUDED_SEGMENT_CAPACITY,
523>;
524
525impl parachain_info::Config for Runtime {}
526
527impl pallet_aura::Config for Runtime {
528    type AuthorityId = AuraId;
529    type DisabledValidators = ();
530    type MaxAuthorities = ConstU32<250>;
531    type AllowMultipleBlocksPerSlot = ConstBool<true>;
532    type SlotDuration = ConstU64<SLOT_DURATION>;
533}
534
535impl cumulus_pallet_aura_ext::Config for Runtime {}
536
537impl pallet_authorship::Config for Runtime {
538    type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Aura>;
539    type EventHandler = (CollatorSelection,);
540}
541
542parameter_types! {
543    pub const SessionPeriod: BlockNumber = HOURS;
544    pub const SessionOffset: BlockNumber = 0;
545}
546
547impl pallet_session::Config for Runtime {
548    type RuntimeEvent = RuntimeEvent;
549    type ValidatorId = <Self as frame_system::Config>::AccountId;
550    type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
551    type ShouldEndSession = pallet_session::PeriodicSessions<SessionPeriod, SessionOffset>;
552    type NextSessionRotation = pallet_session::PeriodicSessions<SessionPeriod, SessionOffset>;
553    type SessionManager = CollatorSelection;
554    type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
555    type Keys = SessionKeys;
556    type DisablingStrategy = ();
557    type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
558    type Currency = Balances;
559    type KeyDeposit = ();
560}
561
562parameter_types! {
563    pub const PotId: PalletId = PalletId(*b"PotStake");
564    pub const MaxCandidates: u32 = 148;
565    pub const MinCandidates: u32 = 1;
566    pub const MaxInvulnerables: u32 = 48;
567    pub const SlashRatio: Perbill = Perbill::from_percent(1);
568    pub const KickThreshold: BlockNumber = 2 * HOURS; // 2 SessionPeriod
569}
570
571pub struct CollatorSelectionAccountCheck;
572impl pallet_collator_selection::AccountCheck<AccountId> for CollatorSelectionAccountCheck {
573    fn allowed_candidacy(account: &AccountId) -> bool {
574        !DappStaking::is_staker(account)
575    }
576}
577
578impl pallet_collator_selection::Config for Runtime {
579    type Currency = Balances;
580    type UpdateOrigin = EnsureRoot<AccountId>;
581    type ForceRemovalOrigin = EnsureRoot<AccountId>;
582    type GovernanceOrigin = EnsureRoot<AccountId>;
583    type PotId = PotId;
584    type MaxCandidates = MaxCandidates;
585    type MinCandidates = MinCandidates;
586    type MaxInvulnerables = MaxInvulnerables;
587    // should be a multiple of session or things will get inconsistent
588    type KickThreshold = KickThreshold;
589    type ValidatorId = <Self as frame_system::Config>::AccountId;
590    type ValidatorIdOf = pallet_collator_selection::IdentityCollator;
591    type ValidatorRegistration = Session;
592    type ValidatorSet = Session;
593    type SlashRatio = SlashRatio;
594    type AccountCheck = CollatorSelectionAccountCheck;
595    type WeightInfo = pallet_collator_selection::weights::SubstrateWeight<Runtime>;
596}
597
598parameter_types! {
599    pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry");
600    pub TreasuryAccountId: AccountId = TreasuryPalletId::get().into_account_truncating();
601}
602
603pub struct CollatorRewardPot;
604impl OnUnbalanced<Credit<AccountId, Balances>> for CollatorRewardPot {
605    fn on_nonzero_unbalanced(amount: Credit<AccountId, Balances>) {
606        let staking_pot = PotId::get().into_account_truncating();
607        let _ = Balances::resolve(&staking_pot, amount);
608    }
609}
610
611parameter_types! {
612    pub const ExistentialDeposit: Balance = 1_000_000;
613    pub const MaxLocks: u32 = 50;
614    pub const MaxReserves: u32 = 50;
615}
616
617impl pallet_balances::Config for Runtime {
618    type Balance = Balance;
619    type DustRemoval = ();
620    type RuntimeEvent = RuntimeEvent;
621    type MaxLocks = MaxLocks;
622    type MaxReserves = MaxReserves;
623    type ReserveIdentifier = [u8; 8];
624    type ExistentialDeposit = ExistentialDeposit;
625    type AccountStore = frame_system::Pallet<Runtime>;
626    type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
627    type RuntimeHoldReason = RuntimeHoldReason;
628    type RuntimeFreezeReason = RuntimeFreezeReason;
629    type FreezeIdentifier = RuntimeFreezeReason;
630    type MaxFreezes = ConstU32<1>;
631    type DoneSlashHandler = ();
632}
633
634impl AddressToAssetId<AssetId> for Runtime {
635    fn address_to_asset_id(address: H160) -> Option<AssetId> {
636        let mut data = [0u8; 16];
637        let address_bytes: [u8; 20] = address.into();
638        if ASSET_PRECOMPILE_ADDRESS_PREFIX.eq(&address_bytes[0..4]) {
639            data.copy_from_slice(&address_bytes[4..20]);
640            Some(u128::from_be_bytes(data))
641        } else {
642            None
643        }
644    }
645
646    fn asset_id_to_address(asset_id: AssetId) -> H160 {
647        let mut data = [0u8; 20];
648        data[0..4].copy_from_slice(ASSET_PRECOMPILE_ADDRESS_PREFIX);
649        data[4..20].copy_from_slice(&asset_id.to_be_bytes());
650        H160::from(data)
651    }
652}
653
654parameter_types! {
655    pub const AssetDeposit: Balance = 10 * SDN;
656    pub const AssetsStringLimit: u32 = 50;
657    /// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1)
658    // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271
659    pub const MetadataDepositBase: Balance = deposit(1, 68);
660    pub const MetadataDepositPerByte: Balance = deposit(0, 1);
661    pub const AssetAccountDeposit: Balance = deposit(1, 18);
662}
663
664impl pallet_assets::Config for Runtime {
665    type RuntimeEvent = RuntimeEvent;
666    type Balance = Balance;
667    type AssetId = AssetId;
668    type Currency = Balances;
669    type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
670    type ForceOrigin = EnsureRoot<AccountId>;
671    type AssetDeposit = AssetDeposit;
672    type MetadataDepositBase = MetadataDepositBase;
673    type MetadataDepositPerByte = MetadataDepositPerByte;
674    type AssetAccountDeposit = AssetAccountDeposit;
675    type ApprovalDeposit = ExistentialDeposit;
676    type StringLimit = AssetsStringLimit;
677    type Freezer = ();
678    type Extra = ();
679    type Holder = ();
680    type WeightInfo = weights::pallet_assets::SubstrateWeight<Runtime>;
681    type RemoveItemsLimit = ConstU32<1000>;
682    type AssetIdParameter = Compact<AssetId>;
683    type ReserveData = ();
684    type CallbackHandle = EvmRevertCodeHandler<Self, Self>;
685    #[cfg(feature = "runtime-benchmarks")]
686    type BenchmarkHelper = astar_primitives::benchmarks::AssetsBenchmarkHelper;
687}
688
689parameter_types! {
690    pub const MinVestedTransfer: Balance = 1 * SDN;
691    pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons =
692        WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE);
693}
694
695impl pallet_vesting::Config for Runtime {
696    type RuntimeEvent = RuntimeEvent;
697    type Currency = Balances;
698    type BlockNumberToBalance = ConvertInto;
699    type MinVestedTransfer = MinVestedTransfer;
700    type WeightInfo = pallet_vesting::weights::SubstrateWeight<Runtime>;
701    type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
702    type BlockNumberProvider = System;
703    // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the
704    // highest number of schedules that encodes less than 2^10.
705    const MAX_VESTING_SCHEDULES: u32 = 28;
706}
707
708parameter_types! {
709    pub const TransactionLengthFeeFactor: Balance = 235_000_000_000; // 0.000_000_235_000_000_000 SDN per byte
710    pub const WeightFeeFactor: Balance = 308_550_000_000_000; // Around 0.000_300 SDN per unit of base weight.
711    pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25);
712    pub const OperationalFeeMultiplier: u8 = 5;
713    pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(000_015, 1_000_000); // 0.000_015
714    pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 10); // 0.1
715    pub MaximumMultiplier: Multiplier = Multiplier::saturating_from_integer(10); // 10
716}
717
718/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the
719/// node's balance type.
720///
721/// This should typically create a mapping between the following ranges:
722///   - [0, MAXIMUM_BLOCK_WEIGHT]
723///   - [Balance::min, Balance::max]
724///
725/// Yet, it can be used for any other sort of change to weight-fee. Some examples being:
726///   - Setting it to `0` will essentially disable the weight fee.
727///   - Setting it to `1` will cause the literal `#[weight = x]` values to be charged.
728pub struct WeightToFee;
729impl WeightToFeePolynomial for WeightToFee {
730    type Balance = Balance;
731    fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
732        #[cfg(feature = "runtime-benchmarks")]
733        let (p, q) = (Balance::from(1u128), Balance::from(1u128));
734
735        #[cfg(not(feature = "runtime-benchmarks"))]
736        let (p, q) = (
737            WeightFeeFactor::get(),
738            Balance::from(ExtrinsicBaseWeight::get().ref_time()),
739        );
740        smallvec::smallvec![WeightToFeeCoefficient {
741            degree: 1,
742            negative: false,
743            coeff_frac: Perbill::from_rational(p % q, q),
744            coeff_integer: p / q,
745        }]
746    }
747}
748
749/// Handles coverting weight consumed by XCM into native currency fee.
750///
751/// Similar to standard `WeightToFee` handler, but force uses the minimum multiplier.
752pub struct XcmWeightToFee;
753impl WeightToFeeT for XcmWeightToFee {
754    type Balance = Balance;
755
756    fn weight_to_fee(n: &Weight) -> Self::Balance {
757        MinimumMultiplier::get().saturating_mul_int(WeightToFee::weight_to_fee(&n))
758    }
759}
760
761pub struct DealWithFees;
762impl OnUnbalanced<Credit<AccountId, Balances>> for DealWithFees {
763    fn on_unbalanceds(mut fees_then_tips: impl Iterator<Item = Credit<AccountId, Balances>>) {
764        if let Some(fees) = fees_then_tips.next() {
765            // Burn 80% of fees, rest goes to collator, including 100% of the tips.
766            let (to_burn, mut collator) = fees.ration(80, 20);
767            if let Some(tips) = fees_then_tips.next() {
768                tips.merge_into(&mut collator);
769            }
770
771            // burn part of the fees
772            drop(to_burn);
773
774            // pay fees to collator
775            <CollatorRewardPot as OnUnbalanced<_>>::on_unbalanced(collator);
776        }
777    }
778
779    fn on_unbalanced(amount: Credit<AccountId, Balances>) {
780        Self::on_unbalanceds(Some(amount).into_iter());
781    }
782}
783
784impl pallet_transaction_payment::Config for Runtime {
785    type RuntimeEvent = RuntimeEvent;
786    type OnChargeTransaction = pallet_transaction_payment::FungibleAdapter<Balances, DealWithFees>;
787    type WeightToFee = WeightToFee;
788    type OperationalFeeMultiplier = OperationalFeeMultiplier;
789    type FeeMultiplierUpdate = TargetedFeeAdjustment<
790        Self,
791        TargetBlockFullness,
792        AdjustmentVariable,
793        MinimumMultiplier,
794        MaximumMultiplier,
795    >;
796    #[cfg(not(feature = "runtime-benchmarks"))]
797    type LengthToFee = ConstantMultiplier<Balance, TransactionLengthFeeFactor>;
798    #[cfg(feature = "runtime-benchmarks")]
799    type LengthToFee = ConstantMultiplier<Balance, sp_core::ConstU128<1>>;
800    type WeightInfo = weights::pallet_transaction_payment::SubstrateWeight<Self>;
801}
802
803parameter_types! {
804    pub DefaultBaseFeePerGas: U256 = U256::from(14_700_000_000_u128);
805    pub MinBaseFeePerGas: U256 = U256::from(8_000_000_000_u128);
806    pub MaxBaseFeePerGas: U256 = U256::from(800_000_000_000_u128);
807    pub StepLimitRatio: Perquintill = Perquintill::from_rational(5_u128, 100_000);
808}
809
810/// Simple wrapper for fetching current native transaction fee weight fee multiplier.
811pub struct AdjustmentFactorGetter;
812impl Get<Multiplier> for AdjustmentFactorGetter {
813    fn get() -> Multiplier {
814        pallet_transaction_payment::NextFeeMultiplier::<Runtime>::get()
815    }
816}
817
818impl pallet_dynamic_evm_base_fee::Config for Runtime {
819    type DefaultBaseFeePerGas = DefaultBaseFeePerGas;
820    type MinBaseFeePerGas = MinBaseFeePerGas;
821    type MaxBaseFeePerGas = MaxBaseFeePerGas;
822    type AdjustmentFactor = AdjustmentFactorGetter;
823    type WeightFactor = WeightFeeFactor;
824    type StepLimitRatio = StepLimitRatio;
825    type WeightInfo = pallet_dynamic_evm_base_fee::weights::SubstrateWeight<Runtime>;
826}
827
828/// Current approximation of the gas/s consumption considering
829/// EVM execution over compiled WASM (on 4.4Ghz CPU).
830/// Given the 500ms Weight, from which 75% only are used for transactions,
831/// the total EVM execution gas limit is: GAS_PER_SECOND * 0.500 * 0.75 ~= 15_000_000.
832pub const GAS_PER_SECOND: u64 = 40_000_000;
833
834/// Approximate ratio of the amount of Weight per Gas.
835/// u64 works for approximations because Weight is a very small unit compared to gas.
836pub const WEIGHT_PER_GAS: u64 = WEIGHT_REF_TIME_PER_SECOND.saturating_div(GAS_PER_SECOND);
837
838pub struct FindAuthorTruncated<F>(PhantomData<F>);
839impl<F: FindAuthor<u32>> FindAuthor<H160> for FindAuthorTruncated<F> {
840    fn find_author<'a, I>(digests: I) -> Option<H160>
841    where
842        I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
843    {
844        if let Some(author_index) = F::find_author(digests) {
845            let authority_id =
846                pallet_aura::Authorities::<Runtime>::get()[author_index as usize].clone();
847            return Some(H160::from_slice(&authority_id.encode()[4..24]));
848        }
849
850        None
851    }
852}
853
854parameter_types! {
855    /// Ethereum-compatible chain_id:
856    /// * Dusty:   80
857    /// * Shibuya: 81
858    /// * Shiden: 336
859    pub ChainId: u64 = 0x150;
860    /// EVM gas limit
861    pub BlockGasLimit: U256 = U256::from(
862        NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT.ref_time() / WEIGHT_PER_GAS
863    );
864    pub PrecompilesValue: Precompiles = ShidenPrecompiles::<_, _>::new();
865    pub WeightPerGas: Weight = Weight::from_parts(WEIGHT_PER_GAS, 0);
866    /// The amount of gas per PoV size. Value is calculated as:
867    ///
868    /// max_gas_limit = max_tx_ref_time / WEIGHT_PER_GAS = max_pov_size * gas_limit_pov_size_ratio
869    /// gas_limit_pov_size_ratio = ceil((max_tx_ref_time / WEIGHT_PER_GAS) / max_pov_size)
870    pub const GasLimitPovSizeRatio: u64 = 8;
871    /// Maximum gas allowed per transaction (EIP-7825). Set above the EIP-7825 default
872    /// of 16,777,216 to accommodate large contract deployments and complex calls.
873    pub TransactionGasLimit: Option<U256> = Some(U256::from(TX_MAX_GAS_LIMIT));
874}
875
876impl pallet_evm::Config for Runtime {
877    type FeeCalculator = DynamicEvmBaseFee;
878    type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
879    type WeightPerGas = WeightPerGas;
880    type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Runtime>;
881    type CallOrigin = pallet_evm::EnsureAddressRoot<AccountId>;
882    type WithdrawOrigin = pallet_evm::EnsureAddressTruncated;
883    type AddressMapping = pallet_evm::HashedAddressMapping<BlakeTwo256>;
884    type Currency = Balances;
885    type Runner = pallet_evm::runner::stack::Runner<Self>;
886    type PrecompilesType = Precompiles;
887    type PrecompilesValue = PrecompilesValue;
888    type ChainId = ChainId;
889    type OnChargeTransaction = EVMFungibleAdapterWrapper<Balances, DealWithFees, CollatorRewardPot>;
890    type BlockGasLimit = BlockGasLimit;
891    type Timestamp = Timestamp;
892    type OnCreate = ();
893    type FindAuthor = FindAuthorTruncated<Aura>;
894    type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
895    type AccountProvider = pallet_evm::FrameSystemAccountProvider<Self>;
896    // gas based storage limit not enabled
897    type GasLimitStorageGrowthRatio = ConstU64<0>;
898    type TransactionGasLimit = TransactionGasLimit;
899    type WeightInfo = pallet_evm::weights::SubstrateWeight<Runtime>;
900    type CreateOriginFilter = ();
901    type CreateInnerOriginFilter = ();
902}
903
904parameter_types! {
905    pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes;
906}
907
908impl pallet_ethereum::Config for Runtime {
909    type StateRoot =
910        pallet_ethereum::IntermediateStateRoot<<Self as frame_system::Config>::Version>;
911    type PostLogContent = PostBlockAndTxnHashes;
912    // Maximum length (in bytes) of revert message to include in Executed event
913    type ExtraDataLength = ConstU32<30>;
914    type AllowUnprotectedTxs = ConstBool<false>;
915}
916
917impl pallet_sudo::Config for Runtime {
918    type RuntimeEvent = RuntimeEvent;
919    type RuntimeCall = RuntimeCall;
920    type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
921}
922
923impl pallet_xc_asset_config::Config for Runtime {
924    type AssetId = AssetId;
925    type ManagerOrigin = EnsureRoot<AccountId>;
926    type WeightInfo = pallet_xc_asset_config::weights::SubstrateWeight<Self>;
927}
928
929/// The type used to represent the kinds of proxying allowed.
930#[derive(
931    Copy,
932    Clone,
933    Eq,
934    PartialEq,
935    Ord,
936    PartialOrd,
937    Encode,
938    Decode,
939    DecodeWithMemTracking,
940    RuntimeDebug,
941    MaxEncodedLen,
942    scale_info::TypeInfo,
943)]
944pub enum ProxyType {
945    /// Allows all runtime calls for proxy account
946    Any,
947    /// Allows only NonTransfer runtime calls for proxy account
948    /// To know exact calls check InstanceFilter implementation for ProxyTypes
949    NonTransfer,
950    /// All Runtime calls from Pallet Balances allowed for proxy account
951    Balances,
952    /// All Runtime calls from Pallet Assets allowed for proxy account
953    Assets,
954    /// Only provide_judgement call from pallet identity allowed for proxy account
955    IdentityJudgement,
956    /// Only reject_announcement call from pallet proxy allowed for proxy account
957    CancelProxy,
958    /// All runtime calls from pallet DappStaking allowed for proxy account
959    DappStaking,
960    /// Only claim_staker call from pallet DappStaking allowed for proxy account
961    StakerRewardClaim,
962}
963
964impl Default for ProxyType {
965    fn default() -> Self {
966        Self::Any
967    }
968}
969
970impl InstanceFilter<RuntimeCall> for ProxyType {
971    fn filter(&self, c: &RuntimeCall) -> bool {
972        match self {
973            // Always allowed RuntimeCall::Utility no matter type.
974            // Only transactions allowed by Proxy.filter can be executed
975            _ if matches!(c, RuntimeCall::Utility(..)) => true,
976            ProxyType::Any => true,
977            ProxyType::NonTransfer => {
978                matches!(
979                    c,
980                    RuntimeCall::System(..)
981                        | RuntimeCall::Identity(..)
982                        | RuntimeCall::Multisig(..)
983                        | RuntimeCall::Proxy(..)
984                        | RuntimeCall::Vesting(
985                            pallet_vesting::Call::vest { .. }
986                                | pallet_vesting::Call::vest_other { .. }
987                        )
988                        | RuntimeCall::DappStaking(..)
989                        | RuntimeCall::CollatorSelection(..)
990                        | RuntimeCall::Session(..)
991                )
992            }
993            ProxyType::Balances => {
994                matches!(c, RuntimeCall::Balances(..))
995            }
996            ProxyType::Assets => {
997                matches!(c, RuntimeCall::Assets(..))
998            }
999            ProxyType::IdentityJudgement => {
1000                matches!(
1001                    c,
1002                    RuntimeCall::Identity(pallet_identity::Call::provide_judgement { .. })
1003                )
1004            }
1005            ProxyType::CancelProxy => {
1006                matches!(
1007                    c,
1008                    RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. })
1009                )
1010            }
1011            ProxyType::DappStaking => {
1012                matches!(c, RuntimeCall::DappStaking(..))
1013            }
1014            ProxyType::StakerRewardClaim => {
1015                matches!(
1016                    c,
1017                    RuntimeCall::DappStaking(
1018                        pallet_dapp_staking::Call::claim_staker_rewards { .. }
1019                    )
1020                )
1021            }
1022        }
1023    }
1024
1025    fn is_superset(&self, o: &Self) -> bool {
1026        match (self, o) {
1027            (x, y) if x == y => true,
1028            (ProxyType::Any, _) => true,
1029            (_, ProxyType::Any) => false,
1030            (ProxyType::DappStaking, ProxyType::StakerRewardClaim) => true,
1031            _ => false,
1032        }
1033    }
1034}
1035
1036parameter_types! {
1037    // One storage item; key size 32, value size 8; .
1038    pub const ProxyDepositBase: Balance = deposit(1, 8);
1039    // Additional storage item size of 33 bytes.
1040    pub const ProxyDepositFactor: Balance = deposit(0, 33);
1041    pub const MaxProxies: u16 = 32;
1042    pub const MaxPending: u16 = 32;
1043    pub const AnnouncementDepositBase: Balance = deposit(1, 8);
1044    pub const AnnouncementDepositFactor: Balance = deposit(0, 66);
1045}
1046
1047impl pallet_proxy::Config for Runtime {
1048    type RuntimeEvent = RuntimeEvent;
1049    type RuntimeCall = RuntimeCall;
1050    type Currency = Balances;
1051    type ProxyType = ProxyType;
1052    type ProxyDepositBase = ProxyDepositBase;
1053    type ProxyDepositFactor = ProxyDepositFactor;
1054    type MaxProxies = MaxProxies;
1055    type BlockNumberProvider = System;
1056    type WeightInfo = pallet_proxy::weights::SubstrateWeight<Runtime>;
1057    type MaxPending = MaxPending;
1058    type CallHasher = BlakeTwo256;
1059    type AnnouncementDepositBase = AnnouncementDepositBase;
1060    type AnnouncementDepositFactor = AnnouncementDepositFactor;
1061}
1062
1063parameter_types! {
1064    pub MbmServiceWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block;
1065    /// Storage prefix of the decommissioned `pallet-contracts`.
1066    pub const ContractsPalletName: &'static str = "Contracts";
1067    /// Storage prefix of the decommissioned `pallet-insecure-randomness-collective-flip`.
1068    pub const RandomnessPalletName: &'static str = "RandomnessCollectiveFlip";
1069}
1070
1071/// Benchmarked weights backing the contract decommission migrations.
1072type ContractsMbmWeights = contracts_mbm::weights::SubstrateWeight<Runtime>;
1073
1074/// Multi-block migrations executed by `pallet-migrations`.
1075///
1076/// Step two of decommissioning Wasm (ink!) smart contracts: `pallet-contracts` is gone, so the
1077/// storage it left behind is purged over multiple blocks. The purge also hands back the consumer
1078/// reference the pallet took on every live contract account - without it those accounts could
1079/// never be reaped. Registered dApps pointing at Wasm contracts are expected to have been
1080/// unregistered from dApp staking by governance beforehand.
1081pub type MultiBlockMigrationsList = (
1082    // Must come first: it needs the `trie_id`s stored under the `Contracts` prefix.
1083    contracts_mbm::PurgeContractsChildTries<Runtime, ContractsPalletName, ContractsMbmWeights>,
1084    contracts_mbm::RemovePalletStepped<ContractsPalletName, ContractsMbmWeights>,
1085    contracts_mbm::RemovePalletStepped<RandomnessPalletName, ContractsMbmWeights>,
1086);
1087
1088// Carries no storage and no calls, it only exists so the migrations above can be
1089// benchmarked. Deliberately not part of the production runtime.
1090#[cfg(feature = "runtime-benchmarks")]
1091impl contracts_mbm::Config for Runtime {}
1092
1093impl pallet_migrations::Config for Runtime {
1094    type RuntimeEvent = RuntimeEvent;
1095    #[cfg(not(feature = "runtime-benchmarks"))]
1096    type Migrations = MultiBlockMigrationsList;
1097    // Benchmarks need mocked migrations to guarantee that they succeed.
1098    #[cfg(feature = "runtime-benchmarks")]
1099    type Migrations = pallet_migrations::mock_helpers::MockedMigrations;
1100    type CursorMaxLen = ConstU32<65_536>;
1101    type IdentifierMaxLen = ConstU32<256>;
1102    type MigrationStatusHandler = ();
1103    type FailedMigrationHandler = UnfreezeChainOnFailedMigration;
1104    type MaxServiceWeight = MbmServiceWeight;
1105    type WeightInfo = pallet_migrations::weights::SubstrateWeight<Runtime>;
1106}
1107
1108#[frame_support::runtime]
1109mod runtime {
1110    #[runtime::runtime]
1111    #[runtime::derive(
1112        RuntimeCall,
1113        RuntimeEvent,
1114        RuntimeError,
1115        RuntimeOrigin,
1116        RuntimeFreezeReason,
1117        RuntimeHoldReason,
1118        RuntimeSlashReason,
1119        RuntimeLockId,
1120        RuntimeTask
1121    )]
1122    pub struct Runtime;
1123
1124    #[runtime::pallet_index(10)]
1125    pub type System = frame_system;
1126    #[runtime::pallet_index(11)]
1127    pub type Utility = pallet_utility;
1128    #[runtime::pallet_index(12)]
1129    pub type Identity = pallet_identity;
1130    #[runtime::pallet_index(13)]
1131    pub type Timestamp = pallet_timestamp;
1132    #[runtime::pallet_index(14)]
1133    pub type Multisig = pallet_multisig;
1134    #[runtime::pallet_index(15)]
1135    pub type Proxy = pallet_proxy;
1136
1137    #[runtime::pallet_index(20)]
1138    pub type ParachainSystem = cumulus_pallet_parachain_system;
1139    #[runtime::pallet_index(21)]
1140    pub type ParachainInfo = parachain_info;
1141
1142    #[runtime::pallet_index(30)]
1143    pub type TransactionPayment = pallet_transaction_payment;
1144    #[runtime::pallet_index(31)]
1145    pub type Balances = pallet_balances;
1146    #[runtime::pallet_index(32)]
1147    pub type Vesting = pallet_vesting;
1148    // Inflation needs to execute `on_initialize` as soon as possible, and `on_finalize` as late as possible.
1149    // However, we need to execute Balance genesis before Inflation genesis, otherwise we'll have zero issuance when Inflation
1150    // logic is executed.
1151    // TODO: Address this later. It would be best if Inflation was first pallet.
1152    #[runtime::pallet_index(33)]
1153    pub type Inflation = pallet_inflation;
1154    #[runtime::pallet_index(34)]
1155    pub type DappStaking = pallet_dapp_staking;
1156    #[runtime::pallet_index(36)]
1157    pub type Assets = pallet_assets;
1158    // skip 37 - price_aggregator previously
1159    // skip 38/39 - oracle and oracle_membership previously
1160    #[runtime::pallet_index(40)]
1161    pub type Authorship = pallet_authorship;
1162    #[runtime::pallet_index(41)]
1163    pub type CollatorSelection = pallet_collator_selection;
1164    #[runtime::pallet_index(42)]
1165    pub type Session = pallet_session;
1166    #[runtime::pallet_index(43)]
1167    pub type Aura = pallet_aura;
1168    #[runtime::pallet_index(44)]
1169    pub type AuraExt = cumulus_pallet_aura_ext;
1170
1171    #[runtime::pallet_index(50)]
1172    pub type XcmpQueue = cumulus_pallet_xcmp_queue;
1173    #[runtime::pallet_index(51)]
1174    pub type PolkadotXcm = pallet_xcm;
1175    #[runtime::pallet_index(52)]
1176    pub type CumulusXcm = cumulus_pallet_xcm;
1177    // skip 53 - cumulus_pallet_dmp_queue previously
1178    #[runtime::pallet_index(54)]
1179    pub type XcAssetConfig = pallet_xc_asset_config;
1180    // skip 55 - orml_xtokens previously
1181    #[runtime::pallet_index(56)]
1182    pub type MessageQueue = pallet_message_queue;
1183
1184    #[runtime::pallet_index(60)]
1185    pub type EVM = pallet_evm;
1186    #[runtime::pallet_index(61)]
1187    pub type Ethereum = pallet_ethereum;
1188    #[runtime::pallet_index(63)]
1189    pub type DynamicEvmBaseFee = pallet_dynamic_evm_base_fee;
1190
1191    // skip 70 - pallet_contracts previously
1192    // skip 71 - pallet_insecure_randomness_collective_flip previously
1193    #[runtime::pallet_index(99)]
1194    pub type Sudo = pallet_sudo;
1195
1196    #[runtime::pallet_index(120)]
1197    pub type MultiBlockMigrations = pallet_migrations;
1198
1199    #[runtime::pallet_index(250)]
1200    #[cfg(feature = "runtime-benchmarks")]
1201    pub type ContractsMBM = contracts_mbm;
1202}
1203
1204/// Block type as expected by this runtime.
1205pub type Block = generic::Block<Header, UncheckedExtrinsic>;
1206/// A Block signed with a Justification
1207pub type SignedBlock = generic::SignedBlock<Block>;
1208/// BlockId type as expected by this runtime.
1209pub type BlockId = generic::BlockId<Block>;
1210/// The SignedExtension to the basic transaction logic.
1211pub type SignedExtra = (
1212    frame_system::CheckSpecVersion<Runtime>,
1213    frame_system::CheckTxVersion<Runtime>,
1214    frame_system::CheckGenesis<Runtime>,
1215    frame_system::CheckEra<Runtime>,
1216    frame_system::CheckNonce<Runtime>,
1217    frame_system::CheckWeight<Runtime>,
1218    pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
1219    frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
1220);
1221/// Unchecked extrinsic type as expected by this runtime.
1222pub type UncheckedExtrinsic =
1223    fp_self_contained::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
1224/// Extrinsic type that has already been checked.
1225pub type CheckedExtrinsic =
1226    fp_self_contained::CheckedExtrinsic<AccountId, RuntimeCall, SignedExtra, H160>;
1227/// The payload being signed in transactions.
1228pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
1229/// Executive: handles dispatch to the various modules.
1230pub type Executive = frame_executive::Executive<
1231    Runtime,
1232    Block,
1233    frame_system::ChainContext<Runtime>,
1234    Runtime,
1235    AllPalletsWithSystem,
1236    Migrations,
1237>;
1238
1239parameter_types! {
1240    pub const PriceAggregatorPalletStr: &'static str = "PriceAggregator";
1241    pub const OraclePalletStr: &'static str = "Oracle";
1242    pub const OracleMembershipPalletStr: &'static str = "OracleMembership";
1243}
1244
1245/// All migrations that will run on the next runtime upgrade.
1246///
1247/// __NOTE:__ THE ORDER IS IMPORTANT.
1248pub type Migrations = (Unreleased, Permanent);
1249
1250/// Unreleased migrations. Add new ones here:
1251pub type Unreleased = (frame_support::migrations::RemovePallet<XTokensPalletName, RocksDbWeight>,);
1252
1253parameter_types! {
1254    pub const XTokensPalletName: &'static str = "XTokens";
1255}
1256
1257/// Migrations/checks that do not need to be versioned and can run on every upgrade.
1258pub type Permanent = (pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,);
1259
1260impl fp_self_contained::SelfContainedCall for RuntimeCall {
1261    type SignedInfo = H160;
1262
1263    fn is_self_contained(&self) -> bool {
1264        match self {
1265            RuntimeCall::Ethereum(call) => call.is_self_contained(),
1266            _ => false,
1267        }
1268    }
1269
1270    fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
1271        match self {
1272            RuntimeCall::Ethereum(call) => call.check_self_contained(),
1273            _ => None,
1274        }
1275    }
1276
1277    fn validate_self_contained(
1278        &self,
1279        info: &Self::SignedInfo,
1280        dispatch_info: &DispatchInfoOf<RuntimeCall>,
1281        len: usize,
1282    ) -> Option<TransactionValidity> {
1283        match self {
1284            RuntimeCall::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),
1285            _ => None,
1286        }
1287    }
1288
1289    fn pre_dispatch_self_contained(
1290        &self,
1291        info: &Self::SignedInfo,
1292        dispatch_info: &DispatchInfoOf<RuntimeCall>,
1293        len: usize,
1294    ) -> Option<Result<(), TransactionValidityError>> {
1295        match self {
1296            RuntimeCall::Ethereum(call) => {
1297                call.pre_dispatch_self_contained(info, dispatch_info, len)
1298            }
1299            _ => None,
1300        }
1301    }
1302
1303    fn apply_self_contained(
1304        self,
1305        info: Self::SignedInfo,
1306    ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {
1307        match self {
1308            call @ RuntimeCall::Ethereum(pallet_ethereum::Call::transact { .. }) => {
1309                Some(call.dispatch(RuntimeOrigin::from(
1310                    pallet_ethereum::RawOrigin::EthereumTransaction(info),
1311                )))
1312            }
1313            _ => None,
1314        }
1315    }
1316}
1317
1318#[cfg(feature = "runtime-benchmarks")]
1319mod benches {
1320    define_benchmarks!(
1321        [frame_benchmarking, BaselineBench::<Runtime>]
1322        [frame_system, SystemBench::<Runtime>]
1323        [frame_system_extensions, SystemExtensionsBench::<Runtime>]
1324        [pallet_assets, pallet_assets::Pallet::<Runtime>]
1325        [pallet_balances, Balances]
1326        [pallet_timestamp, Timestamp]
1327        [pallet_transaction_payment, TransactionPayment]
1328        [pallet_dapp_staking, DappStaking]
1329        [pallet_inflation, Inflation]
1330        [pallet_migrations, MultiBlockMigrations]
1331        [contracts_mbm, ContractsMBM]
1332        [pallet_xc_asset_config, XcAssetConfig]
1333        [pallet_collator_selection, CollatorSelection]
1334        [pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
1335        [pallet_dynamic_evm_base_fee, DynamicEvmBaseFee]
1336        [xcm_benchmarks_generic, XcmGeneric]
1337        [xcm_benchmarks_fungible, XcmFungible]
1338    );
1339}
1340
1341impl_runtime_apis! {
1342    impl sp_api::Core<Block> for Runtime {
1343        fn version() -> RuntimeVersion {
1344            VERSION
1345        }
1346
1347        fn execute_block(block: <Block as BlockT>::LazyBlock) {
1348            Executive::execute_block(block)
1349        }
1350
1351        fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
1352            Executive::initialize_block(header)
1353        }
1354    }
1355
1356    impl sp_api::Metadata<Block> for Runtime {
1357        fn metadata() -> OpaqueMetadata {
1358            OpaqueMetadata::new(Runtime::metadata().into())
1359        }
1360
1361        fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
1362            Runtime::metadata_at_version(version)
1363        }
1364
1365        fn metadata_versions() -> Vec<u32> {
1366            Runtime::metadata_versions()
1367        }
1368    }
1369
1370    impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
1371        fn slot_duration() -> sp_consensus_aura::SlotDuration {
1372            sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION)
1373        }
1374
1375        fn authorities() -> Vec<AuraId> {
1376            pallet_aura::Authorities::<Runtime>::get().into_inner()
1377        }
1378    }
1379
1380    impl cumulus_primitives_aura::AuraUnincludedSegmentApi<Block> for Runtime {
1381        fn can_build_upon(
1382            included_hash: <Block as BlockT>::Hash,
1383            slot: cumulus_primitives_aura::Slot,
1384        ) -> bool {
1385            ConsensusHook::can_build_upon(included_hash, slot)
1386        }
1387    }
1388
1389    impl sp_block_builder::BlockBuilder<Block> for Runtime {
1390        fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
1391            Executive::apply_extrinsic(extrinsic)
1392        }
1393
1394        fn finalize_block() -> <Block as BlockT>::Header {
1395            Executive::finalize_block()
1396        }
1397
1398        fn inherent_extrinsics(data: InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
1399            data.create_extrinsics()
1400        }
1401
1402        fn check_inherents(block: <Block as BlockT>::LazyBlock, data: InherentData) -> CheckInherentsResult {
1403            data.check_extrinsics(&block)
1404        }
1405    }
1406
1407    impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
1408        fn validate_transaction(
1409            source: TransactionSource,
1410            tx: <Block as BlockT>::Extrinsic,
1411            block_hash: <Block as BlockT>::Hash,
1412        ) -> TransactionValidity {
1413            Executive::validate_transaction(source, tx, block_hash)
1414        }
1415    }
1416
1417    impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
1418        fn offchain_worker(header: &<Block as BlockT>::Header) {
1419            Executive::offchain_worker(header)
1420        }
1421    }
1422
1423    impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
1424        fn account_nonce(account: AccountId) -> Nonce {
1425            System::account_nonce(account)
1426        }
1427    }
1428
1429    impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<
1430        Block,
1431        Balance,
1432    > for Runtime {
1433        fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {
1434            TransactionPayment::query_info(uxt, len)
1435        }
1436        fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {
1437            TransactionPayment::query_fee_details(uxt, len)
1438        }
1439        fn query_weight_to_fee(weight: Weight) -> Balance {
1440            TransactionPayment::weight_to_fee(weight)
1441        }
1442        fn query_length_to_fee(length: u32) -> Balance {
1443            TransactionPayment::length_to_fee(length)
1444        }
1445    }
1446
1447    impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall>
1448        for Runtime
1449    {
1450        fn query_call_info(
1451            call: RuntimeCall,
1452            len: u32,
1453        ) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> {
1454            TransactionPayment::query_call_info(call, len)
1455        }
1456        fn query_call_fee_details(
1457            call: RuntimeCall,
1458            len: u32,
1459        ) -> pallet_transaction_payment::FeeDetails<Balance> {
1460            TransactionPayment::query_call_fee_details(call, len)
1461        }
1462        fn query_weight_to_fee(weight: Weight) -> Balance {
1463            TransactionPayment::weight_to_fee(weight)
1464        }
1465
1466        fn query_length_to_fee(length: u32) -> Balance {
1467            TransactionPayment::length_to_fee(length)
1468        }
1469    }
1470
1471    impl sp_session::SessionKeys<Block> for Runtime {
1472        fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
1473            SessionKeys::generate(seed)
1474        }
1475
1476        fn decode_session_keys(
1477            encoded: Vec<u8>,
1478        ) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
1479            SessionKeys::decode_into_raw_public_keys(&encoded)
1480        }
1481    }
1482
1483    impl cumulus_primitives_core::RelayParentOffsetApi<Block> for Runtime {
1484        fn relay_parent_offset() -> u32 {
1485            RelayParentOffset::get()
1486        }
1487    }
1488
1489    impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
1490        fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
1491            ParachainSystem::collect_collation_info(header)
1492        }
1493    }
1494
1495    impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
1496        fn chain_id() -> u64 {
1497            ChainId::get()
1498        }
1499
1500        fn account_basic(address: H160) -> pallet_evm::Account {
1501            let (account, _) = EVM::account_basic(&address);
1502            account
1503        }
1504
1505        fn gas_price() -> U256 {
1506            let (gas_price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();
1507            gas_price
1508        }
1509
1510        fn account_code_at(address: H160) -> Vec<u8> {
1511            pallet_evm::AccountCodes::<Runtime>::get(address)
1512        }
1513
1514        fn author() -> H160 {
1515            <pallet_evm::Pallet<Runtime>>::find_author()
1516        }
1517
1518        fn storage_at(address: H160, index: U256) -> H256 {
1519            let tmp: [u8; 32] = index.to_big_endian();
1520            pallet_evm::AccountStorages::<Runtime>::get(address, H256::from_slice(&tmp[..]))
1521        }
1522
1523        fn call(
1524            from: H160,
1525            to: H160,
1526            data: Vec<u8>,
1527            value: U256,
1528            gas_limit: U256,
1529            max_fee_per_gas: Option<U256>,
1530            max_priority_fee_per_gas: Option<U256>,
1531            nonce: Option<U256>,
1532            estimate: bool,
1533            access_list: Option<Vec<(H160, Vec<H256>)>>,
1534            authorization_list: Option<AuthorizationList>,
1535        ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
1536            let config = if estimate {
1537                let mut config = <Runtime as pallet_evm::Config>::config().clone();
1538                config.estimate = true;
1539                Some(config)
1540            } else {
1541                None
1542            };
1543
1544            let is_transactional = false;
1545            let validate = true;
1546
1547            // Reused approach from Moonbeam since Frontier implementation doesn't support this
1548            let mut estimated_transaction_len = data.len() +
1549                // to: 20
1550                // from: 20
1551                // value: 32
1552                // gas_limit: 32
1553                // nonce: 32
1554                // 1 byte transaction action variant
1555                // chain id 8 bytes
1556                // 65 bytes signature
1557                210;
1558            if max_fee_per_gas.is_some() {
1559                estimated_transaction_len += 32;
1560            }
1561            if max_priority_fee_per_gas.is_some() {
1562                estimated_transaction_len += 32;
1563            }
1564            if access_list.is_some() {
1565                estimated_transaction_len += access_list.encoded_size();
1566            }
1567
1568            let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
1569            let without_base_extrinsic_weight = true;
1570
1571            let (weight_limit, proof_size_base_cost) =
1572                match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
1573                    gas_limit,
1574                    without_base_extrinsic_weight
1575                ) {
1576                    weight_limit if weight_limit.proof_size() > 0 => {
1577                        (Some(weight_limit), Some(estimated_transaction_len as u64))
1578                    }
1579                    _ => (None, None),
1580                };
1581
1582            <Runtime as pallet_evm::Config>::Runner::call(
1583                from,
1584                to,
1585                data,
1586                value,
1587                gas_limit.unique_saturated_into(),
1588                max_fee_per_gas,
1589                max_priority_fee_per_gas,
1590                nonce,
1591                access_list.unwrap_or_default(),
1592                authorization_list.unwrap_or_default(),
1593                is_transactional,
1594                validate,
1595                weight_limit,
1596                proof_size_base_cost,
1597                config
1598                    .as_ref()
1599                    .unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),
1600            )
1601            .map_err(|err| err.error.into())
1602        }
1603
1604        fn create(
1605            from: H160,
1606            data: Vec<u8>,
1607            value: U256,
1608            gas_limit: U256,
1609            max_fee_per_gas: Option<U256>,
1610            max_priority_fee_per_gas: Option<U256>,
1611            nonce: Option<U256>,
1612            estimate: bool,
1613            access_list: Option<Vec<(H160, Vec<H256>)>>,
1614            authorization_list: Option<AuthorizationList>,
1615        ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
1616            let config = if estimate {
1617                let mut config = <Runtime as pallet_evm::Config>::config().clone();
1618                config.estimate = true;
1619                Some(config)
1620            } else {
1621                None
1622            };
1623
1624            let is_transactional = false;
1625            let validate = true;
1626
1627            // Reused approach from Moonbeam since Frontier implementation doesn't support this
1628            let mut estimated_transaction_len = data.len() +
1629                // to: 20
1630                // from: 20
1631                // value: 32
1632                // gas_limit: 32
1633                // nonce: 32
1634                // 1 byte transaction action variant
1635                // chain id 8 bytes
1636                // 65 bytes signature
1637                210;
1638            if max_fee_per_gas.is_some() {
1639                estimated_transaction_len += 32;
1640            }
1641            if max_priority_fee_per_gas.is_some() {
1642                estimated_transaction_len += 32;
1643            }
1644            if access_list.is_some() {
1645                estimated_transaction_len += access_list.encoded_size();
1646            }
1647
1648            let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
1649            let without_base_extrinsic_weight = true;
1650
1651            let (weight_limit, proof_size_base_cost) =
1652                match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
1653                    gas_limit,
1654                    without_base_extrinsic_weight
1655                ) {
1656                    weight_limit if weight_limit.proof_size() > 0 => {
1657                        (Some(weight_limit), Some(estimated_transaction_len as u64))
1658                    }
1659                    _ => (None, None),
1660                };
1661
1662            #[allow(clippy::or_fun_call)] // suggestion not helpful here
1663            <Runtime as pallet_evm::Config>::Runner::create(
1664                from,
1665                data,
1666                value,
1667                gas_limit.unique_saturated_into(),
1668                max_fee_per_gas,
1669                max_priority_fee_per_gas,
1670                nonce,
1671                access_list.unwrap_or_default(),
1672                authorization_list.unwrap_or_default(),
1673                is_transactional,
1674                validate,
1675                weight_limit,
1676                proof_size_base_cost,
1677                config
1678                    .as_ref()
1679                    .unwrap_or(<Runtime as pallet_evm::Config>::config()),
1680                )
1681                .map_err(|err| err.error.into())
1682        }
1683
1684        fn current_transaction_statuses() -> Option<Vec<fp_rpc::TransactionStatus>> {
1685            pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
1686        }
1687
1688        fn current_block() -> Option<pallet_ethereum::Block> {
1689            pallet_ethereum::CurrentBlock::<Runtime>::get()
1690        }
1691
1692        fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {
1693            pallet_ethereum::CurrentReceipts::<Runtime>::get()
1694        }
1695
1696        fn current_all() -> (
1697            Option<pallet_ethereum::Block>,
1698            Option<Vec<pallet_ethereum::Receipt>>,
1699            Option<Vec<fp_rpc::TransactionStatus>>,
1700        ) {
1701            (
1702                pallet_ethereum::CurrentBlock::<Runtime>::get(),
1703                pallet_ethereum::CurrentReceipts::<Runtime>::get(),
1704                pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
1705            )
1706        }
1707
1708        fn extrinsic_filter(
1709            xts: Vec<<Block as BlockT>::Extrinsic>,
1710        ) -> Vec<pallet_ethereum::Transaction> {
1711            xts.into_iter().filter_map(|xt| match xt.0.function {
1712                RuntimeCall::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),
1713                _ => None
1714            }).collect::<Vec<pallet_ethereum::Transaction>>()
1715        }
1716
1717        fn elasticity() -> Option<Permill> {
1718            Some(Permill::zero())
1719        }
1720
1721        fn gas_limit_multiplier_support() {}
1722
1723        fn pending_block(
1724            xts: Vec<<Block as BlockT>::Extrinsic>,
1725        ) -> (Option<pallet_ethereum::Block>, Option<Vec<fp_rpc::TransactionStatus>>) {
1726            for ext in xts.into_iter() {
1727                let _ = Executive::apply_extrinsic(ext);
1728            }
1729
1730            Ethereum::on_finalize(System::block_number() + 1);
1731
1732            (
1733                pallet_ethereum::CurrentBlock::<Runtime>::get(),
1734                pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
1735            )
1736        }
1737
1738        fn initialize_pending_block(header: &<Block as BlockT>::Header) {
1739            Executive::initialize_block(header);
1740        }
1741    }
1742
1743    impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {
1744        fn convert_transaction(
1745            transaction: pallet_ethereum::Transaction
1746        ) -> <Block as BlockT>::Extrinsic {
1747            UncheckedExtrinsic::new_bare(
1748                pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
1749            )
1750        }
1751    }
1752
1753    impl dapp_staking_runtime_api::DappStakingApi<Block> for Runtime {
1754        fn periods_per_cycle() -> PeriodNumber {
1755            InflationCycleConfig::periods_per_cycle()
1756        }
1757
1758        fn eras_per_voting_subperiod() -> EraNumber {
1759            InflationCycleConfig::eras_per_voting_subperiod()
1760        }
1761
1762        fn eras_per_build_and_earn_subperiod() -> EraNumber {
1763            InflationCycleConfig::eras_per_build_and_earn_subperiod()
1764        }
1765
1766        fn blocks_per_era() -> BlockNumber {
1767            InflationCycleConfig::blocks_per_era()
1768        }
1769
1770        fn get_dapp_tier_assignment() -> BTreeMap<DAppId, RankedTier> {
1771            DappStaking::get_dapp_tier_assignment()
1772        }
1773    }
1774
1775    impl xcm_runtime_apis::fees::XcmPaymentApi<Block> for Runtime {
1776        fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
1777            if !matches!(xcm_version, xcm::v3::VERSION | xcm::v4::VERSION | xcm::v5::VERSION) {
1778                return Err(XcmPaymentApiError::UnhandledXcmVersion);
1779            }
1780
1781            // Native asset is always supported
1782            let mut acceptable_assets = vec![XcmAssetId::from(xcm_config::ShidenLocation::get())];
1783
1784            // Add foreign assets that have 'units per second' configured
1785            acceptable_assets.extend(
1786                pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::iter_keys().filter_map(
1787                    |asset_location| match XcmLocation::try_from(asset_location) {
1788                        Ok(location) => Some(XcmAssetId::from(location)),
1789                        Err(_) => None,
1790                    },
1791                ),
1792            );
1793
1794            PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets)
1795        }
1796
1797        fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
1798            let asset = asset.into_version(xcm::v5::VERSION).map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
1799            let asset_id: XcmAssetId = asset.try_into().map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
1800
1801            // for native token
1802            if asset_id.0 == xcm_config::ShidenLocation::get() {
1803                Ok(XcmWeightToFee::weight_to_fee(&weight))
1804            }
1805            // for foreign assets with “units per second” configurations
1806            else {
1807                let versioned_location = VersionedLocation::V5(asset_id.0);
1808
1809                match pallet_xc_asset_config::AssetLocationUnitsPerSecond::<Runtime>::get(versioned_location) {
1810                    Some(units_per_sec) => {
1811                        Ok(pallet_xc_asset_config::Pallet::<Runtime>::weight_to_fee(weight, units_per_sec))
1812                    }
1813                    None => Err(XcmPaymentApiError::AssetNotFound),
1814                }
1815            }
1816        }
1817
1818        fn query_xcm_weight(message: VersionedXcm<()>) -> Result<Weight, XcmPaymentApiError> {
1819            PolkadotXcm::query_xcm_weight(message)
1820        }
1821
1822        fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>, asset_id: VersionedAssetId) -> Result<VersionedAssets, XcmPaymentApiError> {
1823            type AssetExchanger = <xcm_config::XcmConfig as xcm_executor::Config>::AssetExchanger;
1824            PolkadotXcm::query_delivery_fees::<AssetExchanger>(destination, message, asset_id)
1825        }
1826    }
1827
1828    impl xcm_runtime_apis::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller> for Runtime {
1829        fn dry_run_call(origin: OriginCaller, call: RuntimeCall, result_xcms_version: XcmVersion) -> Result<CallDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
1830            PolkadotXcm::dry_run_call::<Runtime, xcm_config::XcmRouter, OriginCaller, RuntimeCall>(origin, call, result_xcms_version)
1831        }
1832
1833        fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm<RuntimeCall>) -> Result<XcmDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
1834            PolkadotXcm::dry_run_xcm::<xcm_config::XcmRouter>(origin_location, xcm)
1835        }
1836    }
1837
1838    impl xcm_runtime_apis::trusted_query::TrustedQueryApi<Block> for Runtime {
1839        fn is_trusted_reserve(asset: VersionedAsset, location: VersionedLocation) -> Result<bool, xcm_runtime_apis::trusted_query::Error> {
1840            PolkadotXcm::is_trusted_reserve(asset, location)
1841        }
1842        fn is_trusted_teleporter(asset: VersionedAsset, location: VersionedLocation) -> Result<bool, xcm_runtime_apis::trusted_query::Error> {
1843            PolkadotXcm::is_trusted_teleporter(asset, location)
1844        }
1845    }
1846
1847    impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
1848
1849        fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
1850            genesis_builder_helper::build_state::<RuntimeGenesisConfig>(config)
1851        }
1852
1853        fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
1854            genesis_builder_helper::get_preset::<RuntimeGenesisConfig>(id, &genesis_config::get_preset)
1855        }
1856
1857        fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
1858            vec![
1859                sp_genesis_builder::PresetId::from("development"),
1860            ]
1861        }
1862    }
1863
1864    #[cfg(feature = "runtime-benchmarks")]
1865    impl frame_benchmarking::Benchmark<Block> for Runtime {
1866        fn benchmark_metadata(extra: bool) -> (
1867            Vec<frame_benchmarking::BenchmarkList>,
1868            Vec<frame_support::traits::StorageInfo>,
1869        ) {
1870            use frame_benchmarking::{baseline, BenchmarkList};
1871            use frame_support::traits::StorageInfoTrait;
1872            pub use frame_system_benchmarking::{
1873                extensions::Pallet as SystemExtensionsBench, Pallet as SystemBench
1874            };
1875            use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
1876            use baseline::Pallet as BaselineBench;
1877
1878            // This is defined once again in dispatch_benchmark, because list_benchmarks!
1879            // and add_benchmarks! are macros exported by define_benchmarks! macros and those types
1880            // are referenced in that call.
1881            type XcmFungible = astar_xcm_benchmarks::fungible::benchmarking::XcmFungibleBenchmarks::<Runtime>;
1882            type XcmGeneric = astar_xcm_benchmarks::generic::benchmarking::XcmGenericBenchmarks::<Runtime>;
1883
1884            let mut list = Vec::<BenchmarkList>::new();
1885            list_benchmarks!(list, extra);
1886
1887            let storage_info = AllPalletsWithSystem::storage_info();
1888
1889            (list, storage_info)
1890        }
1891
1892        #[allow(non_local_definitions)]
1893        fn dispatch_benchmark(
1894            config: frame_benchmarking::BenchmarkConfig
1895        ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
1896            use alloc::boxed::Box;
1897            use frame_benchmarking::{baseline, BenchmarkBatch, BenchmarkError};
1898            pub use frame_system_benchmarking::{
1899                extensions::Pallet as SystemExtensionsBench, Pallet as SystemBench
1900            };
1901            use frame_support::{traits::{WhitelistedStorageKeys, TrackedStorageKey, tokens::fungible::{ItemOf}}, assert_ok};
1902            use baseline::Pallet as BaselineBench;
1903            use xcm::latest::prelude::*;
1904            use xcm_builder::MintLocation;
1905            use astar_primitives::{benchmarks::XcmBenchmarkHelper, xcm::ASSET_HUB_PARA_ID};
1906            use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
1907
1908            pub struct TestDeliveryHelper;
1909            impl xcm_builder::EnsureDelivery for TestDeliveryHelper {
1910                fn ensure_successful_delivery(
1911                    origin_ref: &Location,
1912                    dest: &Location,
1913                    _fee_reason: xcm_executor::traits::FeeReason,
1914                ) -> (Option<xcm_executor::FeesMode>, Option<Assets>) {
1915                    use xcm_executor::traits::ConvertLocation;
1916
1917                    // This sets up the necessary infrastructure (HostConfiguration) for sending XCM messages
1918                    <xcm_config::XcmRouter as xcm::latest::SendXcm>::ensure_successful_delivery(
1919                        Some(dest.clone())
1920                    );
1921
1922                    // Open HRMP channel for sibling parachain destinations
1923                    if let Some(Parachain(para_id)) = dest.interior().first() {
1924                        ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
1925                            (*para_id).into()
1926                        );
1927                    }
1928
1929                    if let Some(account) = xcm_config::LocationToAccountId::convert_location(origin_ref) {
1930                        // Give the account some balance to ensure delivery
1931                        let balance = ExistentialDeposit::get() * 1000u128; // Give more than just ED
1932                        let _ = <Balances as frame_support::traits::Currency<_>>::
1933                            make_free_balance_be(&account.into(), balance);
1934                    }
1935
1936                    (None, None)
1937                }
1938            }
1939
1940            impl pallet_xcm::benchmarking::Config for Runtime {
1941                type DeliveryHelper = TestDeliveryHelper;
1942
1943                fn reachable_dest() -> Option<Location> {
1944                    Some(AssetHubLocation::get())
1945                }
1946
1947                fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
1948                    None
1949                }
1950
1951                fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
1952                    let random_para_id = 43211234;
1953                    ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
1954                        random_para_id.into()
1955                    );
1956                    Some((
1957                        Asset {
1958                            fun: Fungible(ExistentialDeposit::get()),
1959                            id: AssetId(Here.into())
1960                        },
1961                        ParentThen(Parachain(random_para_id).into()).into(),
1962                    ))
1963                }
1964
1965                fn set_up_complex_asset_transfer(
1966                ) -> Option<(Assets, u32, Location, Box<dyn FnOnce()>)> {
1967                    XcmBenchmarkHelper::<Runtime>::set_up_complex_asset_transfer()
1968                }
1969
1970                fn get_asset() -> Asset {
1971                    Asset {
1972                        id: AssetId(Here.into()),
1973                        fun: Fungible(ExistentialDeposit::get()),
1974                    }
1975                }
1976            }
1977
1978            // Needed to run `set_code` and `apply_authorized_upgrade` frame_system benchmarks
1979            // https://github.com/paritytech/cumulus/pull/2766
1980            impl frame_system_benchmarking::Config for Runtime {
1981                fn setup_set_code_requirements(code: &Vec<u8>) -> Result<(), BenchmarkError> {
1982                    ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32);
1983                    Ok(())
1984                }
1985
1986                fn verify_set_code() {
1987                    System::assert_last_event(cumulus_pallet_parachain_system::Event::<Runtime>::ValidationFunctionStored.into());
1988                }
1989            }
1990            impl baseline::Config for Runtime {}
1991
1992            // XCM Benchmarks
1993            impl astar_xcm_benchmarks::Config for Runtime {}
1994            impl astar_xcm_benchmarks::generic::Config for Runtime {}
1995            impl astar_xcm_benchmarks::fungible::Config for Runtime {}
1996
1997            impl pallet_xcm_benchmarks::Config for Runtime {
1998                type XcmConfig = xcm_config::XcmConfig;
1999                type AccountIdConverter = xcm_config::LocationToAccountId;
2000                type DeliveryHelper = TestDeliveryHelper;
2001
2002                // destination location to be used in benchmarks
2003                fn valid_destination() -> Result<Location, BenchmarkError> {
2004                    let asset_hub = AssetHubLocation::get();
2005                    assert_ok!(PolkadotXcm::force_xcm_version(RuntimeOrigin::root(), Box::new(asset_hub.clone()), xcm::v5::VERSION));
2006
2007                    // This sets up the necessary infrastructure (HostConfiguration) for sending XCM messages
2008                    <xcm_config::XcmRouter as xcm::latest::SendXcm>::ensure_successful_delivery(
2009                        Some(asset_hub.clone())
2010                    );
2011
2012                    // Open HRMP channel for sibling parachain destinations
2013                    ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
2014                        AssetHubParaId::get().into()
2015                    );
2016
2017                    Ok(asset_hub)
2018                }
2019                fn worst_case_holding(_depositable_count: u32) -> Assets {
2020                    XcmBenchmarkHelper::<Runtime>::worst_case_holding()
2021                }
2022            }
2023
2024            impl pallet_xcm_benchmarks::generic::Config for Runtime {
2025                type RuntimeCall = RuntimeCall;
2026                type TransactAsset = Balances;
2027
2028                fn worst_case_response() -> (u64, Response) {
2029                    (0u64, Response::Version(Default::default()))
2030                }
2031                fn worst_case_asset_exchange()
2032                    -> Result<(Assets, Assets), BenchmarkError> {
2033                    Err(BenchmarkError::Skip)
2034                }
2035                fn universal_alias() -> Result<(Location, Junction), BenchmarkError> {
2036                    Err(BenchmarkError::Skip)
2037                }
2038                fn transact_origin_and_runtime_call()
2039                    -> Result<(Location, RuntimeCall), BenchmarkError> {
2040                    assert_ok!(PolkadotXcm::force_xcm_version(RuntimeOrigin::root(), Box::new(Location::parent()), xcm::v5::VERSION));
2041                    Ok((Location::parent(), frame_system::Call::remark_with_event {
2042                        remark: vec![]
2043                    }.into()))
2044                }
2045                fn subscribe_origin() -> Result<Location, BenchmarkError> {
2046                    assert_ok!(PolkadotXcm::force_xcm_version(RuntimeOrigin::root(), Box::new(Location::parent()), xcm::v5::VERSION));
2047                    Ok(Location::parent())
2048                }
2049                fn claimable_asset()
2050                    -> Result<(Location, Location, Assets), BenchmarkError> {
2051                    let origin = Location::parent();
2052                    let assets: Assets = (AssetId(Location::parent()), 1_000u128)
2053                        .into();
2054                    let ticket = Location { parents: 0, interior: Here };
2055                    Ok((origin, ticket, assets))
2056                }
2057                fn unlockable_asset()
2058                    -> Result<(Location, Location, Asset), BenchmarkError> {
2059                    Err(BenchmarkError::Skip)
2060                }
2061                fn export_message_origin_and_destination(
2062                ) -> Result<(Location, NetworkId, InteriorLocation), BenchmarkError> {
2063                    Err(BenchmarkError::Skip)
2064                }
2065                fn alias_origin() -> Result<(Location, Location), BenchmarkError> {
2066                    Err(BenchmarkError::Skip)
2067                }
2068                fn worst_case_for_trader() -> Result<(Asset, WeightLimit), BenchmarkError> {
2069                    Ok((
2070                        (AssetId(Here.into()), 1_000_000_000_000_000_000u128).into(),
2071                        Limited(Weight::from_parts(5000, 5000)),
2072                    ))
2073                }
2074            }
2075
2076            parameter_types! {
2077                pub const NoCheckingAccount: Option<(AccountId, MintLocation)> = None;
2078                pub const NoTeleporter: Option<(Location, Asset)> = None;
2079                pub const TransactAssetId: u128 = 1001;
2080                pub TransactAssetLocation: Location = Location { parents: 0, interior: [GeneralIndex(TransactAssetId::get())].into() };
2081
2082                pub const AssetHubParaId: u32 = ASSET_HUB_PARA_ID;
2083                pub AssetHubLocation: Location = Location::new(1, [Parachain(AssetHubParaId::get())]);
2084                pub TrustedReserveLocation: Location = AssetHubLocation::get();
2085                pub TrustedReserveAsset: Asset = Asset { id: AssetId(TrustedReserveLocation::get()), fun: Fungible(1_000_000) };
2086                pub TrustedReserve: Option<(Location, Asset)> = Some((TrustedReserveLocation::get(), TrustedReserveAsset::get()));
2087            }
2088
2089            impl pallet_xcm_benchmarks::fungible::Config for Runtime {
2090                type TransactAsset = ItemOf<pallet_assets::Pallet<Runtime>, TransactAssetId, AccountId>;
2091                type CheckedAccount = NoCheckingAccount;
2092                type TrustedTeleporter = NoTeleporter;
2093                type TrustedReserve = TrustedReserve;
2094
2095                fn get_asset() -> Asset {
2096                    let min_balance = 100u128;
2097                    // create the transact asset and make it sufficient
2098                    assert_ok!(pallet_assets::Pallet::<Runtime>::force_create(
2099                        RuntimeOrigin::root(),
2100                        TransactAssetId::get().into(),
2101                        Address::Id([0u8; 32].into()),
2102                        true,
2103                        // min balance
2104                        min_balance
2105                    ));
2106
2107                    // convert mapping for asset id
2108                    assert_ok!(
2109                        XcAssetConfig::register_asset_location(
2110                            RuntimeOrigin::root(),
2111                            Box::new(TransactAssetLocation::get().into_versioned()),
2112                            TransactAssetId::get(),
2113                        )
2114                    );
2115
2116                    Asset {
2117                        id: AssetId(TransactAssetLocation::get()),
2118                        fun: Fungible(min_balance * 100),
2119                    }
2120                }
2121            }
2122
2123            type XcmFungible = astar_xcm_benchmarks::fungible::benchmarking::XcmFungibleBenchmarks::<Runtime>;
2124            type XcmGeneric = astar_xcm_benchmarks::generic::benchmarking::XcmGenericBenchmarks::<Runtime>;
2125
2126            let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
2127
2128            let mut batches = Vec::<BenchmarkBatch>::new();
2129            let params = (&config, &whitelist);
2130
2131            add_benchmarks!(params, batches);
2132
2133            if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
2134            Ok(batches)
2135        }
2136    }
2137
2138    #[cfg(feature = "evm-tracing")]
2139    impl moonbeam_rpc_primitives_debug::DebugRuntimeApi<Block> for Runtime {
2140        fn trace_transaction(
2141            extrinsics: Vec<<Block as BlockT>::Extrinsic>,
2142            traced_transaction: &pallet_ethereum::Transaction,
2143            header: &<Block as BlockT>::Header,
2144        ) -> Result<
2145            (),
2146            sp_runtime::DispatchError,
2147        > {
2148            use moonbeam_evm_tracer::tracer::EvmTracer;
2149
2150            // We need to follow the order when replaying the transactions.
2151            // Block initialize happens first then apply_extrinsic.
2152            Executive::initialize_block(header);
2153
2154            // Apply the a subset of extrinsics: all the substrate-specific or ethereum
2155            // transactions that preceded the requested transaction.
2156            for ext in extrinsics.into_iter() {
2157                let _ = match &ext.0.function {
2158                    RuntimeCall::Ethereum(pallet_ethereum::Call::transact { transaction }) => {
2159                        if transaction == traced_transaction {
2160                            EvmTracer::new().trace(|| Executive::apply_extrinsic(ext));
2161                            return Ok(());
2162                        } else {
2163                            Executive::apply_extrinsic(ext)
2164                        }
2165                    }
2166                    _ => Executive::apply_extrinsic(ext),
2167                };
2168            }
2169            Err(sp_runtime::DispatchError::Other(
2170                "Failed to find Ethereum transaction among the extrinsics.",
2171            ))
2172        }
2173
2174        fn trace_block(
2175            extrinsics: Vec<<Block as BlockT>::Extrinsic>,
2176            known_transactions: Vec<H256>,
2177            header: &<Block as BlockT>::Header,
2178        ) -> Result<
2179            (),
2180            sp_runtime::DispatchError,
2181        > {
2182            use moonbeam_evm_tracer::tracer::EvmTracer;
2183
2184            let mut config = <Runtime as pallet_evm::Config>::config().clone();
2185            config.estimate = true;
2186
2187            // We need to follow the order when replaying the transactions.
2188            // Block initialize happens first then apply_extrinsic.
2189            Executive::initialize_block(header);
2190
2191            // Apply all extrinsics. Ethereum extrinsics are traced.
2192            for ext in extrinsics.into_iter() {
2193                match &ext.0.function {
2194                    RuntimeCall::Ethereum(pallet_ethereum::Call::transact { transaction }) => {
2195                        if known_transactions.contains(&transaction.hash()) {
2196                            // Each known extrinsic is a new call stack.
2197                            EvmTracer::emit_new();
2198                            EvmTracer::new().trace(|| Executive::apply_extrinsic(ext));
2199                        } else {
2200                            let _ = Executive::apply_extrinsic(ext);
2201                        }
2202                    }
2203                    _ => {
2204                        let _ = Executive::apply_extrinsic(ext);
2205                    }
2206                };
2207            }
2208
2209            Ok(())
2210        }
2211
2212        fn trace_call(
2213            header: &<Block as BlockT>::Header,
2214            from: H160,
2215            to: H160,
2216            data: Vec<u8>,
2217            value: U256,
2218            gas_limit: U256,
2219            max_fee_per_gas: Option<U256>,
2220            max_priority_fee_per_gas: Option<U256>,
2221            nonce: Option<U256>,
2222            access_list: Option<Vec<(H160, Vec<H256>)>>,
2223            authorization_list: Option<AuthorizationList>,
2224        ) -> Result<(), sp_runtime::DispatchError> {
2225            use moonbeam_evm_tracer::tracer::EvmTracer;
2226
2227            // Initialize block: calls the "on_initialize" hook on every pallet
2228            // in AllPalletsWithSystem.
2229            Executive::initialize_block(header);
2230
2231            EvmTracer::new().trace(|| {
2232                let is_transactional = false;
2233                let validate = true;
2234                let without_base_extrinsic_weight = true;
2235
2236                // Estimated encoded transaction size must be based on the heaviest transaction
2237                // type (EIP1559Transaction) to be compatible with all transaction types.
2238                let mut estimated_transaction_len = data.len() +
2239                // pallet ethereum index: 1
2240                // transact call index: 1
2241                // Transaction enum variant: 1
2242                // chain_id 8 bytes
2243                // nonce: 32
2244                // max_priority_fee_per_gas: 32
2245                // max_fee_per_gas: 32
2246                // gas_limit: 32
2247                // action: 21 (enum varianrt + call address)
2248                // value: 32
2249                // access_list: 1 (empty vec size)
2250                // 65 bytes signature
2251                258;
2252
2253                if access_list.is_some() {
2254                    estimated_transaction_len += access_list.encoded_size();
2255                }
2256
2257                let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
2258
2259                let (weight_limit, proof_size_base_cost) =
2260                    match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
2261                        gas_limit,
2262                        without_base_extrinsic_weight
2263                    ) {
2264                        weight_limit if weight_limit.proof_size() > 0 => {
2265                            (Some(weight_limit), Some(estimated_transaction_len as u64))
2266                        }
2267                        _ => (None, None),
2268                    };
2269
2270                let _ = <Runtime as pallet_evm::Config>::Runner::call(
2271                    from,
2272                    to,
2273                    data,
2274                    value,
2275                    gas_limit,
2276                    max_fee_per_gas,
2277                    max_priority_fee_per_gas,
2278                    nonce,
2279                    access_list.unwrap_or_default(),
2280                    authorization_list.unwrap_or_default(),
2281                    is_transactional,
2282                    validate,
2283                    weight_limit,
2284                    proof_size_base_cost,
2285                    <Runtime as pallet_evm::Config>::config(),
2286                );
2287            });
2288            Ok(())
2289        }
2290    }
2291
2292    #[cfg(feature = "evm-tracing")]
2293    impl moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block> for Runtime {
2294        fn extrinsic_filter(
2295            xts_ready: Vec<<Block as BlockT>::Extrinsic>,
2296            xts_future: Vec<<Block as BlockT>::Extrinsic>,
2297        ) -> moonbeam_rpc_primitives_txpool::TxPoolResponse {
2298            moonbeam_rpc_primitives_txpool::TxPoolResponse {
2299                ready: xts_ready
2300                    .into_iter()
2301                    .filter_map(|xt| match xt.0.function {
2302                        RuntimeCall::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),
2303                        _ => None,
2304                    })
2305                    .collect(),
2306                future: xts_future
2307                    .into_iter()
2308                    .filter_map(|xt| match xt.0.function {
2309                        RuntimeCall::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),
2310                        _ => None,
2311                    })
2312                    .collect(),
2313            }
2314        }
2315    }
2316
2317    #[cfg(feature = "try-runtime")]
2318    impl frame_try_runtime::TryRuntime<Block> for Runtime {
2319        fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
2320            log::info!("try-runtime::on_runtime_upgrade");
2321            let weight = Executive::try_runtime_upgrade(checks).unwrap();
2322            (weight, RuntimeBlockWeights::get().max_block)
2323        }
2324
2325        fn execute_block(
2326            block: <Block as BlockT>::LazyBlock,
2327            state_root_check: bool,
2328            signature_check: bool,
2329            select: frame_try_runtime::TryStateSelect
2330        ) -> Weight {
2331            log::info!(
2332                "try-runtime: executing block #{} ({:?}) / root checks: {:?} / sanity-checks: {:?}",
2333                block.header.number,
2334                block.header.hash(),
2335                state_root_check,
2336                select,
2337            );
2338            Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed")
2339        }
2340    }
2341}
2342
2343cumulus_pallet_parachain_system::register_validate_block! {
2344    Runtime = Runtime,
2345    BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
2346}