ink_node_runtime/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
3#![recursion_limit = "256"]
4
5// Make the WASM binary available.
6#[cfg(feature = "std")]
7include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
8
9mod assets_config;
10mod revive_config;
11
12extern crate alloc;
13use alloc::{vec, vec::Vec};
14use codec::Encode;
15use frame_support::{
16	derive_impl,
17	dispatch::DispatchClass,
18	genesis_builder_helper::{build_state, get_preset},
19};
20use frame_system::limits::{BlockLength, BlockWeights};
21use pallet_revive::{evm::runtime::EthExtra, AddressMapper};
22use polkadot_runtime_common::SlowAdjustingFeeUpdate;
23use sp_api::impl_runtime_apis;
24use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H160, U256};
25use sp_runtime::{
26	generic, impl_opaque_keys,
27	traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, Verify},
28	transaction_validity::{TransactionSource, TransactionValidity},
29	ApplyExtrinsicResult, MultiSignature,
30};
31#[cfg(feature = "std")]
32use sp_version::NativeVersion;
33use sp_version::RuntimeVersion;
34
35// A few exports that help ease life for downstream crates.
36use frame_support::dispatch::DispatchInfo;
37pub use frame_support::{
38	construct_runtime, parameter_types,
39	traits::{
40		AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU8, KeyOwnerProofSystem,
41		Randomness, StorageInfo,
42	},
43	weights::{
44		constants::{
45			BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND,
46		},
47		IdentityFee, Weight,
48	},
49	StorageValue,
50};
51pub use frame_system::Call as SystemCall;
52pub use pallet_balances::Call as BalancesCall;
53pub use pallet_timestamp::Call as TimestampCall;
54use pallet_transaction_payment::{FeeDetails, FungibleAdapter, RuntimeDispatchInfo};
55use sp_runtime::traits::TransactionExtension;
56#[cfg(any(feature = "std", test))]
57pub use sp_runtime::BuildStorage;
58pub use sp_runtime::{Perbill, Permill};
59
60/// An index to a block.
61pub type BlockNumber = u32;
62
63/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
64pub type Signature = MultiSignature;
65
66/// Some way of identifying an account on the chain. We intentionally make it equivalent
67/// to the public key of our transaction signing scheme.
68pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
69
70/// Balance of an account.
71pub type Balance = u128;
72
73/// Index of a transaction in the chain.
74pub type Nonce = u32;
75
76/// A hash of some data used by the chain.
77pub type Hash = sp_core::H256;
78
79/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
80/// the specifics of the runtime. They can then be made to be agnostic over specific formats
81/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
82/// to even the core data structures.
83pub mod opaque {
84	use super::*;
85
86	pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
87
88	/// Opaque block header type.
89	pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
90	/// Opaque block type.
91	pub type Block = generic::Block<Header, UncheckedExtrinsic>;
92	/// Opaque block identifier type.
93	pub type BlockId = generic::BlockId<Block>;
94
95	impl_opaque_keys! {
96		pub struct SessionKeys {}
97	}
98}
99// To learn more about runtime versioning, see:
100// https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning
101#[sp_version::runtime_version]
102pub const VERSION: RuntimeVersion = RuntimeVersion {
103	spec_name: alloc::borrow::Cow::Borrowed("ink-node"),
104	impl_name: alloc::borrow::Cow::Borrowed("ink-node"),
105	authoring_version: 1,
106	// The version of the runtime specification. A full node will not attempt to use its native
107	//   runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`,
108	//   `spec_version`, and `authoring_version` are the same between Wasm and native.
109	// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
110	//   the compatible custom types.
111	spec_version: 100,
112	impl_version: 1,
113	apis: RUNTIME_API_VERSIONS,
114	transaction_version: 1,
115	system_version: 1,
116};
117
118/// The version information used to identify this runtime when compiled natively.
119#[cfg(feature = "std")]
120pub fn native_version() -> NativeVersion {
121	NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
122}
123
124const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
125
126/// We assume that ~10% of the block weight is consumed by `on_initialize` handlers.
127/// This is used to limit the maximal weight of a single extrinsic.
128const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
129
130/// We allow for 2 seconds of compute with a 6 second average block time, with maximum proof size.
131const MAXIMUM_BLOCK_WEIGHT: Weight =
132	Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX);
133
134// Unit = the base number of indivisible units for balances
135const MILLIUNIT: Balance = 1_000_000_000;
136pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT;
137
138impl pallet_insecure_randomness_collective_flip::Config for Runtime {}
139
140parameter_types! {
141	pub const BlockHashCount: BlockNumber = 2400;
142	pub const Version: RuntimeVersion = VERSION;
143
144	// This part is copied from Substrate's `bin/node/runtime/src/lib.rs`.
145	//  The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the
146	// `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize
147	// the lazy contract deletion.
148	pub RuntimeBlockLength: BlockLength =
149		BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
150	pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
151		.base_block(BlockExecutionWeight::get())
152		.for_class(DispatchClass::all(), |weights| {
153			weights.base_extrinsic = ExtrinsicBaseWeight::get();
154		})
155		.for_class(DispatchClass::Normal, |weights| {
156			weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
157		})
158		.for_class(DispatchClass::Operational, |weights| {
159			weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
160			// Operational transactions have some extra reserved space, so that they
161			// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
162			weights.reserved = Some(
163				MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
164			);
165		})
166		.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
167		.build_or_panic();
168
169	pub const SS58Prefix: u8 = 42;
170}
171
172// Configure FRAME pallets to include in runtime.
173
174#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)]
175impl frame_system::Config for Runtime {
176	/// The block type for the runtime.
177	type Block = Block;
178	/// Block & extrinsics weights: base values and limits.
179	type BlockWeights = RuntimeBlockWeights;
180	/// The maximum length of a block (in bytes).
181	type BlockLength = RuntimeBlockLength;
182	/// The identifier used to distinguish between accounts.
183	type AccountId = AccountId;
184	/// The type for storing how many extrinsics an account has signed.
185	type Nonce = Nonce;
186	/// The type for hashing blocks and tries.
187	type Hash = Hash;
188	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
189	type BlockHashCount = BlockHashCount;
190	/// The weight of database operations that the runtime can invoke.
191	type DbWeight = RocksDbWeight;
192	/// Version of the runtime.
193	type Version = Version;
194	/// The data to be stored in an account.
195	type AccountData = pallet_balances::AccountData<Balance>;
196	/// This is used as an identifier of the chain. 42 is the generic substrate prefix.
197	type SS58Prefix = SS58Prefix;
198	type MaxConsumers = frame_support::traits::ConstU32<16>;
199}
200
201parameter_types! {
202	pub const UncleGenerations: u32 = 0;
203}
204
205impl pallet_authorship::Config for Runtime {
206	type FindAuthor = ();
207	type EventHandler = ();
208}
209
210parameter_types! {
211	pub const MinimumPeriod: u64 = 0;
212}
213
214impl pallet_timestamp::Config for Runtime {
215	/// A timestamp: milliseconds since the unix epoch.
216	type Moment = u64;
217	type OnTimestampSet = ();
218	type MinimumPeriod = MinimumPeriod;
219	type WeightInfo = ();
220}
221
222parameter_types! {
223	pub const MaxLocks: u32 = 50;
224	pub const MaxReserves: u32 = 50;
225}
226
227impl pallet_balances::Config for Runtime {
228	type MaxLocks = MaxLocks;
229	type MaxReserves = MaxReserves;
230	type ReserveIdentifier = [u8; 8];
231	/// The type for recording an account's balance.
232	type Balance = Balance;
233	/// The ubiquitous event type.
234	type RuntimeEvent = RuntimeEvent;
235	type DustRemoval = ();
236	type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
237	type AccountStore = System;
238	type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
239	type FreezeIdentifier = ();
240	type MaxFreezes = ();
241	type RuntimeHoldReason = RuntimeHoldReason;
242	type RuntimeFreezeReason = RuntimeFreezeReason;
243	type DoneSlashHandler = ();
244}
245
246impl pallet_transaction_payment::Config for Runtime {
247	type RuntimeEvent = RuntimeEvent;
248	type OnChargeTransaction = FungibleAdapter<Balances, ()>;
249	type OperationalFeeMultiplier = ConstU8<5>;
250	type WeightToFee = IdentityFee<Balance>;
251	type LengthToFee = IdentityFee<Balance>;
252	type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
253	type WeightInfo = pallet_transaction_payment::weights::SubstrateWeight<Runtime>;
254}
255
256impl pallet_sudo::Config for Runtime {
257	type RuntimeEvent = RuntimeEvent;
258	type RuntimeCall = RuntimeCall;
259	type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
260}
261
262impl pallet_utility::Config for Runtime {
263	type RuntimeEvent = RuntimeEvent;
264	type RuntimeCall = RuntimeCall;
265	type PalletsOrigin = OriginCaller;
266	type WeightInfo = pallet_utility::weights::SubstrateWeight<Runtime>;
267}
268
269// Create the runtime by composing the FRAME pallets that were previously configured.
270#[frame_support::runtime]
271mod runtime {
272	#[runtime::runtime]
273	#[runtime::derive(
274		RuntimeCall,
275		RuntimeEvent,
276		RuntimeError,
277		RuntimeOrigin,
278		RuntimeFreezeReason,
279		RuntimeHoldReason,
280		RuntimeSlashReason,
281		RuntimeLockId,
282		RuntimeTask,
283		RuntimeViewFunction
284	)]
285	pub struct Runtime;
286	#[runtime::pallet_index(0)]
287	pub type System = frame_system;
288	#[runtime::pallet_index(1)]
289	pub type RandomnessCollectiveFlip = pallet_insecure_randomness_collective_flip;
290	#[runtime::pallet_index(2)]
291	pub type Utility = pallet_utility;
292	#[runtime::pallet_index(3)]
293	pub type Timestamp = pallet_timestamp;
294	#[runtime::pallet_index(4)]
295	pub type Balances = pallet_balances;
296	#[runtime::pallet_index(5)]
297	pub type Authorship = pallet_authorship;
298	#[runtime::pallet_index(6)]
299	pub type TransactionPayment = pallet_transaction_payment;
300	#[runtime::pallet_index(7)]
301	pub type Sudo = pallet_sudo;
302	#[runtime::pallet_index(8)]
303	pub type Revive = pallet_revive;
304	#[runtime::pallet_index(9)]
305	pub type Assets = pallet_assets;
306}
307
308/// The address format for describing accounts.
309pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
310/// Block header type as expected by this runtime.
311pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
312/// Block type as expected by this runtime.
313pub type Block = generic::Block<Header, UncheckedExtrinsic>;
314/// The TransactionExtension to the basic transaction logic.
315pub type TxExtension = (
316	frame_system::CheckNonZeroSender<Runtime>,
317	frame_system::CheckSpecVersion<Runtime>,
318	frame_system::CheckTxVersion<Runtime>,
319	frame_system::CheckGenesis<Runtime>,
320	frame_system::CheckEra<Runtime>,
321	frame_system::CheckNonce<Runtime>,
322	frame_system::CheckWeight<Runtime>,
323	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
324);
325
326#[derive(Clone, PartialEq, Eq, Debug)]
327pub struct EthExtraImpl;
328
329impl EthExtra for EthExtraImpl {
330	type Config = Runtime;
331	type Extension = TxExtension;
332
333	fn get_eth_extension(nonce: u32, tip: Balance) -> Self::Extension {
334		(
335			frame_system::CheckNonZeroSender::<Runtime>::new(),
336			frame_system::CheckSpecVersion::<Runtime>::new(),
337			frame_system::CheckTxVersion::<Runtime>::new(),
338			frame_system::CheckGenesis::<Runtime>::new(),
339			frame_system::CheckEra::from(crate::generic::Era::Immortal),
340			frame_system::CheckNonce::<Runtime>::from(nonce),
341			frame_system::CheckWeight::<Runtime>::new(),
342			pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
343		)
344	}
345}
346
347/// Unchecked extrinsic type as expected by this runtime.
348pub type UncheckedExtrinsic =
349	pallet_revive::evm::runtime::UncheckedExtrinsic<Address, Signature, EthExtraImpl>;
350
351/// Executive: handles dispatch to the various modules.
352pub type Executive = frame_executive::Executive<
353	Runtime,
354	Block,
355	frame_system::ChainContext<Runtime>,
356	Runtime,
357	AllPalletsWithSystem,
358>;
359
360impl TryFrom<RuntimeCall> for pallet_revive::Call<Runtime> {
361	type Error = ();
362
363	fn try_from(value: RuntimeCall) -> Result<Self, Self::Error> {
364		match value {
365			RuntimeCall::Revive(call) => Ok(call),
366			_ => Err(()),
367		}
368	}
369}
370
371impl_runtime_apis! {
372	impl sp_api::Core<Block> for Runtime {
373		fn version() -> RuntimeVersion {
374			VERSION
375		}
376
377		fn execute_block(block: Block) {
378			Executive::execute_block(block);
379		}
380
381		fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
382			Executive::initialize_block(header)
383		}
384	}
385
386	impl sp_api::Metadata<Block> for Runtime {
387		fn metadata() -> OpaqueMetadata {
388			OpaqueMetadata::new(Runtime::metadata().into())
389		}
390		fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
391			Runtime::metadata_at_version(version)
392		}
393
394		fn metadata_versions() -> Vec<u32> {
395			Runtime::metadata_versions()
396		}
397	}
398
399	impl frame_support::view_functions::runtime_api::RuntimeViewFunction<Block> for Runtime {
400		fn execute_view_function(id: frame_support::view_functions::ViewFunctionId, input: Vec<u8>) -> Result<Vec<u8>, frame_support::view_functions::ViewFunctionDispatchError> {
401			Runtime::execute_view_function(id, input)
402		}
403	}
404
405	impl sp_block_builder::BlockBuilder<Block> for Runtime {
406		fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
407			Executive::apply_extrinsic(extrinsic)
408		}
409
410		fn finalize_block() -> <Block as BlockT>::Header {
411			Executive::finalize_block()
412		}
413
414		fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
415			data.create_extrinsics()
416		}
417
418		fn check_inherents(
419			block: Block,
420			data: sp_inherents::InherentData,
421		) -> sp_inherents::CheckInherentsResult {
422			data.check_extrinsics(&block)
423		}
424	}
425
426	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
427		fn validate_transaction(
428			source: TransactionSource,
429			tx: <Block as BlockT>::Extrinsic,
430			block_hash: <Block as BlockT>::Hash,
431		) -> TransactionValidity {
432			Executive::validate_transaction(source, tx, block_hash)
433		}
434	}
435
436	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
437		fn offchain_worker(header: &<Block as BlockT>::Header) {
438			Executive::offchain_worker(header)
439		}
440	}
441
442	impl sp_session::SessionKeys<Block> for Runtime {
443		fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
444			opaque::SessionKeys::generate(seed)
445		}
446
447		fn decode_session_keys(
448			encoded: Vec<u8>,
449		) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
450			opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
451		}
452	}
453
454	impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
455		fn account_nonce(account: AccountId) -> Nonce {
456			System::account_nonce(account)
457		}
458	}
459
460	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<
461		Block,
462		Balance,
463	> for Runtime {
464		fn query_info(uxt: <Block as BlockT>::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance> {
465			TransactionPayment::query_info(uxt, len)
466		}
467		fn query_fee_details(uxt: <Block as BlockT>::Extrinsic, len: u32) -> FeeDetails<Balance> {
468			TransactionPayment::query_fee_details(uxt, len)
469		}
470		fn query_weight_to_fee(weight: Weight) -> Balance {
471			TransactionPayment::weight_to_fee(weight)
472		}
473		fn query_length_to_fee(length: u32) -> Balance {
474			TransactionPayment::length_to_fee(length)
475		}
476	}
477
478	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall> for Runtime {
479		fn query_call_info(
480			call: RuntimeCall,
481			len: u32,
482		) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> {
483			TransactionPayment::query_call_info(call, len)
484		}
485		fn query_call_fee_details(
486			call: RuntimeCall,
487			len: u32,
488		) -> pallet_transaction_payment::FeeDetails<Balance> {
489			TransactionPayment::query_call_fee_details(call, len)
490		}
491		fn query_weight_to_fee(weight: Weight) -> Balance {
492			TransactionPayment::weight_to_fee(weight)
493		}
494		fn query_length_to_fee(length: u32) -> Balance {
495			TransactionPayment::length_to_fee(length)
496		}
497	}
498
499	impl pallet_revive::ReviveApi<Block, AccountId, Balance, Nonce, BlockNumber> for Runtime
500	{
501		fn balance(address: H160) -> U256 {
502			Revive::evm_balance(&address)
503		}
504
505		fn block_gas_limit() -> U256 {
506			Revive::evm_block_gas_limit()
507		}
508
509		fn gas_price() -> U256 {
510			log::info!("-----gas price");
511			Revive::evm_gas_price()
512		}
513
514		fn nonce(address: H160) -> Nonce {
515			let account = <Runtime as pallet_revive::Config>::AddressMapper::to_account_id(&address);
516			System::account_nonce(account)
517		}
518
519		fn eth_transact(tx: pallet_revive::evm::GenericTransaction) -> Result<pallet_revive::EthTransactInfo<Balance>, pallet_revive::EthTransactError>
520		{
521			let blockweights: BlockWeights = <Runtime as frame_system::Config>::BlockWeights::get();
522			let tx_fee = |pallet_call, mut dispatch_info: DispatchInfo| {
523				let call = RuntimeCall::Revive(pallet_call);
524				dispatch_info.extension_weight = EthExtraImpl::get_eth_extension(0, 0u32.into()).weight(&call);
525				let uxt: UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic::new_bare(call).into();
526
527				pallet_transaction_payment::Pallet::<Runtime>::compute_fee(
528					uxt.encoded_size() as u32,
529					&dispatch_info,
530					0u32.into(),
531				)
532			};
533
534			Revive::bare_eth_transact(tx, blockweights.max_block, tx_fee)
535		}
536
537		fn call(
538			origin: AccountId,
539			dest: H160,
540			value: Balance,
541			gas_limit: Option<Weight>,
542			storage_deposit_limit: Option<Balance>,
543			input_data: Vec<u8>,
544		) -> pallet_revive::ContractResult<pallet_revive::ExecReturnValue, Balance> {
545			Revive::bare_call(
546				RuntimeOrigin::signed(origin),
547				dest,
548				value,
549				gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block),
550				pallet_revive::DepositLimit::Balance(storage_deposit_limit.unwrap_or(u128::MAX)),
551				input_data,
552			)
553		}
554
555		fn instantiate(
556			origin: AccountId,
557			value: Balance,
558			gas_limit: Option<Weight>,
559			storage_deposit_limit: Option<Balance>,
560			code: pallet_revive::Code,
561			data: Vec<u8>,
562			salt: Option<[u8; 32]>,
563		) -> pallet_revive::ContractResult<pallet_revive::InstantiateReturnValue, Balance>
564		{
565			Revive::bare_instantiate(
566				RuntimeOrigin::signed(origin),
567				value,
568				gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block),
569				pallet_revive::DepositLimit::Balance(storage_deposit_limit.unwrap_or(u128::MAX)),
570				code,
571				data,
572				salt,
573			)
574		}
575
576		fn upload_code(
577			origin: AccountId,
578			code: Vec<u8>,
579			storage_deposit_limit: Option<Balance>,
580		) -> pallet_revive::CodeUploadResult<Balance>
581		{
582			Revive::bare_upload_code(
583				RuntimeOrigin::signed(origin),
584				code,
585				storage_deposit_limit.unwrap_or(u128::MAX),
586			)
587		}
588
589		fn get_storage(
590			address: H160,
591			key: [u8; 32],
592		) -> pallet_revive::GetStorageResult {
593			Revive::get_storage(
594				address,
595				key
596			)
597		}
598
599		fn trace_block(
600			block: Block,
601			config: pallet_revive::evm::TracerConfig
602		) -> Vec<(u32, pallet_revive::evm::CallTrace)> {
603			use pallet_revive::tracing::trace;
604			let mut tracer = config.build(Revive::evm_gas_from_weight);
605			let mut traces = vec![];
606			let (header, extrinsics) = block.deconstruct();
607
608			Executive::initialize_block(&header);
609			for (index, ext) in extrinsics.into_iter().enumerate() {
610				trace(&mut tracer, || {
611					let _ = Executive::apply_extrinsic(ext);
612				});
613
614				if let Some(tx_trace) = tracer.collect_traces().pop() {
615					traces.push((index as u32, tx_trace));
616				}
617			}
618
619			traces
620		}
621
622		fn trace_tx(
623			block: Block,
624			tx_index: u32,
625			config: pallet_revive::evm::TracerConfig
626		) -> Option<pallet_revive::evm::CallTrace> {
627			log::info!("-----trace_tx called with tx_index {:?}", tx_index);
628			use pallet_revive::tracing::trace;
629			let mut tracer = config.build(Revive::evm_gas_from_weight);
630			let (header, extrinsics) = block.deconstruct();
631
632			log::info!("-----trace_tx found {:?} xts", extrinsics.len());
633			Executive::initialize_block(&header);
634			log::info!("-----trace_tx initialized block");
635			for (index, ext) in extrinsics.into_iter().enumerate() {
636				log::info!("-----trace_tx enumerating {:?}", index);
637				if index as u32 == tx_index {
638					log::info!("-----trace_tx found tx_index {:?}", tx_index);
639					trace(&mut tracer, || {
640						log::info!("-----trace_tx applying extrinsic");
641						let res = Executive::apply_extrinsic(ext);
642						log::info!("-----trace_tx after applying extrinsic {:?}", res);
643					});
644						log::info!("-----trace_tx break");
645					break;
646				} else {
647						log::info!("-----trace_tx apply extrinsic without tx_index match");
648					let res = Executive::apply_extrinsic(ext);
649						log::info!("-----trace_tx apply extrinsic without tx_index match {:?}", res);
650				}
651			}
652			log::info!("-----trace_tx after loop");
653
654			let mut traces = tracer.collect_traces();
655			log::info!("-----trace_tx traces.len() {:?}", traces.len());
656			log::info!("-----trace_tx traces {:?}", traces);
657
658			let traces = traces.pop();
659			log::info!("-----trace_tx traces popped {:?}", traces);
660
661			traces
662		}
663
664		fn trace_call(
665			tx: pallet_revive::evm::GenericTransaction,
666			config: pallet_revive::evm::TracerConfig)
667			-> Result<pallet_revive::evm::CallTrace, pallet_revive::EthTransactError>
668		{
669			use pallet_revive::tracing::trace;
670			let mut tracer = config.build(Revive::evm_gas_from_weight);
671			trace(&mut tracer, || {
672				Self::eth_transact(tx)
673			})?;
674
675			Ok(tracer.collect_traces().pop().expect("eth_transact succeeded, trace must exist, qed"))
676		}
677	}
678
679	impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
680		fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
681			build_state::<RuntimeGenesisConfig>(config)
682		}
683
684		fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
685			get_preset::<RuntimeGenesisConfig>(id, |_| None)
686		}
687
688		fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
689			Default::default()
690		}
691	}
692}