1#![cfg_attr(not(feature = "std"), no_std)]
4#![recursion_limit = "256"]
6#![allow(clippy::new_without_default, clippy::or_fun_call)]
7#![cfg_attr(feature = "runtime-benchmarks", warn(unused_crate_dependencies))]
8
9extern crate alloc;
10
11mod genesis_config_preset;
12mod precompiles;
13mod weights;
14
15#[cfg(feature = "std")]
17include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
18
19use alloc::{borrow::Cow, vec, vec::Vec};
20use core::marker::PhantomData;
21use ethereum::AuthorizationList;
22use scale_codec::{Decode, Encode};
23use sp_api::impl_runtime_apis;
24use sp_consensus_aura::sr25519::AuthorityId as AuraId;
25use sp_consensus_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};
26use sp_core::{
27 crypto::{ByteArray, KeyTypeId},
28 ConstU128, OpaqueMetadata, H160, H256, U256,
29};
30use sp_runtime::{
31 generic, impl_opaque_keys,
32 traits::{
33 BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, Get, IdentifyAccount,
34 IdentityLookup, NumberFor, PostDispatchInfoOf, UniqueSaturatedInto, Verify,
35 },
36 transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError},
37 ApplyExtrinsicResult, ConsensusEngineId, ExtrinsicInclusionMode, Perbill, Permill,
38};
39use sp_version::RuntimeVersion;
40#[cfg(feature = "with-paritydb-weights")]
42use frame_support::weights::constants::ParityDbWeight as RuntimeDbWeight;
43#[cfg(feature = "with-rocksdb-weights")]
44use frame_support::weights::constants::RocksDbWeight as RuntimeDbWeight;
45use frame_support::{
46 derive_impl,
47 genesis_builder_helper::build_state,
48 parameter_types,
49 traits::{ConstBool, ConstU32, ConstU64, ConstU8, FindAuthor, OnFinalize, OnTimestampSet},
50 weights::{constants::WEIGHT_REF_TIME_PER_MILLIS, IdentityFee, Weight},
51};
52use pallet_transaction_payment::FungibleAdapter;
53use polkadot_runtime_common::SlowAdjustingFeeUpdate;
54use sp_genesis_builder::PresetId;
55use fp_account::EthereumSignature;
57use fp_evm::weight_per_gas;
58use fp_rpc::TransactionStatus;
59use pallet_ethereum::{Call::transact, PostLogContent, Transaction as EthereumTransaction};
60use pallet_evm::{
61 Account as EVMAccount, EnsureAccountId20, FeeCalculator, IdentityAddressMapping, Runner,
62};
63
64pub use frame_system::Call as SystemCall;
66pub use pallet_balances::Call as BalancesCall;
67pub use pallet_timestamp::Call as TimestampCall;
68
69use precompiles::FrontierPrecompiles;
70
71pub type BlockNumber = u32;
73
74pub type Signature = EthereumSignature;
76
77pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
80
81pub type AccountIndex = u32;
84
85pub type Balance = u128;
87
88pub type Nonce = u32;
90
91pub type Hash = H256;
93
94pub type Hashing = BlakeTwo256;
96
97pub type DigestItem = generic::DigestItem;
99
100pub type Address = AccountId;
102
103pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
105
106pub type Block = generic::Block<Header, UncheckedExtrinsic>;
108
109pub type SignedBlock = generic::SignedBlock<Block>;
111
112pub type BlockId = generic::BlockId<Block>;
114
115pub type SignedExtra = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
117 Runtime,
118 (
119 frame_system::CheckNonZeroSender<Runtime>,
120 frame_system::CheckSpecVersion<Runtime>,
121 frame_system::CheckTxVersion<Runtime>,
122 frame_system::CheckGenesis<Runtime>,
123 frame_system::CheckEra<Runtime>,
124 frame_system::CheckNonce<Runtime>,
125 frame_system::CheckWeight<Runtime>,
126 pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
127 ),
128>;
129
130pub type UncheckedExtrinsic =
132 fp_self_contained::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
133
134pub type CheckedExtrinsic =
136 fp_self_contained::CheckedExtrinsic<AccountId, RuntimeCall, SignedExtra, H160>;
137
138pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
140
141pub type Executive = frame_executive::Executive<
143 Runtime,
144 Block,
145 frame_system::ChainContext<Runtime>,
146 Runtime,
147 AllPalletsWithSystem,
148>;
149
150pub const MILLISECS_PER_BLOCK: u64 = 6000;
152pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
153pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
154pub const HOURS: BlockNumber = MINUTES * 60;
155pub const DAYS: BlockNumber = HOURS * 24;
156
157pub mod opaque {
162 use super::*;
163
164 pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
165
166 pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
168 pub type Block = generic::Block<Header, UncheckedExtrinsic>;
170 pub type BlockId = generic::BlockId<Block>;
172
173 impl_opaque_keys! {
174 pub struct SessionKeys {
175 pub aura: Aura,
176 pub grandpa: Grandpa,
177 }
178 }
179}
180
181#[sp_version::runtime_version]
182pub const VERSION: RuntimeVersion = RuntimeVersion {
183 spec_name: Cow::Borrowed("frontier-template"),
184 impl_name: Cow::Borrowed("frontier-template"),
185 authoring_version: 1,
186 spec_version: 1,
187 impl_version: 1,
188 apis: RUNTIME_API_VERSIONS,
189 transaction_version: 1,
190 system_version: 1,
191};
192
193#[cfg(feature = "std")]
195pub fn native_version() -> sp_version::NativeVersion {
196 sp_version::NativeVersion {
197 runtime_version: VERSION,
198 can_author_with: Default::default(),
199 }
200}
201
202const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
203pub const WEIGHT_MILLISECS_PER_BLOCK: u64 = 2000;
205pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(
206 WEIGHT_MILLISECS_PER_BLOCK * WEIGHT_REF_TIME_PER_MILLIS,
207 u64::MAX,
208);
209pub const MAXIMUM_BLOCK_LENGTH: u32 = 5 * 1024 * 1024;
210
211parameter_types! {
212 pub const Version: RuntimeVersion = VERSION;
213 pub const BlockHashCount: BlockNumber = 256;
214 pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights
215 ::with_sensible_defaults(MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO);
216 pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength
217 ::max_with_normal_ratio(MAXIMUM_BLOCK_LENGTH, NORMAL_DISPATCH_RATIO);
218 pub const SS58Prefix: u8 = 42;
219}
220
221#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig as frame_system::DefaultConfig)]
223impl frame_system::Config for Runtime {
224 type BlockWeights = BlockWeights;
226 type BlockLength = BlockLength;
228 type Nonce = Nonce;
230 type Hash = Hash;
232 type Hashing = Hashing;
234 type AccountId = AccountId;
236 type Lookup = IdentityLookup<AccountId>;
238 type Block = Block;
240 type BlockHashCount = BlockHashCount;
242 type DbWeight = RuntimeDbWeight;
244 type Version = Version;
246 type AccountData = pallet_balances::AccountData<Balance>;
248 type SS58Prefix = SS58Prefix;
250 type MaxConsumers = ConstU32<16>;
251}
252
253impl pallet_aura::Config for Runtime {
254 type AuthorityId = AuraId;
255 type MaxAuthorities = ConstU32<32>;
256 type DisabledValidators = ();
257 type AllowMultipleBlocksPerSlot = ConstBool<false>;
258 type SlotDuration = pallet_aura::MinimumPeriodTimesTwo<Runtime>;
259}
260
261impl pallet_grandpa::Config for Runtime {
262 type RuntimeEvent = RuntimeEvent;
263 type WeightInfo = ();
264 type MaxAuthorities = ConstU32<32>;
265 type MaxNominators = ConstU32<0>;
266 type MaxSetIdSessionEntries = ConstU64<0>;
267 type KeyOwnerProof = sp_core::Void;
268 type EquivocationReportSystem = ();
269}
270
271impl cumulus_pallet_weight_reclaim::Config for Runtime {
272 type WeightInfo = ();
273}
274
275parameter_types! {
276 pub storage EnableManualSeal: bool = false;
277}
278
279pub struct ConsensusOnTimestampSet<T>(PhantomData<T>);
280impl<T: pallet_aura::Config> OnTimestampSet<T::Moment> for ConsensusOnTimestampSet<T> {
281 fn on_timestamp_set(moment: T::Moment) {
282 if EnableManualSeal::get() {
283 return;
284 }
285 <pallet_aura::Pallet<T> as OnTimestampSet<T::Moment>>::on_timestamp_set(moment)
286 }
287}
288
289impl pallet_timestamp::Config for Runtime {
290 type Moment = u64;
291 type OnTimestampSet = ConsensusOnTimestampSet<Self>;
292 type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
293 type WeightInfo = ();
294}
295
296pub const EXISTENTIAL_DEPOSIT: u128 = 0;
297
298impl pallet_balances::Config for Runtime {
299 type RuntimeEvent = RuntimeEvent;
300 type RuntimeHoldReason = RuntimeHoldReason;
301 type RuntimeFreezeReason = RuntimeFreezeReason;
302 type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;
303 type Balance = Balance;
304 type DustRemoval = ();
305 type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
306 type AccountStore = System;
307 type ReserveIdentifier = [u8; 8];
308 type FreezeIdentifier = RuntimeFreezeReason;
309 type MaxLocks = ConstU32<50>;
310 type MaxReserves = ConstU32<50>;
311 type MaxFreezes = ConstU32<1>;
312 type DoneSlashHandler = ();
313}
314
315impl pallet_transaction_payment::Config for Runtime {
316 type RuntimeEvent = RuntimeEvent;
317 type OnChargeTransaction = FungibleAdapter<Balances, ()>;
318 type WeightToFee = IdentityFee<Balance>;
319 type LengthToFee = IdentityFee<Balance>;
320 type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Runtime>;
323 type OperationalFeeMultiplier = ConstU8<5>;
324 type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight<Runtime>;
325}
326
327impl pallet_sudo::Config for Runtime {
328 type RuntimeEvent = RuntimeEvent;
329 type RuntimeCall = RuntimeCall;
330 type WeightInfo = pallet_sudo::weights::SubstrateWeight<Self>;
331}
332
333impl pallet_evm_chain_id::Config for Runtime {}
334
335pub struct FindAuthorTruncated<F>(PhantomData<F>);
336impl<F: FindAuthor<u32>> FindAuthor<H160> for FindAuthorTruncated<F> {
337 fn find_author<'a, I>(digests: I) -> Option<H160>
338 where
339 I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
340 {
341 if let Some(author_index) = F::find_author(digests) {
342 let authority_id =
343 pallet_aura::Authorities::<Runtime>::get()[author_index as usize].clone();
344 return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));
345 }
346 None
347 }
348}
349
350const BLOCK_GAS_LIMIT: u64 = 75_000_000;
351const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
352const MAX_STORAGE_GROWTH: u64 = 400 * 1024;
354
355parameter_types! {
356 pub BlockGasLimit: U256 = U256::from(BLOCK_GAS_LIMIT);
357 pub const GasLimitPovSizeRatio: u64 = BLOCK_GAS_LIMIT.saturating_div(MAX_POV_SIZE);
358 pub const GasLimitStorageGrowthRatio: u64 = BLOCK_GAS_LIMIT.saturating_div(MAX_STORAGE_GROWTH);
359 pub PrecompilesValue: FrontierPrecompiles<Runtime> = FrontierPrecompiles::<_>::new();
360 pub WeightPerGas: Weight = Weight::from_parts(weight_per_gas(BLOCK_GAS_LIMIT, NORMAL_DISPATCH_RATIO, WEIGHT_MILLISECS_PER_BLOCK), 0);
361}
362
363impl pallet_evm::Config for Runtime {
364 type AccountProvider = pallet_evm::FrameSystemAccountProvider<Self>;
365 type FeeCalculator = BaseFee;
366 type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
367 type WeightPerGas = WeightPerGas;
368 type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
369 type CallOrigin = EnsureAccountId20;
370 type WithdrawOrigin = EnsureAccountId20;
371 type AddressMapping = IdentityAddressMapping;
372 type Currency = Balances;
373 type PrecompilesType = FrontierPrecompiles<Self>;
374 type PrecompilesValue = PrecompilesValue;
375 type ChainId = EVMChainId;
376 type BlockGasLimit = BlockGasLimit;
377 type Runner = pallet_evm::runner::stack::Runner<Self>;
378 type OnChargeTransaction = ();
379 type OnCreate = ();
380 type FindAuthor = FindAuthorTruncated<Aura>;
381 type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
382 type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
383 type Timestamp = Timestamp;
384 type CreateOriginFilter = ();
385 type CreateInnerOriginFilter = ();
386 type WeightInfo = pallet_evm::weights::SubstrateWeight<Self>;
387}
388
389parameter_types! {
390 pub const PostBlockAndTxnHashes: PostLogContent = PostLogContent::BlockAndTxnHashes;
391}
392
393impl pallet_ethereum::Config for Runtime {
394 type StateRoot = pallet_ethereum::IntermediateStateRoot<Self::Version>;
395 type PostLogContent = PostBlockAndTxnHashes;
396 type ExtraDataLength = ConstU32<30>;
397}
398
399parameter_types! {
400 pub BoundDivision: U256 = U256::from(1024);
401}
402
403impl pallet_dynamic_fee::Config for Runtime {
404 type MinGasPriceBoundDivisor = BoundDivision;
405}
406
407parameter_types! {
408 pub DefaultBaseFeePerGas: U256 = U256::from(1_000_000_000);
409 pub DefaultElasticity: Permill = Permill::from_parts(125_000);
410}
411pub struct BaseFeeThreshold;
412impl pallet_base_fee::BaseFeeThreshold for BaseFeeThreshold {
413 fn lower() -> Permill {
414 Permill::zero()
415 }
416 fn ideal() -> Permill {
417 Permill::from_parts(500_000)
418 }
419 fn upper() -> Permill {
420 Permill::from_parts(1_000_000)
421 }
422}
423impl pallet_base_fee::Config for Runtime {
424 type Threshold = BaseFeeThreshold;
425 type DefaultBaseFeePerGas = DefaultBaseFeePerGas;
426 type DefaultElasticity = DefaultElasticity;
427}
428
429#[frame_support::pallet]
430pub mod pallet_manual_seal {
431 use super::*;
432 use frame_support::pallet_prelude::*;
433
434 #[pallet::pallet]
435 pub struct Pallet<T>(PhantomData<T>);
436
437 #[pallet::config]
438 pub trait Config: frame_system::Config {}
439
440 #[pallet::genesis_config]
441 #[derive(frame_support::DefaultNoBound)]
442 pub struct GenesisConfig<T> {
443 pub enable: bool,
444 #[serde(skip)]
445 pub _config: PhantomData<T>,
446 }
447
448 #[pallet::genesis_build]
449 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
450 fn build(&self) {
451 EnableManualSeal::set(&self.enable);
452 }
453 }
454}
455
456impl pallet_manual_seal::Config for Runtime {}
457
458#[frame_support::runtime]
460mod runtime {
461 #[runtime::runtime]
462 #[runtime::derive(
463 RuntimeEvent,
464 RuntimeCall,
465 RuntimeError,
466 RuntimeOrigin,
467 RuntimeFreezeReason,
468 RuntimeHoldReason,
469 RuntimeSlashReason,
470 RuntimeLockId,
471 RuntimeTask
472 )]
473 pub struct Runtime;
474
475 #[runtime::pallet_index(0)]
476 pub type System = frame_system;
477
478 #[runtime::pallet_index(1)]
479 pub type Timestamp = pallet_timestamp;
480
481 #[runtime::pallet_index(2)]
482 pub type Aura = pallet_aura;
483
484 #[runtime::pallet_index(3)]
485 pub type Grandpa = pallet_grandpa;
486
487 #[runtime::pallet_index(4)]
488 pub type Balances = pallet_balances;
489
490 #[runtime::pallet_index(5)]
491 pub type TransactionPayment = pallet_transaction_payment;
492
493 #[runtime::pallet_index(6)]
494 pub type Sudo = pallet_sudo;
495
496 #[runtime::pallet_index(7)]
497 pub type Ethereum = pallet_ethereum;
498
499 #[runtime::pallet_index(8)]
500 pub type EVM = pallet_evm;
501
502 #[runtime::pallet_index(9)]
503 pub type EVMChainId = pallet_evm_chain_id;
504
505 #[runtime::pallet_index(10)]
506 pub type BaseFee = pallet_base_fee;
507
508 #[runtime::pallet_index(11)]
509 pub type ManualSeal = pallet_manual_seal;
510}
511
512#[derive(Clone)]
513pub struct TransactionConverter<B>(PhantomData<B>);
514
515impl<B> Default for TransactionConverter<B> {
516 fn default() -> Self {
517 Self(PhantomData)
518 }
519}
520
521impl<B: BlockT> fp_rpc::ConvertTransaction<<B as BlockT>::Extrinsic> for TransactionConverter<B> {
522 fn convert_transaction(
523 &self,
524 transaction: pallet_ethereum::Transaction,
525 ) -> <B as BlockT>::Extrinsic {
526 let extrinsic = UncheckedExtrinsic::new_bare(
527 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
528 );
529 let encoded = extrinsic.encode();
530 <B as BlockT>::Extrinsic::decode(&mut &encoded[..])
531 .expect("Encoded extrinsic is always valid")
532 }
533}
534
535impl fp_self_contained::SelfContainedCall for RuntimeCall {
536 type SignedInfo = H160;
537
538 fn is_self_contained(&self) -> bool {
539 match self {
540 RuntimeCall::Ethereum(call) => call.is_self_contained(),
541 _ => false,
542 }
543 }
544
545 fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
546 match self {
547 RuntimeCall::Ethereum(call) => call.check_self_contained(),
548 _ => None,
549 }
550 }
551
552 fn validate_self_contained(
553 &self,
554 info: &Self::SignedInfo,
555 dispatch_info: &DispatchInfoOf<RuntimeCall>,
556 len: usize,
557 ) -> Option<TransactionValidity> {
558 match self {
559 RuntimeCall::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),
560 _ => None,
561 }
562 }
563
564 fn pre_dispatch_self_contained(
565 &self,
566 info: &Self::SignedInfo,
567 dispatch_info: &DispatchInfoOf<RuntimeCall>,
568 len: usize,
569 ) -> Option<Result<(), TransactionValidityError>> {
570 match self {
571 RuntimeCall::Ethereum(call) => {
572 call.pre_dispatch_self_contained(info, dispatch_info, len)
573 }
574 _ => None,
575 }
576 }
577
578 fn apply_self_contained(
579 self,
580 info: Self::SignedInfo,
581 ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {
582 match self {
583 call @ RuntimeCall::Ethereum(pallet_ethereum::Call::transact { .. }) => {
584 Some(call.dispatch(RuntimeOrigin::from(
585 pallet_ethereum::RawOrigin::EthereumTransaction(info),
586 )))
587 }
588 _ => None,
589 }
590 }
591}
592
593#[cfg(feature = "runtime-benchmarks")]
594mod benches {
595 frame_benchmarking::define_benchmarks!(
596 [frame_benchmarking, BaselineBench::<Runtime>]
597 [frame_system, SystemBench::<Runtime>]
598 [pallet_balances, Balances]
599 [pallet_timestamp, Timestamp]
600 [pallet_sudo, Sudo]
601 [pallet_evm, EVM]
602 [pallet_evm_precompile_curve25519, EVMPrecompileCurve25519Bench::<Runtime>]
603 [pallet_evm_precompile_sha3fips, EVMPrecompileSha3FIPSBench::<Runtime>]
604 );
605}
606
607impl_runtime_apis! {
608 impl sp_api::Core<Block> for Runtime {
609 fn version() -> RuntimeVersion {
610 VERSION
611 }
612
613 fn execute_block(block: Block) {
614 Executive::execute_block(block)
615 }
616
617 fn initialize_block(header: &<Block as BlockT>::Header) -> ExtrinsicInclusionMode {
618 Executive::initialize_block(header)
619 }
620 }
621
622 impl sp_api::Metadata<Block> for Runtime {
623 fn metadata() -> OpaqueMetadata {
624 OpaqueMetadata::new(Runtime::metadata().into())
625 }
626
627 fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
628 Runtime::metadata_at_version(version)
629 }
630
631 fn metadata_versions() -> Vec<u32> {
632 Runtime::metadata_versions()
633 }
634 }
635
636 impl sp_block_builder::BlockBuilder<Block> for Runtime {
637 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
638 Executive::apply_extrinsic(extrinsic)
639 }
640
641 fn finalize_block() -> <Block as BlockT>::Header {
642 Executive::finalize_block()
643 }
644
645 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
646 data.create_extrinsics()
647 }
648
649 fn check_inherents(
650 block: Block,
651 data: sp_inherents::InherentData,
652 ) -> sp_inherents::CheckInherentsResult {
653 data.check_extrinsics(&block)
654 }
655 }
656
657 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
658 fn validate_transaction(
659 source: TransactionSource,
660 tx: <Block as BlockT>::Extrinsic,
661 block_hash: <Block as BlockT>::Hash,
662 ) -> TransactionValidity {
663 Executive::validate_transaction(source, tx, block_hash)
664 }
665 }
666
667 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
668 fn offchain_worker(header: &<Block as BlockT>::Header) {
669 Executive::offchain_worker(header)
670 }
671 }
672
673 impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
674 fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
675 build_state::<RuntimeGenesisConfig>(config)
676 }
677
678 fn get_preset(id: &Option<PresetId>) -> Option<Vec<u8>> {
679 frame_support::genesis_builder_helper::get_preset::<RuntimeGenesisConfig>(id, genesis_config_preset::get_preset)
680 }
681
682 fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
683 vec![PresetId::from(sp_genesis_builder::DEV_RUNTIME_PRESET)]
684 }
685 }
686
687 impl sp_session::SessionKeys<Block> for Runtime {
688 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
689 opaque::SessionKeys::generate(seed)
690 }
691
692 fn decode_session_keys(
693 encoded: Vec<u8>,
694 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
695 opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
696 }
697 }
698
699 impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
700 fn slot_duration() -> sp_consensus_aura::SlotDuration {
701 sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
702 }
703
704 fn authorities() -> Vec<AuraId> {
705 pallet_aura::Authorities::<Runtime>::get().into_inner()
706 }
707 }
708
709 impl sp_consensus_grandpa::GrandpaApi<Block> for Runtime {
710 fn grandpa_authorities() -> GrandpaAuthorityList {
711 Grandpa::grandpa_authorities()
712 }
713
714 fn current_set_id() -> sp_consensus_grandpa::SetId {
715 Grandpa::current_set_id()
716 }
717
718 fn submit_report_equivocation_unsigned_extrinsic(
719 _equivocation_proof: sp_consensus_grandpa::EquivocationProof<
720 <Block as BlockT>::Hash,
721 NumberFor<Block>,
722 >,
723 _key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof,
724 ) -> Option<()> {
725 None
726 }
727
728 fn generate_key_ownership_proof(
729 _set_id: sp_consensus_grandpa::SetId,
730 _authority_id: GrandpaId,
731 ) -> Option<sp_consensus_grandpa::OpaqueKeyOwnershipProof> {
732 None
736 }
737 }
738
739 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
740 fn account_nonce(account: AccountId) -> Nonce {
741 System::account_nonce(account)
742 }
743 }
744
745 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<
746 Block,
747 Balance,
748 > for Runtime {
749 fn query_info(
750 uxt: <Block as BlockT>::Extrinsic,
751 len: u32
752 ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
753 TransactionPayment::query_info(uxt, len)
754 }
755
756 fn query_fee_details(
757 uxt: <Block as BlockT>::Extrinsic,
758 len: u32,
759 ) -> pallet_transaction_payment::FeeDetails<Balance> {
760 TransactionPayment::query_fee_details(uxt, len)
761 }
762
763 fn query_weight_to_fee(weight: Weight) -> Balance {
764 TransactionPayment::weight_to_fee(weight)
765 }
766
767 fn query_length_to_fee(length: u32) -> Balance {
768 TransactionPayment::length_to_fee(length)
769 }
770 }
771
772 impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
773 fn chain_id() -> u64 {
774 <Runtime as pallet_evm::Config>::ChainId::get()
775 }
776
777 fn account_basic(address: H160) -> EVMAccount {
778 let (account, _) = pallet_evm::Pallet::<Runtime>::account_basic(&address);
779 account
780 }
781
782 fn gas_price() -> U256 {
783 let (gas_price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();
784 gas_price
785 }
786
787 fn account_code_at(address: H160) -> Vec<u8> {
788 pallet_evm::AccountCodes::<Runtime>::get(address)
789 }
790
791 fn author() -> H160 {
792 <pallet_evm::Pallet<Runtime>>::find_author()
793 }
794
795 fn storage_at(address: H160, index: U256) -> H256 {
796 pallet_evm::AccountStorages::<Runtime>::get(address, H256::from(index.to_big_endian()))
797 }
798
799 fn call(
800 from: H160,
801 to: H160,
802 data: Vec<u8>,
803 value: U256,
804 gas_limit: U256,
805 max_fee_per_gas: Option<U256>,
806 max_priority_fee_per_gas: Option<U256>,
807 nonce: Option<U256>,
808 estimate: bool,
809 access_list: Option<Vec<(H160, Vec<H256>)>>,
810 authorization_list: Option<AuthorizationList>,
811 ) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
812 use pallet_evm::GasWeightMapping as _;
813
814 let config = if estimate {
815 let mut config = <Runtime as pallet_evm::Config>::config().clone();
816 config.estimate = true;
817 Some(config)
818 } else {
819 None
820 };
821
822 let mut estimated_transaction_len = data.len() +
825 259;
839
840 if access_list.is_some() {
841 estimated_transaction_len += access_list.encoded_size();
842 }
843
844 if authorization_list.is_some() {
845 estimated_transaction_len += authorization_list.encoded_size();
846 }
847
848 let gas_limit = if gas_limit > U256::from(u64::MAX) {
849 u64::MAX
850 } else {
851 gas_limit.low_u64()
852 };
853 let without_base_extrinsic_weight = true;
854
855 let (weight_limit, proof_size_base_cost) =
856 match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
857 gas_limit,
858 without_base_extrinsic_weight
859 ) {
860 weight_limit if weight_limit.proof_size() > 0 => {
861 (Some(weight_limit), Some(estimated_transaction_len as u64))
862 }
863 _ => (None, None),
864 };
865
866 <Runtime as pallet_evm::Config>::Runner::call(
867 from,
868 to,
869 data,
870 value,
871 gas_limit.unique_saturated_into(),
872 max_fee_per_gas,
873 max_priority_fee_per_gas,
874 nonce,
875 access_list.unwrap_or_default(),
876 authorization_list.unwrap_or_default(),
877 false,
878 true,
879 weight_limit,
880 proof_size_base_cost,
881 config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
882 ).map_err(|err| err.error.into())
883 }
884
885 fn create(
886 from: H160,
887 data: Vec<u8>,
888 value: U256,
889 gas_limit: U256,
890 max_fee_per_gas: Option<U256>,
891 max_priority_fee_per_gas: Option<U256>,
892 nonce: Option<U256>,
893 estimate: bool,
894 access_list: Option<Vec<(H160, Vec<H256>)>>,
895 authorization_list: Option<AuthorizationList>,
896 ) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
897 use pallet_evm::GasWeightMapping as _;
898
899 let config = if estimate {
900 let mut config = <Runtime as pallet_evm::Config>::config().clone();
901 config.estimate = true;
902 Some(config)
903 } else {
904 None
905 };
906
907
908 let mut estimated_transaction_len = data.len() +
909 190;
917
918 if max_fee_per_gas.is_some() {
919 estimated_transaction_len += 32;
920 }
921 if max_priority_fee_per_gas.is_some() {
922 estimated_transaction_len += 32;
923 }
924 if access_list.is_some() {
925 estimated_transaction_len += access_list.encoded_size();
926 }
927 if authorization_list.is_some() {
928 estimated_transaction_len += authorization_list.encoded_size();
929 }
930
931 let gas_limit = if gas_limit > U256::from(u64::MAX) {
932 u64::MAX
933 } else {
934 gas_limit.low_u64()
935 };
936 let without_base_extrinsic_weight = true;
937
938 let (weight_limit, proof_size_base_cost) =
939 match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
940 gas_limit,
941 without_base_extrinsic_weight
942 ) {
943 weight_limit if weight_limit.proof_size() > 0 => {
944 (Some(weight_limit), Some(estimated_transaction_len as u64))
945 }
946 _ => (None, None),
947 };
948
949 <Runtime as pallet_evm::Config>::Runner::create(
950 from,
951 data,
952 value,
953 gas_limit.unique_saturated_into(),
954 max_fee_per_gas,
955 max_priority_fee_per_gas,
956 nonce,
957 access_list.unwrap_or_default(),
958 authorization_list.unwrap_or_default(),
959 false,
960 true,
961 weight_limit,
962 proof_size_base_cost,
963 config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config()),
964 ).map_err(|err| err.error.into())
965 }
966
967 fn current_transaction_statuses() -> Option<Vec<TransactionStatus>> {
968 pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
969 }
970
971 fn current_block() -> Option<pallet_ethereum::Block> {
972 pallet_ethereum::CurrentBlock::<Runtime>::get()
973 }
974
975 fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {
976 pallet_ethereum::CurrentReceipts::<Runtime>::get()
977 }
978
979 fn current_all() -> (
980 Option<pallet_ethereum::Block>,
981 Option<Vec<pallet_ethereum::Receipt>>,
982 Option<Vec<TransactionStatus>>
983 ) {
984 (
985 pallet_ethereum::CurrentBlock::<Runtime>::get(),
986 pallet_ethereum::CurrentReceipts::<Runtime>::get(),
987 pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
988 )
989 }
990
991 fn extrinsic_filter(
992 xts: Vec<<Block as BlockT>::Extrinsic>,
993 ) -> Vec<EthereumTransaction> {
994 xts.into_iter().filter_map(|xt| match xt.0.function {
995 RuntimeCall::Ethereum(transact { transaction }) => Some(transaction),
996 _ => None
997 }).collect::<Vec<EthereumTransaction>>()
998 }
999
1000 fn elasticity() -> Option<Permill> {
1001 Some(pallet_base_fee::Elasticity::<Runtime>::get())
1002 }
1003
1004 fn gas_limit_multiplier_support() {}
1005
1006 fn pending_block(
1007 xts: Vec<<Block as BlockT>::Extrinsic>,
1008 ) -> (Option<pallet_ethereum::Block>, Option<Vec<TransactionStatus>>) {
1009 for ext in xts.into_iter() {
1010 let _ = Executive::apply_extrinsic(ext);
1011 }
1012
1013 Ethereum::on_finalize(System::block_number() + 1);
1014
1015 (
1016 pallet_ethereum::CurrentBlock::<Runtime>::get(),
1017 pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
1018 )
1019 }
1020
1021 fn initialize_pending_block(header: &<Block as BlockT>::Header) {
1022 Executive::initialize_block(header);
1023 }
1024 }
1025
1026 impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {
1027 fn convert_transaction(transaction: EthereumTransaction) -> <Block as BlockT>::Extrinsic {
1028 UncheckedExtrinsic::new_bare(
1029 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
1030 )
1031 }
1032 }
1033
1034 #[cfg(feature = "runtime-benchmarks")]
1035 impl frame_benchmarking::Benchmark<Block> for Runtime {
1036 fn benchmark_metadata(extra: bool) -> (
1037 Vec<frame_benchmarking::BenchmarkList>,
1038 Vec<frame_support::traits::StorageInfo>,
1039 ) {
1040 use frame_benchmarking::{baseline, BenchmarkList};
1041 use frame_support::traits::StorageInfoTrait;
1042
1043 use baseline::Pallet as BaselineBench;
1044 use frame_system_benchmarking::Pallet as SystemBench;
1045
1046 use pallet_evm_precompile_curve25519_benchmarking::Pallet as EVMPrecompileCurve25519Bench;
1047 use pallet_evm_precompile_sha3fips_benchmarking::Pallet as EVMPrecompileSha3FIPSBench;
1048
1049 let mut list = Vec::<BenchmarkList>::new();
1050 list_benchmarks!(list, extra);
1051
1052 let storage_info = AllPalletsWithSystem::storage_info();
1053 (list, storage_info)
1054 }
1055
1056 #[allow(non_local_definitions)]
1057 fn dispatch_benchmark(
1058 config: frame_benchmarking::BenchmarkConfig
1059 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
1060 use frame_benchmarking::{baseline, BenchmarkBatch};
1061 use frame_support::traits::TrackedStorageKey;
1062
1063 use baseline::Pallet as BaselineBench;
1064 use frame_system_benchmarking::Pallet as SystemBench;
1065 use pallet_evm_precompile_curve25519_benchmarking::Pallet as EVMPrecompileCurve25519Bench;
1066 use pallet_evm_precompile_sha3fips_benchmarking::Pallet as EVMPrecompileSha3FIPSBench;
1067
1068 impl baseline::Config for Runtime {}
1069 impl frame_system_benchmarking::Config for Runtime {}
1070 impl pallet_evm_precompile_curve25519_benchmarking::Config for Runtime {}
1071 impl pallet_evm_precompile_sha3fips_benchmarking::Config for Runtime {}
1072
1073 let whitelist: Vec<TrackedStorageKey> = Vec::new();
1074
1075 let mut batches = Vec::<BenchmarkBatch>::new();
1076 let params = (&config, &whitelist);
1077 add_benchmarks!(params, batches);
1078 Ok(batches)
1079 }
1080 }
1081}
1082
1083#[cfg(test)]
1084mod tests {
1085 use super::{Runtime, WeightPerGas};
1086 #[test]
1087 fn configured_base_extrinsic_weight_is_evm_compatible() {
1088 let min_ethereum_transaction_weight = WeightPerGas::get() * 21_000;
1089 let base_extrinsic = <Runtime as frame_system::Config>::BlockWeights::get()
1090 .get(frame_support::dispatch::DispatchClass::Normal)
1091 .base_extrinsic;
1092 assert!(base_extrinsic.ref_time() <= min_ethereum_transaction_weight.ref_time());
1093 }
1094}