Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ members = [
"cli/test-utils",
"config",
"fmt",
"ui"
"ui",
"evm"
]

# Binary size optimizations
Expand Down
2 changes: 1 addition & 1 deletion cli/src/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use ethers::{
types::{Address, Bytes, U256},
};
use forge::{
debugger::DebugArena,
debug::DebugArena,
decode::decode_console_logs,
executor::{
opts::EvmOpts, CallResult, DatabaseRef, DeployResult, EvmError, Executor, ExecutorBuilder,
Expand Down
39 changes: 39 additions & 0 deletions evm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[package]
name = "foundry-evm"
version = "0.1.0"
edition = "2021"

# TODO: We can probably reduce dependencies here or in the forge crate
[dependencies]
foundry-utils = { path = "./../utils" }

# Encoding/decoding
serde_json = "1.0.67"
serde = "1.0.130"
hex = "0.4.3"
ethers = { git = "https://github.com/gakonst/ethers-rs", default-features = false, features = ["solc-full"] }

# Error handling
eyre = "0.6.5"
thiserror = "1.0.29"

# Logging
tracing = "0.1.26"
tracing-subscriber = "0.2.20"

# Threading/futures
tokio = { version = "1.10.1" }
parking_lot = "0.12.0"
futures = "0.3.21"
once_cell = "1.9.0"

# EVM
bytes = "1.1.0"
hashbrown = "0.12"
revm = { package = "revm", git = "https://github.com/bluealloy/revm", default-features = false, features = ["std", "k256"] }

# Fuzzer
proptest = "1.0.0"

# Display
ansi_term = "0.12.1"
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{abi::HEVMCalls, executor::fuzz::ASSUME_MAGIC_RETURN_CODE};
use crate::{abi::HEVMCalls, fuzz::ASSUME_MAGIC_RETURN_CODE};
use bytes::Bytes;
use revm::{Database, EVMData};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
debugger::{DebugArena, DebugNode, DebugStep, Instruction},
debug::{DebugArena, DebugNode, DebugStep, Instruction},
executor::{
inspector::utils::{gas_used, get_create_address},
CHEATCODE_ADDRESS,
Expand Down
File renamed without changes.
5 changes: 1 addition & 4 deletions forge/src/executor/mod.rs → evm/src/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,14 @@ pub mod fork;
pub mod builder;
pub use builder::{ExecutorBuilder, Fork};

/// Fuzzing wrapper for executors
pub mod fuzz;

/// Executor EVM spec identifiers
pub use revm::SpecId;

/// Executor database trait
pub use revm::db::DatabaseRef;

use self::inspector::InspectorStackConfig;
use crate::{debugger::DebugArena, trace::CallTraceArena, CALLER};
use crate::{debug::DebugArena, trace::CallTraceArena, CALLER};
use bytes::Bytes;
use ethers::{
abi::{Abi, Detokenize, RawLog, Tokenize},
Expand Down
File renamed without changes.
27 changes: 0 additions & 27 deletions forge/src/executor/fuzz/mod.rs → evm/src/fuzz/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,30 +251,3 @@ pub struct FuzzCase {
/// The initial gas stipend for the transaction
pub stipend: u64,
}

#[cfg(test)]
mod tests {
use super::FuzzTestResult;
use crate::{
executor::DeployResult,
test_helpers::{fuzz_executor, test_executor, COMPILED},
CALLER,
};

#[test]
fn prints_fuzzed_revert_reasons() {
let mut executor = test_executor();

let compiled = COMPILED.find("FuzzTests").expect("could not find contract");
let DeployResult { address, .. } =
executor.deploy(*CALLER, compiled.bytecode().unwrap().0.clone(), 0.into()).unwrap();

let executor = fuzz_executor(&executor);

let func = compiled.abi.unwrap().function("testFuzzedRevert").unwrap();
let FuzzTestResult { reason, success, .. } =
executor.fuzz(func, address, false, compiled.abi);
assert!(!success, "test did not revert");
assert_eq!(reason, Some("fuzztest-revert".to_string()));
}
}
22 changes: 22 additions & 0 deletions evm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/// Decoding helpers
pub mod decode;

/// Call trace arena, decoding and formatting
pub mod trace;

/// Debugger data structures
pub mod debug;

/// Forge test execution backends
pub mod executor;
pub use executor::abi;

/// Fuzzing wrapper for executors
pub mod fuzz;

// Re-exports
pub use ethers::types::Address;
pub use hashbrown::HashMap;

use once_cell::sync::Lazy;
pub static CALLER: Lazy<Address> = Lazy::new(Address::random);
File renamed without changes.
File renamed without changes.
File renamed without changes.
9 changes: 1 addition & 8 deletions forge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ license = "MIT OR Apache-2.0"

[dependencies]
foundry-utils = { path = "./../utils" }
foundry-evm = { path = "./../evm" }

ethers = { git = "https://github.com/gakonst/ethers-rs", default-features = false, features = ["solc-full"] }
eyre = "0.6.5"
Expand All @@ -22,15 +23,7 @@ tracing-subscriber = "0.2.20"
proptest = "1.0.0"
rayon = "1.5"
rlp = "0.5.1"

bytes = "1.1.0"
thiserror = "1.0.29"
revm = { package = "revm", git = "https://github.com/bluealloy/revm", default-features = false, features = ["std", "k256"] }
hashbrown = "0.12"
once_cell = "1.9.0"
parking_lot = "0.12.0"
futures = "0.3.21"
ansi_term = "0.12.1"
comfy-table = "5.0.0"

[dev-dependencies]
Expand Down
39 changes: 12 additions & 27 deletions forge/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
pub mod decode;

/// Call trace arena, decoding and formatting
pub mod trace;

/// Debugger arena
pub mod debugger;

/// Gas reports
pub mod gas_report;

Expand All @@ -17,39 +9,32 @@ pub use runner::{ContractRunner, TestKind, TestKindGas, TestResult};
mod multi_runner;
pub use multi_runner::{MultiContractRunner, MultiContractRunnerBuilder};

/// Forge test execution backends
pub mod executor;
pub use executor::abi;

pub trait TestFilter {
fn matches_test(&self, test_name: impl AsRef<str>) -> bool;
fn matches_contract(&self, contract_name: impl AsRef<str>) -> bool;
fn matches_path(&self, path: impl AsRef<str>) -> bool;
}

pub static CALLER: Lazy<Address> = Lazy::new(Address::random);

use ethers::types::Address;
use once_cell::sync::Lazy;
/// The Forge EVM backend
pub use foundry_evm::*;

#[cfg(test)]
pub mod test_helpers {
use crate::executor::fuzz::FuzzedExecutor;

use super::{
executor::{
builder::Backend,
opts::{Env, EvmOpts},
Executor, ExecutorBuilder,
},
*,
};
use crate::TestFilter;
use ethers::{
prelude::Lazy,
solc::{AggregatedCompilerOutput, Project, ProjectPathsConfig},
types::U256,
};
use revm::db::DatabaseRef;
use foundry_evm::{
executor::{
builder::Backend,
opts::{Env, EvmOpts},
DatabaseRef, Executor, ExecutorBuilder,
},
fuzz::FuzzedExecutor,
CALLER,
};

pub static COMPILED: Lazy<AggregatedCompilerOutput> = Lazy::new(|| {
let paths =
Expand Down
10 changes: 3 additions & 7 deletions forge/src/multi_runner.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
use crate::{
executor::{opts::EvmOpts, Executor, ExecutorBuilder, Fork, SpecId},
runner::TestResult,
ContractRunner, TestFilter,
};
use crate::{ContractRunner, TestFilter, TestResult};
use ethers::{
abi::Abi,
prelude::{artifacts::CompactContractBytecode, ArtifactId, ArtifactOutput},
solc::{Artifact, ProjectCompileOutput},
types::{Address, Bytes, U256},
};
use eyre::Result;
use foundry_evm::executor::{opts::EvmOpts, DatabaseRef, Executor, ExecutorBuilder, Fork, SpecId};
use foundry_utils::PostLinkInput;
use proptest::test_runner::TestRunner;
use rayon::prelude::*;
use revm::db::DatabaseRef;
use std::{collections::BTreeMap, marker::Sync, sync::mpsc::Sender};

/// Builder used for instantiating the multi-contract runner
Expand Down Expand Up @@ -292,7 +288,7 @@ mod tests {
let results = runner.test(&Filter::new(".*", ".*", ".*"), None).unwrap();

// 9 contracts being built
assert_eq!(results.keys().len(), 11);
assert_eq!(results.keys().len(), 12);
for (key, contract_tests) in results {
match key.as_str() {
// Tests that should revert
Expand Down
40 changes: 28 additions & 12 deletions forge/src/runner.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
use crate::{
executor::{
fuzz::{CounterExample, FuzzedCases, FuzzedExecutor},
CallResult, DeployResult, EvmError, Executor,
},
trace::{CallTraceArena, TraceKind},
TestFilter, CALLER,
};
use crate::TestFilter;
use ethers::{
abi::{Abi, Function, RawLog},
types::{Address, Bytes, U256},
};
use eyre::Result;
use foundry_evm::{
executor::{CallResult, DatabaseRef, DeployResult, EvmError, Executor},
fuzz::{CounterExample, FuzzedCases, FuzzedExecutor},
trace::{CallTraceArena, TraceKind},
CALLER,
};
use proptest::test_runner::TestRunner;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use revm::db::DatabaseRef;
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, fmt, time::Instant};

Expand Down Expand Up @@ -411,9 +409,10 @@ impl<'a, DB: DatabaseRef + Send + Sync> ContractRunner<'a, DB> {
#[cfg(test)]
mod tests {
use super::*;
use crate::{
executor::builder::Backend,
test_helpers::{filter::Filter, test_executor, COMPILED, EVM_OPTS},
use crate::test_helpers::{filter::Filter, fuzz_executor, test_executor, COMPILED, EVM_OPTS};
use foundry_evm::{
executor::{builder::Backend, DeployResult},
fuzz::FuzzTestResult,
};
use proptest::test_runner::Config as FuzzConfig;

Expand Down Expand Up @@ -531,4 +530,21 @@ mod tests {
let product_without_shrinking = args[0].saturating_mul(args[1]);
assert!(product_without_shrinking > product_with_shrinking.into());
}

#[test]
fn prints_fuzzed_revert_reasons() {
let mut executor = test_executor();

let compiled = COMPILED.find("FuzzTests").expect("could not find contract");
let DeployResult { address, .. } =
executor.deploy(*CALLER, compiled.bytecode().unwrap().0.clone(), 0.into()).unwrap();

let executor = fuzz_executor(&executor);

let func = compiled.abi.unwrap().function("testFuzzedRevert").unwrap();
let FuzzTestResult { reason, success, .. } =
executor.fuzz(func, address, false, compiled.abi);
assert!(!success, "test did not revert");
assert_eq!(reason, Some("fuzztest-revert".to_string()));
}
}
2 changes: 1 addition & 1 deletion ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crossterm::{
};
use ethers::{solc::artifacts::ContractBytecodeSome, types::Address};
use eyre::Result;
use forge::debugger::DebugStep;
use forge::debug::DebugStep;
use std::{
cmp::{max, min},
collections::{BTreeMap, VecDeque},
Expand Down