1#![cfg_attr(not(feature = "std"), no_std)]
2#![recursion_limit = "256"]
4
5#[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
35use 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
60pub type BlockNumber = u32;
62
63pub type Signature = MultiSignature;
65
66pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
69
70pub type Balance = u128;
72
73pub type Nonce = u32;
75
76pub type Hash = sp_core::H256;
78
79pub mod opaque {
84 use super::*;
85
86 pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
87
88 pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
90 pub type Block = generic::Block<Header, UncheckedExtrinsic>;
92 pub type BlockId = generic::BlockId<Block>;
94
95 impl_opaque_keys! {
96 pub struct SessionKeys {}
97 }
98}
99#[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 spec_version: 100,
112 impl_version: 1,
113 apis: RUNTIME_API_VERSIONS,
114 transaction_version: 1,
115 system_version: 1,
116};
117
118#[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
126const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
129
130const MAXIMUM_BLOCK_WEIGHT: Weight =
132 Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX);
133
134const 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 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 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#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)]
175impl frame_system::Config for Runtime {
176 type Block = Block;
178 type BlockWeights = RuntimeBlockWeights;
180 type BlockLength = RuntimeBlockLength;
182 type AccountId = AccountId;
184 type Nonce = Nonce;
186 type Hash = Hash;
188 type BlockHashCount = BlockHashCount;
190 type DbWeight = RocksDbWeight;
192 type Version = Version;
194 type AccountData = pallet_balances::AccountData<Balance>;
196 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 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 type Balance = Balance;
233 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#[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
308pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
310pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
312pub type Block = generic::Block<Header, UncheckedExtrinsic>;
314pub 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
347pub type UncheckedExtrinsic =
349 pallet_revive::evm::runtime::UncheckedExtrinsic<Address, Signature, EthExtraImpl>;
350
351pub 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}