diff --git a/Cargo.lock b/Cargo.lock index c01cd660f8..062d7af981 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1999,9 +1999,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "evm" -version = "0.37.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4448c65b71e8e2b9718232d84d09045eeaaccb2320494e6bd6dbf7e58fec8ff" +checksum = "1099df1dac16f32a136452ad98ee0f1ff42acd3e12ce65bea4462b61d656608a" dependencies = [ "auto_impl", "environmental", @@ -2020,9 +2020,9 @@ dependencies = [ [[package]] name = "evm-core" -version = "0.37.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c51bec0eb68a891c2575c758eaaa1d61373fc51f7caaf216b1fb5c3fea3b5d" +checksum = "4f1f13264b044cb66f0602180f0bc781c29accb41ff560669a3ec15858d5b606" dependencies = [ "parity-scale-codec", "primitive-types", @@ -2032,9 +2032,9 @@ dependencies = [ [[package]] name = "evm-gasometer" -version = "0.37.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8b93c59c54fc26522d842f0e0d3f8e8be331c776df18ff3e540b53c2f64d509" +checksum = "8d43eadc395bd1a52990787ca1495c26b0248165444912be075c28909a853b8c" dependencies = [ "environmental", "evm-core", @@ -2044,9 +2044,9 @@ dependencies = [ [[package]] name = "evm-runtime" -version = "0.37.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79b9459ce64f1a28688397c4013764ce53cd57bb84efc16b5187fa9b05b13ad" +checksum = "2aa5b32f59ec582a5651978004e5c784920291263b7dcb6de418047438e37f4f" dependencies = [ "auto_impl", "environmental", @@ -2749,6 +2749,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "frontier-template-runtime", "futures", + "hex-literal", "jsonrpsee", "log", "pallet-transaction-payment", @@ -3240,6 +3241,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + [[package]] name = "hkdf" version = "0.12.3" diff --git a/Cargo.toml b/Cargo.toml index 2e5c9fcec6..5c39828862 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,8 @@ bn = { package = "substrate-bn", version = "0.6", default-features = false } environmental = { version = "1.1.4", default-features = false } ethereum = { version = "0.14.0", default-features = false } ethereum-types = { version = "0.14.1", default-features = false } -evm = { version = "0.37.0", default-features = false } +evm = { version = "0.39.0", default-features = false } +hex-literal = { version = "0.3.4" } impl-serde = { version = "0.4.0", default-features = false } jsonrpsee = "0.16.2" kvdb-rocksdb = "0.18.0" diff --git a/frame/evm/src/lib.rs b/frame/evm/src/lib.rs index d646dbc19b..0fda563c8b 100644 --- a/frame/evm/src/lib.rs +++ b/frame/evm/src/lib.rs @@ -95,8 +95,8 @@ use fp_account::AccountId20; use fp_evm::GenesisAccount; pub use fp_evm::{ Account, CallInfo, CreateInfo, ExecutionInfo, FeeCalculator, InvalidEvmTransactionError, - LinearCostPrecompile, Log, Precompile, PrecompileFailure, PrecompileHandle, PrecompileOutput, - PrecompileResult, PrecompileSet, Vicinity, + IsPrecompileResult, LinearCostPrecompile, Log, Precompile, PrecompileFailure, PrecompileHandle, + PrecompileOutput, PrecompileResult, PrecompileSet, Vicinity, }; pub use self::{ diff --git a/frame/evm/src/mock.rs b/frame/evm/src/mock.rs index 65fe2968b4..2a9d49f1f3 100644 --- a/frame/evm/src/mock.rs +++ b/frame/evm/src/mock.rs @@ -17,7 +17,7 @@ //! Test mock for unit tests and benchmarking -use fp_evm::Precompile; +use fp_evm::{IsPrecompileResult, Precompile}; use frame_support::{ parameter_types, traits::{ConstU32, FindAuthor}, @@ -179,7 +179,10 @@ impl PrecompileSet for MockPrecompileSet { /// Check if the given address is a precompile. Should only be called to /// perform the check while not executing the precompile afterward, since /// `execute` already performs a check internally. - fn is_precompile(&self, address: H160) -> bool { - address == H160::from_low_u64_be(1) + fn is_precompile(&self, address: H160, _gas: u64) -> IsPrecompileResult { + IsPrecompileResult::Answer { + is_precompile: address == H160::from_low_u64_be(1), + extra_cost: 0, + } } } diff --git a/frame/evm/src/runner/stack.rs b/frame/evm/src/runner/stack.rs index ae9500a4b4..f5c2d8e737 100644 --- a/frame/evm/src/runner/stack.rs +++ b/frame/evm/src/runner/stack.rs @@ -37,7 +37,9 @@ use sp_std::{ vec::Vec, }; // Frontier -use fp_evm::{CallInfo, CreateInfo, ExecutionInfo, Log, PrecompileSet, Vicinity}; +use fp_evm::{ + CallInfo, CreateInfo, ExecutionInfo, IsPrecompileResult, Log, PrecompileSet, Vicinity, +}; use crate::{ runner::Runner as RunnerT, AccountCodes, AccountStorages, AddressMapping, BalanceOf, @@ -79,6 +81,7 @@ where T::PrecompilesType, >, ) -> (ExitReason, R), + R: Default, { let (base_fee, weight) = T::FeeCalculator::min_gas_price(); @@ -116,7 +119,7 @@ where fn execute_inner<'config, 'precompiles, F, R>( source: H160, value: U256, - gas_limit: u64, + mut gas_limit: u64, max_fee_per_gas: Option, max_priority_fee_per_gas: Option, config: &'config evm::Config, @@ -135,7 +138,28 @@ where T::PrecompilesType, >, ) -> (ExitReason, R), + R: Default, { + // The precompile check is only used for transactional invocations. However, here we always + // execute the check, because the check has side effects. + let is_precompile = match precompiles.is_precompile(source, gas_limit) { + IsPrecompileResult::Answer { + is_precompile, + extra_cost, + } => { + gas_limit = gas_limit.saturating_sub(extra_cost); + is_precompile + } + IsPrecompileResult::OutOfGas => { + return Ok(ExecutionInfo { + exit_reason: ExitError::OutOfGas.into(), + value: Default::default(), + used_gas: gas_limit.into(), + logs: Default::default(), + }) + } + }; + // Only check the restrictions of EIP-3607 if the source of the EVM operation is from an external transaction. // If the source of this EVM operation is from an internal call, like from `eth_call` or `eth_estimateGas` RPC, // we will skip the checks for the EIP-3607. @@ -147,9 +171,7 @@ where // of a precompile. While mainnet Ethereum currently only has stateless precompiles, // projects using Frontier can have stateful precompiles that can manage funds or // which calls other contracts that expects this precompile address to be trustworthy. - if is_transactional - && (!>::get(source).is_empty() || precompiles.is_precompile(source)) - { + if is_transactional && (!>::get(source).is_empty() || is_precompile) { return Err(RunnerError { error: Error::::TransactionMustComeFromEOA, weight, @@ -622,6 +644,10 @@ impl<'vicinity, 'config, T: Config> BackendT for SubstrateStackState<'vicinity, self.vicinity.origin } + fn block_randomness(&self) -> Option { + None + } + fn block_hash(&self, number: U256) -> H256 { if number > U256::from(u32::MAX) { H256::default() @@ -731,9 +757,10 @@ where self.substate.deleted(address) } - fn inc_nonce(&mut self, address: H160) { + fn inc_nonce(&mut self, address: H160) -> Result<(), ExitError> { let account_id = T::AddressMapping::into_account_id(address); frame_system::Pallet::::inc_account_nonce(&account_id); + Ok(()) } fn set_storage(&mut self, address: H160, index: H256, value: H256) { diff --git a/primitives/evm/src/lib.rs b/primitives/evm/src/lib.rs index caf2463ede..25739061e1 100644 --- a/primitives/evm/src/lib.rs +++ b/primitives/evm/src/lib.rs @@ -32,6 +32,7 @@ use sp_std::vec::Vec; pub use evm::{ backend::{Basic as Account, Log}, + executor::stack::IsPrecompileResult, Config, ExitReason, }; diff --git a/template/node/Cargo.toml b/template/node/Cargo.toml index 0e3083c928..95d238afc1 100644 --- a/template/node/Cargo.toml +++ b/template/node/Cargo.toml @@ -16,6 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] async-trait = "0.1" clap = { version = "4.1", features = ["derive", "deprecated"] } futures = "0.3.25" +hex-literal = { workspace = true } jsonrpsee = { workspace = true, features = ["server", "macros"] } log = "0.4.17" scale-codec = { package = "parity-scale-codec", workspace = true } diff --git a/template/node/src/benchmarking.rs b/template/node/src/benchmarking.rs index 81b88077b5..58d09ca92e 100644 --- a/template/node/src/benchmarking.rs +++ b/template/node/src/benchmarking.rs @@ -106,7 +106,7 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder { self.client.as_ref(), acc, BalancesCall::transfer_keep_alive { - dest: self.dest.into(), + dest: self.dest, value: self.value, } .into(), @@ -171,7 +171,7 @@ pub fn create_benchmark_extrinsic( runtime::UncheckedExtrinsic::new_signed( call, - AccountId20::from(sender.public()).into(), + AccountId20::from(sender.public()), runtime::Signature::new(signature), extra, ) diff --git a/template/node/src/chain_spec.rs b/template/node/src/chain_spec.rs index d53c230903..f58201bd25 100644 --- a/template/node/src/chain_spec.rs +++ b/template/node/src/chain_spec.rs @@ -1,11 +1,14 @@ use std::{collections::BTreeMap, str::FromStr}; +use hex_literal::hex; use serde::{Deserialize, Serialize}; // Substrate use sc_chain_spec::{ChainType, Properties}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_consensus_grandpa::AuthorityId as GrandpaId; -use sp_core::{ecdsa, storage::Storage, Pair, Public, H160, U256}; +#[allow(unused_imports)] +use sp_core::ecdsa; +use sp_core::{storage::Storage, Pair, Public, H160, U256}; use sp_runtime::traits::{IdentifyAccount, Verify}; use sp_state_machine::BasicExternalities; // Frontier @@ -49,9 +52,12 @@ pub fn get_from_seed(seed: &str) -> ::Pu .public() } +#[allow(dead_code)] type AccountPublic = ::Signer; /// Generate an account ID from seed. +/// For use with `AccountId32`, `dead_code` if `AccountId20`. +#[allow(dead_code)] pub fn get_account_id_from_seed(seed: &str) -> AccountId where AccountPublic: From<::Public>, @@ -84,14 +90,16 @@ pub fn development_config(enable_manual_seal: Option) -> DevChainSpec { DevGenesisExt { genesis_config: testnet_genesis( wasm_binary, - // Sudo account - get_account_id_from_seed::("Alice"), + // Sudo account (Alith) + AccountId::from(hex!("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac")), // Pre-funded accounts vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), + AccountId::from(hex!("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac")), // Alith + AccountId::from(hex!("3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0")), // Baltathar + AccountId::from(hex!("798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc")), // Charleth + AccountId::from(hex!("773539d4Ac0e786233D90A233654ccEE26a613D9")), // Dorothy + AccountId::from(hex!("Ff64d3F6efE2317EE2807d223a0Bdc4c0c49dfDB")), // Ethan + AccountId::from(hex!("C0F0f4ab324C46e55D02D0033343B4Be8A55532d")), // Faith ], // Initial PoA authorities vec![authority_keys_from_seed("Alice")], @@ -129,22 +137,16 @@ pub fn local_testnet_config() -> ChainSpec { testnet_genesis( wasm_binary, // Initial PoA authorities - // Sudo account - get_account_id_from_seed::("Alice"), + // Sudo account (Alith) + AccountId::from(hex!("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac")), // Pre-funded accounts vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), + AccountId::from(hex!("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac")), // Alith + AccountId::from(hex!("3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0")), // Baltathar + AccountId::from(hex!("798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc")), // Charleth + AccountId::from(hex!("773539d4Ac0e786233D90A233654ccEE26a613D9")), // Dorothy + AccountId::from(hex!("Ff64d3F6efE2317EE2807d223a0Bdc4c0c49dfDB")), // Ethan + AccountId::from(hex!("C0F0f4ab324C46e55D02D0033343B4Be8A55532d")), // Faith ], vec![ authority_keys_from_seed("Alice"), diff --git a/template/node/src/service.rs b/template/node/src/service.rs index de24a58b8d..c280044a6e 100644 --- a/template/node/src/service.rs +++ b/template/node/src/service.rs @@ -652,7 +652,7 @@ pub fn build_full( } pub fn new_chain_ops( - mut config: &mut Configuration, + config: &mut Configuration, eth_config: &EthConfiguration, ) -> Result< ( diff --git a/template/runtime/src/lib.rs b/template/runtime/src/lib.rs index fd61fdf536..f11a61fa40 100644 --- a/template/runtime/src/lib.rs +++ b/template/runtime/src/lib.rs @@ -20,8 +20,8 @@ use sp_core::{ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, Get, - IdentifyAccount, NumberFor, PostDispatchInfoOf, UniqueSaturatedInto, Verify, + BlakeTwo256, Block as BlockT, DispatchInfoOf, Dispatchable, Get, IdentifyAccount, + IdentityLookup, NumberFor, PostDispatchInfoOf, UniqueSaturatedInto, Verify, }, transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, ApplyExtrinsicResult, ConsensusEngineId, Perbill, Permill, @@ -181,7 +181,7 @@ impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; + type Lookup = IdentityLookup; /// The header type. type Header = generic::Header; /// The ubiquitous event type. @@ -440,7 +440,7 @@ impl fp_rpc::ConvertTransaction for TransactionConve } /// The address format for describing accounts. -pub type Address = sp_runtime::MultiAddress; +pub type Address = AccountId; /// Block header type as expected by this runtime. pub type Header = generic::Header; /// Block type as expected by this runtime. diff --git a/template/runtime/src/precompiles.rs b/template/runtime/src/precompiles.rs index 3395dcf144..c563f8e1f2 100644 --- a/template/runtime/src/precompiles.rs +++ b/template/runtime/src/precompiles.rs @@ -1,4 +1,6 @@ -use pallet_evm::{Precompile, PrecompileHandle, PrecompileResult, PrecompileSet}; +use pallet_evm::{ + IsPrecompileResult, Precompile, PrecompileHandle, PrecompileResult, PrecompileSet, +}; use sp_core::H160; use sp_std::marker::PhantomData; @@ -46,8 +48,11 @@ where } } - fn is_precompile(&self, address: H160) -> bool { - Self::used_addresses().contains(&address) + fn is_precompile(&self, address: H160, _gas: u64) -> IsPrecompileResult { + IsPrecompileResult::Answer { + is_precompile: Self::used_addresses().contains(&address), + extra_cost: 0, + } } }