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
590 changes: 221 additions & 369 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[workspace]
members = [
"evm-adapters",
"utils",
"cast",
"forge",
Expand Down
15 changes: 3 additions & 12 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ foundry-utils = { path = "../utils" }
forge = { path = "../forge" }
foundry-config = { path = "../config" }
cast = { path = "../cast" }
evm-adapters = { path = "../evm-adapters" }
ui = { path = "../ui" }
# TODO: Re-enable when ported
#ui = { path = "../ui" }
dunce = "1.0.2"
# ethers = "0.5"
ethers = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
Expand All @@ -45,9 +45,6 @@ hex = "0.4.3"
rayon = "1.5.1"
serde = "1.0.133"

## EVM Implementations
# evm = { version = "0.30.1" }
sputnik = { package = "evm", git = "https://github.com/rust-blockchain/evm", optional = true }
proptest = "1.0.0"
glob = "0.3.0"
semver = "1.0.4"
Expand All @@ -65,17 +62,11 @@ pretty_assertions = "1.0.0"
toml = "0.5"

[features]
default = ["sputnik-evm", "rustls"]
default = ["rustls"]
solc-asm = ["ethers/solc-sha2-asm"]
rustls = ["ethers/rustls"]
openssl = ["ethers/openssl"]

sputnik-evm = [
"sputnik",
"evm-adapters/sputnik",
"evm-adapters/sputnik-helpers",
]

integration-tests = []

[[bin]]
Expand Down
3 changes: 2 additions & 1 deletion cli/src/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ pub mod fmt;
pub mod init;
pub mod install;
pub mod remappings;
pub mod run;
// TODO: Re-enable when ported
//pub mod run;
pub mod snapshot;
pub mod test;
pub mod verify;
Expand Down
100 changes: 74 additions & 26 deletions cli/src/cmd/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ use crate::{
};
use ansi_term::Colour;
use clap::{AppSettings, Parser};
use ethers::solc::{ArtifactOutput, Project};
use evm_adapters::{
call_tracing::ExecutionInfo, evm_opts::EvmOpts, gas_report::GasReport, sputnik::helpers::vm,
use ethers::{
abi::RawLog,
contract::EthLogDecode,
solc::{ArtifactOutput, Project},
};
use forge::{MultiContractRunnerBuilder, TestFilter};
use forge::{executor::opts::EvmOpts, MultiContractRunnerBuilder, TestFilter};
use foundry_config::{figment::Figment, Config};
use std::collections::BTreeMap;

Expand Down Expand Up @@ -140,13 +141,11 @@ impl Cmd for TestArgs {
let project = config.project()?;

// prepare the test builder
let mut evm_cfg = crate::utils::sputnik_cfg(&config.evm_version);
evm_cfg.create_contract_limit = None;

let evm_spec = crate::utils::evm_spec(&config.evm_version);
let builder = MultiContractRunnerBuilder::default()
.fuzzer(fuzzer)
.initial_balance(evm_opts.initial_balance)
.evm_cfg(evm_cfg)
.evm_spec(evm_spec)
.sender(evm_opts.sender);

test(
Expand Down Expand Up @@ -267,6 +266,7 @@ fn short_test_result(name: &str, result: &forge::TestResult) {
}

/// Runs all the tests
// TODO: We should consider a test reporter abstraction to de-clutter this function
fn test<A: ArtifactOutput + 'static>(
builder: MultiContractRunnerBuilder,
project: Project<A>,
Expand All @@ -288,9 +288,10 @@ fn test<A: ArtifactOutput + 'static>(

let results = runner.test(&filter)?;

let mut gas_report = GasReport::new(gas_reports.1);
// TODO: Re-enable when ported
//let mut gas_report = GasReport::new(gas_reports.1);

let (funcs, events, errors) = runner.execution_info;
//let (funcs, events, errors) = runner.execution_info;
if json {
let res = serde_json::to_string(&results)?;
println!("{}", res);
Expand All @@ -306,29 +307,37 @@ fn test<A: ArtifactOutput + 'static>(
}

for (name, result) in tests {
// build up gas report
if gas_reporting {
if let (Some(traces), Some(identified_contracts)) =
(&result.traces, &result.identified_contracts)
{
gas_report.analyze(traces, identified_contracts);
}
}
// TODO: build up gas report
//if gas_reporting {
// if let (Some(traces), Some(identified_contracts)) =
// (&result.traces, &result.identified_contracts)
// {
// gas_report.analyze(traces, identified_contracts);
// }
//}

short_test_result(name, result);

// adds a linebreak only if there were any traces or logs, so that the
// output does not look like 1 big block.
let mut add_newline = false;
if verbosity > 1 && !result.logs.is_empty() {
if verbosity > 1 {
add_newline = true;
println!("Logs:");
for log in &result.logs {
println!(" {}", log);

// We only decode logs from Hardhat and DS-style console events
let console_logs: Vec<String> =
result.logs.iter().filter_map(decode_console_log).collect();

if !console_logs.is_empty() {
println!("Logs:");
for log in console_logs {
println!(" {}", log);
}
}
}

if verbosity > 2 {
// TODO: Re-enable this portion when traces are ported
/*if verbosity > 2 {
if let (Some(traces), Some(identified_contracts)) =
(&result.traces, &result.identified_contracts)
{
Expand Down Expand Up @@ -383,7 +392,7 @@ fn test<A: ArtifactOutput + 'static>(
}
}
}
}
}*/

if add_newline {
println!();
Expand All @@ -392,10 +401,49 @@ fn test<A: ArtifactOutput + 'static>(
}
}

if gas_reporting {
// TODO: Re-enable when gas reports are ported
/*if gas_reporting {
gas_report.finalize();
println!("{}", gas_report);
}
}*/

Ok(TestOutcome::new(results, allow_failure))
}

fn decode_console_log(log: &RawLog) -> Option<String> {
use forge::abi::ConsoleEvents::{self, *};

let decoded = match ConsoleEvents::decode_log(log).ok()? {
LogsFilter(inner) => format!("{}", inner.0),
LogBytesFilter(inner) => format!("{}", inner.0),
LogNamedAddressFilter(inner) => format!("{}: {:?}", inner.key, inner.val),
LogNamedBytes32Filter(inner) => {
format!("{}: 0x{}", inner.key, hex::encode(inner.val))
}
LogNamedDecimalIntFilter(inner) => {
let (sign, val) = inner.val.into_sign_and_abs();
format!(
"{}: {}{}",
inner.key,
sign,
ethers::utils::format_units(val, inner.decimals.as_u32()).unwrap()
)
}
LogNamedDecimalUintFilter(inner) => {
format!(
"{}: {}",
inner.key,
ethers::utils::format_units(inner.val, inner.decimals.as_u32()).unwrap()
)
}
LogNamedIntFilter(inner) => format!("{}: {:?}", inner.key, inner.val),
LogNamedUintFilter(inner) => format!("{}: {:?}", inner.key, inner.val),
LogNamedBytesFilter(inner) => {
format!("{}: 0x{}", inner.key, hex::encode(inner.val))
}
LogNamedStringFilter(inner) => format!("{}: {}", inner.key, inner.val),

e => e.to_string(),
};
Some(decoded)
}
7 changes: 4 additions & 3 deletions cli/src/forge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ fn main() -> eyre::Result<()> {
Subcommands::Build(cmd) => {
cmd.run()?;
}
Subcommands::Run(cmd) => {
cmd.run()?;
}
// TODO: Re-enable when ported
//Subcommands::Run(cmd) => {
// cmd.run()?;
//}
Subcommands::VerifyContract(args) => {
let rt = tokio::runtime::Runtime::new().expect("could not start tokio rt");
rt.block_on(cmd::verify::run_verify(&args))?;
Expand Down
12 changes: 1 addition & 11 deletions cli/src/opts/evm.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! cli arguments for configuring the evm settings
use clap::Parser;
use ethers::types::{Address, U256};
use evm_adapters::evm_opts::EvmType;
use foundry_config::{
figment::{
self,
Expand All @@ -27,7 +26,7 @@ use serde::Serialize;
//
// ```ignore
// use foundry_config::Config;
// use evm_adapter::EvmOpts;
// use forge::executor::opts::EvmOpts;
// # fn t(args: EvmArgs) {
// let figment = Config::figment_with_root(".").merge(args);
// let opts = figment.extract::<EvmOpts>().unwrap()
Expand All @@ -40,14 +39,6 @@ pub struct EvmArgs {
#[serde(flatten)]
pub env: EnvArgs,

#[clap(
long,
short,
help = "the EVM type you want to use (e.g. sputnik)",
default_value = "sputnik"
)]
pub evm_type: EvmType,

#[clap(help = "fetch state over a remote instead of starting from empty state", long, short)]
#[clap(alias = "rpc-url")]
#[serde(rename = "eth_rpc_url", skip_serializing_if = "Option::is_none")]
Expand Down Expand Up @@ -152,5 +143,4 @@ pub struct EnvArgs {
#[clap(help = "the block.gaslimit value during EVM execution", long)]
#[serde(skip_serializing_if = "Option::is_none")]
pub block_gas_limit: Option<u64>,
// TODO: Add configuration option for base fee.
}
9 changes: 4 additions & 5 deletions cli/src/opts/forge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use crate::cmd::{
init::InitArgs,
install::InstallArgs,
remappings::RemappingArgs,
run::RunArgs,
snapshot, test,
verify::{VerifyArgs, VerifyCheckArgs},
};
Expand Down Expand Up @@ -46,10 +45,10 @@ pub enum Subcommands {
#[clap(alias = "b")]
Build(BuildArgs),

#[clap(about = "Run a single smart contract as a script")]
#[clap(alias = "r")]
Run(RunArgs),

// TODO: Re-enable when ported
//#[clap(about = "Run a single smart contract as a script")]
//#[clap(alias = "r")]
//Run(RunArgs),
#[clap(alias = "u", about = "Fetches all upstream lib changes")]
Update {
#[clap(
Expand Down
12 changes: 5 additions & 7 deletions cli/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use std::str::FromStr;

use ethers::{solc::EvmVersion, types::U256};
#[cfg(feature = "sputnik-evm")]
use sputnik::Config;

use forge::executor::SpecId;
// reexport all `foundry_config::utils`
#[doc(hidden)]
pub use foundry_config::utils::*;
Expand All @@ -28,12 +27,11 @@ pub fn subscriber() {
.init();
}

#[cfg(feature = "sputnik-evm")]
pub fn sputnik_cfg(evm: &EvmVersion) -> Config {
pub fn evm_spec(evm: &EvmVersion) -> SpecId {
match evm {
EvmVersion::Istanbul => Config::istanbul(),
EvmVersion::Berlin => Config::berlin(),
EvmVersion::London => Config::london(),
EvmVersion::Istanbul => SpecId::ISTANBUL,
EvmVersion::Berlin => SpecId::BERLIN,
EvmVersion::London => SpecId::LONDON,
_ => panic!("Unsupported EVM version"),
}
}
Expand Down
12 changes: 3 additions & 9 deletions cli/tests/cmd.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
//! Contains various tests for checking forge's commands
use ethers::solc::{artifacts::Metadata, ConfigurableContractArtifact};
use evm_adapters::evm_opts::{EvmOpts, EvmType};
use forge::executor::opts::EvmOpts;
use foundry_cli_test_utils::{
ethers_solc::{remappings::Remapping, PathStyle},
forgetest, forgetest_ignore, forgetest_init, pretty_eq,
util::{pretty_err, read_string, TestCommand, TestProject},
};
use foundry_config::{parse_with_profile, BasicConfig, Config};
use pretty_assertions::assert_eq;
use std::{
env::{self},
fs,
str::FromStr,
};
use std::{env, fs, str::FromStr};

// import forge utils as mod
#[allow(unused)]
Expand Down Expand Up @@ -218,9 +214,7 @@ forgetest_init!(can_get_evm_opts, |prj: TestProject, mut cmd: TestCommand| {
assert!(config.ffi);

cmd.set_env("FOUNDRY_ETH_RPC_URL", url);
let figment = Config::figment_with_root(prj.root())
.merge(("evm_type", EvmType::Sputnik))
.merge(("debug", false));
let figment = Config::figment_with_root(prj.root()).merge(("debug", false));
let evm_opts: EvmOpts = figment.extract().unwrap();
assert_eq!(evm_opts.fork_url, Some(url.to_string()));
});
Expand Down
37 changes: 0 additions & 37 deletions evm-adapters/Cargo.toml

This file was deleted.

Loading