local_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#![cfg_attr(not(feature = "std"), no_std)]
20// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
21#![recursion_limit = "256"]
22
23// Make the WASM binary available.
24#[cfg(feature = "std")]
25include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
26
27extern crate alloc;
28extern crate core;
29
30use alloc::{borrow::Cow, collections::btree_map::BTreeMap, vec, vec::Vec};
31use core::marker::PhantomData;
32
33use ethereum::AuthorizationList;
34use frame_support::{
35    construct_runtime, genesis_builder_helper, parameter_types,
36    traits::{
37        fungible::{Balanced, Credit, HoldConsideration},
38        AsEnsureOriginWithArg, ConstU128, ConstU32, ConstU64, ConstU8, Contains,
39        EqualPrivilegeOnly, FindAuthor, Get, InsideBoth, InstanceFilter, LinearStoragePrice,
40        Nothing, OnFinalize, WithdrawReasons,
41    },
42    weights::{
43        constants::{ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND},
44        ConstantMultiplier, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients,
45        WeightToFeePolynomial,
46    },
47    ConsensusEngineId, PalletId,
48};
49use frame_system::{
50    limits::{BlockLength, BlockWeights},
51    EnsureRoot, EnsureSigned, EnsureWithSuccess,
52};
53use pallet_ethereum::PostLogContent;
54use pallet_evm::{FeeCalculator, GasWeightMapping, Runner};
55use pallet_evm_precompile_assets_erc20::AddressToAssetId;
56use pallet_grandpa::{fg_primitives, AuthorityList as GrandpaAuthorityList};
57use pallet_transaction_payment::{FungibleAdapter, Multiplier, TargetedFeeAdjustment};
58use parity_scale_codec::{Compact, Decode, Encode, MaxEncodedLen};
59use sp_api::impl_runtime_apis;
60use sp_core::{
61    crypto::KeyTypeId, sr25519, ConstBool, DecodeWithMemTracking, OpaqueMetadata, H160, H256, U256,
62};
63use sp_runtime::{
64    generic, impl_opaque_keys,
65    traits::{
66        AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto,
67        DispatchInfoOf, Dispatchable, NumberFor, PostDispatchInfoOf, UniqueSaturatedInto,
68    },
69    transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError},
70    ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perbill, Permill, Perquintill, RuntimeDebug,
71};
72
73use astar_primitives::{
74    dapp_staking::{
75        CycleConfiguration, DAppId, EraNumber, PeriodNumber, RankedTier, SmartContract,
76        StandardTierSlots,
77    },
78    evm::{EvmRevertCodeHandler, HashedDefaultMappings},
79    governance::{
80        CommunityCouncilCollectiveInst, CommunityCouncilMembershipInst, CommunityTreasuryInst,
81        EnsureRootOrAllMainCouncil, EnsureRootOrAllTechnicalCommittee,
82        EnsureRootOrHalfTechnicalCommittee, EnsureRootOrTwoThirdsCommunityCouncil,
83        EnsureRootOrTwoThirdsMainCouncil, EnsureRootOrTwoThirdsTechnicalCommittee,
84        MainCouncilCollectiveInst, MainCouncilMembershipInst, MainTreasuryInst,
85        TechnicalCommitteeCollectiveInst, TechnicalCommitteeMembershipInst,
86    },
87    Address, AssetId, Balance, BlockNumber, Hash, Header, Nonce,
88};
89
90pub use astar_primitives::{AccountId, Signature};
91pub use pallet_dapp_staking::TierThreshold;
92
93pub use crate::precompiles::WhitelistedCalls;
94#[cfg(feature = "std")]
95use sp_version::NativeVersion;
96use sp_version::RuntimeVersion;
97
98pub use frame_system::Call as SystemCall;
99pub use pallet_balances::Call as BalancesCall;
100pub use pallet_grandpa::AuthorityId as GrandpaId;
101pub use pallet_inflation::InflationParameters;
102pub use pallet_timestamp::Call as TimestampCall;
103pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
104#[cfg(any(feature = "std", test))]
105pub use sp_runtime::BuildStorage;
106
107#[cfg(feature = "std")]
108/// Wasm binary unwrapped. If built with `BUILD_DUMMY_WASM_BINARY`, the function panics.
109pub fn wasm_binary_unwrap() -> &'static [u8] {
110    WASM_BINARY.expect(
111        "Development wasm binary is not available. This means the client is \
112                        built with `BUILD_DUMMY_WASM_BINARY` flag and it is only usable for \
113                        production chains. Please rebuild with the flag disabled.",
114    )
115}
116
117#[sp_version::runtime_version]
118pub const VERSION: RuntimeVersion = RuntimeVersion {
119    spec_name: Cow::Borrowed("local"),
120    impl_name: Cow::Borrowed("local"),
121    authoring_version: 1,
122    spec_version: 1,
123    impl_version: 1,
124    apis: RUNTIME_API_VERSIONS,
125    transaction_version: 1,
126    system_version: 1,
127};
128
129impl_opaque_keys! {
130    pub struct SessionKeys {
131        pub aura: Aura,
132        pub grandpa: Grandpa,
133    }
134}
135
136mod precompiles;
137pub use precompiles::{LocalPrecompiles, ASSET_PRECOMPILE_ADDRESS_PREFIX};
138pub type Precompiles = LocalPrecompiles<Runtime>;
139
140mod chain_extensions;
141pub use chain_extensions::LocalChainExtensions;
142
143pub mod genesis_config;
144mod weights;
145
146/// Constant values used within the runtime.
147pub const MICROAST: Balance = 1_000_000_000_000;
148pub const MILLIAST: Balance = 1_000 * MICROAST;
149pub const AST: Balance = 1_000 * MILLIAST;
150
151pub const STORAGE_BYTE_FEE: Balance = 100 * MICROAST;
152
153/// Charge fee for stored bytes and items.
154pub const fn deposit(items: u32, bytes: u32) -> Balance {
155    items as Balance * 1 * AST + (bytes as Balance) * STORAGE_BYTE_FEE
156}
157
158/// This determines the average expected block time that we are targeting.
159/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`.
160/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked
161/// up by `pallet_aura` to implement `fn slot_duration()`.
162///
163/// Change this to adjust the block time.
164pub const MILLISECS_PER_BLOCK: u64 = 2000;
165pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
166
167// Time is measured by number of blocks.
168pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
169pub const HOURS: BlockNumber = MINUTES * 60;
170pub const DAYS: BlockNumber = HOURS * 24;
171
172impl AddressToAssetId<AssetId> for Runtime {
173    fn address_to_asset_id(address: H160) -> Option<AssetId> {
174        let mut data = [0u8; 16];
175        let address_bytes: [u8; 20] = address.into();
176        if ASSET_PRECOMPILE_ADDRESS_PREFIX.eq(&address_bytes[0..4]) {
177            data.copy_from_slice(&address_bytes[4..20]);
178            Some(u128::from_be_bytes(data))
179        } else {
180            None
181        }
182    }
183
184    fn asset_id_to_address(asset_id: AssetId) -> H160 {
185        let mut data = [0u8; 20];
186        data[0..4].copy_from_slice(ASSET_PRECOMPILE_ADDRESS_PREFIX);
187        data[4..20].copy_from_slice(&asset_id.to_be_bytes());
188        H160::from(data)
189    }
190}
191
192/// The version information used to identify this runtime when compiled natively.
193#[cfg(feature = "std")]
194pub fn native_version() -> NativeVersion {
195    NativeVersion {
196        runtime_version: VERSION,
197        can_author_with: Default::default(),
198    }
199}
200
201/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used
202/// by  Operational  extrinsics.
203const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
204
205parameter_types! {
206    pub const Version: RuntimeVersion = VERSION;
207    pub const BlockHashCount: BlockNumber = 2400;
208    /// We allow for 1 seconds of compute with a 2 second average block time.
209    pub RuntimeBlockWeights: BlockWeights = BlockWeights
210        ::with_sensible_defaults(Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND, u64::MAX), NORMAL_DISPATCH_RATIO);
211    pub RuntimeBlockLength: BlockLength = BlockLength
212        ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
213    pub const SS58Prefix: u8 = 5;
214}
215
216// Configure FRAME pallets to include in runtime.
217impl frame_system::Config for Runtime {
218    /// The basic call filter to use in dispatchable.
219    type BaseCallFilter = InsideBoth<SafeMode, TxPause>;
220    /// Block & extrinsics weights: base values and limits.
221    type BlockWeights = RuntimeBlockWeights;
222    /// The maximum length of a block (in bytes).
223    type BlockLength = RuntimeBlockLength;
224    /// The identifier used to distinguish between accounts.
225    type AccountId = AccountId;
226    /// The aggregated dispatch type that is available for extrinsics.
227    type RuntimeCall = RuntimeCall;
228    /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
229    type Lookup = (AccountIdLookup<AccountId, ()>, UnifiedAccounts);
230    /// The nonce type for storing how many extrinsics an account has signed.
231    type Nonce = Nonce;
232    /// The type for blocks.
233    type Block = Block;
234    /// The type for hashing blocks and tries.
235    type Hash = Hash;
236    /// The hashing algorithm used.
237    type Hashing = BlakeTwo256;
238    /// The ubiquitous event type.
239    type RuntimeEvent = RuntimeEvent;
240    /// The ubiquitous origin type.
241    type RuntimeOrigin = RuntimeOrigin;
242    /// The aggregated RuntimeTask type.
243    type RuntimeTask = RuntimeTask;
244    /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
245    type BlockHashCount = BlockHashCount;
246    /// The weight of database operations that the runtime can invoke.
247    type DbWeight = RocksDbWeight;
248    /// Version of the runtime.
249    type Version = Version;
250    /// Converts a module to the index of the module in `construct_runtime!`.
251    ///
252    /// This type is being generated by `construct_runtime!`.
253    type PalletInfo = PalletInfo;
254    /// What to do if a new account is created.
255    type OnNewAccount = ();
256    /// What to do if an account is fully reaped from the system.
257    type OnKilledAccount = pallet_unified_accounts::KillAccountMapping<Self>;
258    /// The data to be stored in an account.
259    type AccountData = pallet_balances::AccountData<Balance>;
260    /// Weight information for the extrinsics of this pallet.
261    type SystemWeightInfo = frame_system::weights::SubstrateWeight<Runtime>;
262    /// This is used as an identifier of the chain. 42 is the generic substrate prefix.
263    type SS58Prefix = SS58Prefix;
264    /// The set code logic, just the default since we're not a parachain.
265    type OnSetCode = ();
266    type MaxConsumers = frame_support::traits::ConstU32<16>;
267    type SingleBlockMigrations = ();
268    type MultiBlockMigrator = ();
269    type PreInherents = ();
270    type PostInherents = ();
271    type PostTransactions = ();
272    type ExtensionsWeightInfo = ();
273}
274
275impl pallet_aura::Config for Runtime {
276    type AuthorityId = AuraId;
277    type DisabledValidators = ();
278    type MaxAuthorities = ConstU32<50>;
279    type SlotDuration = pallet_aura::MinimumPeriodTimesTwo<Runtime>;
280    type AllowMultipleBlocksPerSlot = ConstBool<false>;
281}
282
283impl pallet_grandpa::Config for Runtime {
284    type RuntimeEvent = RuntimeEvent;
285
286    type KeyOwnerProof = sp_core::Void;
287    type EquivocationReportSystem = ();
288
289    type WeightInfo = ();
290    type MaxAuthorities = ConstU32<50>;
291    type MaxSetIdSessionEntries = ConstU64<0>;
292    type MaxNominators = ConstU32<0>;
293}
294
295parameter_types! {
296    pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
297}
298
299impl pallet_timestamp::Config for Runtime {
300    /// A timestamp: milliseconds since the unix epoch.
301    type Moment = u64;
302    type OnTimestampSet = Aura;
303    type MinimumPeriod = MinimumPeriod;
304    type WeightInfo = pallet_timestamp::weights::SubstrateWeight<Runtime>;
305}
306
307impl pallet_insecure_randomness_collective_flip::Config for Runtime {}
308
309parameter_types! {
310    pub const ExistentialDeposit: u128 = 500;
311    pub const MaxLocks: u32 = 50;
312}
313
314impl pallet_balances::Config for Runtime {
315    type MaxLocks = MaxLocks;
316    type MaxReserves = ();
317    type ReserveIdentifier = [u8; 8];
318    /// The type for recording an account's balance.
319    type Balance = Balance;
320    /// The ubiquitous event type.
321    type RuntimeEvent = RuntimeEvent;
322    type DustRemoval = ();
323    type ExistentialDeposit = ExistentialDeposit;
324    type AccountStore = System;
325    type WeightInfo = weights::pallet_balances::SubstrateWeight<Runtime>;
326    type RuntimeHoldReason = RuntimeHoldReason;
327    type RuntimeFreezeReason = RuntimeFreezeReason;
328    type FreezeIdentifier = RuntimeFreezeReason;
329    type MaxFreezes = ConstU32<1>;
330    type DoneSlashHandler = ();
331}
332
333parameter_types! {
334    pub const AssetDeposit: Balance = 1 * AST;
335    pub const AssetsStringLimit: u32 = 50;
336    /// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1)
337    // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271
338    pub const MetadataDepositBase: Balance = deposit(1, 68);
339    pub const MetadataDepositPerByte: Balance = deposit(0, 1);
340    pub const AssetAccountDeposit: Balance = deposit(1, 18);
341}
342
343impl pallet_assets::Config for Runtime {
344    type RuntimeEvent = RuntimeEvent;
345    type Balance = Balance;
346    type AssetId = AssetId;
347    type Currency = Balances;
348    type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
349    type ForceOrigin = EnsureRoot<AccountId>;
350    type AssetDeposit = AssetDeposit;
351    type MetadataDepositBase = MetadataDepositBase;
352    type MetadataDepositPerByte = MetadataDepositPerByte;
353    type AssetAccountDeposit = AssetAccountDeposit;
354    type ApprovalDeposit = ExistentialDeposit;
355    type StringLimit = AssetsStringLimit;
356    type Freezer = ();
357    type Extra = ();
358    type Holder = ();
359    type WeightInfo = weights::pallet_assets::SubstrateWeight<Runtime>;
360    type RemoveItemsLimit = ConstU32<1000>;
361    type AssetIdParameter = Compact<AssetId>;
362    type CallbackHandle = EvmRevertCodeHandler<Self, Self>;
363    #[cfg(feature = "runtime-benchmarks")]
364    type BenchmarkHelper = astar_primitives::benchmarks::AssetsBenchmarkHelper;
365}
366
367// These values are based on the Astar 2.0 Tokenomics Modeling report.
368parameter_types! {
369    pub const TransactionLengthFeeFactor: Balance = 23_500_000_000_000; // 0.000_023_500_000_000_000 AST per byte
370    pub const WeightFeeFactor: Balance = 30_855_000_000_000_000; // Around 0.03 AST per unit of ref time.
371    pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25);
372    pub const OperationalFeeMultiplier: u8 = 5;
373    pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(000_015, 1_000_000); // 0.000_015
374    pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 10); // 0.1
375    pub MaximumMultiplier: Multiplier = Multiplier::saturating_from_integer(10); // 10
376}
377
378/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the
379/// node's balance type.
380///
381/// This should typically create a mapping between the following ranges:
382///   - [0, MAXIMUM_BLOCK_WEIGHT]
383///   - [Balance::min, Balance::max]
384///
385/// Yet, it can be used for any other sort of change to weight-fee. Some examples being:
386///   - Setting it to `0` will essentially disable the weight fee.
387///   - Setting it to `1` will cause the literal `#[weight = x]` values to be charged.
388pub struct WeightToFee;
389impl WeightToFeePolynomial for WeightToFee {
390    type Balance = Balance;
391    fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
392        let p = WeightFeeFactor::get();
393        let q = Balance::from(ExtrinsicBaseWeight::get().ref_time());
394        smallvec::smallvec![WeightToFeeCoefficient {
395            degree: 1,
396            negative: false,
397            coeff_frac: Perbill::from_rational(p % q, q),
398            coeff_integer: p / q,
399        }]
400    }
401}
402
403impl pallet_transaction_payment::Config for Runtime {
404    type RuntimeEvent = RuntimeEvent;
405    type OnChargeTransaction = FungibleAdapter<Balances, ()>;
406    type WeightToFee = WeightToFee;
407    type OperationalFeeMultiplier = OperationalFeeMultiplier;
408    type FeeMultiplierUpdate = TargetedFeeAdjustment<
409        Self,
410        TargetBlockFullness,
411        AdjustmentVariable,
412        MinimumMultiplier,
413        MaximumMultiplier,
414    >;
415    type LengthToFee = ConstantMultiplier<Balance, TransactionLengthFeeFactor>;
416    type WeightInfo = ();
417}
418
419parameter_types! {
420    pub DefaultBaseFeePerGas: U256 = U256::from(1_470_000_000_000_u128);
421    pub MinBaseFeePerGas: U256 = U256::from(800_000_000_000_u128);
422    pub MaxBaseFeePerGas: U256 = U256::from(80_000_000_000_000_u128);
423    pub StepLimitRatio: Perquintill = Perquintill::from_rational(5_u128, 100_000);
424}
425
426/// Simple wrapper for fetching current native transaction fee weight fee multiplier.
427pub struct AdjustmentFactorGetter;
428impl Get<Multiplier> for AdjustmentFactorGetter {
429    fn get() -> Multiplier {
430        pallet_transaction_payment::NextFeeMultiplier::<Runtime>::get()
431    }
432}
433
434impl pallet_dynamic_evm_base_fee::Config for Runtime {
435    type DefaultBaseFeePerGas = DefaultBaseFeePerGas;
436    type MinBaseFeePerGas = MinBaseFeePerGas;
437    type MaxBaseFeePerGas = MaxBaseFeePerGas;
438    type AdjustmentFactor = AdjustmentFactorGetter;
439    type WeightFactor = WeightFeeFactor;
440    type StepLimitRatio = StepLimitRatio;
441    type WeightInfo = pallet_dynamic_evm_base_fee::weights::SubstrateWeight<Runtime>;
442}
443
444parameter_types! {
445    pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry");
446    pub const DappsStakingPalletId: PalletId = PalletId(*b"py/dpsst");
447}
448
449impl pallet_static_price_provider::Config for Runtime {}
450
451#[cfg(feature = "runtime-benchmarks")]
452pub struct BenchmarkHelper<SC, ACC>(PhantomData<(SC, ACC)>);
453#[cfg(feature = "runtime-benchmarks")]
454impl pallet_dapp_staking::BenchmarkHelper<SmartContract<AccountId>, AccountId>
455    for BenchmarkHelper<SmartContract<AccountId>, AccountId>
456{
457    fn get_smart_contract(id: u32) -> SmartContract<AccountId> {
458        SmartContract::Wasm(AccountId::from([id as u8; 32]))
459    }
460
461    fn set_balance(account: &AccountId, amount: Balance) {
462        use frame_support::traits::fungible::Unbalanced as FunUnbalanced;
463        Balances::write_balance(account, amount)
464            .expect("Must succeed in test/benchmark environment.");
465    }
466}
467
468parameter_types! {
469    pub const BaseNativeCurrencyPrice: FixedU128 = FixedU128::from_rational(5, 100);
470}
471
472impl pallet_dapp_staking::Config for Runtime {
473    type RuntimeEvent = RuntimeEvent;
474    type RuntimeFreezeReason = RuntimeFreezeReason;
475    type Currency = Balances;
476    type SmartContract = SmartContract<AccountId>;
477    type ContractRegisterOrigin = EnsureRootOrTwoThirdsCommunityCouncil;
478    type ContractUnregisterOrigin = EnsureRoot<AccountId>;
479    type ManagerOrigin = EnsureRootOrTwoThirdsTechnicalCommittee;
480    type NativePriceProvider = StaticPriceProvider;
481    type StakingRewardHandler = Inflation;
482    type CycleConfiguration = InflationCycleConfig;
483    type Observers = Inflation;
484    type AccountCheck = ();
485    type TierSlots = StandardTierSlots;
486    type BaseNativeCurrencyPrice = BaseNativeCurrencyPrice;
487    type EraRewardSpanLength = ConstU32<8>;
488    type RewardRetentionInPeriods = ConstU32<2>;
489    type MaxNumberOfContracts = ConstU32<100>;
490    type MaxUnlockingChunks = ConstU32<5>;
491    type MinimumLockedAmount = ConstU128<AST>;
492    type UnlockingPeriod = ConstU32<2>;
493    type MaxNumberOfStakedContracts = ConstU32<3>;
494    type MinimumStakeAmount = ConstU128<AST>;
495    type NumberOfTiers = ConstU32<4>;
496    type RankingEnabled = ConstBool<true>;
497    type MaxBonusSafeMovesPerPeriod = ConstU8<0>;
498    type WeightInfo = pallet_dapp_staking::weights::SubstrateWeight<Runtime>;
499    #[cfg(feature = "runtime-benchmarks")]
500    type BenchmarkHelper = BenchmarkHelper<SmartContract<AccountId>, AccountId>;
501}
502
503pub struct InflationPayoutPerBlock;
504impl pallet_inflation::PayoutPerBlock<Credit<AccountId, Balances>> for InflationPayoutPerBlock {
505    fn treasury(reward: Credit<AccountId, Balances>) {
506        let _ = Balances::resolve(&TreasuryPalletId::get().into_account_truncating(), reward);
507    }
508
509    fn collators(_reward: Credit<AccountId, Balances>) {
510        // no collators for local dev node
511    }
512}
513
514pub struct InflationCycleConfig;
515impl CycleConfiguration for InflationCycleConfig {
516    fn periods_per_cycle() -> PeriodNumber {
517        4
518    }
519
520    fn eras_per_voting_subperiod() -> EraNumber {
521        2
522    }
523
524    fn eras_per_build_and_earn_subperiod() -> EraNumber {
525        22
526    }
527
528    fn blocks_per_era() -> BlockNumber {
529        30
530    }
531}
532
533impl pallet_inflation::Config for Runtime {
534    type Currency = Balances;
535    type PayoutPerBlock = InflationPayoutPerBlock;
536    type CycleConfiguration = InflationCycleConfig;
537    type WeightInfo = pallet_inflation::weights::SubstrateWeight<Runtime>;
538}
539
540impl pallet_utility::Config for Runtime {
541    type RuntimeEvent = RuntimeEvent;
542    type RuntimeCall = RuntimeCall;
543    type PalletsOrigin = OriginCaller;
544    type WeightInfo = pallet_utility::weights::SubstrateWeight<Runtime>;
545}
546
547parameter_types! {
548    // 2 storage items with value size 20 and 32
549    pub const AccountMappingStorageFee: u128 = deposit(2, 32 + 20);
550}
551
552impl pallet_unified_accounts::Config for Runtime {
553    type Currency = Balances;
554    type DefaultMappings = HashedDefaultMappings<BlakeTwo256>;
555    type ChainId = ChainId;
556    type AccountMappingStorageFee = AccountMappingStorageFee;
557    type WeightInfo = pallet_unified_accounts::weights::SubstrateWeight<Self>;
558}
559
560parameter_types! {
561    pub ReservedXcmpWeight: Weight = Weight::zero();
562}
563
564impl pallet_ethereum_checked::Config for Runtime {
565    type ReservedXcmpWeight = ReservedXcmpWeight;
566    type InvalidEvmTransactionError = pallet_ethereum::InvalidTransactionWrapper;
567    type ValidatedTransaction = pallet_ethereum::ValidatedTransaction<Self>;
568    type AddressMapper = UnifiedAccounts;
569    type XcmTransactOrigin = pallet_ethereum_checked::EnsureXcmEthereumTx<AccountId>;
570    type WeightInfo = pallet_ethereum_checked::weights::SubstrateWeight<Runtime>;
571}
572
573/// Current approximation of the gas/s consumption considering
574/// EVM execution over compiled WASM (on 4.4Ghz CPU).
575/// Given the 500ms Weight, from which 75% only are used for transactions,
576/// the total EVM execution gas limit is: GAS_PER_SECOND * 0.500 * 0.75 ~= 15_000_000.
577pub const GAS_PER_SECOND: u64 = 40_000_000;
578
579/// Approximate ratio of the amount of Weight per Gas.
580/// u64 works for approximations because Weight is a very small unit compared to gas.
581pub const WEIGHT_PER_GAS: u64 = WEIGHT_REF_TIME_PER_SECOND.saturating_div(GAS_PER_SECOND);
582
583pub struct FindAuthorTruncated<F>(PhantomData<F>);
584impl<F: FindAuthor<u32>> FindAuthor<H160> for FindAuthorTruncated<F> {
585    fn find_author<'a, I>(digests: I) -> Option<H160>
586    where
587        I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
588    {
589        if let Some(author_index) = F::find_author(digests) {
590            let authority_id =
591                pallet_aura::Authorities::<Runtime>::get()[author_index as usize].clone();
592            return Some(H160::from_slice(&authority_id.encode()[4..24]));
593        }
594
595        None
596    }
597}
598
599parameter_types! {
600    /// Ethereum-compatible chain_id:
601    /// * Dusty:   80
602    /// * Shibuya: 81
603    /// * Shiden: 336
604    /// * Local: 4369
605    pub ChainId: u64 = 0x1111;
606    /// EVM gas limit
607    pub BlockGasLimit: U256 = U256::from(
608        NORMAL_DISPATCH_RATIO * WEIGHT_REF_TIME_PER_SECOND / WEIGHT_PER_GAS
609    );
610    pub PrecompilesValue: Precompiles = LocalPrecompiles::<_>::new();
611    pub WeightPerGas: Weight = Weight::from_parts(WEIGHT_PER_GAS, 0);
612    /// The amount of gas per PoV size. Value is calculated as:
613    ///
614    /// max_gas_limit = max_tx_ref_time / WEIGHT_PER_GAS = max_pov_size * gas_limit_pov_size_ratio
615    /// gas_limit_pov_size_ratio = ceil((max_tx_ref_time / WEIGHT_PER_GAS) / max_pov_size)
616    ///
617    /// Local runtime has no strict bounds as parachain, but we keep the value set to 4 for consistency.
618    pub const GasLimitPovSizeRatio: u64 = 4;
619}
620
621impl pallet_evm::Config for Runtime {
622    type FeeCalculator = DynamicEvmBaseFee;
623    type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
624    type WeightPerGas = WeightPerGas;
625    type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Runtime>;
626    type CallOrigin = pallet_evm::EnsureAddressRoot<AccountId>;
627    type WithdrawOrigin = pallet_evm::EnsureAddressTruncated;
628    type AddressMapping = UnifiedAccounts;
629    type Currency = Balances;
630    type Runner = pallet_evm::runner::stack::Runner<Self>;
631    type PrecompilesType = Precompiles;
632    type PrecompilesValue = PrecompilesValue;
633    type ChainId = ChainId;
634    type OnChargeTransaction = pallet_evm::EVMFungibleAdapter<Balances, ()>;
635    type BlockGasLimit = BlockGasLimit;
636    type Timestamp = Timestamp;
637    type OnCreate = ();
638    type FindAuthor = FindAuthorTruncated<Aura>;
639    type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
640    type AccountProvider = pallet_evm::FrameSystemAccountProvider<Self>;
641    // gas based storage limit not enabled
642    type GasLimitStorageGrowthRatio = ConstU64<0>;
643    type CreateOriginFilter = ();
644    type CreateInnerOriginFilter = ();
645    type WeightInfo = pallet_evm::weights::SubstrateWeight<Runtime>;
646}
647
648parameter_types! {
649    pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes;
650}
651
652impl pallet_ethereum::Config for Runtime {
653    type StateRoot =
654        pallet_ethereum::IntermediateStateRoot<<Self as frame_system::Config>::Version>;
655    type PostLogContent = PostBlockAndTxnHashes;
656    // Maximum length (in bytes) of revert message to include in Executed event
657    type ExtraDataLength = ConstU32<30>;
658}
659
660parameter_types! {
661    pub MaximumSchedulerWeight: Weight = NORMAL_DISPATCH_RATIO * RuntimeBlockWeights::get().max_block;
662}
663
664impl pallet_scheduler::Config for Runtime {
665    type RuntimeEvent = RuntimeEvent;
666    type RuntimeOrigin = RuntimeOrigin;
667    type PalletsOrigin = OriginCaller;
668    type RuntimeCall = RuntimeCall;
669    type MaximumWeight = MaximumSchedulerWeight;
670    type ScheduleOrigin = EnsureRoot<AccountId>;
671    type MaxScheduledPerBlock = ConstU32<50>;
672    // TODO: re-bench pallet_scheduler weights or use default weights.
673    type WeightInfo = pallet_scheduler::weights::SubstrateWeight<Runtime>;
674    type OriginPrivilegeCmp = EqualPrivilegeOnly;
675    type Preimages = Preimage;
676    type BlockNumberProvider = System;
677}
678
679parameter_types! {
680    pub const PreimageBaseDeposit: Balance = deposit(1, 0);
681    pub const PreimageByteDeposit: Balance = deposit(0, 1);
682    pub const PreimageHoldReason: RuntimeHoldReason = RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage);
683}
684
685impl pallet_preimage::Config for Runtime {
686    type WeightInfo = pallet_preimage::weights::SubstrateWeight<Runtime>;
687    type RuntimeEvent = RuntimeEvent;
688    type Currency = Balances;
689    type ManagerOrigin = EnsureRoot<AccountId>;
690    type Consideration = HoldConsideration<
691        AccountId,
692        Balances,
693        PreimageHoldReason,
694        LinearStoragePrice<PreimageBaseDeposit, PreimageByteDeposit, Balance>,
695    >;
696}
697
698parameter_types! {
699    pub const MinVestedTransfer: Balance = 1 * AST;
700    pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons =
701        WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE);
702}
703
704impl pallet_vesting::Config for Runtime {
705    type RuntimeEvent = RuntimeEvent;
706    type Currency = Balances;
707    type BlockNumberToBalance = ConvertInto;
708    type MinVestedTransfer = MinVestedTransfer;
709    type WeightInfo = pallet_vesting::weights::SubstrateWeight<Runtime>;
710    type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons;
711    type BlockNumberProvider = System;
712    // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the
713    // highest number of schedules that encodes less than 2^10.
714    const MAX_VESTING_SCHEDULES: u32 = 28;
715}
716
717parameter_types! {
718    pub const DepositPerItem: Balance = deposit(1, 0);
719    pub const DepositPerByte: Balance = deposit(0, 1);
720    // Fallback value if storage deposit limit not set by the user
721    pub const DefaultDepositLimit: Balance = deposit(16, 16 * 1024);
722    pub const MaxDelegateDependencies: u32 = 32;
723    pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(10);
724    pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();
725}
726
727impl pallet_contracts::Config for Runtime {
728    type Time = Timestamp;
729    type Randomness = RandomnessCollectiveFlip;
730    type Currency = Balances;
731    type RuntimeEvent = RuntimeEvent;
732    type RuntimeCall = RuntimeCall;
733    /// The safest default is to allow no calls at all.
734    ///
735    /// Runtimes should whitelist dispatchables that are allowed to be called from contracts
736    /// and make sure they are stable. Dispatchables exposed to contracts are not allowed to
737    /// change because that would break already deployed contracts. The `Call` structure itself
738    /// is not allowed to change the indices of existing pallets, too.
739    type CallFilter = Nothing;
740    type DepositPerItem = DepositPerItem;
741    type DepositPerByte = DepositPerByte;
742    type DefaultDepositLimit = DefaultDepositLimit;
743    type CallStack = [pallet_contracts::Frame<Self>; 5];
744    type WeightPrice = pallet_transaction_payment::Pallet<Self>;
745    type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
746    type ChainExtension = LocalChainExtensions<Self, UnifiedAccounts>;
747    type Schedule = Schedule;
748    type AddressGenerator = pallet_contracts::DefaultAddressGenerator;
749    type MaxCodeLen = ConstU32<{ 123 * 1024 }>;
750    type MaxStorageKeyLen = ConstU32<128>;
751    type UnsafeUnstableInterface = ConstBool<true>;
752    type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>;
753    type MaxDelegateDependencies = MaxDelegateDependencies;
754    type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
755    type RuntimeHoldReason = RuntimeHoldReason;
756    type Debug = ();
757    type Environment = ();
758    type Migrations = ();
759    type Xcm = ();
760    type UploadOrigin = EnsureSigned<<Self as frame_system::Config>::AccountId>;
761    type InstantiateOrigin = EnsureSigned<<Self as frame_system::Config>::AccountId>;
762    type ApiVersion = ();
763    type MaxTransientStorageSize = ConstU32<{ 1 * 1024 * 1024 }>;
764}
765
766impl pallet_sudo::Config for Runtime {
767    type RuntimeEvent = RuntimeEvent;
768    type RuntimeCall = RuntimeCall;
769    type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
770}
771
772/// The type used to represent the kinds of proxying allowed.
773#[derive(
774    Copy,
775    Clone,
776    Eq,
777    PartialEq,
778    Ord,
779    PartialOrd,
780    Encode,
781    Decode,
782    DecodeWithMemTracking,
783    RuntimeDebug,
784    MaxEncodedLen,
785    scale_info::TypeInfo,
786)]
787pub enum ProxyType {
788    /// Allows all runtime calls for proxy account
789    Any,
790    /// Allows only NonTransfer runtime calls for proxy account
791    /// To know exact calls check InstanceFilter implementation for ProxyTypes
792    NonTransfer,
793    /// All Runtime calls from Pallet Balances allowed for proxy account
794    Balances,
795    /// All Runtime calls from Pallet Assets allowed for proxy account
796    Assets,
797    /// Only reject_announcement call from pallet proxy allowed for proxy account
798    CancelProxy,
799    /// All runtime calls from pallet DappStaking allowed for proxy account
800    DappStaking,
801    /// Only claim_staker call from pallet DappStaking allowed for proxy account
802    StakerRewardClaim,
803    /// All governance related calls allowed for proxy account
804    Governance,
805}
806
807impl Default for ProxyType {
808    fn default() -> Self {
809        Self::Any
810    }
811}
812
813impl InstanceFilter<RuntimeCall> for ProxyType {
814    fn filter(&self, c: &RuntimeCall) -> bool {
815        match self {
816            // Always allowed RuntimeCall::Utility no matter type.
817            // Only transactions allowed by Proxy.filter can be executed
818            _ if matches!(c, RuntimeCall::Utility(..)) => true,
819            // Allows all runtime calls for proxy account
820            ProxyType::Any => true,
821            // Allows only NonTransfer runtime calls for proxy account
822            ProxyType::NonTransfer => {
823                matches!(
824                    c,
825                    RuntimeCall::System(..)
826                        | RuntimeCall::Proxy(..)
827                        | RuntimeCall::Vesting(
828                            pallet_vesting::Call::vest { .. }
829                                | pallet_vesting::Call::vest_other { .. }
830                        )
831                        | RuntimeCall::DappStaking(..)
832                )
833            }
834            // All Runtime calls from Pallet Balances allowed for proxy account
835            ProxyType::Balances => {
836                matches!(c, RuntimeCall::Balances(..))
837            }
838            // All Runtime calls from Pallet Assets allowed for proxy account
839            ProxyType::Assets => {
840                matches!(c, RuntimeCall::Assets(..))
841            }
842            // Only reject_announcement call from pallet proxy allowed for proxy account
843            ProxyType::CancelProxy => {
844                matches!(
845                    c,
846                    RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. })
847                )
848            }
849            // All runtime calls from pallet DappStaking allowed for proxy account
850            ProxyType::DappStaking => {
851                matches!(c, RuntimeCall::DappStaking(..))
852            }
853            ProxyType::StakerRewardClaim => {
854                matches!(
855                    c,
856                    RuntimeCall::DappStaking(
857                        pallet_dapp_staking::Call::claim_staker_rewards { .. }
858                    )
859                )
860            }
861            ProxyType::Governance => {
862                matches!(
863                    c,
864                    RuntimeCall::Democracy(..)
865                        | RuntimeCall::Council(..)
866                        | RuntimeCall::TechnicalCommittee(..)
867                        | RuntimeCall::CommunityCouncil(..)
868                )
869            }
870        }
871    }
872
873    fn is_superset(&self, o: &Self) -> bool {
874        match (self, o) {
875            (x, y) if x == y => true,
876            (ProxyType::Any, _) => true,
877            (_, ProxyType::Any) => false,
878            (ProxyType::NonTransfer, _) => true,
879            (ProxyType::DappStaking, ProxyType::StakerRewardClaim) => true,
880            _ => false,
881        }
882    }
883}
884
885impl pallet_proxy::Config for Runtime {
886    type RuntimeEvent = RuntimeEvent;
887    type RuntimeCall = RuntimeCall;
888    type Currency = Balances;
889    type ProxyType = ProxyType;
890    // One storage item; key size 32, value size 8; .
891    type ProxyDepositBase = ConstU128<{ AST * 10 }>;
892    // Additional storage item size of 33 bytes.
893    type ProxyDepositFactor = ConstU128<{ MILLIAST * 330 }>;
894    type MaxProxies = ConstU32<32>;
895    type WeightInfo = pallet_proxy::weights::SubstrateWeight<Runtime>;
896    type MaxPending = ConstU32<32>;
897    type CallHasher = BlakeTwo256;
898    // Key size 32 + 1 item
899    type AnnouncementDepositBase = ConstU128<{ AST * 10 }>;
900    // Acc Id + Hash + block number
901    type AnnouncementDepositFactor = ConstU128<{ MILLIAST * 660 }>;
902    type BlockNumberProvider = System;
903}
904
905parameter_types! {
906    pub const CouncilMaxMembers: u32 = 5;
907    pub const TechnicalCommitteeMaxMembers: u32 = 3;
908    pub const CommunityCouncilMaxMembers: u32 = 10;
909}
910
911impl pallet_membership::Config<MainCouncilMembershipInst> for Runtime {
912    type RuntimeEvent = RuntimeEvent;
913    type AddOrigin = EnsureRootOrTwoThirdsMainCouncil;
914    type RemoveOrigin = EnsureRootOrTwoThirdsMainCouncil;
915    type SwapOrigin = EnsureRootOrTwoThirdsMainCouncil;
916    type ResetOrigin = EnsureRootOrTwoThirdsMainCouncil;
917    type PrimeOrigin = EnsureRootOrTwoThirdsMainCouncil;
918    type MembershipInitialized = Council;
919    type MembershipChanged = Council;
920    type MaxMembers = CouncilMaxMembers;
921    type WeightInfo = pallet_membership::weights::SubstrateWeight<Runtime>;
922}
923
924impl pallet_membership::Config<TechnicalCommitteeMembershipInst> for Runtime {
925    type RuntimeEvent = RuntimeEvent;
926    type AddOrigin = EnsureRootOrTwoThirdsMainCouncil;
927    type RemoveOrigin = EnsureRootOrTwoThirdsMainCouncil;
928    type SwapOrigin = EnsureRootOrTwoThirdsMainCouncil;
929    type ResetOrigin = EnsureRootOrTwoThirdsMainCouncil;
930    type PrimeOrigin = EnsureRootOrTwoThirdsMainCouncil;
931    type MembershipInitialized = TechnicalCommittee;
932    type MembershipChanged = TechnicalCommittee;
933    type MaxMembers = TechnicalCommitteeMaxMembers;
934    type WeightInfo = pallet_membership::weights::SubstrateWeight<Runtime>;
935}
936
937impl pallet_membership::Config<CommunityCouncilMembershipInst> for Runtime {
938    type RuntimeEvent = RuntimeEvent;
939    type AddOrigin = EnsureRootOrTwoThirdsMainCouncil;
940    type RemoveOrigin = EnsureRootOrTwoThirdsMainCouncil;
941    type SwapOrigin = EnsureRootOrTwoThirdsMainCouncil;
942    type ResetOrigin = EnsureRootOrTwoThirdsMainCouncil;
943    type PrimeOrigin = EnsureRootOrTwoThirdsMainCouncil;
944    type MembershipInitialized = CommunityCouncil;
945    type MembershipChanged = CommunityCouncil;
946    type MaxMembers = CommunityCouncilMaxMembers;
947    type WeightInfo = pallet_membership::weights::SubstrateWeight<Runtime>;
948}
949
950parameter_types! {
951    pub MaxProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block;
952}
953
954impl pallet_collective::Config<MainCouncilCollectiveInst> for Runtime {
955    type RuntimeOrigin = RuntimeOrigin;
956    type Proposal = RuntimeCall;
957    type RuntimeEvent = RuntimeEvent;
958    type MotionDuration = ConstU32<{ 5 * MINUTES }>;
959    type MaxProposals = ConstU32<16>;
960    type MaxMembers = CouncilMaxMembers;
961    type DefaultVote = pallet_collective::PrimeDefaultVote;
962    type SetMembersOrigin = EnsureRoot<AccountId>;
963    type MaxProposalWeight = MaxProposalWeight;
964    type KillOrigin = EnsureRoot<AccountId>;
965    type DisapproveOrigin = EnsureRoot<AccountId>;
966    type Consideration = ();
967    type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
968}
969
970impl pallet_collective::Config<TechnicalCommitteeCollectiveInst> for Runtime {
971    type RuntimeOrigin = RuntimeOrigin;
972    type Proposal = RuntimeCall;
973    type RuntimeEvent = RuntimeEvent;
974    type MotionDuration = ConstU32<{ 5 * MINUTES }>;
975    type MaxProposals = ConstU32<16>;
976    type MaxMembers = TechnicalCommitteeMaxMembers;
977    type DefaultVote = pallet_collective::PrimeDefaultVote;
978    type SetMembersOrigin = EnsureRoot<AccountId>;
979    type MaxProposalWeight = MaxProposalWeight;
980    type KillOrigin = EnsureRoot<AccountId>;
981    type DisapproveOrigin = EnsureRoot<AccountId>;
982    type Consideration = ();
983    type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
984}
985
986impl pallet_collective::Config<CommunityCouncilCollectiveInst> for Runtime {
987    type RuntimeOrigin = RuntimeOrigin;
988    type Proposal = RuntimeCall;
989    type RuntimeEvent = RuntimeEvent;
990    type MotionDuration = ConstU32<{ 5 * MINUTES }>;
991    type MaxProposals = ConstU32<16>;
992    type MaxMembers = CommunityCouncilMaxMembers;
993    type DefaultVote = pallet_collective::PrimeDefaultVote;
994    type SetMembersOrigin = EnsureRoot<AccountId>;
995    type MaxProposalWeight = MaxProposalWeight;
996    type KillOrigin = EnsureRoot<AccountId>;
997    type DisapproveOrigin = EnsureRoot<AccountId>;
998    type Consideration = ();
999    type WeightInfo = pallet_collective::weights::SubstrateWeight<Runtime>;
1000}
1001
1002impl pallet_democracy::Config for Runtime {
1003    type RuntimeEvent = RuntimeEvent;
1004    type Currency = Balances;
1005    type EnactmentPeriod = ConstU32<{ 5 * MINUTES }>;
1006    type LaunchPeriod = ConstU32<{ 5 * MINUTES }>;
1007    type VotingPeriod = ConstU32<{ 5 * MINUTES }>;
1008    type VoteLockingPeriod = ConstU32<{ 2 * MINUTES }>;
1009    type MinimumDeposit = ConstU128<{ 10 * AST }>;
1010    type FastTrackVotingPeriod = ConstU32<{ MINUTES / 2 }>;
1011    type CooloffPeriod = ConstU32<{ 2 * MINUTES }>;
1012
1013    type MaxVotes = ConstU32<128>;
1014    type MaxProposals = ConstU32<128>;
1015    type MaxDeposits = ConstU32<128>;
1016    type MaxBlacklisted = ConstU32<128>;
1017
1018    /// A two third majority of the Council can choose the next external "super majority approve" proposal.
1019    type ExternalOrigin = EnsureRootOrTwoThirdsMainCouncil;
1020    /// A two third majority of the Council can choose the next external "majority approve" proposal. Also bypasses blacklist filter.
1021    type ExternalMajorityOrigin = EnsureRootOrTwoThirdsMainCouncil;
1022    /// Unanimous approval of the Council can choose the next external "super majority against" proposal.
1023    type ExternalDefaultOrigin = EnsureRootOrAllMainCouncil;
1024    /// A two third majority of the Technical Committee can have an external proposal tabled immediately
1025    /// for a _fast track_ vote, and a custom enactment period.
1026    type FastTrackOrigin = EnsureRootOrTwoThirdsTechnicalCommittee;
1027    /// Unanimous approval of the Technical Committee can have an external proposal tabled immediately
1028    /// for a completely custom _voting period length_ vote, and a custom enactment period.
1029    type InstantOrigin = EnsureRootOrAllTechnicalCommittee;
1030    type InstantAllowed = ConstBool<true>;
1031
1032    /// A two third majority of the Council can cancel a passed proposal. Can happen only once per unique proposal.
1033    type CancellationOrigin = EnsureRootOrTwoThirdsMainCouncil;
1034    /// Only a passed public referendum can permanently blacklist a proposal.
1035    type BlacklistOrigin = EnsureRoot<AccountId>;
1036    /// An unanimous Technical Committee can cancel a public proposal, slashing the deposit(s).
1037    type CancelProposalOrigin = EnsureRootOrAllTechnicalCommittee;
1038    /// Any member of the Technical Committee can veto Council's proposal. This can be only done once per proposal, and _veto_ lasts for a _cooloff_ period.
1039    type VetoOrigin = pallet_collective::EnsureMember<AccountId, TechnicalCommitteeCollectiveInst>;
1040
1041    type SubmitOrigin = EnsureSigned<AccountId>;
1042    type PalletsOrigin = OriginCaller;
1043    type Preimages = Preimage;
1044    type Scheduler = Scheduler;
1045    type Slash = ();
1046    type WeightInfo = pallet_democracy::weights::SubstrateWeight<Runtime>;
1047}
1048
1049parameter_types! {
1050    pub const ProposalBond: Permill = Permill::from_percent(5);
1051    pub MainTreasuryAccount: AccountId = Treasury::account_id();
1052}
1053
1054impl pallet_treasury::Config<MainTreasuryInst> for Runtime {
1055    type PalletId = TreasuryPalletId;
1056    type Currency = Balances;
1057    type RuntimeEvent = RuntimeEvent;
1058
1059    // Two origins which can either approve or reject the spending proposal
1060    type ApproveOrigin = EnsureRootOrTwoThirdsMainCouncil;
1061    type RejectOrigin = EnsureRootOrTwoThirdsMainCouncil;
1062
1063    type OnSlash = Treasury;
1064    type ProposalBond = ProposalBond;
1065    type ProposalBondMinimum = ConstU128<{ 10 * AST }>;
1066    type ProposalBondMaximum = ConstU128<{ 100 * AST }>;
1067    type SpendPeriod = ConstU32<{ 1 * MINUTES }>;
1068
1069    // We don't do periodic burns of the treasury
1070    type Burn = ();
1071    type BurnDestination = ();
1072    type SpendFunds = ();
1073    type MaxApprovals = ConstU32<64>;
1074
1075    type WeightInfo = pallet_treasury::weights::SubstrateWeight<Runtime>;
1076}
1077
1078parameter_types! {
1079    pub const CommunityTreasuryPalletId: PalletId = PalletId(*b"py/comtr");
1080}
1081
1082impl pallet_treasury::Config<CommunityTreasuryInst> for Runtime {
1083    type PalletId = CommunityTreasuryPalletId;
1084    type Currency = Balances;
1085    type RuntimeEvent = RuntimeEvent;
1086
1087    // Two origins which can either approve or reject the spending proposal
1088    type ApproveOrigin = EnsureRootOrTwoThirdsCommunityCouncil;
1089    type RejectOrigin = EnsureRootOrTwoThirdsCommunityCouncil;
1090
1091    type OnSlash = CommunityTreasury;
1092    type ProposalBond = ProposalBond;
1093    type ProposalBondMinimum = ConstU128<{ 10 * AST }>;
1094    type ProposalBondMaximum = ConstU128<{ 100 * AST }>;
1095    type SpendPeriod = ConstU32<{ 1 * MINUTES }>;
1096
1097    // We don't do periodic burns of the community treasury
1098    type Burn = ();
1099    type BurnDestination = ();
1100    type SpendFunds = ();
1101    type MaxApprovals = ConstU32<64>;
1102
1103    type WeightInfo = pallet_treasury::weights::SubstrateWeight<Runtime>;
1104}
1105
1106parameter_types! {
1107    pub CommunityTreasuryAccountId: AccountId = CommunityTreasuryPalletId::get().into_account_truncating();
1108}
1109
1110#[derive(Default)]
1111pub struct CommunityCouncilCallFilter;
1112impl InstanceFilter<RuntimeCall> for CommunityCouncilCallFilter {
1113    fn filter(&self, c: &RuntimeCall) -> bool {
1114        matches!(
1115            c,
1116            RuntimeCall::DappStaking(..)
1117                | RuntimeCall::System(frame_system::Call::remark { .. })
1118                | RuntimeCall::Utility(pallet_utility::Call::batch { .. })
1119                | RuntimeCall::Utility(pallet_utility::Call::batch_all { .. })
1120        )
1121    }
1122}
1123
1124impl pallet_collective_proxy::Config for Runtime {
1125    type RuntimeCall = RuntimeCall;
1126    type CollectiveProxy = EnsureRootOrTwoThirdsCommunityCouncil;
1127    type ProxyAccountId = CommunityTreasuryAccountId;
1128    type CallFilter = CommunityCouncilCallFilter;
1129    type WeightInfo = pallet_collective_proxy::weights::SubstrateWeight<Runtime>;
1130}
1131
1132/// Calls that can bypass the safe-mode pallet.
1133pub struct SafeModeWhitelistedCalls;
1134impl Contains<RuntimeCall> for SafeModeWhitelistedCalls {
1135    fn contains(call: &RuntimeCall) -> bool {
1136        match call {
1137            // System and Timestamp are required for block production
1138            RuntimeCall::System(_)
1139            | RuntimeCall::Timestamp(_)
1140            | RuntimeCall::Sudo(_)
1141            | RuntimeCall::TxPause(_) => true,
1142            _ => false,
1143        }
1144    }
1145}
1146
1147impl pallet_safe_mode::Config for Runtime {
1148    type RuntimeEvent = RuntimeEvent;
1149    type Currency = Balances;
1150    type RuntimeHoldReason = RuntimeHoldReason;
1151    type WhitelistedCalls = SafeModeWhitelistedCalls;
1152    type EnterDuration = ConstU32<{ 5 * MINUTES }>;
1153    type EnterDepositAmount = ();
1154    type ExtendDuration = ConstU32<{ 2 * MINUTES }>;
1155    type ExtendDepositAmount = ();
1156    // The 'Success' values below represent the number of blocks that the origin may induce safe mode
1157    type ForceEnterOrigin =
1158        EnsureWithSuccess<EnsureRootOrHalfTechnicalCommittee, AccountId, ConstU32<{ 5 * MINUTES }>>;
1159    type ForceExtendOrigin =
1160        EnsureWithSuccess<EnsureRootOrHalfTechnicalCommittee, AccountId, ConstU32<{ 2 * MINUTES }>>;
1161    type ForceExitOrigin = EnsureRootOrTwoThirdsTechnicalCommittee;
1162    type ForceDepositOrigin = EnsureRootOrTwoThirdsTechnicalCommittee;
1163    type ReleaseDelay = ();
1164    type Notify = DappStaking;
1165    type WeightInfo = pallet_safe_mode::weights::SubstrateWeight<Runtime>;
1166}
1167
1168impl pallet_tx_pause::Config for Runtime {
1169    type RuntimeEvent = RuntimeEvent;
1170    type RuntimeCall = RuntimeCall;
1171    type PauseOrigin = EnsureRootOrHalfTechnicalCommittee;
1172    type UnpauseOrigin = EnsureRootOrHalfTechnicalCommittee;
1173    type WhitelistedCalls = ();
1174    type MaxNameLen = ConstU32<256>;
1175    type WeightInfo = pallet_tx_pause::weights::SubstrateWeight<Runtime>;
1176}
1177
1178construct_runtime!(
1179    pub struct Runtime {
1180        System: frame_system = 10,
1181        Utility: pallet_utility = 11,
1182        Timestamp: pallet_timestamp = 13,
1183        RandomnessCollectiveFlip: pallet_insecure_randomness_collective_flip = 16,
1184        Scheduler: pallet_scheduler = 17,
1185        Proxy: pallet_proxy = 18,
1186
1187        TransactionPayment: pallet_transaction_payment = 30,
1188        Balances: pallet_balances = 31,
1189        Vesting: pallet_vesting = 32,
1190        DappStaking: pallet_dapp_staking = 34,
1191        Inflation: pallet_inflation = 35,
1192        Assets: pallet_assets = 36,
1193        StaticPriceProvider: pallet_static_price_provider = 37,
1194
1195        Aura: pallet_aura = 43,
1196        Grandpa: pallet_grandpa = 44,
1197
1198        EVM: pallet_evm = 60,
1199        Ethereum: pallet_ethereum = 61,
1200        DynamicEvmBaseFee: pallet_dynamic_evm_base_fee = 62,
1201        EthereumChecked: pallet_ethereum_checked = 64,
1202        UnifiedAccounts: pallet_unified_accounts = 65,
1203
1204        Contracts: pallet_contracts = 70,
1205
1206        Preimage: pallet_preimage = 84,
1207
1208        // skip 90 - for runtimes consistency (pallet_xvm previously)
1209
1210        // Governance
1211        Sudo: pallet_sudo = 99,
1212        CouncilMembership: pallet_membership::<Instance2> = 100,
1213        TechnicalCommitteeMembership: pallet_membership::<Instance3> = 101,
1214        CommunityCouncilMembership: pallet_membership::<Instance4> = 102,
1215        Council: pallet_collective::<Instance2> = 103,
1216        TechnicalCommittee: pallet_collective::<Instance3> = 104,
1217        CommunityCouncil: pallet_collective::<Instance4> = 105,
1218        Democracy: pallet_democracy = 106,
1219        Treasury: pallet_treasury::<Instance1> = 107,
1220        CommunityTreasury: pallet_treasury::<Instance2> = 108,
1221        CollectiveProxy: pallet_collective_proxy = 109,
1222        SafeMode: pallet_safe_mode = 110,
1223        TxPause: pallet_tx_pause = 111,
1224    }
1225);
1226
1227/// Block type as expected by this runtime.
1228pub type Block = generic::Block<Header, UncheckedExtrinsic>;
1229/// A Block signed with a Justification
1230pub type SignedBlock = generic::SignedBlock<Block>;
1231/// BlockId type as expected by this runtime.
1232pub type BlockId = generic::BlockId<Block>;
1233/// The SignedExtension to the basic transaction logic.
1234pub type SignedExtra = (
1235    frame_system::CheckSpecVersion<Runtime>,
1236    frame_system::CheckTxVersion<Runtime>,
1237    frame_system::CheckGenesis<Runtime>,
1238    frame_system::CheckEra<Runtime>,
1239    frame_system::CheckNonce<Runtime>,
1240    frame_system::CheckWeight<Runtime>,
1241    pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
1242    frame_metadata_hash_extension::CheckMetadataHash<Runtime>,
1243);
1244/// Unchecked extrinsic type as expected by this runtime.
1245pub type UncheckedExtrinsic =
1246    fp_self_contained::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
1247/// Extrinsic type that has already been checked.
1248pub type CheckedExtrinsic =
1249    fp_self_contained::CheckedExtrinsic<AccountId, RuntimeCall, SignedExtra, H160>;
1250/// The payload being signed in transactions.
1251pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
1252/// Executive: handles dispatch to the various modules.
1253pub type Executive = frame_executive::Executive<
1254    Runtime,
1255    Block,
1256    frame_system::ChainContext<Runtime>,
1257    Runtime,
1258    AllPalletsWithSystem,
1259    Migrations,
1260>;
1261
1262pub type Migrations = ();
1263
1264type EventRecord = frame_system::EventRecord<
1265    <Runtime as frame_system::Config>::RuntimeEvent,
1266    <Runtime as frame_system::Config>::Hash,
1267>;
1268
1269impl fp_self_contained::SelfContainedCall for RuntimeCall {
1270    type SignedInfo = H160;
1271
1272    fn is_self_contained(&self) -> bool {
1273        match self {
1274            RuntimeCall::Ethereum(call) => call.is_self_contained(),
1275            _ => false,
1276        }
1277    }
1278
1279    fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
1280        match self {
1281            RuntimeCall::Ethereum(call) => call.check_self_contained(),
1282            _ => None,
1283        }
1284    }
1285
1286    fn validate_self_contained(
1287        &self,
1288        info: &Self::SignedInfo,
1289        dispatch_info: &DispatchInfoOf<RuntimeCall>,
1290        len: usize,
1291    ) -> Option<TransactionValidity> {
1292        match self {
1293            RuntimeCall::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),
1294            _ => None,
1295        }
1296    }
1297
1298    fn pre_dispatch_self_contained(
1299        &self,
1300        info: &Self::SignedInfo,
1301        dispatch_info: &DispatchInfoOf<RuntimeCall>,
1302        len: usize,
1303    ) -> Option<Result<(), TransactionValidityError>> {
1304        match self {
1305            RuntimeCall::Ethereum(call) => {
1306                call.pre_dispatch_self_contained(info, dispatch_info, len)
1307            }
1308            _ => None,
1309        }
1310    }
1311
1312    fn apply_self_contained(
1313        self,
1314        info: Self::SignedInfo,
1315    ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {
1316        match self {
1317            call @ RuntimeCall::Ethereum(pallet_ethereum::Call::transact { .. }) => {
1318                Some(call.dispatch(RuntimeOrigin::from(
1319                    pallet_ethereum::RawOrigin::EthereumTransaction(info),
1320                )))
1321            }
1322            _ => None,
1323        }
1324    }
1325}
1326
1327#[cfg(feature = "runtime-benchmarks")]
1328#[macro_use]
1329extern crate frame_benchmarking;
1330
1331#[cfg(feature = "runtime-benchmarks")]
1332mod benches {
1333    define_benchmarks!(
1334        [frame_benchmarking, BaselineBench::<Runtime>]
1335        [pallet_assets, pallet_assets::Pallet::<Runtime>]
1336        [frame_system, SystemBench::<Runtime>]
1337        [frame_system_extensions, SystemExtensionsBench::<Runtime>]
1338        [pallet_balances, Balances]
1339        [pallet_timestamp, Timestamp]
1340        [pallet_transaction_payment, TransactionPayment]
1341        [pallet_ethereum_checked, EthereumChecked]
1342        [pallet_dapp_staking, DappStaking]
1343        [pallet_inflation, Inflation]
1344        [pallet_dynamic_evm_base_fee, DynamicEvmBaseFee]
1345        [pallet_tx_pause, TxPause]
1346        [pallet_safe_mode, SafeMode]
1347    );
1348}
1349
1350impl_runtime_apis! {
1351    impl sp_api::Core<Block> for Runtime {
1352        fn version() -> RuntimeVersion {
1353            VERSION
1354        }
1355
1356        fn execute_block(block: Block) {
1357            Executive::execute_block(block);
1358        }
1359
1360        fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
1361            Executive::initialize_block(header)
1362        }
1363    }
1364
1365    impl sp_api::Metadata<Block> for Runtime {
1366        fn metadata() -> OpaqueMetadata {
1367            OpaqueMetadata::new(Runtime::metadata().into())
1368        }
1369
1370        fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
1371            Runtime::metadata_at_version(version)
1372        }
1373
1374        fn metadata_versions() -> Vec<u32> {
1375            Runtime::metadata_versions()
1376        }
1377    }
1378
1379    impl sp_block_builder::BlockBuilder<Block> for Runtime {
1380        fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
1381            Executive::apply_extrinsic(extrinsic)
1382        }
1383
1384        fn finalize_block() -> <Block as BlockT>::Header {
1385            Executive::finalize_block()
1386        }
1387
1388        fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
1389            data.create_extrinsics()
1390        }
1391
1392        fn check_inherents(
1393            block: Block,
1394            data: sp_inherents::InherentData,
1395        ) -> sp_inherents::CheckInherentsResult {
1396            data.check_extrinsics(&block)
1397        }
1398    }
1399
1400    impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
1401        fn validate_transaction(
1402            source: TransactionSource,
1403            tx: <Block as BlockT>::Extrinsic,
1404            block_hash: <Block as BlockT>::Hash,
1405        ) -> TransactionValidity {
1406            Executive::validate_transaction(source, tx, block_hash)
1407        }
1408    }
1409
1410    impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
1411        fn offchain_worker(header: &<Block as BlockT>::Header) {
1412            Executive::offchain_worker(header)
1413        }
1414    }
1415
1416    impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
1417        fn slot_duration() -> sp_consensus_aura::SlotDuration {
1418            sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION)
1419        }
1420
1421        fn authorities() -> Vec<AuraId> {
1422            pallet_aura::Authorities::<Runtime>::get().into_inner()
1423        }
1424    }
1425
1426    impl sp_session::SessionKeys<Block> for Runtime {
1427        fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
1428            SessionKeys::generate(seed)
1429        }
1430
1431        fn decode_session_keys(
1432            encoded: Vec<u8>,
1433        ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
1434            SessionKeys::decode_into_raw_public_keys(&encoded)
1435        }
1436    }
1437
1438    impl fg_primitives::GrandpaApi<Block> for Runtime {
1439        fn grandpa_authorities() -> GrandpaAuthorityList {
1440            Grandpa::grandpa_authorities()
1441        }
1442
1443        fn current_set_id() -> fg_primitives::SetId {
1444            Grandpa::current_set_id()
1445        }
1446
1447        fn submit_report_equivocation_unsigned_extrinsic(
1448            _equivocation_proof: fg_primitives::EquivocationProof<
1449                <Block as BlockT>::Hash,
1450                NumberFor<Block>,
1451            >,
1452            _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,
1453        ) -> Option<()> {
1454            None
1455        }
1456
1457        fn generate_key_ownership_proof(
1458            _set_id: fg_primitives::SetId,
1459            _authority_id: GrandpaId,
1460        ) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {
1461            // NOTE: this is the only implementation possible since we've
1462            // defined our key owner proof type as a bottom type (i.e. a type
1463            // with no values).
1464            None
1465        }
1466    }
1467
1468    impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
1469        fn account_nonce(account: AccountId) -> Nonce {
1470            System::account_nonce(account)
1471        }
1472    }
1473
1474    impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
1475        fn query_info(
1476            uxt: <Block as BlockT>::Extrinsic,
1477            len: u32,
1478        ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
1479            TransactionPayment::query_info(uxt, len)
1480        }
1481        fn query_fee_details(
1482            uxt: <Block as BlockT>::Extrinsic,
1483            len: u32,
1484        ) -> pallet_transaction_payment::FeeDetails<Balance> {
1485            TransactionPayment::query_fee_details(uxt, len)
1486        }
1487        fn query_weight_to_fee(weight: Weight) -> Balance {
1488            TransactionPayment::weight_to_fee(weight)
1489        }
1490        fn query_length_to_fee(length: u32) -> Balance {
1491            TransactionPayment::length_to_fee(length)
1492        }
1493    }
1494
1495    impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall>
1496        for Runtime
1497    {
1498        fn query_call_info(
1499            call: RuntimeCall,
1500            len: u32,
1501        ) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> {
1502            TransactionPayment::query_call_info(call, len)
1503        }
1504        fn query_call_fee_details(
1505            call: RuntimeCall,
1506            len: u32,
1507        ) -> pallet_transaction_payment::FeeDetails<Balance> {
1508            TransactionPayment::query_call_fee_details(call, len)
1509        }
1510        fn query_weight_to_fee(weight: Weight) -> Balance {
1511            TransactionPayment::weight_to_fee(weight)
1512        }
1513
1514        fn query_length_to_fee(length: u32) -> Balance {
1515            TransactionPayment::length_to_fee(length)
1516        }
1517    }
1518
1519    impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
1520        fn chain_id() -> u64 {
1521            ChainId::get()
1522        }
1523
1524        fn account_basic(address: H160) -> pallet_evm::Account {
1525            let (account, _) = EVM::account_basic(&address);
1526            account
1527        }
1528
1529        fn gas_price() -> U256 {
1530            let (gas_price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();
1531            gas_price
1532        }
1533
1534        fn account_code_at(address: H160) -> Vec<u8> {
1535            pallet_evm::AccountCodes::<Runtime>::get(address)
1536        }
1537
1538        fn author() -> H160 {
1539            <pallet_evm::Pallet<Runtime>>::find_author()
1540        }
1541
1542        fn storage_at(address: H160, index: U256) -> H256 {
1543            let tmp: [u8; 32] = index.to_big_endian();
1544            pallet_evm::AccountStorages::<Runtime>::get(address, H256::from_slice(&tmp[..]))
1545        }
1546
1547        fn call(
1548            from: H160,
1549            to: H160,
1550            data: Vec<u8>,
1551            value: U256,
1552            gas_limit: U256,
1553            max_fee_per_gas: Option<U256>,
1554            max_priority_fee_per_gas: Option<U256>,
1555            nonce: Option<U256>,
1556            estimate: bool,
1557            access_list: Option<Vec<(H160, Vec<H256>)>>,
1558            authorization_list: Option<AuthorizationList>,
1559        ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
1560            let config = if estimate {
1561                let mut config = <Runtime as pallet_evm::Config>::config().clone();
1562                config.estimate = true;
1563                Some(config)
1564            } else {
1565                None
1566            };
1567
1568            let is_transactional = false;
1569            let validate = true;
1570
1571            // Reused approach from Moonbeam since Frontier implementation doesn't support this
1572            let mut estimated_transaction_len = data.len() +
1573                // to: 20
1574                // from: 20
1575                // value: 32
1576                // gas_limit: 32
1577                // nonce: 32
1578                // 1 byte transaction action variant
1579                // chain id 8 bytes
1580                // 65 bytes signature
1581                210;
1582            if max_fee_per_gas.is_some() {
1583                estimated_transaction_len += 32;
1584            }
1585            if max_priority_fee_per_gas.is_some() {
1586                estimated_transaction_len += 32;
1587            }
1588            if access_list.is_some() {
1589                estimated_transaction_len += access_list.encoded_size();
1590            }
1591
1592            let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
1593            let without_base_extrinsic_weight = true;
1594
1595            let (weight_limit, proof_size_base_cost) =
1596                match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
1597                    gas_limit,
1598                    without_base_extrinsic_weight
1599                ) {
1600                    weight_limit if weight_limit.proof_size() > 0 => {
1601                        (Some(weight_limit), Some(estimated_transaction_len as u64))
1602                    }
1603                    _ => (None, None),
1604                };
1605
1606            <Runtime as pallet_evm::Config>::Runner::call(
1607                from,
1608                to,
1609                data,
1610                value,
1611                gas_limit.unique_saturated_into(),
1612                max_fee_per_gas,
1613                max_priority_fee_per_gas,
1614                nonce,
1615                access_list.unwrap_or_default(),
1616                authorization_list.unwrap_or_default(),
1617                is_transactional,
1618                validate,
1619                weight_limit,
1620                proof_size_base_cost,
1621                config
1622                    .as_ref()
1623                    .unwrap_or_else(|| <Runtime as pallet_evm::Config>::config()),
1624            )
1625            .map_err(|err| err.error.into())
1626        }
1627
1628        fn create(
1629            from: H160,
1630            data: Vec<u8>,
1631            value: U256,
1632            gas_limit: U256,
1633            max_fee_per_gas: Option<U256>,
1634            max_priority_fee_per_gas: Option<U256>,
1635            nonce: Option<U256>,
1636            estimate: bool,
1637            access_list: Option<Vec<(H160, Vec<H256>)>>,
1638            authorization_list: Option<AuthorizationList>,
1639        ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
1640            let config = if estimate {
1641                let mut config = <Runtime as pallet_evm::Config>::config().clone();
1642                config.estimate = true;
1643                Some(config)
1644            } else {
1645                None
1646            };
1647
1648            let is_transactional = false;
1649            let validate = true;
1650
1651            // Reused approach from Moonbeam since Frontier implementation doesn't support this
1652            let mut estimated_transaction_len = data.len() +
1653                // to: 20
1654                // from: 20
1655                // value: 32
1656                // gas_limit: 32
1657                // nonce: 32
1658                // 1 byte transaction action variant
1659                // chain id 8 bytes
1660                // 65 bytes signature
1661                210;
1662            if max_fee_per_gas.is_some() {
1663                estimated_transaction_len += 32;
1664            }
1665            if max_priority_fee_per_gas.is_some() {
1666                estimated_transaction_len += 32;
1667            }
1668            if access_list.is_some() {
1669                estimated_transaction_len += access_list.encoded_size();
1670            }
1671
1672            let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
1673            let without_base_extrinsic_weight = true;
1674
1675            let (weight_limit, proof_size_base_cost) =
1676                match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
1677                    gas_limit,
1678                    without_base_extrinsic_weight
1679                ) {
1680                    weight_limit if weight_limit.proof_size() > 0 => {
1681                        (Some(weight_limit), Some(estimated_transaction_len as u64))
1682                    }
1683                    _ => (None, None),
1684                };
1685
1686            #[allow(clippy::or_fun_call)] // suggestion not helpful here
1687            <Runtime as pallet_evm::Config>::Runner::create(
1688                from,
1689                data,
1690                value,
1691                gas_limit.unique_saturated_into(),
1692                max_fee_per_gas,
1693                max_priority_fee_per_gas,
1694                nonce,
1695                access_list.unwrap_or_default(),
1696                authorization_list.unwrap_or_default(),
1697                is_transactional,
1698                validate,
1699                weight_limit,
1700                proof_size_base_cost,
1701                config
1702                    .as_ref()
1703                    .unwrap_or(<Runtime as pallet_evm::Config>::config()),
1704                )
1705                .map_err(|err| err.error.into())
1706        }
1707
1708        fn current_transaction_statuses() -> Option<Vec<fp_rpc::TransactionStatus>> {
1709            pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
1710        }
1711
1712        fn current_block() -> Option<pallet_ethereum::Block> {
1713            pallet_ethereum::CurrentBlock::<Runtime>::get()
1714        }
1715
1716        fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {
1717            pallet_ethereum::CurrentReceipts::<Runtime>::get()
1718        }
1719
1720        fn current_all() -> (
1721            Option<pallet_ethereum::Block>,
1722            Option<Vec<pallet_ethereum::Receipt>>,
1723            Option<Vec<fp_rpc::TransactionStatus>>,
1724        ) {
1725            (
1726                pallet_ethereum::CurrentBlock::<Runtime>::get(),
1727                pallet_ethereum::CurrentReceipts::<Runtime>::get(),
1728                pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
1729            )
1730        }
1731
1732        fn extrinsic_filter(
1733            xts: Vec<<Block as BlockT>::Extrinsic>,
1734        ) -> Vec<pallet_ethereum::Transaction> {
1735            xts.into_iter().filter_map(|xt| match xt.0.function {
1736                RuntimeCall::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),
1737                _ => None
1738            }).collect::<Vec<pallet_ethereum::Transaction>>()
1739        }
1740
1741        fn elasticity() -> Option<Permill> {
1742            Some(Permill::zero())
1743        }
1744
1745        fn gas_limit_multiplier_support() {}
1746
1747        fn pending_block(
1748            xts: Vec<<Block as BlockT>::Extrinsic>,
1749        ) -> (Option<pallet_ethereum::Block>, Option<Vec<fp_rpc::TransactionStatus>>) {
1750            for ext in xts.into_iter() {
1751                let _ = Executive::apply_extrinsic(ext);
1752            }
1753
1754            Ethereum::on_finalize(System::block_number() + 1);
1755
1756            (
1757                pallet_ethereum::CurrentBlock::<Runtime>::get(),
1758                pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
1759            )
1760        }
1761
1762        fn initialize_pending_block(header: &<Block as BlockT>::Header) {
1763            Executive::initialize_block(header);
1764        }
1765    }
1766
1767    impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {
1768        fn convert_transaction(
1769            transaction: pallet_ethereum::Transaction
1770        ) -> <Block as BlockT>::Extrinsic {
1771            UncheckedExtrinsic::new_bare(
1772                pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
1773            )
1774        }
1775    }
1776
1777    impl pallet_contracts::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash, EventRecord> for Runtime {
1778        fn call(
1779            origin: AccountId,
1780            dest: AccountId,
1781            value: Balance,
1782            gas_limit: Option<Weight>,
1783            storage_deposit_limit: Option<Balance>,
1784            input_data: Vec<u8>,
1785        ) -> pallet_contracts::ContractExecResult<Balance, EventRecord> {
1786            let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block);
1787            Contracts::bare_call(
1788                origin,
1789                dest,
1790                value,
1791                gas_limit,
1792                storage_deposit_limit,
1793                input_data,
1794                pallet_contracts::DebugInfo::UnsafeDebug,
1795                pallet_contracts::CollectEvents::UnsafeCollect,
1796                pallet_contracts::Determinism::Enforced,
1797            )
1798        }
1799
1800        fn instantiate(
1801            origin: AccountId,
1802            value: Balance,
1803            gas_limit: Option<Weight>,
1804            storage_deposit_limit: Option<Balance>,
1805            code: pallet_contracts::Code<Hash>,
1806            data: Vec<u8>,
1807            salt: Vec<u8>,
1808        ) -> pallet_contracts::ContractInstantiateResult<AccountId, Balance, EventRecord> {
1809            let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block);
1810            Contracts::bare_instantiate(
1811                origin,
1812                value,
1813                gas_limit,
1814                storage_deposit_limit,
1815                code,
1816                data,
1817                salt,
1818                pallet_contracts::DebugInfo::UnsafeDebug,
1819                pallet_contracts::CollectEvents::UnsafeCollect,
1820            )
1821        }
1822
1823        fn upload_code(
1824            origin: AccountId,
1825            code: Vec<u8>,
1826            storage_deposit_limit: Option<Balance>,
1827            determinism: pallet_contracts::Determinism,
1828        ) -> pallet_contracts::CodeUploadResult<Hash, Balance>
1829        {
1830            Contracts::bare_upload_code(origin, code, storage_deposit_limit, determinism)
1831        }
1832
1833        fn get_storage(
1834            address: AccountId,
1835            key: Vec<u8>,
1836        ) -> pallet_contracts::GetStorageResult {
1837            Contracts::get_storage(address, key)
1838        }
1839    }
1840
1841    impl dapp_staking_runtime_api::DappStakingApi<Block> for Runtime {
1842        fn periods_per_cycle() -> PeriodNumber {
1843            InflationCycleConfig::periods_per_cycle()
1844        }
1845
1846        fn eras_per_voting_subperiod() -> EraNumber {
1847            InflationCycleConfig::eras_per_voting_subperiod()
1848        }
1849
1850        fn eras_per_build_and_earn_subperiod() -> EraNumber {
1851            InflationCycleConfig::eras_per_build_and_earn_subperiod()
1852        }
1853
1854        fn blocks_per_era() -> BlockNumber {
1855            InflationCycleConfig::blocks_per_era()
1856        }
1857
1858        fn get_dapp_tier_assignment() -> BTreeMap<DAppId, RankedTier> {
1859            DappStaking::get_dapp_tier_assignment()
1860        }
1861    }
1862
1863
1864    impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
1865
1866        fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
1867            genesis_builder_helper::build_state::<RuntimeGenesisConfig>(config)
1868        }
1869
1870        fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
1871            genesis_builder_helper::get_preset::<RuntimeGenesisConfig>(id, &genesis_config::get_preset)
1872        }
1873
1874        fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
1875            vec![
1876                sp_genesis_builder::PresetId::from("development"),
1877            ]
1878        }
1879    }
1880
1881    #[cfg(feature = "runtime-benchmarks")]
1882    impl frame_benchmarking::Benchmark<Block> for Runtime {
1883        fn benchmark_metadata(extra: bool) -> (
1884            Vec<frame_benchmarking::BenchmarkList>,
1885            Vec<frame_support::traits::StorageInfo>,
1886        ) {
1887            use frame_benchmarking::{baseline, BenchmarkList};
1888            use frame_support::traits::StorageInfoTrait;
1889            pub use frame_system_benchmarking::{
1890                extensions::Pallet as SystemExtensionsBench, Pallet as SystemBench
1891            };
1892            use baseline::Pallet as BaselineBench;
1893
1894            let mut list = Vec::<BenchmarkList>::new();
1895            list_benchmarks!(list, extra);
1896
1897            let storage_info = AllPalletsWithSystem::storage_info();
1898
1899            (list, storage_info)
1900        }
1901
1902        #[allow(non_local_definitions)]
1903        fn dispatch_benchmark(
1904            config: frame_benchmarking::BenchmarkConfig
1905        ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
1906            use frame_benchmarking::{baseline, BenchmarkBatch};
1907            pub use frame_system_benchmarking::{
1908                extensions::Pallet as SystemExtensionsBench, Pallet as SystemBench
1909            };
1910            use baseline::Pallet as BaselineBench;
1911
1912            impl frame_system_benchmarking::Config for Runtime {}
1913            impl baseline::Config for Runtime {}
1914
1915            use frame_support::traits::{WhitelistedStorageKeys, TrackedStorageKey};
1916            let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
1917
1918            let mut batches = Vec::<BenchmarkBatch>::new();
1919            let params = (&config, &whitelist);
1920            add_benchmarks!(params, batches);
1921
1922            if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
1923            Ok(batches)
1924        }
1925    }
1926
1927    impl moonbeam_rpc_primitives_debug::DebugRuntimeApi<Block> for Runtime {
1928        fn trace_transaction(
1929            extrinsics: Vec<<Block as BlockT>::Extrinsic>,
1930            traced_transaction: &pallet_ethereum::Transaction,
1931            header: &<Block as BlockT>::Header,
1932        ) -> Result<
1933            (),
1934            sp_runtime::DispatchError,
1935        > {
1936            use moonbeam_evm_tracer::tracer::EvmTracer;
1937
1938            // We need to follow the order when replaying the transactions.
1939            // Block initialize happens first then apply_extrinsic.
1940            Executive::initialize_block(header);
1941
1942            // Apply the a subset of extrinsics: all the substrate-specific or ethereum
1943            // transactions that preceded the requested transaction.
1944            for ext in extrinsics.into_iter() {
1945                let _ = match &ext.0.function {
1946                    RuntimeCall::Ethereum(pallet_ethereum::Call::transact { transaction }) => {
1947                        if transaction == traced_transaction {
1948                            EvmTracer::new().trace(|| Executive::apply_extrinsic(ext));
1949                            return Ok(());
1950                        } else {
1951                            Executive::apply_extrinsic(ext)
1952                        }
1953                    }
1954                    _ => Executive::apply_extrinsic(ext),
1955                };
1956            }
1957            Err(sp_runtime::DispatchError::Other(
1958                "Failed to find Ethereum transaction among the extrinsics.",
1959            ))
1960        }
1961
1962        fn trace_block(
1963            extrinsics: Vec<<Block as BlockT>::Extrinsic>,
1964            known_transactions: Vec<H256>,
1965            header: &<Block as BlockT>::Header,
1966        ) -> Result<
1967            (),
1968            sp_runtime::DispatchError,
1969        > {
1970            use moonbeam_evm_tracer::tracer::EvmTracer;
1971
1972            let mut config = <Runtime as pallet_evm::Config>::config().clone();
1973            config.estimate = true;
1974
1975            // We need to follow the order when replaying the transactions.
1976            // Block initialize happens first then apply_extrinsic.
1977            Executive::initialize_block(header);
1978
1979            // Apply all extrinsics. Ethereum extrinsics are traced.
1980            for ext in extrinsics.into_iter() {
1981                match &ext.0.function {
1982                    RuntimeCall::Ethereum(pallet_ethereum::Call::transact { transaction }) => {
1983                        if known_transactions.contains(&transaction.hash()) {
1984                            // Each known extrinsic is a new call stack.
1985                            EvmTracer::emit_new();
1986                            EvmTracer::new().trace(|| Executive::apply_extrinsic(ext));
1987                        } else {
1988                            let _ = Executive::apply_extrinsic(ext);
1989                        }
1990                    }
1991                    _ => {
1992                        let _ = Executive::apply_extrinsic(ext);
1993                    }
1994                };
1995            }
1996
1997            Ok(())
1998        }
1999
2000        fn trace_call(
2001            header: &<Block as BlockT>::Header,
2002            from: H160,
2003            to: H160,
2004            data: Vec<u8>,
2005            value: U256,
2006            gas_limit: U256,
2007            max_fee_per_gas: Option<U256>,
2008            max_priority_fee_per_gas: Option<U256>,
2009            nonce: Option<U256>,
2010            access_list: Option<Vec<(H160, Vec<H256>)>>,
2011            authorization_list: Option<AuthorizationList>,
2012        ) -> Result<(), sp_runtime::DispatchError> {
2013            use moonbeam_evm_tracer::tracer::EvmTracer;
2014
2015            // Initialize block: calls the "on_initialize" hook on every pallet
2016            // in AllPalletsWithSystem.
2017            Executive::initialize_block(header);
2018
2019            EvmTracer::new().trace(|| {
2020                let is_transactional = false;
2021                let validate = true;
2022                let without_base_extrinsic_weight = true;
2023
2024
2025                // Estimated encoded transaction size must be based on the heaviest transaction
2026                // type (EIP1559Transaction) to be compatible with all transaction types.
2027                let mut estimated_transaction_len = data.len() +
2028                // pallet ethereum index: 1
2029                // transact call index: 1
2030                // Transaction enum variant: 1
2031                // chain_id 8 bytes
2032                // nonce: 32
2033                // max_priority_fee_per_gas: 32
2034                // max_fee_per_gas: 32
2035                // gas_limit: 32
2036                // action: 21 (enum varianrt + call address)
2037                // value: 32
2038                // access_list: 1 (empty vec size)
2039                // 65 bytes signature
2040                258;
2041
2042                if access_list.is_some() {
2043                    estimated_transaction_len += access_list.encoded_size();
2044                }
2045
2046                let gas_limit = gas_limit.min(u64::MAX.into()).low_u64();
2047
2048                let (weight_limit, proof_size_base_cost) =
2049                    match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
2050                        gas_limit,
2051                        without_base_extrinsic_weight
2052                    ) {
2053                        weight_limit if weight_limit.proof_size() > 0 => {
2054                            (Some(weight_limit), Some(estimated_transaction_len as u64))
2055                        }
2056                        _ => (None, None),
2057                    };
2058
2059                let _ = <Runtime as pallet_evm::Config>::Runner::call(
2060                    from,
2061                    to,
2062                    data,
2063                    value,
2064                    gas_limit,
2065                    max_fee_per_gas,
2066                    max_priority_fee_per_gas,
2067                    nonce,
2068                    access_list.unwrap_or_default(),
2069                    authorization_list.unwrap_or_default(),
2070                    is_transactional,
2071                    validate,
2072                    weight_limit,
2073                    proof_size_base_cost,
2074                    <Runtime as pallet_evm::Config>::config(),
2075                );
2076            });
2077            Ok(())
2078        }
2079    }
2080
2081    impl moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block> for Runtime {
2082        fn extrinsic_filter(
2083            xts_ready: Vec<<Block as BlockT>::Extrinsic>,
2084            xts_future: Vec<<Block as BlockT>::Extrinsic>,
2085        ) -> moonbeam_rpc_primitives_txpool::TxPoolResponse {
2086            moonbeam_rpc_primitives_txpool::TxPoolResponse {
2087                ready: xts_ready
2088                    .into_iter()
2089                    .filter_map(|xt| match xt.0.function {
2090                        RuntimeCall::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),
2091                        _ => None,
2092                    })
2093                    .collect(),
2094                future: xts_future
2095                    .into_iter()
2096                    .filter_map(|xt| match xt.0.function {
2097                        RuntimeCall::Ethereum(pallet_ethereum::Call::transact { transaction }) => Some(transaction),
2098                        _ => None,
2099                    })
2100                    .collect(),
2101            }
2102        }
2103    }
2104
2105    #[cfg(feature = "try-runtime")]
2106    impl frame_try_runtime::TryRuntime<Block> for Runtime {
2107        fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
2108            log::info!("try-runtime::on_runtime_upgrade");
2109            let weight = Executive::try_runtime_upgrade(checks).unwrap();
2110            (weight, RuntimeBlockWeights::get().max_block)
2111        }
2112
2113        fn execute_block(
2114            block: Block,
2115            state_root_check: bool,
2116            signature_check: bool,
2117            select: frame_try_runtime::TryStateSelect
2118        ) -> Weight {
2119            log::info!(
2120                "try-runtime: executing block #{} ({:?}) / root checks: {:?} / sanity-checks: {:?}",
2121                block.header.number,
2122                block.header.hash(),
2123                state_root_check,
2124                select,
2125            );
2126            Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed")
2127        }
2128    }
2129}