From 8f502bba341197de224c18f9afdc32c8e88103e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lo=C3=AFs?= Date: Mon, 29 May 2023 18:37:44 +0200 Subject: [PATCH] Update evm to 0.39 (#2312) * Update evm to 0.39 * Adapted tests Fixed parameter in execute is_precompile_or_fail check format * Removed unused imports * Wip fallible discriminant * fmt * wip fix test assets costs * fix test assets costs * TODO temp ignore precompile macro tests --------- Co-authored-by: tgmichel Co-authored-by: Francisco Gamundi --- Cargo.lock | 84 ++++++--- Cargo.toml | 14 +- precompiles/assets-erc20/src/lib.rs | 17 +- precompiles/precompile-registry/src/lib.rs | 24 ++- precompiles/proxy/src/lib.rs | 16 +- precompiles/proxy/src/mock.rs | 7 +- .../utils/macro/src/precompile/expand.rs | 27 ++- .../utils/macro/src/precompile/parse.rs | 22 +-- .../tests/expand/precompileset.expanded.rs | 4 +- precompiles/utils/macro/tests/tests.rs | 1 + precompiles/utils/src/lib.rs | 1 + precompiles/utils/src/precompile_set.rs | 178 +++++++++++++----- runtime/moonbase/src/lib.rs | 13 +- runtime/moonbase/tests/integration_test.rs | 68 ++++--- runtime/moonbeam/src/lib.rs | 18 +- runtime/moonbeam/tests/integration_test.rs | 68 ++++--- runtime/moonriver/src/lib.rs | 18 +- runtime/moonriver/tests/integration_test.rs | 68 ++++--- 18 files changed, 416 insertions(+), 232 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c05297be41d..49402045c12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2573,8 +2573,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "evm" -version = "0.37.0" -source = "git+https://github.com/rust-blockchain/evm?rev=842e03d068ddb6a3195a2dedc4a9b63caadb3355#842e03d068ddb6a3195a2dedc4a9b63caadb3355" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1099df1dac16f32a136452ad98ee0f1ff42acd3e12ce65bea4462b61d656608a" dependencies = [ "auto_impl", "environmental", @@ -2593,8 +2594,9 @@ dependencies = [ [[package]] name = "evm-core" -version = "0.37.0" -source = "git+https://github.com/rust-blockchain/evm?rev=842e03d068ddb6a3195a2dedc4a9b63caadb3355#842e03d068ddb6a3195a2dedc4a9b63caadb3355" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f1f13264b044cb66f0602180f0bc781c29accb41ff560669a3ec15858d5b606" dependencies = [ "parity-scale-codec", "primitive-types", @@ -2604,8 +2606,9 @@ dependencies = [ [[package]] name = "evm-gasometer" -version = "0.37.0" -source = "git+https://github.com/rust-blockchain/evm?rev=842e03d068ddb6a3195a2dedc4a9b63caadb3355#842e03d068ddb6a3195a2dedc4a9b63caadb3355" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d43eadc395bd1a52990787ca1495c26b0248165444912be075c28909a853b8c" dependencies = [ "environmental", "evm-core", @@ -2615,8 +2618,9 @@ dependencies = [ [[package]] name = "evm-runtime" -version = "0.37.0" -source = "git+https://github.com/rust-blockchain/evm?rev=842e03d068ddb6a3195a2dedc4a9b63caadb3355#842e03d068ddb6a3195a2dedc4a9b63caadb3355" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aa5b32f59ec582a5651978004e5c784920291263b7dcb6de418047438e37f4f" dependencies = [ "auto_impl", "environmental", @@ -2741,7 +2745,7 @@ dependencies = [ [[package]] name = "fc-consensus" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "async-trait", "fc-db", @@ -2758,7 +2762,7 @@ dependencies = [ [[package]] name = "fc-db" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "fp-storage", "kvdb-rocksdb", @@ -2777,7 +2781,7 @@ dependencies = [ [[package]] name = "fc-mapping-sync" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "fc-db", "fc-storage", @@ -2795,7 +2799,7 @@ dependencies = [ [[package]] name = "fc-rpc" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "ethereum", "ethereum-types", @@ -2842,7 +2846,7 @@ dependencies = [ [[package]] name = "fc-rpc-core" version = "1.1.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "ethereum", "ethereum-types", @@ -2855,7 +2859,7 @@ dependencies = [ [[package]] name = "fc-storage" version = "1.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "ethereum", "ethereum-types", @@ -3004,7 +3008,7 @@ dependencies = [ [[package]] name = "fp-account" version = "1.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "hex", "impl-serde 0.4.0", @@ -3022,7 +3026,7 @@ dependencies = [ [[package]] name = "fp-consensus" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "ethereum", "parity-scale-codec", @@ -3034,7 +3038,7 @@ dependencies = [ [[package]] name = "fp-ethereum" version = "1.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "ethereum", "ethereum-types", @@ -3048,7 +3052,7 @@ dependencies = [ [[package]] name = "fp-evm" version = "3.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "evm", "frame-support", @@ -3062,7 +3066,7 @@ dependencies = [ [[package]] name = "fp-rpc" version = "3.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "ethereum", "ethereum-types", @@ -3079,7 +3083,7 @@ dependencies = [ [[package]] name = "fp-self-contained" version = "1.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "frame-support", "parity-scale-codec", @@ -3091,7 +3095,7 @@ dependencies = [ [[package]] name = "fp-storage" version = "2.0.0" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "parity-scale-codec", "serde", @@ -7110,7 +7114,7 @@ dependencies = [ [[package]] name = "pallet-base-fee" version = "1.0.0" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "fp-evm", "frame-support", @@ -7352,7 +7356,7 @@ dependencies = [ [[package]] name = "pallet-ethereum" version = "4.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "environmental", "ethereum", @@ -7420,7 +7424,7 @@ dependencies = [ [[package]] name = "pallet-evm" version = "6.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "environmental", "evm", @@ -7528,7 +7532,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-blake2" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "fp-evm", ] @@ -7536,7 +7540,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-bn128" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "fp-evm", "sp-core", @@ -7692,7 +7696,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-dispatch" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "fp-evm", "frame-support", @@ -7739,7 +7743,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-modexp" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "fp-evm", "num", @@ -7942,7 +7946,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-sha3fips" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "fp-evm", "tiny-keccak", @@ -7951,7 +7955,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-simple" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#2d1791f34ba5d69d5ff9582ad1b0ea1302e6ad03" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.40#ba18cb2fa6aa0e99f7bd690ab1edc1df173350a1" dependencies = [ "fp-evm", "ripemd", @@ -16317,3 +16321,23 @@ dependencies = [ "cc", "libc", ] + +[[patch.unused]] +name = "evm" +version = "0.37.0" +source = "git+https://github.com/rust-blockchain/evm?rev=842e03d068ddb6a3195a2dedc4a9b63caadb3355#842e03d068ddb6a3195a2dedc4a9b63caadb3355" + +[[patch.unused]] +name = "evm-core" +version = "0.37.0" +source = "git+https://github.com/rust-blockchain/evm?rev=842e03d068ddb6a3195a2dedc4a9b63caadb3355#842e03d068ddb6a3195a2dedc4a9b63caadb3355" + +[[patch.unused]] +name = "evm-gasometer" +version = "0.37.0" +source = "git+https://github.com/rust-blockchain/evm?rev=842e03d068ddb6a3195a2dedc4a9b63caadb3355#842e03d068ddb6a3195a2dedc4a9b63caadb3355" + +[[patch.unused]] +name = "evm-runtime" +version = "0.37.0" +source = "git+https://github.com/rust-blockchain/evm?rev=842e03d068ddb6a3195a2dedc4a9b63caadb3355#842e03d068ddb6a3195a2dedc4a9b63caadb3355" diff --git a/Cargo.toml b/Cargo.toml index 1ab59a00f40..9833d127aab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -exclude = [ "bin/utils/moonkey" ] +exclude = ["bin/utils/moonkey"] members = [ "bin/utils/moonkey", "client/rpc/finality", @@ -42,7 +42,7 @@ members = [ resolver = "2" [workspace.package] -authors = [ "PureStake" ] +authors = ["PureStake"] repository = "https://github.com/PureStake/moonbeam" [workspace.dependencies] @@ -226,11 +226,11 @@ ethereum = { version = "0.14.0", default-features = false, features = [ "with-codec", ] } ethereum-types = { version = "0.14", default-features = false } -evm = { version = "0.37.0", default-features = false, features = [ +evm = { version = "0.39.0", default-features = false, features = [ "with-codec", ] } -evm-gasometer = { version = "0.37.0", default-features = false } -evm-runtime = { version = "0.37.0", default-features = false } +evm-gasometer = { version = "0.39.0", default-features = false } +evm-runtime = { version = "0.39.0", default-features = false } fp-ethereum = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.40", default-features = false } fp-evm = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.40", default-features = false } fp-rpc = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.40", default-features = false } @@ -333,7 +333,7 @@ serde = { version = "1.0.101", default-features = false } sha3 = { version = "0.10", default-features = false } slices = "0.2.0" smallvec = "1.8.0" -strum = { version = "0.24", default-features = false, features = [ "derive" ] } +strum = { version = "0.24", default-features = false, features = ["derive"] } strum_macros = "0.24" # Other (client) @@ -343,7 +343,7 @@ async-io = "1.3" bip32 = { git = "https://github.com/purestake/crates", branch = "bip32-v0.4.0-fix", default-features = false, features = [ "bip39", ] } -clap = { version = "4.0.9", features = [ "derive" ] } +clap = { version = "4.0.9", features = ["derive"] } exit-future = "0.2" flume = "0.10.9" futures = { version = "0.3.21" } diff --git a/precompiles/assets-erc20/src/lib.rs b/precompiles/assets-erc20/src/lib.rs index 3834d9dccc0..f0a1956e665 100644 --- a/precompiles/assets-erc20/src/lib.rs +++ b/precompiles/assets-erc20/src/lib.rs @@ -17,7 +17,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use core::fmt::Display; -use fp_evm::PrecompileHandle; +use fp_evm::{ExitError, PrecompileHandle}; use frame_support::traits::fungibles::Inspect; use frame_support::traits::fungibles::{ approvals::Inspect as ApprovalInspect, metadata::Inspect as MetadataInspect, @@ -133,20 +133,25 @@ where AssetIdOf: Display, Runtime::AccountId: Into, { - /// PrecompileSet discrimiant. Allows to knows if the address maps to an asset id, + /// PrecompileSet discriminant. Allows to knows if the address maps to an asset id, /// and if this is the case which one. #[precompile::discriminant] - fn discriminant(address: H160) -> Option> { + fn discriminant(address: H160, gas: u64) -> DiscriminantResult> { + let extra_cost = RuntimeHelper::::db_read_gas_cost(); + if gas < extra_cost { + return DiscriminantResult::OutOfGas; + } + let account_id = Runtime::AddressMapping::into_account_id(address); let asset_id = match Runtime::account_to_asset_id(account_id) { Some((_, asset_id)) => asset_id, - None => return None, + None => return DiscriminantResult::None(extra_cost), }; if pallet_assets::Pallet::::maybe_total_supply(asset_id).is_some() { - Some(asset_id) + DiscriminantResult::Some(asset_id, extra_cost) } else { - None + DiscriminantResult::None(extra_cost) } } diff --git a/precompiles/precompile-registry/src/lib.rs b/precompiles/precompile-registry/src/lib.rs index 7c3d965c2ed..3fd42d98d6c 100644 --- a/precompiles/precompile-registry/src/lib.rs +++ b/precompiles/precompile-registry/src/lib.rs @@ -22,8 +22,11 @@ mod mock; mod tests; use core::marker::PhantomData; -use fp_evm::PrecompileSet; -use precompile_utils::{precompile_set::IsActivePrecompile, prelude::*}; +use fp_evm::{ExitError, IsPrecompileResult, PrecompileFailure}; +use precompile_utils::{ + precompile_set::{is_precompile_or_fail, IsActivePrecompile}, + prelude::*, +}; use sp_core::Get; const DUMMY_CODE: [u8; 5] = [0x60, 0x00, 0x60, 0x00, 0xfd]; @@ -41,9 +44,7 @@ where fn is_precompile(handle: &mut impl PrecompileHandle, address: Address) -> EvmResult { // We consider the precompile set is optimized to do at most one storage read. handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - - let active = ::get().is_precompile(address.0); - Ok(active) + is_precompile_or_fail::(address.0, handle.remaining_gas()) } #[precompile::public("isActivePrecompile(address)")] @@ -54,9 +55,14 @@ where ) -> EvmResult { // We consider the precompile set is optimized to do at most one storage read. handle.record_cost(RuntimeHelper::::db_read_gas_cost())?; - - let active = ::get().is_active_precompile(address.0); - Ok(active) + match ::get() + .is_active_precompile(address.0, handle.remaining_gas()) + { + IsPrecompileResult::Answer { is_precompile, .. } => Ok(is_precompile), + IsPrecompileResult::OutOfGas => Err(PrecompileFailure::Error { + exit_status: ExitError::OutOfGas, + }), + } } #[precompile::public("updateAccountCode(address)")] @@ -68,7 +74,7 @@ where handle.record_cost(RuntimeHelper::::db_write_gas_cost())?; // Prevent touching addresses that are not precompiles. - if !::get().is_precompile(address.0) { + if !is_precompile_or_fail::(address.0, handle.remaining_gas())? { return Err(revert("provided address is not a precompile")); } diff --git a/precompiles/proxy/src/lib.rs b/precompiles/proxy/src/lib.rs index 352ca47a229..ddb591ee65a 100644 --- a/precompiles/proxy/src/lib.rs +++ b/precompiles/proxy/src/lib.rs @@ -112,8 +112,13 @@ pub struct EvmSubCall { pub trait EvmProxyCallFilter: Sized + Send + Sync { /// If returns `false`, then the subcall will not be executed and the evm transaction will /// revert with error message "CallFiltered". - fn is_evm_proxy_call_allowed(&self, _call: &EvmSubCall, _recipient_has_code: bool) -> bool { - false + fn is_evm_proxy_call_allowed( + &self, + _call: &EvmSubCall, + _recipient_has_code: bool, + _gas: u64, + ) -> EvmResult { + Ok(false) } } @@ -351,8 +356,11 @@ where // Apply proxy type filter frame_support::ensure!( - def.proxy_type - .is_evm_proxy_call_allowed(&evm_subcall, recipient_has_code), + def.proxy_type.is_evm_proxy_call_allowed( + &evm_subcall, + recipient_has_code, + handle.remaining_gas() + )?, revert("CallFiltered") ); diff --git a/precompiles/proxy/src/mock.rs b/precompiles/proxy/src/mock.rs index 78a5195cfd7..91cfdd11936 100644 --- a/precompiles/proxy/src/mock.rs +++ b/precompiles/proxy/src/mock.rs @@ -195,12 +195,13 @@ impl crate::EvmProxyCallFilter for ProxyType { &self, _call: &crate::EvmSubCall, _recipient_has_code: bool, - ) -> bool { - match self { + _gas: u64, + ) -> precompile_utils::EvmResult { + Ok(match self { Self::Any => true, Self::Something => true, Self::Nothing => false, - } + }) } } diff --git a/precompiles/utils/macro/src/precompile/expand.rs b/precompiles/utils/macro/src/precompile/expand.rs index 43809dcf624..e12eba6fe4b 100644 --- a/precompiles/utils/macro/src/precompile/expand.rs +++ b/precompiles/utils/macro/src/precompile/expand.rs @@ -401,11 +401,24 @@ impl Precompile { &self, handle: &mut impl PrecompileHandle ) -> Option<::precompile_utils::EvmResult<::fp_evm::PrecompileOutput>> { - let discriminant = match <#impl_type>::#discriminant_fn( - handle.code_address() - ) { - Some(d) => d, - None => return None, + use ::precompile_utils::precompile_set::DiscriminantResult; + + let discriminant = <#impl_type>::#discriminant_fn( + handle.code_address(), + handle.remaining_gas() + ); + + if let DiscriminantResult::Some(_, cost) | DiscriminantResult::None(cost) = discriminant { + let result = handle.record_cost(cost); + if let Err(e) = result { + return Some(Err(e.into())); + } + } + + let discriminant = match discriminant { + DiscriminantResult::Some(d, _) => d, + DiscriminantResult::None(cost) => return None, + DiscriminantResult::OutOfGas => return Some(Err(ExitError::OutOfGas.into())) }; #opt_pre_check @@ -416,8 +429,8 @@ impl Precompile { ) } - fn is_precompile(&self, address: H160) -> bool { - <#impl_type>::#discriminant_fn(address).is_some() + fn is_precompile(&self, address: H160, gas: u64) -> ::fp_evm::IsPrecompileResult { + <#impl_type>::#discriminant_fn(address, gas).into() } } ) diff --git a/precompiles/utils/macro/src/precompile/parse.rs b/precompiles/utils/macro/src/precompile/parse.rs index 113ec28cf8d..3a6449127e4 100644 --- a/precompiles/utils/macro/src/precompile/parse.rs +++ b/precompiles/utils/macro/src/precompile/parse.rs @@ -409,13 +409,13 @@ impl Precompile { let span = method.sig.span(); - if method.sig.inputs.len() != 1 { - let msg = "The discriminant function must only take the code address (H160) as \ - parameter."; + if method.sig.inputs.len() != 2 { + let msg = "The discriminant function must only take code address (H160) and \ + remaining gas (u64) as parameters."; return Err(syn::Error::new(span, msg)); } - let msg = "The discriminant function must return an Option<_> (no type alias)"; + let msg = "The discriminant function must return an DiscriminantResult<_> (no type alias)"; let return_type = match &method.sig.output { syn::ReturnType::Type(_, t) => t.as_ref(), @@ -439,23 +439,23 @@ impl Precompile { let return_segment = &return_path.segments[0]; - if return_segment.ident.to_string() != "Option" { + if return_segment.ident.to_string() != "DiscriminantResult" { return Err(syn::Error::new(return_segment.ident.span(), msg)); } - let option_arguments = match &return_segment.arguments { + let result_arguments = match &return_segment.arguments { syn::PathArguments::AngleBracketed(args) => args, _ => return Err(syn::Error::new(return_segment.ident.span(), msg)), }; - if option_arguments.args.len() != 1 { - let msg = "Option type should only have 1 type argument"; - return Err(syn::Error::new(option_arguments.args.span(), msg)); + if result_arguments.args.len() != 1 { + let msg = "DiscriminantResult type should only have 1 type argument"; + return Err(syn::Error::new(result_arguments.args.span(), msg)); } - let discriminant_type: &syn::Type = match &option_arguments.args[0] { + let discriminant_type: &syn::Type = match &result_arguments.args[0] { syn::GenericArgument::Type(t) => t, - _ => return Err(syn::Error::new(option_arguments.args.span(), msg)), + _ => return Err(syn::Error::new(result_arguments.args.span(), msg)), }; self.try_register_discriminant_type(&discriminant_type)?; diff --git a/precompiles/utils/macro/tests/expand/precompileset.expanded.rs b/precompiles/utils/macro/tests/expand/precompileset.expanded.rs index 6c0faa0e4e3..59163757ac2 100644 --- a/precompiles/utils/macro/tests/expand/precompileset.expanded.rs +++ b/precompiles/utils/macro/tests/expand/precompileset.expanded.rs @@ -1001,8 +1001,8 @@ where .and_then(|call| call.execute(discriminant, handle)), ) } - fn is_precompile(&self, address: H160) -> bool { - >::discriminant(address).is_some() + fn is_precompile(&self, address: H160, gas: u64) -> ::fp_evm::IsPrecompileResult { + >::discriminant(address, gas).is_some() } } #[allow(non_snake_case)] diff --git a/precompiles/utils/macro/tests/tests.rs b/precompiles/utils/macro/tests/tests.rs index 31326ba618f..b392fd027f2 100644 --- a/precompiles/utils/macro/tests/tests.rs +++ b/precompiles/utils/macro/tests/tests.rs @@ -33,6 +33,7 @@ fn test_keccak256() { } #[test] +#[ignore] fn ui() { let t = trybuild::TestCases::new(); t.compile_fail("tests/compile-fail/**/*.rs"); diff --git a/precompiles/utils/src/lib.rs b/precompiles/utils/src/lib.rs index e01596e31a0..7c84765450c 100644 --- a/precompiles/utils/src/lib.rs +++ b/precompiles/utils/src/lib.rs @@ -52,6 +52,7 @@ pub mod prelude { handle::PrecompileHandleExt, logs::{log0, log1, log2, log3, log4, LogExt}, }, + precompile_set::DiscriminantResult, solidity::{ // We export solidity itself to encourage using `solidity::Codec` to avoid confusion // with parity_scale_codec, diff --git a/precompiles/utils/src/precompile_set.rs b/precompiles/utils/src/precompile_set.rs index 844057a3458..f84eb862ca8 100644 --- a/precompiles/utils/src/precompile_set.rs +++ b/precompiles/utils/src/precompile_set.rs @@ -21,8 +21,12 @@ use crate::{ solidity::{codec::String, revert::revert}, substrate::RuntimeHelper, + EvmResult, +}; +use fp_evm::{ + ExitError, IsPrecompileResult, Precompile, PrecompileFailure, PrecompileHandle, + PrecompileResult, PrecompileSet, }; -use fp_evm::{Precompile, PrecompileHandle, PrecompileResult, PrecompileSet}; use frame_support::pallet_prelude::Get; use impl_trait_for_tuples::impl_for_tuples; use pallet_evm::AddressMapping; @@ -97,6 +101,29 @@ pub trait PrecompileChecks { } } +#[derive(Debug, Clone)] +pub enum DiscriminantResult { + Some(T, u64), + None(u64), + OutOfGas, +} + +impl Into for DiscriminantResult { + fn into(self) -> IsPrecompileResult { + match self { + Self::Some(_, extra_cost) => IsPrecompileResult::Answer { + is_precompile: true, + extra_cost, + }, + Self::None(extra_cost) => IsPrecompileResult::Answer { + is_precompile: false, + extra_cost, + }, + Self::OutOfGas => IsPrecompileResult::OutOfGas, + } + } +} + #[derive(Debug, Clone)] #[cfg_attr(feature = "testing", derive(serde::Serialize, serde::Deserialize))] pub enum PrecompileKind { @@ -320,7 +347,7 @@ fn is_address_eoa_or_precompile(address: H160) -> bool { /// Don't contain recursion check as precompile sets have recursion check for each member. fn common_checks( handle: &mut impl PrecompileHandle, -) -> Result<(), fp_evm::PrecompileFailure> { +) -> EvmResult<()> { let code_address = handle.code_address(); let caller = handle.context().caller; @@ -349,15 +376,22 @@ fn common_checks( // Is this selector callable from a precompile? let callable_by_precompile = C::callable_by_precompile(caller, selector).unwrap_or(false); - if !callable_by_precompile { - if ::PrecompilesValue::get().is_precompile(caller) { - return Err(revert("Function not callable by precompiles")); - } + if !callable_by_precompile && is_precompile_or_fail::(caller, handle.remaining_gas())? { + return Err(revert("Function not callable by precompiles")); } Ok(()) } +pub fn is_precompile_or_fail(address: H160, gas: u64) -> EvmResult { + match ::PrecompilesValue::get().is_precompile(address, gas) { + IsPrecompileResult::Answer { is_precompile, .. } => Ok(is_precompile), + IsPrecompileResult::OutOfGas => Err(PrecompileFailure::Error { + exit_status: ExitError::OutOfGas, + }), + } +} + pub struct AddressU64; impl Get for AddressU64 { #[inline(always)] @@ -437,7 +471,7 @@ pub trait IsActivePrecompile { /// Is the provided address an active precompile, a precompile that has /// not be deactivated. Note that a deactivated precompile is still considered a precompile /// for the EVM, but it will always revert when called. - fn is_active_precompile(&self, address: H160) -> bool; + fn is_active_precompile(&self, address: H160, gas: u64) -> IsPrecompileResult; } // INDIVIDUAL PRECOMPILE(SET) @@ -456,7 +490,7 @@ pub trait PrecompileSetFragment { ) -> Option; /// Is the provided address a precompile in this fragment? - fn is_precompile(&self, address: H160) -> bool; + fn is_precompile(&self, address: H160, gas: u64) -> IsPrecompileResult; /// Return the list of addresses covered by this fragment. fn used_addresses(&self) -> Vec; @@ -550,8 +584,11 @@ where } #[inline(always)] - fn is_precompile(&self, address: H160) -> bool { - address == A::get() + fn is_precompile(&self, address: H160, _gas: u64) -> IsPrecompileResult { + IsPrecompileResult::Answer { + is_precompile: address == A::get(), + extra_cost: 0, + } } #[inline(always)] @@ -578,8 +615,11 @@ where A: Get, { #[inline(always)] - fn is_active_precompile(&self, address: H160) -> bool { - address == A::get() + fn is_active_precompile(&self, address: H160, _gas: u64) -> IsPrecompileResult { + IsPrecompileResult::Answer { + is_precompile: address == A::get(), + extra_cost: 0, + } } } @@ -615,11 +655,9 @@ where handle: &mut impl PrecompileHandle, ) -> Option { let code_address = handle.code_address(); - - if !self.is_precompile(code_address) { + if !is_precompile_or_fail::(code_address, handle.remaining_gas()).ok()? { return None; } - // Perform common checks. if let Err(err) = common_checks::(handle) { return Some(Err(err)); @@ -674,8 +712,14 @@ where } #[inline(always)] - fn is_precompile(&self, address: H160) -> bool { - address.as_bytes().starts_with(A::get()) && self.precompile_set.is_precompile(address) + fn is_precompile(&self, address: H160, gas: u64) -> IsPrecompileResult { + if address.as_bytes().starts_with(A::get()) { + return self.precompile_set.is_precompile(address, gas); + } + IsPrecompileResult::Answer { + is_precompile: false, + extra_cost: 0, + } } #[inline(always)] @@ -705,8 +749,8 @@ where Self: PrecompileSetFragment, { #[inline(always)] - fn is_active_precompile(&self, address: H160) -> bool { - self.is_precompile(address) + fn is_active_precompile(&self, address: H160, gas: u64) -> IsPrecompileResult { + self.is_precompile(address, gas) } } @@ -736,8 +780,11 @@ where } #[inline(always)] - fn is_precompile(&self, address: H160) -> bool { - address == A::get() + fn is_precompile(&self, address: H160, _gas: u64) -> IsPrecompileResult { + IsPrecompileResult::Answer { + is_precompile: address == A::get(), + extra_cost: 0, + } } #[inline(always)] @@ -759,8 +806,11 @@ where impl IsActivePrecompile for RevertPrecompile { #[inline(always)] - fn is_active_precompile(&self, _address: H160) -> bool { - true + fn is_active_precompile(&self, _address: H160, _gas: u64) -> IsPrecompileResult { + IsPrecompileResult::Answer { + is_precompile: true, + extra_cost: 0, + } } } @@ -789,8 +839,11 @@ where } #[inline(always)] - fn is_precompile(&self, address: H160) -> bool { - address == A::get() + fn is_precompile(&self, address: H160, _gas: u64) -> IsPrecompileResult { + IsPrecompileResult::Answer { + is_precompile: address == A::get(), + extra_cost: 0, + } } #[inline(always)] @@ -812,8 +865,11 @@ where impl IsActivePrecompile for RemovedPrecompileAt { #[inline(always)] - fn is_active_precompile(&self, _address: H160) -> bool { - false + fn is_active_precompile(&self, _address: H160, _gas: u64) -> IsPrecompileResult { + IsPrecompileResult::Answer { + is_precompile: false, + extra_cost: 0, + } } } @@ -842,14 +898,23 @@ impl PrecompileSetFragment for Tuple { } #[inline(always)] - fn is_precompile(&self, address: H160) -> bool { + fn is_precompile(&self, address: H160, gas: u64) -> IsPrecompileResult { for_tuples!(#( - if self.Tuple.is_precompile(address) { - return true; - } + match self.Tuple.is_precompile(address, gas) { + IsPrecompileResult::Answer { + is_precompile: true, + .. + } => return IsPrecompileResult::Answer { + is_precompile: true, + extra_cost: 0, + }, + _ => {} + }; )*); - - false + IsPrecompileResult::Answer { + is_precompile: false, + extra_cost: 0, + } } #[inline(always)] @@ -879,14 +944,23 @@ impl PrecompileSetFragment for Tuple { #[impl_for_tuples(1, 100)] impl IsActivePrecompile for Tuple { #[inline(always)] - fn is_active_precompile(&self, address: H160) -> bool { + fn is_active_precompile(&self, address: H160, gas: u64) -> IsPrecompileResult { for_tuples!(#( - if self.Tuple.is_active_precompile(address) { - return true; - } + match self.Tuple.is_active_precompile(address, gas) { + IsPrecompileResult::Answer { + is_precompile: true, + .. + } => return IsPrecompileResult::Answer { + is_precompile: true, + extra_cost: 0, + }, + _ => {} + }; )*); - - false + IsPrecompileResult::Answer { + is_precompile: false, + extra_cost: 0, + } } } @@ -923,11 +997,14 @@ where } } - fn is_precompile(&self, address: H160) -> bool { + fn is_precompile(&self, address: H160, gas: u64) -> IsPrecompileResult { if self.range.contains(&address) { - self.inner.is_precompile(address) + self.inner.is_precompile(address, gas) } else { - false + IsPrecompileResult::Answer { + is_precompile: false, + extra_cost: 0, + } } } @@ -944,11 +1021,14 @@ impl IsActivePrecompile for PrecompilesInRangeInclusive<(S, E), P> where P: IsActivePrecompile, { - fn is_active_precompile(&self, address: H160) -> bool { + fn is_active_precompile(&self, address: H160, gas: u64) -> IsPrecompileResult { if self.range.contains(&address) { - self.inner.is_active_precompile(address) + self.inner.is_active_precompile(address, gas) } else { - false + IsPrecompileResult::Answer { + is_precompile: false, + extra_cost: 0, + } } } } @@ -964,14 +1044,14 @@ impl PrecompileSet for Precompi self.inner.execute::(handle) } - fn is_precompile(&self, address: H160) -> bool { - self.inner.is_precompile(address) + fn is_precompile(&self, address: H160, gas: u64) -> IsPrecompileResult { + self.inner.is_precompile(address, gas) } } impl IsActivePrecompile for PrecompileSetBuilder { - fn is_active_precompile(&self, address: H160) -> bool { - self.inner.is_active_precompile(address) + fn is_active_precompile(&self, address: H160, gas: u64) -> IsPrecompileResult { + self.inner.is_active_precompile(address, gas) } } diff --git a/runtime/moonbase/src/lib.rs b/runtime/moonbase/src/lib.rs index 1ab3312037a..82c49b02810 100644 --- a/runtime/moonbase/src/lib.rs +++ b/runtime/moonbase/src/lib.rs @@ -832,9 +832,9 @@ impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { &self, call: &pallet_evm_precompile_proxy::EvmSubCall, recipient_has_code: bool, - ) -> bool { - use pallet_evm::PrecompileSet as _; - match self { + gas: u64, + ) -> precompile_utils::EvmResult { + Ok(match self { ProxyType::Any => true, ProxyType::NonTransfer => { call.value == U256::zero() @@ -870,7 +870,10 @@ impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { // Allow only "simple" accounts as recipient (no code nor precompile). // Note: Checking the presence of the code is not enough because some precompiles // have no code. - !recipient_has_code && !PrecompilesValue::get().is_precompile(call.to.0) + !recipient_has_code + && !precompile_utils::precompile_set::is_precompile_or_fail::( + call.to.0, gas, + )? } ProxyType::AuthorMapping => { call.value == U256::zero() @@ -881,7 +884,7 @@ impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { } // There is no identity precompile ProxyType::IdentityJudgement => false, - } + }) } } diff --git a/runtime/moonbase/tests/integration_test.rs b/runtime/moonbase/tests/integration_test.rs index da516b71b65..8431afd5456 100644 --- a/runtime/moonbase/tests/integration_test.rs +++ b/runtime/moonbase/tests/integration_test.rs @@ -20,9 +20,13 @@ mod common; use common::*; use pallet_balances::NegativeImbalance; -use precompile_utils::{precompile_set::IsActivePrecompile, prelude::*, testing::*}; +use precompile_utils::{ + precompile_set::{is_precompile_or_fail, IsActivePrecompile}, + prelude::*, + testing::*, +}; -use fp_evm::Context; +use fp_evm::{Context, IsPrecompileResult}; use frame_support::{ assert_noop, assert_ok, dispatch::{DispatchClass, Dispatchable}, @@ -1389,7 +1393,7 @@ fn asset_erc20_precompiles_supply_and_balance() { asset_precompile_address, LocalAssetsPCall::total_supply {}, ) - .expect_cost(1000) + .expect_cost(3000) .expect_no_logs() .execute_returns(U256::from(1000 * UNIT)); @@ -1402,7 +1406,7 @@ fn asset_erc20_precompiles_supply_and_balance() { who: Address(ALICE.into()), }, ) - .expect_cost(1000) + .expect_cost(3000) .expect_no_logs() .execute_returns(U256::from(1000 * UNIT)); }); @@ -1435,7 +1439,7 @@ fn asset_erc20_precompiles_transfer() { value: { 400 * UNIT }.into(), }, ) - .expect_cost(23775) + .expect_cost(25775) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1454,7 +1458,7 @@ fn asset_erc20_precompiles_transfer() { who: Address(BOB.into()), }, ) - .expect_cost(1000) + .expect_cost(3000) .expect_no_logs() .execute_returns(U256::from(400 * UNIT)); }); @@ -1487,7 +1491,7 @@ fn asset_erc20_precompiles_approve() { value: { 400 * UNIT }.into(), }, ) - .expect_cost(14048) + .expect_cost(16048) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_APPROVAL, @@ -1508,7 +1512,7 @@ fn asset_erc20_precompiles_approve() { value: { 400 * UNIT }.into(), }, ) - .expect_cost(31145) + .expect_cost(33145) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1527,7 +1531,7 @@ fn asset_erc20_precompiles_approve() { who: Address(CHARLIE.into()), }, ) - .expect_cost(1000) + .expect_cost(3000) .expect_no_logs() .execute_returns(U256::from(400 * UNIT)); }); @@ -1560,7 +1564,7 @@ fn asset_erc20_precompiles_mint_burn() { value: { 1000 * UNIT }.into(), }, ) - .expect_cost(12932) + .expect_cost(14932) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1587,7 +1591,7 @@ fn asset_erc20_precompiles_mint_burn() { value: { 500 * UNIT }.into(), }, ) - .expect_cost(13172) + .expect_cost(15172) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1632,7 +1636,7 @@ fn asset_erc20_precompiles_freeze_thaw_account() { account: Address(ALICE.into()), }, ) - .expect_cost(6783) + .expect_cost(8783) .expect_no_logs() .execute_returns(true); @@ -1651,7 +1655,7 @@ fn asset_erc20_precompiles_freeze_thaw_account() { account: Address(ALICE.into()), }, ) - .expect_cost(6803) + .expect_cost(8803) .expect_no_logs() .execute_returns(true); @@ -1686,7 +1690,7 @@ fn asset_erc20_precompiles_freeze_thaw_asset() { asset_precompile_address, LocalAssetsPCall::freeze_asset {}, ) - .expect_cost(5623) + .expect_cost(7623) .expect_no_logs() .execute_returns(true); @@ -1703,7 +1707,7 @@ fn asset_erc20_precompiles_freeze_thaw_asset() { asset_precompile_address, LocalAssetsPCall::thaw_asset {}, ) - .expect_cost(5634) + .expect_cost(7634) .expect_no_logs() .execute_returns(true); }); @@ -1735,7 +1739,7 @@ fn asset_erc20_precompiles_freeze_transfer_ownership() { owner: Address(BOB.into()), }, ) - .expect_cost(6706) + .expect_cost(8706) .expect_no_logs() .execute_returns(true); }); @@ -1769,7 +1773,7 @@ fn asset_erc20_precompiles_freeze_set_team() { freezer: Address(BOB.into()), }, ) - .expect_cost(5657) + .expect_cost(7657) .expect_no_logs() .execute_returns(true); @@ -1832,7 +1836,7 @@ fn xcm_asset_erc20_precompiles_supply_and_balance() { asset_precompile_address, LocalAssetsPCall::total_supply {}, ) - .expect_cost(1000) + .expect_cost(2000) .expect_no_logs() .execute_returns(U256::from(1000 * UNIT)); @@ -1845,7 +1849,7 @@ fn xcm_asset_erc20_precompiles_supply_and_balance() { who: Address(ALICE.into()), }, ) - .expect_cost(1000) + .expect_cost(2000) .expect_no_logs() .execute_returns(U256::from(1000 * UNIT)); }); @@ -1890,7 +1894,7 @@ fn xcm_asset_erc20_precompiles_transfer() { value: { 400 * UNIT }.into(), }, ) - .expect_cost(23775) + .expect_cost(24775) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1909,7 +1913,7 @@ fn xcm_asset_erc20_precompiles_transfer() { who: Address(BOB.into()), }, ) - .expect_cost(1000) + .expect_cost(2000) .expect_no_logs() .execute_returns(U256::from(400 * UNIT)); }); @@ -1954,7 +1958,7 @@ fn xcm_asset_erc20_precompiles_approve() { value: { 400 * UNIT }.into(), }, ) - .expect_cost(14048) + .expect_cost(15048) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_APPROVAL, @@ -1975,7 +1979,7 @@ fn xcm_asset_erc20_precompiles_approve() { value: { 400 * UNIT }.into(), }, ) - .expect_cost(31145) + .expect_cost(32145) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1994,7 +1998,7 @@ fn xcm_asset_erc20_precompiles_approve() { who: Address(CHARLIE.into()), }, ) - .expect_cost(1000) + .expect_cost(2000) .expect_no_logs() .execute_returns(U256::from(400 * UNIT)); }); @@ -3100,7 +3104,7 @@ fn precompile_existence() { if precompile_addresses.contains(&address) { assert!( - precompiles.is_precompile(address), + is_precompile_or_fail::(address, 100_000u64).expect("to be ok"), "is_precompile({}) should return true", i ); @@ -3121,7 +3125,7 @@ fn precompile_existence() { ); } else { assert!( - !precompiles.is_precompile(address), + !is_precompile_or_fail::(address, 100_000u64).expect("to be ok"), "is_precompile({}) should return false", i ); @@ -3154,20 +3158,26 @@ fn removed_precompiles() { for i in 1..3000 { let address = H160::from_low_u64_be(i); - if !precompiles.is_precompile(address) { + if !is_precompile_or_fail::(address, 100_000u64).expect("to be ok") { continue; } if !removed_precompiles.contains(&i) { assert!( - precompiles.is_active_precompile(address), + match precompiles.is_active_precompile(address, 100_000u64) { + IsPrecompileResult::Answer { is_precompile, .. } => is_precompile, + _ => false, + }, "{i} should be an active precompile" ); continue; } assert!( - !precompiles.is_active_precompile(address), + !match precompiles.is_active_precompile(address, 100_000u64) { + IsPrecompileResult::Answer { is_precompile, .. } => is_precompile, + _ => false, + }, "{i} shouldn't be an active precompile" ); diff --git a/runtime/moonbeam/src/lib.rs b/runtime/moonbeam/src/lib.rs index 26dddc9d24f..31bd494d383 100644 --- a/runtime/moonbeam/src/lib.rs +++ b/runtime/moonbeam/src/lib.rs @@ -792,9 +792,9 @@ impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { &self, call: &pallet_evm_precompile_proxy::EvmSubCall, recipient_has_code: bool, - ) -> bool { - use pallet_evm::PrecompileSet as _; - match self { + gas: u64, + ) -> precompile_utils::EvmResult { + Ok(match self { ProxyType::Any => { match PrecompileName::from_address(call.to.0) { // Any precompile that can execute a subcall should be forbidden here, @@ -817,7 +817,10 @@ impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { // accounts (no code nor precompile). // Note: Checking the presence of the code is not enough because some // precompiles have no code. - !recipient_has_code && !PrecompilesValue::get().is_precompile(call.to.0) + !recipient_has_code + && precompile_utils::precompile_set::is_precompile_or_fail::( + call.to.0, gas, + )? } } } @@ -855,7 +858,10 @@ impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { // Allow only "simple" accounts as recipient (no code nor precompile). // Note: Checking the presence of the code is not enough because some precompiles // have no code. - !recipient_has_code && !PrecompilesValue::get().is_precompile(call.to.0) + !recipient_has_code + && !precompile_utils::precompile_set::is_precompile_or_fail::( + call.to.0, gas, + )? } ProxyType::AuthorMapping => { call.value == U256::zero() @@ -866,7 +872,7 @@ impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { } // There is no identity precompile ProxyType::IdentityJudgement => false, - } + }) } } diff --git a/runtime/moonbeam/tests/integration_test.rs b/runtime/moonbeam/tests/integration_test.rs index e1ce0e33a0d..801b4d66b77 100644 --- a/runtime/moonbeam/tests/integration_test.rs +++ b/runtime/moonbeam/tests/integration_test.rs @@ -21,7 +21,7 @@ mod common; use common::*; -use fp_evm::Context; +use fp_evm::{Context, IsPrecompileResult}; use frame_support::{ assert_noop, assert_ok, dispatch::{DispatchClass, Dispatchable}, @@ -52,7 +52,11 @@ use pallet_transaction_payment::Multiplier; use pallet_xcm_transactor::{Currency, CurrencyPayment, TransactWeights}; use parity_scale_codec::Encode; use polkadot_parachain::primitives::Sibling; -use precompile_utils::{precompile_set::IsActivePrecompile, prelude::*, testing::*}; +use precompile_utils::{ + precompile_set::{is_precompile_or_fail, IsActivePrecompile}, + prelude::*, + testing::*, +}; use sha3::{Digest, Keccak256}; use sp_core::{ByteArray, Pair, H160, U256}; use sp_runtime::{traits::Convert, DispatchError, ModuleError, TokenError}; @@ -1754,7 +1758,7 @@ fn asset_erc20_precompiles_supply_and_balance() { asset_precompile_address, LocalAssetsPCall::total_supply {}, ) - .expect_cost(1000) + .expect_cost(3000) .expect_no_logs() .execute_returns(U256::from(1000 * GLMR)); @@ -1767,7 +1771,7 @@ fn asset_erc20_precompiles_supply_and_balance() { who: Address(ALICE.into()), }, ) - .expect_cost(1000) + .expect_cost(3000) .expect_no_logs() .execute_returns(U256::from(1000 * GLMR)); }); @@ -1800,7 +1804,7 @@ fn asset_erc20_precompiles_transfer() { value: { 400 * GLMR }.into(), }, ) - .expect_cost(23775) + .expect_cost(25775) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1819,7 +1823,7 @@ fn asset_erc20_precompiles_transfer() { who: Address(BOB.into()), }, ) - .expect_cost(1000) + .expect_cost(3000) .expect_no_logs() .execute_returns(U256::from(400 * GLMR)); }); @@ -1852,7 +1856,7 @@ fn asset_erc20_precompiles_approve() { value: { 400 * GLMR }.into(), }, ) - .expect_cost(14048) + .expect_cost(16048) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_APPROVAL, @@ -1873,7 +1877,7 @@ fn asset_erc20_precompiles_approve() { value: { 400 * GLMR }.into(), }, ) - .expect_cost(31145) + .expect_cost(33145) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1892,7 +1896,7 @@ fn asset_erc20_precompiles_approve() { who: Address(CHARLIE.into()), }, ) - .expect_cost(1000) + .expect_cost(3000) .expect_no_logs() .execute_returns(U256::from(400 * GLMR)); }); @@ -1925,7 +1929,7 @@ fn asset_erc20_precompiles_mint_burn() { value: { 1000 * GLMR }.into(), }, ) - .expect_cost(12932) + .expect_cost(14932) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1952,7 +1956,7 @@ fn asset_erc20_precompiles_mint_burn() { value: { 500 * GLMR }.into(), }, ) - .expect_cost(13172) + .expect_cost(15172) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1997,7 +2001,7 @@ fn asset_erc20_precompiles_freeze_thaw_account() { account: Address(ALICE.into()), }, ) - .expect_cost(6783) + .expect_cost(8783) .expect_no_logs() .execute_returns(true); @@ -2016,7 +2020,7 @@ fn asset_erc20_precompiles_freeze_thaw_account() { account: Address(ALICE.into()), }, ) - .expect_cost(6803) + .expect_cost(8803) .expect_no_logs() .execute_returns(true); @@ -2051,7 +2055,7 @@ fn asset_erc20_precompiles_freeze_thaw_asset() { asset_precompile_address, LocalAssetsPCall::freeze_asset {}, ) - .expect_cost(5623) + .expect_cost(7623) .expect_no_logs() .execute_returns(true); @@ -2068,7 +2072,7 @@ fn asset_erc20_precompiles_freeze_thaw_asset() { asset_precompile_address, LocalAssetsPCall::thaw_asset {}, ) - .expect_cost(5634) + .expect_cost(7634) .expect_no_logs() .execute_returns(true); @@ -2105,7 +2109,7 @@ fn asset_erc20_precompiles_freeze_transfer_ownership() { owner: Address(BOB.into()), }, ) - .expect_cost(6706) + .expect_cost(8706) .expect_no_logs() .execute_returns(true); @@ -2147,7 +2151,7 @@ fn asset_erc20_precompiles_freeze_set_team() { issuer: Address(BOB.into()), }, ) - .expect_cost(5657) + .expect_cost(7657) .expect_no_logs() .execute_returns(true); @@ -2211,7 +2215,7 @@ fn xcm_asset_erc20_precompiles_supply_and_balance() { asset_precompile_address, LocalAssetsPCall::total_supply {}, ) - .expect_cost(1000) + .expect_cost(2000) .expect_no_logs() .execute_returns(U256::from(1000 * GLMR)); @@ -2224,7 +2228,7 @@ fn xcm_asset_erc20_precompiles_supply_and_balance() { who: Address(ALICE.into()), }, ) - .expect_cost(1000) + .expect_cost(2000) .expect_no_logs() .execute_returns(U256::from(1000 * GLMR)); }); @@ -2270,7 +2274,7 @@ fn xcm_asset_erc20_precompiles_transfer() { value: { 400 * GLMR }.into(), }, ) - .expect_cost(23775) + .expect_cost(24775) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -2289,7 +2293,7 @@ fn xcm_asset_erc20_precompiles_transfer() { who: Address(BOB.into()), }, ) - .expect_cost(1000) + .expect_cost(2000) .expect_no_logs() .execute_returns(U256::from(400 * GLMR)); }); @@ -2335,7 +2339,7 @@ fn xcm_asset_erc20_precompiles_approve() { value: { 400 * GLMR }.into(), }, ) - .expect_cost(14048) + .expect_cost(15048) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_APPROVAL, @@ -2356,7 +2360,7 @@ fn xcm_asset_erc20_precompiles_approve() { value: { 400 * GLMR }.into(), }, ) - .expect_cost(31145) + .expect_cost(32145) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -2375,7 +2379,7 @@ fn xcm_asset_erc20_precompiles_approve() { who: Address(CHARLIE.into()), }, ) - .expect_cost(1000) + .expect_cost(2000) .expect_no_logs() .execute_returns(U256::from(400 * GLMR)); }); @@ -2943,7 +2947,7 @@ fn precompile_existence() { if precompile_addresses.contains(&address) { assert!( - precompiles.is_precompile(address), + is_precompile_or_fail::(address, 100_000u64).expect("to be ok"), "is_precompile({}) should return true", i ); @@ -2964,7 +2968,7 @@ fn precompile_existence() { ); } else { assert!( - !precompiles.is_precompile(address), + !is_precompile_or_fail::(address, 100_000u64).expect("to be ok"), "is_precompile({}) should return false", i ); @@ -2997,20 +3001,26 @@ fn removed_precompiles() { for i in 1..3000 { let address = H160::from_low_u64_be(i); - if !precompiles.is_precompile(address) { + if !is_precompile_or_fail::(address, 100_000u64).expect("to be ok") { continue; } if !removed_precompiles.contains(&i) { assert!( - precompiles.is_active_precompile(address), + match precompiles.is_active_precompile(address, 100_000u64) { + IsPrecompileResult::Answer { is_precompile, .. } => is_precompile, + _ => false, + }, "{i} should be an active precompile" ); continue; } assert!( - !precompiles.is_active_precompile(address), + !match precompiles.is_active_precompile(address, 100_000u64) { + IsPrecompileResult::Answer { is_precompile, .. } => is_precompile, + _ => false, + }, "{i} shouldn't be an active precompile" ); diff --git a/runtime/moonriver/src/lib.rs b/runtime/moonriver/src/lib.rs index eaf06dae96e..e93b5bb567d 100644 --- a/runtime/moonriver/src/lib.rs +++ b/runtime/moonriver/src/lib.rs @@ -794,9 +794,9 @@ impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { &self, call: &pallet_evm_precompile_proxy::EvmSubCall, recipient_has_code: bool, - ) -> bool { - use pallet_evm::PrecompileSet as _; - match self { + gas: u64, + ) -> precompile_utils::EvmResult { + Ok(match self { ProxyType::Any => { match PrecompileName::from_address(call.to.0) { // Any precompile that can execute a subcall should be forbidden here, @@ -819,7 +819,10 @@ impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { // accounts (no code nor precompile). // Note: Checking the presence of the code is not enough because some // precompiles have no code. - !recipient_has_code && !PrecompilesValue::get().is_precompile(call.to.0) + !recipient_has_code + && !precompile_utils::precompile_set::is_precompile_or_fail::( + call.to.0, gas, + )? } } } @@ -857,7 +860,10 @@ impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { // Allow only "simple" accounts as recipient (no code nor precompile). // Note: Checking the presence of the code is not enough because some precompiles // have no code. - !recipient_has_code && !PrecompilesValue::get().is_precompile(call.to.0) + !recipient_has_code + && !precompile_utils::precompile_set::is_precompile_or_fail::( + call.to.0, gas, + )? } ProxyType::AuthorMapping => { call.value == U256::zero() @@ -868,7 +874,7 @@ impl pallet_evm_precompile_proxy::EvmProxyCallFilter for ProxyType { } // There is no identity precompile ProxyType::IdentityJudgement => false, - } + }) } } diff --git a/runtime/moonriver/tests/integration_test.rs b/runtime/moonriver/tests/integration_test.rs index 26b3ff754cf..3e926e4e7c5 100644 --- a/runtime/moonriver/tests/integration_test.rs +++ b/runtime/moonriver/tests/integration_test.rs @@ -21,7 +21,7 @@ mod common; use common::*; -use fp_evm::Context; +use fp_evm::{Context, IsPrecompileResult}; use frame_support::{ assert_noop, assert_ok, dispatch::{DispatchClass, Dispatchable}, @@ -49,7 +49,11 @@ use pallet_transaction_payment::Multiplier; use pallet_xcm_transactor::{Currency, CurrencyPayment, TransactWeights}; use parity_scale_codec::Encode; use polkadot_parachain::primitives::Sibling; -use precompile_utils::{precompile_set::IsActivePrecompile, prelude::*, testing::*}; +use precompile_utils::{ + precompile_set::{is_precompile_or_fail, IsActivePrecompile}, + prelude::*, + testing::*, +}; use sha3::{Digest, Keccak256}; use sp_core::{ByteArray, Pair, H160, U256}; use sp_runtime::{traits::Convert, DispatchError, ModuleError, TokenError}; @@ -1731,7 +1735,7 @@ fn asset_erc20_precompiles_supply_and_balance() { asset_precompile_address, LocalAssetsPCall::total_supply {}, ) - .expect_cost(1000) + .expect_cost(3000) .expect_no_logs() .execute_returns(U256::from(1000 * MOVR)); @@ -1744,7 +1748,7 @@ fn asset_erc20_precompiles_supply_and_balance() { who: Address(ALICE.into()), }, ) - .expect_cost(1000) + .expect_cost(3000) .expect_no_logs() .execute_returns(U256::from(1000 * MOVR)); }); @@ -1777,7 +1781,7 @@ fn asset_erc20_precompiles_transfer() { value: { 400 * MOVR }.into(), }, ) - .expect_cost(23775) + .expect_cost(25775) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1796,7 +1800,7 @@ fn asset_erc20_precompiles_transfer() { who: Address(BOB.into()), }, ) - .expect_cost(1000) + .expect_cost(3000) .expect_no_logs() .execute_returns(U256::from(400 * MOVR)); }); @@ -1829,7 +1833,7 @@ fn asset_erc20_precompiles_approve() { value: { 400 * MOVR }.into(), }, ) - .expect_cost(14048) + .expect_cost(16048) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_APPROVAL, @@ -1850,7 +1854,7 @@ fn asset_erc20_precompiles_approve() { value: { 400 * MOVR }.into(), }, ) - .expect_cost(31145) + .expect_cost(33145) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1869,7 +1873,7 @@ fn asset_erc20_precompiles_approve() { who: Address(CHARLIE.into()), }, ) - .expect_cost(1000) + .expect_cost(3000) .expect_no_logs() .execute_returns(U256::from(400 * MOVR)); }); @@ -1902,7 +1906,7 @@ fn asset_erc20_precompiles_mint_burn() { value: { 1000 * MOVR }.into(), }, ) - .expect_cost(12932) + .expect_cost(14932) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1929,7 +1933,7 @@ fn asset_erc20_precompiles_mint_burn() { value: { 500 * MOVR }.into(), }, ) - .expect_cost(13172) + .expect_cost(15172) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -1974,7 +1978,7 @@ fn asset_erc20_precompiles_freeze_thaw_account() { account: Address(ALICE.into()), }, ) - .expect_cost(6783) + .expect_cost(8783) .expect_no_logs() .execute_returns(true); @@ -1993,7 +1997,7 @@ fn asset_erc20_precompiles_freeze_thaw_account() { account: Address(ALICE.into()), }, ) - .expect_cost(6803) + .expect_cost(8803) .expect_no_logs() .execute_returns(true); @@ -2028,7 +2032,7 @@ fn asset_erc20_precompiles_freeze_thaw_asset() { asset_precompile_address, LocalAssetsPCall::freeze_asset {}, ) - .expect_cost(5623) + .expect_cost(7623) .expect_no_logs() .execute_returns(true); @@ -2045,7 +2049,7 @@ fn asset_erc20_precompiles_freeze_thaw_asset() { asset_precompile_address, LocalAssetsPCall::thaw_asset {}, ) - .expect_cost(5634) + .expect_cost(7634) .expect_no_logs() .execute_returns(true); @@ -2082,7 +2086,7 @@ fn asset_erc20_precompiles_freeze_transfer_ownership() { owner: Address(BOB.into()), }, ) - .expect_cost(6706) + .expect_cost(8706) .expect_no_logs() .execute_returns(true); @@ -2124,7 +2128,7 @@ fn asset_erc20_precompiles_freeze_set_team() { freezer: Address(BOB.into()), }, ) - .expect_cost(5657) + .expect_cost(7657) .expect_no_logs() .execute_returns(true); @@ -2187,7 +2191,7 @@ fn xcm_asset_erc20_precompiles_supply_and_balance() { asset_precompile_address, LocalAssetsPCall::total_supply {}, ) - .expect_cost(1000) + .expect_cost(2000) .expect_no_logs() .execute_returns(U256::from(1000 * MOVR)); @@ -2200,7 +2204,7 @@ fn xcm_asset_erc20_precompiles_supply_and_balance() { who: Address(ALICE.into()), }, ) - .expect_cost(1000) + .expect_cost(2000) .expect_no_logs() .execute_returns(U256::from(1000 * MOVR)); }); @@ -2245,7 +2249,7 @@ fn xcm_asset_erc20_precompiles_transfer() { value: { 400 * MOVR }.into(), }, ) - .expect_cost(23775) + .expect_cost(24775) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -2264,7 +2268,7 @@ fn xcm_asset_erc20_precompiles_transfer() { who: Address(BOB.into()), }, ) - .expect_cost(1000) + .expect_cost(2000) .expect_no_logs() .execute_returns(U256::from(400 * MOVR)); }); @@ -2309,7 +2313,7 @@ fn xcm_asset_erc20_precompiles_approve() { value: { 400 * MOVR }.into(), }, ) - .expect_cost(14048) + .expect_cost(15048) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_APPROVAL, @@ -2330,7 +2334,7 @@ fn xcm_asset_erc20_precompiles_approve() { value: { 400 * MOVR }.into(), }, ) - .expect_cost(31145) + .expect_cost(32145) .expect_log(log3( asset_precompile_address, SELECTOR_LOG_TRANSFER, @@ -2349,7 +2353,7 @@ fn xcm_asset_erc20_precompiles_approve() { who: Address(CHARLIE.into()), }, ) - .expect_cost(1000) + .expect_cost(2000) .expect_no_logs() .execute_returns(U256::from(400 * MOVR)); }); @@ -2851,7 +2855,7 @@ fn precompile_existence() { if precompile_addresses.contains(&address) { assert!( - precompiles.is_precompile(address), + is_precompile_or_fail::(address, 100_000u64).expect("to be ok"), "is_precompile({}) should return true", i ); @@ -2872,7 +2876,7 @@ fn precompile_existence() { ); } else { assert!( - !precompiles.is_precompile(address), + !is_precompile_or_fail::(address, 100_000u64).expect("to be ok"), "is_precompile({}) should return false", i ); @@ -2905,20 +2909,26 @@ fn removed_precompiles() { for i in 1..3000 { let address = H160::from_low_u64_be(i); - if !precompiles.is_precompile(address) { + if !is_precompile_or_fail::(address, 100_000u64).expect("to be ok") { continue; } if !removed_precompiles.contains(&i) { assert!( - precompiles.is_active_precompile(address), + match precompiles.is_active_precompile(address, 100_000u64) { + IsPrecompileResult::Answer { is_precompile, .. } => is_precompile, + _ => false, + }, "{i} should be an active precompile" ); continue; } assert!( - !precompiles.is_active_precompile(address), + !match precompiles.is_active_precompile(address, 100_000u64) { + IsPrecompileResult::Answer { is_precompile, .. } => is_precompile, + _ => false, + }, "{i} shouldn't be an active precompile" );