diff --git a/Cargo.lock b/Cargo.lock index 4d043aea157c3..4f55e94355f1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,18 +148,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "auto_impl" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cbf586c80ada5e5ccdecae80d3ef0854f224e2dd74435f8d87e6831b8d0a38" -dependencies = [ - "proc-macro-error 1.0.4", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "auto_impl" version = "0.5.0" @@ -963,16 +951,18 @@ checksum = "bfb684ac8fa8f6c5759f788862bb22ec6fe3cb392f6bfd08e3c64b603661e3f8" dependencies = [ "crunchy", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "tiny-keccak", ] [[package]] name = "ethereum" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ccff962ede8fe7c3ec53d46b8316f3c53377a701a30c0325918b38ce04a497" +checksum = "81fb916554a4dba293ea69c69ad5653e21d770a9d0c2496b5fa0a1f5a3946d87" dependencies = [ "bytes", "ethereum-types", @@ -981,6 +971,7 @@ dependencies = [ "parity-scale-codec", "rlp", "rlp-derive", + "scale-info", "serde", "sha3 0.9.1", "triehash", @@ -994,16 +985,18 @@ checksum = "05136f7057fe789f06e6d41d07b34e6f70d8c86e5693b60f97aaa6553553bdaf" dependencies = [ "ethbloom", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", "primitive-types", + "scale-info", "uint", ] [[package]] name = "ethers" version = "0.5.4" -source = "git+https://github.com/gakonst/ethers-rs#b3fed152a44ecdcc92cf457a5d873d04eddbec33" +source = "git+https://github.com/gakonst/ethers-rs#8eac1997f4cc09ff4343f94e492aa51f23e51e1f" dependencies = [ "ethers-contract", "ethers-core", @@ -1016,7 +1009,7 @@ dependencies = [ [[package]] name = "ethers-contract" version = "0.5.3" -source = "git+https://github.com/gakonst/ethers-rs#b3fed152a44ecdcc92cf457a5d873d04eddbec33" +source = "git+https://github.com/gakonst/ethers-rs#8eac1997f4cc09ff4343f94e492aa51f23e51e1f" dependencies = [ "ethers-contract-abigen", "ethers-contract-derive", @@ -1034,7 +1027,7 @@ dependencies = [ [[package]] name = "ethers-contract-abigen" version = "0.5.3" -source = "git+https://github.com/gakonst/ethers-rs#b3fed152a44ecdcc92cf457a5d873d04eddbec33" +source = "git+https://github.com/gakonst/ethers-rs#8eac1997f4cc09ff4343f94e492aa51f23e51e1f" dependencies = [ "Inflector", "anyhow", @@ -1055,7 +1048,7 @@ dependencies = [ [[package]] name = "ethers-contract-derive" version = "0.5.3" -source = "git+https://github.com/gakonst/ethers-rs#b3fed152a44ecdcc92cf457a5d873d04eddbec33" +source = "git+https://github.com/gakonst/ethers-rs#8eac1997f4cc09ff4343f94e492aa51f23e51e1f" dependencies = [ "ethers-contract-abigen", "ethers-core", @@ -1069,7 +1062,7 @@ dependencies = [ [[package]] name = "ethers-core" version = "0.5.5" -source = "git+https://github.com/gakonst/ethers-rs#b3fed152a44ecdcc92cf457a5d873d04eddbec33" +source = "git+https://github.com/gakonst/ethers-rs#8eac1997f4cc09ff4343f94e492aa51f23e51e1f" dependencies = [ "arrayvec", "bytes", @@ -1097,7 +1090,7 @@ dependencies = [ [[package]] name = "ethers-etherscan" version = "0.1.1" -source = "git+https://github.com/gakonst/ethers-rs#b3fed152a44ecdcc92cf457a5d873d04eddbec33" +source = "git+https://github.com/gakonst/ethers-rs#8eac1997f4cc09ff4343f94e492aa51f23e51e1f" dependencies = [ "ethers-core", "reqwest", @@ -1109,7 +1102,7 @@ dependencies = [ [[package]] name = "ethers-middleware" version = "0.5.3" -source = "git+https://github.com/gakonst/ethers-rs#b3fed152a44ecdcc92cf457a5d873d04eddbec33" +source = "git+https://github.com/gakonst/ethers-rs#8eac1997f4cc09ff4343f94e492aa51f23e51e1f" dependencies = [ "async-trait", "ethers-contract", @@ -1132,10 +1125,10 @@ dependencies = [ [[package]] name = "ethers-providers" version = "0.5.4" -source = "git+https://github.com/gakonst/ethers-rs#b3fed152a44ecdcc92cf457a5d873d04eddbec33" +source = "git+https://github.com/gakonst/ethers-rs#8eac1997f4cc09ff4343f94e492aa51f23e51e1f" dependencies = [ "async-trait", - "auto_impl 0.5.0", + "auto_impl", "ethers-core", "futures-channel", "futures-core", @@ -1161,7 +1154,7 @@ dependencies = [ [[package]] name = "ethers-signers" version = "0.5.3" -source = "git+https://github.com/gakonst/ethers-rs#b3fed152a44ecdcc92cf457a5d873d04eddbec33" +source = "git+https://github.com/gakonst/ethers-rs#8eac1997f4cc09ff4343f94e492aa51f23e51e1f" dependencies = [ "async-trait", "coins-bip32", @@ -1181,7 +1174,7 @@ dependencies = [ [[package]] name = "ethers-solc" version = "0.1.0" -source = "git+https://github.com/gakonst/ethers-rs#b3fed152a44ecdcc92cf457a5d873d04eddbec33" +source = "git+https://github.com/gakonst/ethers-rs#8eac1997f4cc09ff4343f94e492aa51f23e51e1f" dependencies = [ "colored", "ethers-core", @@ -1203,11 +1196,10 @@ dependencies = [ [[package]] name = "evm" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddef7d840592ae19c1392fbec54c9b1425c2534a93e9e512afde571e6ca628c9" +version = "0.33.0" +source = "git+https://github.com/gakonst/evm?branch=feat/auto-impl#1b5e1c67e0b518a265e44f079f3537f5534a68d2" dependencies = [ - "auto_impl 0.4.1", + "auto_impl", "environmental", "ethereum", "evm-core", @@ -1217,6 +1209,7 @@ dependencies = [ "parity-scale-codec", "primitive-types", "rlp", + "scale-info", "serde", "sha3 0.8.2", ] @@ -1244,21 +1237,20 @@ dependencies = [ [[package]] name = "evm-core" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb30090cebf1d85781189859bd6de7a759f6c4cffd7cd2a7b05e7eccb769b60" +version = "0.33.0" +source = "git+https://github.com/gakonst/evm?branch=feat/auto-impl#1b5e1c67e0b518a265e44f079f3537f5534a68d2" dependencies = [ "funty", "parity-scale-codec", "primitive-types", + "scale-info", "serde", ] [[package]] name = "evm-gasometer" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c38e0842db6f66df571675f02018264abf92dbea4d1fb5a92b3a029088663fd" +version = "0.33.0" +source = "git+https://github.com/gakonst/evm?branch=feat/auto-impl#1b5e1c67e0b518a265e44f079f3537f5534a68d2" dependencies = [ "environmental", "evm-core", @@ -1268,11 +1260,10 @@ dependencies = [ [[package]] name = "evm-runtime" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86158aeca104c31ef15b67afc80e8e4f32705bd9f98ac55c6911ab6185a234a4" +version = "0.33.0" +source = "git+https://github.com/gakonst/evm?branch=feat/auto-impl#1b5e1c67e0b518a265e44f079f3537f5534a68d2" dependencies = [ - "auto_impl 0.4.1", + "auto_impl", "environmental", "evm-core", "primitive-types", @@ -2482,6 +2473,7 @@ dependencies = [ "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "uint", ] @@ -3082,6 +3074,31 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-info" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55b744399c25532d63a0d2789b109df8d46fc93752d46b0782991a931a782f" +dependencies = [ + "bitvec 0.20.4", + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" +dependencies = [ + "proc-macro-crate 1.1.0", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "schannel" version = "0.1.19" diff --git a/Cargo.toml b/Cargo.toml index 4afc16258f8cb..87aad15385368 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,6 @@ opt-level = "z" lto = true codegen-units = 1 panic = "abort" + +[patch."https://github.com/rust-blockchain/evm"] +evm = { git = "https://github.com/gakonst/evm", branch = "feat/auto-impl" } diff --git a/dapp/Cargo.toml b/dapp/Cargo.toml index 1bc9abfa158d6..cb8e087a771f5 100644 --- a/dapp/Cargo.toml +++ b/dapp/Cargo.toml @@ -29,5 +29,5 @@ proptest = "1.0.0" [dev-dependencies] evm-adapters = { path = "./../evm-adapters", features = ["sputnik", "sputnik-helpers", "evmodin", "evmodin-helpers"] } evmodin = { git = "https://github.com/vorot93/evmodin", features = ["util"] } -evm = { version = "0.31" } +evm = { git = "https://github.com/rust-blockchain/evm" } ethers = { git = "https://github.com/gakonst/ethers-rs", features = ["solc-full", "solc-tests"] } diff --git a/dapp/src/multi_runner.rs b/dapp/src/multi_runner.rs index 634dfc648b6fd..a13af97cf82c0 100644 --- a/dapp/src/multi_runner.rs +++ b/dapp/src/multi_runner.rs @@ -221,7 +221,7 @@ mod tests { use evm::Config; use evm_adapters::sputnik::{ helpers::{new_backend, new_vicinity}, - Executor, + Executor, PRECOMPILES_MAP, }; #[test] @@ -231,7 +231,9 @@ mod tests { let env = new_vicinity(); let backend = new_backend(&env, Default::default()); // important to instantiate the VM with cheatcodes - let evm = Executor::new_with_cheatcodes(backend, gas_limit, &config, false); + let precompiles = PRECOMPILES_MAP.clone(); + let evm = + Executor::new_with_cheatcodes(backend, gas_limit, &config, &precompiles, false); let mut runner = runner(evm); let results = runner.test(Regex::new(".*").unwrap()).unwrap(); @@ -256,7 +258,8 @@ mod tests { let gas_limit = 12_500_000; let env = new_vicinity(); let backend = new_backend(&env, Default::default()); - let evm = Executor::new(gas_limit, &config, &backend); + let precompiles = PRECOMPILES_MAP.clone(); + let evm = Executor::new(gas_limit, &config, &backend, &precompiles); test_multi_runner(evm); } } diff --git a/dapp/src/runner.rs b/dapp/src/runner.rs index 6047f3b8022ef..635cfe4522a07 100644 --- a/dapp/src/runner.rs +++ b/dapp/src/runner.rs @@ -239,7 +239,7 @@ mod tests { use crate::test_helpers::COMPILED; use ethers::solc::artifacts::CompactContractRef; use evm::Config; - use std::marker::PhantomData; + use evm_adapters::sputnik::PRECOMPILES_MAP; mod sputnik { use std::str::FromStr; @@ -259,7 +259,8 @@ mod tests { let compiled = COMPILED.find("GreeterTest").expect("could not find contract"); let vicinity = new_vicinity(); let backend = new_backend(&vicinity, Default::default()); - let evm = Executor::new(12_000_000, &cfg, &backend); + let precompiles = PRECOMPILES_MAP.clone(); + let evm = Executor::new(12_000_000, &cfg, &backend, &precompiles); super::test_runner(evm, compiled); } @@ -270,7 +271,8 @@ mod tests { let vicinity = new_vicinity(); let backend = new_backend(&vicinity, Default::default()); - let mut evm = Executor::new(12_000_000, &cfg, &backend); + let precompiles = PRECOMPILES_MAP.clone(); + let mut evm = Executor::new(12_000_000, &cfg, &backend, &precompiles); let (addr, _, _, _) = evm.deploy(Address::zero(), compiled.bin.unwrap().clone(), 0.into()).unwrap(); @@ -296,7 +298,8 @@ mod tests { let vicinity = new_vicinity(); let backend = new_backend(&vicinity, Default::default()); - let mut evm = Executor::new(u64::MAX, &cfg, &backend); + let precompiles = PRECOMPILES_MAP.clone(); + let mut evm = Executor::new(u64::MAX, &cfg, &backend, &precompiles); let (addr, _, _, _) = evm.deploy(Address::zero(), compiled.bin.unwrap().clone(), 0.into()).unwrap(); @@ -319,7 +322,8 @@ mod tests { let vicinity = new_vicinity(); let backend = new_backend(&vicinity, Default::default()); - let mut evm = Executor::new(12_000_000, &cfg, &backend); + let precompiles = PRECOMPILES_MAP.clone(); + let mut evm = Executor::new(12_000_000, &cfg, &backend, &precompiles); let (addr, _, _, _) = evm.deploy(Address::zero(), compiled.bin.unwrap().clone(), 0.into()).unwrap(); diff --git a/dapptools/Cargo.toml b/dapptools/Cargo.toml index 8170a03c1b893..26fe655b352a0 100644 --- a/dapptools/Cargo.toml +++ b/dapptools/Cargo.toml @@ -27,7 +27,7 @@ tracing = "0.1.26" ## EVM Implementations # evm = { version = "0.30.1" } -sputnik = { package = "evm", version = "0.31", optional = true } +sputnik = { package = "evm", git = "https://github.com/rust-blockchain/evm", optional = true } evmodin = { git = "https://github.com/vorot93/evmodin", optional = true } proptest = "1.0.0" git2 = "0.13.22" diff --git a/dapptools/src/dapp.rs b/dapptools/src/dapp.rs index d6bba833e61e1..510195c376213 100644 --- a/dapptools/src/dapp.rs +++ b/dapptools/src/dapp.rs @@ -3,7 +3,7 @@ use ethers::{ solc::{remappings::Remapping, ArtifactOutput, Project}, }; use evm_adapters::{ - sputnik::{vicinity, ForkMemoryBackend}, + sputnik::{vicinity, ForkMemoryBackend, PRECOMPILES_MAP}, FAUCET_ACCOUNT, }; use regex::Regex; @@ -98,7 +98,14 @@ fn main() -> eyre::Result<()> { }; let backend = Arc::new(backend); - let evm = Executor::new_with_cheatcodes(backend, env.gas_limit, &cfg, ffi); + let precompiles = PRECOMPILES_MAP.clone(); + let evm = Executor::new_with_cheatcodes( + backend, + env.gas_limit, + &cfg, + &precompiles, + ffi, + ); test(builder, project, evm, pattern, json, verbosity)?; } diff --git a/dapptools/src/dapp_opts.rs b/dapptools/src/dapp_opts.rs index cfc695b4c5a9c..994b822800e25 100644 --- a/dapptools/src/dapp_opts.rs +++ b/dapptools/src/dapp_opts.rs @@ -238,6 +238,7 @@ pub struct BuildOpts { #[structopt(help = "the remappings", long, short)] pub remappings: Vec, + #[structopt(env = "DAPP_REMAPPINGS")] pub remappings_env: Option, @@ -247,7 +248,7 @@ pub struct BuildOpts { #[structopt(help = "path to where the contract artifacts are stored", long = "out", short)] pub out_path: Option, - #[structopt(help = "choose the evm version", long, default_value = "berlin")] + #[structopt(help = "choose the evm version", long, default_value = "london")] pub evm_version: EvmVersion, } #[derive(Clone, Debug)] @@ -294,7 +295,7 @@ impl EvmVersion { Frontier => Config::frontier(), Istanbul => Config::istanbul(), Berlin => Config::berlin(), - other => panic!("The {:?} hard fork is unsupported on Sputnik", other), + London => Config::london(), } } @@ -338,6 +339,9 @@ pub struct Env { #[structopt(help = "the tx.gasprice value during EVM execution", long, default_value = "0")] pub gas_price: u64, + #[structopt(help = "the base fee in a block", long, default_value = "0")] + pub block_base_fee_per_gas: u64, + #[structopt( help = "the tx.origin value during EVM execution", long, @@ -395,6 +399,7 @@ impl Env { block_number: self.block_number.into(), block_timestamp: self.block_timestamp.into(), block_difficulty: self.block_difficulty.into(), + block_base_fee_per_gas: self.block_base_fee_per_gas.into(), block_gas_limit: self.block_gas_limit.unwrap_or(self.gas_limit).into(), block_hashes: Vec::new(), } diff --git a/evm-adapters/Cargo.toml b/evm-adapters/Cargo.toml index a7535d2385f85..af8da3dd53186 100644 --- a/evm-adapters/Cargo.toml +++ b/evm-adapters/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" [dependencies] dapp-utils = { path = "./../utils" } -sputnik = { package = "evm", version = "0.31", optional = true, features = ["tracing"] } +sputnik = { package = "evm", git = "https://github.com/rust-blockchain/evm", optional = true, features = ["tracing"] } evmodin = { git = "https://github.com/vorot93/evmodin", optional = true } diff --git a/evm-adapters/src/sputnik/cheatcodes/backend.rs b/evm-adapters/src/sputnik/cheatcodes/backend.rs index b5c77cd4a12da..bac1ed164ce86 100644 --- a/evm-adapters/src/sputnik/cheatcodes/backend.rs +++ b/evm-adapters/src/sputnik/cheatcodes/backend.rs @@ -43,6 +43,10 @@ impl Backend for CheatcodeBackend { self.cheats.block_timestamp.unwrap_or_else(|| self.backend.block_timestamp()) } + fn block_base_fee_per_gas(&self) -> U256 { + self.cheats.block_base_fee_per_gas.unwrap_or_else(|| self.backend.block_base_fee_per_gas()) + } + fn block_difficulty(&self) -> U256 { self.backend.block_difficulty() } diff --git a/evm-adapters/src/sputnik/cheatcodes/cheatcode_handler.rs b/evm-adapters/src/sputnik/cheatcodes/cheatcode_handler.rs index ab206e0b0e52e..9436a1292f9db 100644 --- a/evm-adapters/src/sputnik/cheatcodes/cheatcode_handler.rs +++ b/evm-adapters/src/sputnik/cheatcodes/cheatcode_handler.rs @@ -3,14 +3,15 @@ use super::{ HevmConsoleEvents, }; use crate::{ - sputnik::{Executor, SputnikExecutor, PRECOMPILES_MAP}, + sputnik::{Executor, SputnikExecutor}, Evm, }; use sputnik::{ backend::Backend, - executor::{ - Log, PrecompileOutput, StackExecutor, StackExitKind, StackState, StackSubstateMetadata, + executor::stack::{ + Log, PrecompileFailure, PrecompileOutput, PrecompileSet, StackExecutor, StackExitKind, + StackState, StackSubstateMetadata, }, gasometer, Capture, Config, Context, CreateScheme, ExitError, ExitReason, ExitRevert, ExitSucceed, Handler, Runtime, Transfer, @@ -45,7 +46,9 @@ pub struct CheatcodeHandler { // Forwards everything internally except for the transact_call which is overwritten. // TODO: Maybe we can pull this functionality up to the `Evm` trait to avoid having so many traits? -impl<'a, B: Backend> SputnikExecutor> for CheatcodeStackExecutor<'a, B> { +impl<'a, 'b, B: Backend, P: PrecompileSet> SputnikExecutor> + for CheatcodeStackExecutor<'a, 'b, B, P> +{ fn config(&self) -> &Config { self.handler.config() } @@ -78,16 +81,10 @@ impl<'a, B: Backend> SputnikExecutor> for CheatcodeSt Err(e) => return (e.into(), Vec::new()), } + // Initialize initial addresses for EIP-2929 // Initialize initial addresses for EIP-2929 if self.config().increase_state_access_gas { - let addresses = self - .handler - .precompile() - .clone() - .into_keys() - .into_iter() - .chain(core::iter::once(caller)) - .chain(core::iter::once(address)); + let addresses = core::iter::once(caller).chain(core::iter::once(address)); self.state_mut().metadata_mut().access_addresses(addresses); self.handler.initialize_with_access_list(access_list); @@ -174,14 +171,17 @@ impl<'a, B: Backend> SputnikExecutor> for CheatcodeSt pub type CheatcodeStackState<'a, B> = MemoryStackStateOwned<'a, CheatcodeBackend>; -pub type CheatcodeStackExecutor<'a, B> = - CheatcodeHandler>>; +pub type CheatcodeStackExecutor<'a, 'b, B, P> = + CheatcodeHandler, P>>; -impl<'a, B: Backend> Executor, CheatcodeStackExecutor<'a, B>> { +impl<'a, 'b, B: Backend, P: PrecompileSet> + Executor, CheatcodeStackExecutor<'a, 'b, B, P>> +{ pub fn new_with_cheatcodes( backend: B, gas_limit: u64, config: &'a Config, + precompiles: &'b P, enable_ffi: bool, ) -> Self { // make this a cheatcode-enabled backend @@ -193,7 +193,7 @@ impl<'a, B: Backend> Executor, CheatcodeStackExecutor let state = MemoryStackStateOwned::new(metadata, backend); // create the executor and wrap it with the cheatcode handler - let executor = StackExecutor::new_with_precompile(state, config, PRECOMPILES_MAP.clone()); + let executor = StackExecutor::new_with_precompiles(state, config, precompiles); let executor = CheatcodeHandler { handler: executor, enable_ffi }; let mut evm = Executor::from_executor(executor, gas_limit); @@ -213,7 +213,7 @@ fn evm_error(retdata: &str) -> Capture<(ExitReason, Vec), Infallible> { )) } -impl<'a, B: Backend> CheatcodeStackExecutor<'a, B> { +impl<'a, 'b, B: Backend, P: PrecompileSet> CheatcodeStackExecutor<'a, 'b, B, P> { /// Decodes the provided calldata as a fn apply_cheatcode(&mut self, input: Vec) -> Capture<(ExitReason, Vec), Infallible> { let mut res = vec![]; @@ -401,8 +401,14 @@ impl<'a, B: Backend> CheatcodeStackExecutor<'a, B> { } } - if let Some(precompile) = self.handler.precompile().get(&code_address) { - return match (*precompile)(&input, Some(gas_limit), &context, is_static) { + if let Some(result) = self.handler.precompiles().execute( + code_address, + &input, + Some(gas_limit), + &context, + is_static, + ) { + return match result { Ok(PrecompileOutput { exit_status, output, cost, logs }) => { for Log { address, topics, data } in logs { match self.log(address, topics, data) { @@ -416,8 +422,15 @@ impl<'a, B: Backend> CheatcodeStackExecutor<'a, B> { Capture::Exit((ExitReason::Succeed(exit_status), output)) } Err(e) => { + let e = match e { + PrecompileFailure::Error { exit_status } => ExitReason::Error(exit_status), + PrecompileFailure::Revert { exit_status, .. } => { + ExitReason::Revert(exit_status) + } + PrecompileFailure::Fatal { exit_status } => ExitReason::Fatal(exit_status), + }; let _ = self.handler.exit_substate(StackExitKind::Failed); - Capture::Exit((ExitReason::Error(e), Vec::new())) + Capture::Exit((e, Vec::new())) } } } @@ -454,7 +467,7 @@ impl<'a, B: Backend> CheatcodeStackExecutor<'a, B> { // Delegates everything internally, except the `call_inner` call, which is hooked // so that we can modify -impl<'a, B: Backend> Handler for CheatcodeStackExecutor<'a, B> { +impl<'a, 'b, B: Backend, P: PrecompileSet> Handler for CheatcodeStackExecutor<'a, 'b, B, P> { type CreateInterrupt = Infallible; type CreateFeedback = Infallible; type CallInterrupt = Infallible; @@ -543,6 +556,10 @@ impl<'a, B: Backend> Handler for CheatcodeStackExecutor<'a, B> { self.handler.block_gas_limit() } + fn block_base_fee_per_gas(&self) -> U256 { + self.handler.block_base_fee_per_gas() + } + fn chain_id(&self) -> U256 { self.handler.chain_id() } @@ -600,7 +617,7 @@ mod tests { fuzz::FuzzedExecutor, sputnik::{ helpers::{new_backend, new_vicinity}, - Executor, + Executor, PRECOMPILES_MAP, }, test_helpers::COMPILED, Evm, @@ -614,7 +631,9 @@ mod tests { let vicinity = new_vicinity(); let backend = new_backend(&vicinity, Default::default()); let gas_limit = 10_000_000; - let mut evm = Executor::new_with_cheatcodes(backend, gas_limit, &config, true); + let precompiles = PRECOMPILES_MAP.clone(); + let mut evm = + Executor::new_with_cheatcodes(backend, gas_limit, &config, &precompiles, true); let compiled = COMPILED.find("DebugLogs").expect("could not find contract"); let (addr, _, _, _) = @@ -653,7 +672,9 @@ mod tests { let vicinity = new_vicinity(); let backend = new_backend(&vicinity, Default::default()); let gas_limit = 10_000_000; - let mut evm = Executor::new_with_cheatcodes(backend, gas_limit, &config, true); + let precompiles = PRECOMPILES_MAP.clone(); + let mut evm = + Executor::new_with_cheatcodes(backend, gas_limit, &config, &precompiles, true); let compiled = COMPILED.find("CheatCodes").expect("could not find contract"); let (addr, _, _, _) = @@ -697,7 +718,9 @@ mod tests { let vicinity = new_vicinity(); let backend = new_backend(&vicinity, Default::default()); let gas_limit = 10_000_000; - let mut evm = Executor::new_with_cheatcodes(backend, gas_limit, &config, false); + let precompiles = PRECOMPILES_MAP.clone(); + let mut evm = + Executor::new_with_cheatcodes(backend, gas_limit, &config, &precompiles, false); let compiled = COMPILED.find("CheatCodes").expect("could not find contract"); let (addr, _, _, _) = diff --git a/evm-adapters/src/sputnik/cheatcodes/memory_stackstate_owned.rs b/evm-adapters/src/sputnik/cheatcodes/memory_stackstate_owned.rs index 17b2f6fdd6a89..93a4779f011ed 100644 --- a/evm-adapters/src/sputnik/cheatcodes/memory_stackstate_owned.rs +++ b/evm-adapters/src/sputnik/cheatcodes/memory_stackstate_owned.rs @@ -1,6 +1,6 @@ use sputnik::{ backend::{Backend, Basic}, - executor::{MemoryStackSubstate, StackState, StackSubstateMetadata}, + executor::stack::{MemoryStackSubstate, StackState, StackSubstateMetadata}, ExitError, Transfer, }; @@ -48,6 +48,9 @@ impl<'config, B: Backend> Backend for MemoryStackStateOwned<'config, B> { fn block_gas_limit(&self) -> U256 { self.backend.block_gas_limit() } + fn block_base_fee_per_gas(&self) -> U256 { + self.backend.block_base_fee_per_gas() + } fn chain_id(&self) -> U256 { self.backend.chain_id() } diff --git a/evm-adapters/src/sputnik/cheatcodes/mod.rs b/evm-adapters/src/sputnik/cheatcodes/mod.rs index 39722d6a20b9a..c47c7e5f4f791 100644 --- a/evm-adapters/src/sputnik/cheatcodes/mod.rs +++ b/evm-adapters/src/sputnik/cheatcodes/mod.rs @@ -16,6 +16,7 @@ use sputnik::backend::{Backend, MemoryAccount, MemoryBackend}; pub struct Cheatcodes { pub block_number: Option, pub block_timestamp: Option, + pub block_base_fee_per_gas: Option, pub accounts: HashMap, } diff --git a/evm-adapters/src/sputnik/evm.rs b/evm-adapters/src/sputnik/evm.rs index e66fe1f62b143..bab40907bdacb 100644 --- a/evm-adapters/src/sputnik/evm.rs +++ b/evm-adapters/src/sputnik/evm.rs @@ -4,7 +4,9 @@ use ethers::types::{Address, Bytes, U256}; use sputnik::{ backend::{Backend, MemoryAccount}, - executor::{MemoryStackState, StackExecutor, StackState, StackSubstateMetadata}, + executor::stack::{ + MemoryStackState, PrecompileSet, StackExecutor, StackState, StackSubstateMetadata, + }, Config, CreateScheme, ExitReason, ExitRevert, Transfer, }; use std::{collections::BTreeMap, marker::PhantomData}; @@ -30,18 +32,18 @@ impl Executor { } // Concrete implementation over the in-memory backend without cheatcodes -impl<'a, B: Backend> - Executor, StackExecutor<'a, MemoryStackState<'a, 'a, B>>> +impl<'a, 'b, B: Backend, P: PrecompileSet> + Executor, StackExecutor<'a, 'b, MemoryStackState<'a, 'a, B>, P>> { /// Given a gas limit, vm version, initial chain configuration and initial state // TOOD: See if we can make lifetimes better here - pub fn new(gas_limit: u64, config: &'a Config, backend: &'a B) -> Self { + pub fn new(gas_limit: u64, config: &'a Config, backend: &'a B, precompiles: &'b P) -> Self { // setup gasometer let metadata = StackSubstateMetadata::new(gas_limit, config); // setup state let state = MemoryStackState::new(metadata, backend); // setup executor - let executor = StackExecutor::new_with_precompile(state, config, Default::default()); + let executor = StackExecutor::new_with_precompiles(state, config, precompiles); Self { executor, gas_limit, marker: PhantomData } } @@ -177,6 +179,7 @@ pub mod helpers { block_timestamp: Default::default(), block_difficulty: Default::default(), block_gas_limit: Default::default(), + block_base_fee_per_gas: Default::default(), chain_id: U256::one(), } } @@ -190,6 +193,7 @@ mod tests { }; use crate::test_helpers::{can_call_vm_directly, solidity_unit_test, COMPILED}; + use crate::sputnik::PRECOMPILES_MAP; use ethers::utils::id; use sputnik::{ExitReason, ExitRevert, ExitSucceed}; @@ -200,7 +204,8 @@ mod tests { let vicinity = new_vicinity(); let backend = new_backend(&vicinity, Default::default()); - let evm = Executor::new(12_000_000, &cfg, &backend); + let precompiles = PRECOMPILES_MAP.clone(); + let evm = Executor::new(12_000_000, &cfg, &backend, &precompiles); can_call_vm_directly(evm, compiled); } @@ -212,7 +217,8 @@ mod tests { let vicinity = new_vicinity(); let backend = new_backend(&vicinity, Default::default()); - let evm = Executor::new(12_000_000, &cfg, &backend); + let precompiles = PRECOMPILES_MAP.clone(); + let evm = Executor::new(12_000_000, &cfg, &backend, &precompiles); solidity_unit_test(evm, compiled); } @@ -224,7 +230,8 @@ mod tests { let vicinity = new_vicinity(); let backend = new_backend(&vicinity, Default::default()); - let mut evm = Executor::new(12_000_000, &cfg, &backend); + let precompiles = PRECOMPILES_MAP.clone(); + let mut evm = Executor::new(12_000_000, &cfg, &backend, &precompiles); let (addr, _, _, _) = evm.deploy(Address::zero(), compiled.bin.unwrap().clone(), 0.into()).unwrap(); @@ -249,7 +256,8 @@ mod tests { let vicinity = new_vicinity(); let backend = new_backend(&vicinity, Default::default()); - let mut evm = Executor::new(12_000_000, &cfg, &backend); + let precompiles = PRECOMPILES_MAP.clone(); + let mut evm = Executor::new(12_000_000, &cfg, &backend, &precompiles); let (addr, _, _, _) = evm.deploy(Address::zero(), compiled.bin.clone().unwrap().clone(), 0.into()).unwrap(); @@ -277,7 +285,8 @@ mod tests { let vicinity = new_vicinity(); let backend = new_backend(&vicinity, Default::default()); - let mut evm = Executor::new(13_000_000, &cfg, &backend); + let precompiles = PRECOMPILES_MAP.clone(); + let mut evm = Executor::new(13_000_000, &cfg, &backend, &precompiles); let from = Address::random(); let (addr, _, _, _) = evm.deploy(from, compiled.bin.unwrap().clone(), 0.into()).unwrap(); diff --git a/evm-adapters/src/sputnik/forked_backend/cache.rs b/evm-adapters/src/sputnik/forked_backend/cache.rs index fbda5e3059b93..cca3a9eca9888 100644 --- a/evm-adapters/src/sputnik/forked_backend/cache.rs +++ b/evm-adapters/src/sputnik/forked_backend/cache.rs @@ -451,6 +451,9 @@ impl Backend for SharedBackend { fn block_gas_limit(&self) -> U256 { self.inner.vicinity.block_gas_limit } + fn block_base_fee_per_gas(&self) -> U256 { + self.inner.vicinity.block_base_fee_per_gas + } fn chain_id(&self) -> U256 { self.inner.vicinity.chain_id diff --git a/evm-adapters/src/sputnik/forked_backend/rpc.rs b/evm-adapters/src/sputnik/forked_backend/rpc.rs index b0ba224df8c7a..00fbcc4409637 100644 --- a/evm-adapters/src/sputnik/forked_backend/rpc.rs +++ b/evm-adapters/src/sputnik/forked_backend/rpc.rs @@ -108,6 +108,10 @@ where self.pin_block_meta.gas_limit } + fn block_base_fee_per_gas(&self) -> U256 { + self.pin_block_meta.base_fee_per_gas.unwrap_or_default() + } + fn chain_id(&self) -> U256 { self.chain_id } @@ -202,7 +206,7 @@ mod tests { use tokio::runtime::Runtime; use crate::{ - sputnik::{helpers::new_backend, vicinity, Executor}, + sputnik::{helpers::new_backend, vicinity, Executor, PRECOMPILES_MAP}, test_helpers::COMPILED, Evm, }; @@ -224,7 +228,8 @@ mod tests { let backend = new_backend(&vicinity, Default::default()); let backend = ForkMemoryBackend::new(provider, backend, blk, Default::default()); - let mut evm = Executor::new(12_000_000, &cfg, &backend); + let precompiles = PRECOMPILES_MAP.clone(); + let mut evm = Executor::new(12_000_000, &cfg, &backend, &precompiles); let (addr, _, _, _) = evm.deploy(Address::zero(), compiled.bin.unwrap().clone(), 0.into()).unwrap(); diff --git a/evm-adapters/src/sputnik/mod.rs b/evm-adapters/src/sputnik/mod.rs index 1534e605aefbe..ee5a2cee47dee 100644 --- a/evm-adapters/src/sputnik/mod.rs +++ b/evm-adapters/src/sputnik/mod.rs @@ -14,11 +14,12 @@ use ethers::{ use sputnik::{ backend::MemoryVicinity, - executor::{PrecompileOutput, StackExecutor, StackState}, + executor::stack::{PrecompileFailure, PrecompileOutput, StackExecutor, StackState}, Config, CreateScheme, ExitError, ExitReason, ExitSucceed, }; pub use sputnik as sputnik_evm; +use sputnik_evm::executor::stack::PrecompileSet; pub async fn vicinity( provider: &M, @@ -45,6 +46,7 @@ pub async fn vicinity( block_difficulty: block.difficulty, block_gas_limit: block.gas_limit, block_timestamp: block.timestamp, + block_base_fee_per_gas: block.base_fee_per_gas.unwrap_or_default(), gas_price, }) } @@ -87,7 +89,9 @@ pub trait SputnikExecutor { } // The implementation for the base Stack Executor just forwards to the internal methods. -impl<'a, S: StackState<'a>> SputnikExecutor for StackExecutor<'a, S> { +impl<'a, 'b, S: StackState<'a>, P: PrecompileSet> SputnikExecutor + for StackExecutor<'a, 'b, S, P> +{ fn config(&self) -> &Config { self.config() } @@ -142,7 +146,7 @@ impl<'a, S: StackState<'a>> SputnikExecutor for StackExecutor<'a, S> { use std::borrow::Cow; type PrecompileFn = - fn(&[u8], Option, &sputnik::Context, bool) -> Result; + fn(&[u8], Option, &sputnik::Context, bool) -> Result; pub static PRECOMPILES: Lazy = Lazy::new(|| { // We use the const to immediately choose the latest revision of available @@ -155,7 +159,12 @@ pub static PRECOMPILES: Lazy = Lazy::new(|| { // variables macro_rules! precompile_entry { ($map:expr, $index:expr) => { - let x: fn(&[u8], Option, &Context, bool) -> Result = + let x: fn( + &[u8], + Option, + &Context, + bool, + ) -> Result = |input: &[u8], gas_limit: Option, _context: &Context, _is_static: bool| { let precompile = PRECOMPILES.get(&H160::from_low_u64_be($index)).unwrap(); crate::sputnik::exec(&precompile, input, gas_limit.unwrap()) @@ -185,7 +194,7 @@ pub fn exec( builtin: &revm_precompiles::Precompile, input: &[u8], gas_limit: u64, -) -> Result { +) -> Result { let res = match builtin { revm_precompiles::Precompile::Standard(func) => func(input, gas_limit), revm_precompiles::Precompile::Custom(func) => func(input, gas_limit), @@ -208,10 +217,8 @@ pub fn exec( logs, }) } - Err(err) => Err(match err { - revm_precompiles::ExitError::Exit => ExitError::Other(Cow::Borrowed("exit")), - revm_precompiles::ExitError::OutOfGas => ExitError::OutOfGas, - revm_precompiles::ExitError::Other(cow) => ExitError::Other(cow), - }), + Err(_) => { + Err(PrecompileFailure::Error { exit_status: ExitError::Other(Cow::Borrowed("error")) }) + } } } diff --git a/evm-adapters/src/sputnik/state.rs b/evm-adapters/src/sputnik/state.rs index b31d47cbf9676..ede9b9ce0e792 100644 --- a/evm-adapters/src/sputnik/state.rs +++ b/evm-adapters/src/sputnik/state.rs @@ -2,7 +2,7 @@ use ethers::abi::ethereum_types::{H160, H256, U256}; use parking_lot::RwLock; use sputnik::{ backend::{Apply, Backend, Basic, Log}, - executor::{MemoryStackSubstate, StackState, StackSubstateMetadata}, + executor::stack::{MemoryStackSubstate, StackState, StackSubstateMetadata}, ExitError, Transfer, }; use std::{fmt::Debug, ops::Deref, sync::Arc}; @@ -95,6 +95,9 @@ where fn block_gas_limit(&self) -> U256 { self.shared_state.read().block_gas_limit() } + fn block_base_fee_per_gas(&self) -> U256 { + self.shared_state.read().block_base_fee_per_gas() + } fn chain_id(&self) -> U256 { self.shared_state.read().chain_id() } @@ -229,7 +232,7 @@ mod tests { use once_cell::sync::Lazy; use sputnik::{ backend::{MemoryBackend, MemoryVicinity}, - executor::MemoryStackState, + executor::stack::MemoryStackState, Config, }; use std::convert::TryFrom;