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
547 changes: 438 additions & 109 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,14 @@ ethers-middleware = { git = "https://github.com/gakonst/ethers-rs", default-feat
ethers-etherscan = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
ethers-solc = { git = "https://github.com/gakonst/ethers-rs", default-features = false }

alloy-primitives = { version = "0.3", default-features = false }
alloy-dyn-abi = { version = "0.3", default-features = false}

chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
hex = { package = "const-hex", version = "1.6", features = ["hex"] }
itertools = "0.11"
solang-parser = "=0.3.2"

alloy-primitives = { version = "0.3", default-features = false }

#[patch."https://github.com/gakonst/ethers-rs"]
#ethers = { path = "../ethers-rs/ethers" }
Expand Down
3 changes: 2 additions & 1 deletion crates/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ revm = { workspace = true, default-features = false, features = [
"optional_no_base_fee",
] }

alloy-primitives = { workspace = true, default-features = false, features = ["std", "serde", "getrandom"] }
alloy-primitives = { workspace = true, default-features = false, features = ["std", "serde", "getrandom", "arbitrary", "rlp"] }
alloy-dyn-abi = { workspace = true, default-features = false, features = ["std", "arbitrary"] }

# Fuzzer
proptest = "1"
Expand Down
14 changes: 8 additions & 6 deletions crates/evm/src/executor/inspector/cheatcodes/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ use crate::{
},
utils::{b160_to_h160, h160_to_b160, ru256_to_u256, u256_to_ru256},
};
use alloy_primitives::B256;
use alloy_dyn_abi::DynSolValue;
use alloy_primitives::{Bytes, B256};
use ethers::{
abi::{self, AbiEncode, RawLog, Token, Tokenizable, Tokenize},
abi::{self, RawLog, Token, Tokenizable, Tokenize},
signers::{LocalWallet, Signer},
types::{Address, Bytes, U256},
types::{Address, U256},
};
use foundry_config::Config;
use foundry_utils::types::ToAlloy;
use revm::{
primitives::{Bytecode, SpecId, KECCAK_EMPTY},
Database, EVMData,
Expand Down Expand Up @@ -398,7 +400,7 @@ pub fn apply<DB: DatabaseExt>(
u256_to_ru256(inner.1.into()),
data.db,
)?;
ru256_to_u256(val).encode().into()
DynSolValue::from(val).encode_single().into()
}
HEVMCalls::Cool(inner) => cool_account(data, inner.0)?,
HEVMCalls::Breakpoint0(inner) => add_breakpoint(state, caller, &inner.0, true)?,
Expand Down Expand Up @@ -542,7 +544,7 @@ pub fn apply<DB: DatabaseExt>(

// we can safely unwrap because `load_account` insert inner.0 to DB.
let account = data.journaled_state.state().get(&h160_to_b160(inner.0)).unwrap();
abi::encode(&[Token::Uint(account.info.nonce.into())]).into()
DynSolValue::from(account.info.nonce).encode_single().into()
}
// [function getNonce(Wallet)] returns the current nonce of the Wallet's ETH address
HEVMCalls::GetNonce0(inner) => {
Expand All @@ -559,7 +561,7 @@ pub fn apply<DB: DatabaseExt>(

// we can safely unwrap because `load_account` insert inner.0 to DB.
let account = data.journaled_state.state().get(&h160_to_b160(inner.0.addr)).unwrap();
abi::encode(&[Token::Uint(account.info.nonce.into())]).into()
DynSolValue::from(account.info.nonce.to_alloy()).encode_single().into()
}
HEVMCalls::ChainId(inner) => {
ensure!(inner.0 <= U256::from(u64::MAX), "Chain ID must be less than 2^64 - 1");
Expand Down
8 changes: 4 additions & 4 deletions crates/evm/src/executor/inspector/cheatcodes/error.rs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can migrate this file too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 745872c

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::executor::backend::{error::NoCheatcodeAccessError, DatabaseError};
use ethers::{
abi::AbiEncode, prelude::k256::ecdsa::signature::Error as SignatureError, types::Bytes,
};
use alloy_dyn_abi::DynSolValue;
use alloy_primitives::Bytes;
use ethers::prelude::k256::ecdsa::signature::Error as SignatureError;
use foundry_common::errors::FsPathError;
use foundry_config::UnresolvedEnvVarError;
use foundry_utils::error::{encode_error, SolError};
Expand Down Expand Up @@ -179,7 +179,7 @@ impl SolError for Error {
fn encode_string(&self) -> Bytes {
match self {
Self::CustomBytes(cow) => cow_to_bytes(cow),
e => e.to_string().encode().into(),
e => DynSolValue::String(e.to_string()).encode_single().into(),
}
}
}
Expand Down
30 changes: 17 additions & 13 deletions crates/evm/src/executor/inspector/cheatcodes/expect.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use super::{bail, ensure, fmt_err, Cheatcodes, Result};
use crate::{abi::HEVMCalls, executor::backend::DatabaseExt, utils::h160_to_b160};
use alloy_primitives::Bytes;
use ethers::{
abi::{AbiDecode, RawLog},
contract::Lazy,
types::{Address, Bytes, H160, U256},
types::{Address, H160, U256},
};
use foundry_utils::error::{ERROR_PREFIX, REVERT_PREFIX};
use revm::{
Expand Down Expand Up @@ -65,8 +66,8 @@ pub fn handle_expect_revert(
}

// If None, accept any revert
let expected_revert = match expected_revert {
Some(x) => x,
let mut expected_revert = match expected_revert {
Some(x) => x.clone(),
None => return success_return!(),
};

Expand All @@ -78,24 +79,24 @@ pub fn handle_expect_revert(
if actual_revert.len() >= 4 &&
matches!(actual_revert[..4].try_into(), Ok(ERROR_PREFIX | REVERT_PREFIX))
{
if let Ok(bytes) = Bytes::decode(&actual_revert[4..]) {
actual_revert = bytes;
if let Ok(bytes) = ethers::types::Bytes::decode(&actual_revert[4..]) {
actual_revert = bytes.0.into();
}
}

if actual_revert == *expected_revert {
success_return!()
} else {
let stringify = |data: &[u8]| {
String::decode(data)
let stringify = |data: &mut Bytes| {
String::decode(data.0.as_ref())
.ok()
.or_else(|| std::str::from_utf8(data).ok().map(ToOwned::to_owned))
.or_else(|| std::str::from_utf8(data.as_ref()).ok().map(ToOwned::to_owned))
.unwrap_or_else(|| format!("0x{}", hex::encode(data)))
};
Err(fmt_err!(
"Error != expected error: {} != {}",
stringify(&actual_revert),
stringify(expected_revert),
stringify(&mut actual_revert),
stringify(&mut expected_revert),
))
}
}
Expand Down Expand Up @@ -334,7 +335,7 @@ pub fn apply<DB: DatabaseExt>(
let result = match call {
HEVMCalls::ExpectRevert0(_) => expect_revert(state, None, data.journaled_state.depth()),
HEVMCalls::ExpectRevert1(inner) => {
expect_revert(state, Some(inner.0.clone()), data.journaled_state.depth())
expect_revert(state, Some(inner.0.clone().0.into()), data.journaled_state.depth())
}
HEVMCalls::ExpectRevert2(inner) => {
expect_revert(state, Some(inner.0.into()), data.journaled_state.depth())
Expand Down Expand Up @@ -503,8 +504,11 @@ pub fn apply<DB: DatabaseExt>(
data.journaled_state.set_code(h160_to_b160(inner.0), code);
}
state.mocked_calls.entry(inner.0).or_default().insert(
MockCallDataContext { calldata: inner.1.clone(), value: None },
MockCallReturnData { data: inner.2.clone(), ret_type: InstructionResult::Return },
MockCallDataContext { calldata: inner.1.clone().0.into(), value: None },
MockCallReturnData {
data: inner.2.clone().0.into(),
ret_type: InstructionResult::Return,
},
);
Ok(Bytes::new())
}
Expand Down
16 changes: 10 additions & 6 deletions crates/evm/src/executor/inspector/cheatcodes/ext.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{bail, ensure, fmt_err, util::MAGIC_SKIP_BYTES, Cheatcodes, Error, Result};
use crate::{abi::HEVMCalls, executor::inspector::cheatcodes::parse};
use alloy_primitives::Bytes;
use ethers::{
abi::{self, AbiEncode, JsonAbi, ParamType, Token},
prelude::artifacts::CompactContractBytecode,
Expand Down Expand Up @@ -106,9 +107,9 @@ impl ArtifactBytecode {
match self {
ArtifactBytecode::Hardhat(inner) => Some(inner.bytecode),
ArtifactBytecode::Forge(inner) => {
inner.bytecode.and_then(|bytecode| bytecode.object.into_bytes())
inner.bytecode.and_then(|bytecode| bytecode.object.into_bytes()).map(|b| b.0.into())
}
ArtifactBytecode::Solc(inner) => inner.bytecode(),
ArtifactBytecode::Solc(inner) => inner.bytecode().map(|b| b.0.into()),
ArtifactBytecode::Huff(inner) => Some(inner.bytecode),
}
}
Expand All @@ -117,9 +118,12 @@ impl ArtifactBytecode {
match self {
ArtifactBytecode::Hardhat(inner) => Some(inner.deployed_bytecode),
ArtifactBytecode::Forge(inner) => inner.deployed_bytecode.and_then(|bytecode| {
bytecode.bytecode.and_then(|bytecode| bytecode.object.into_bytes())
bytecode
.bytecode
.and_then(|bytecode| bytecode.object.into_bytes())
.map(|b| b.0.into())
}),
ArtifactBytecode::Solc(inner) => inner.deployed_bytecode(),
ArtifactBytecode::Solc(inner) => inner.deployed_bytecode().map(|b| b.0.into()),
ArtifactBytecode::Huff(inner) => Some(inner.runtime),
}
}
Expand All @@ -143,7 +147,7 @@ struct HuffArtifact {
fn get_code(state: &Cheatcodes, path: &str) -> Result {
let bytecode = read_bytecode(state, path)?;
if let Some(bin) = bytecode.into_bytecode() {
Ok(bin.encode().into())
Ok(bin.0.clone().encode().into())
} else {
Err(fmt_err!("No bytecode for contract. Is it abstract or unlinked?"))
}
Expand All @@ -153,7 +157,7 @@ fn get_code(state: &Cheatcodes, path: &str) -> Result {
fn get_deployed_code(state: &Cheatcodes, path: &str) -> Result {
let bytecode = read_bytecode(state, path)?;
if let Some(bin) = bytecode.into_deployed_bytecode() {
Ok(bin.encode().into())
Ok(bin.0.clone().encode().into())
} else {
Err(fmt_err!("No deployed bytecode for contract. Is it abstract or unlinked?"))
}
Expand Down
4 changes: 2 additions & 2 deletions crates/evm/src/executor/inspector/cheatcodes/fork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ use crate::{
},
utils::{h160_to_b160, ru256_to_u256, u256_to_ru256, RuntimeOrHandle},
};
use alloy_primitives::{B256, U256};
use alloy_primitives::{Bytes, B256, U256};
use ethers::{
abi::{self, AbiEncode, Token, Tokenizable, Tokenize},
providers::Middleware,
types::{Bytes, Filter, U256 as eU256},
types::{Filter, U256 as eU256},
};
use foundry_abi::hevm::{EthGetLogsCall, RpcCall};
use foundry_common::ProviderBuilder;
Expand Down
6 changes: 2 additions & 4 deletions crates/evm/src/executor/inspector/cheatcodes/fs.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use super::{Cheatcodes, Result};
use crate::abi::hevm::{DirEntry, FsMetadata, HEVMCalls};
use ethers::{
abi::{self, AbiEncode, Token, Tokenize},
types::Bytes,
};
use alloy_primitives::Bytes;
use ethers::abi::{self, AbiEncode, Token, Tokenize};
use foundry_common::fs;
use foundry_config::fs_permissions::FsAccessKind;
use std::{
Expand Down
2 changes: 1 addition & 1 deletion crates/evm/src/executor/inspector/cheatcodes/fuzz.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{Error, Result};
use crate::{abi::HEVMCalls, fuzz::error::ASSUME_MAGIC_RETURN_CODE};
use ethers::types::Bytes;
use alloy_primitives::Bytes;

#[instrument(level = "error", name = "fuzz", target = "evm::cheatcodes", skip_all)]
pub fn apply(call: &HEVMCalls) -> Option<Result> {
Expand Down
3 changes: 2 additions & 1 deletion crates/evm/src/executor/inspector/cheatcodes/mapping.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use super::Cheatcodes;
use crate::utils::{b160_to_h160, ru256_to_u256};
use alloy_primitives::Bytes;
use ethers::{
abi::{self, Token},
types::{Address, Bytes, U256},
types::{Address, U256},
utils::keccak256,
};
use revm::{
Expand Down
11 changes: 5 additions & 6 deletions crates/evm/src/executor/inspector/cheatcodes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@ use crate::{
},
utils::{b160_to_h160, b256_to_h256, h160_to_b160, ru256_to_u256, u256_to_ru256},
};
use alloy_primitives::{Address as rAddress, B256};
use alloy_primitives::{Address as rAddress, Bytes, B256};
use ethers::{
abi::{AbiDecode, AbiEncode, RawLog},
signers::LocalWallet,
types::{
transaction::eip2718::TypedTransaction, Address, Bytes, NameOrAddress, TransactionRequest,
U256,
transaction::eip2718::TypedTransaction, Address, NameOrAddress, TransactionRequest, U256,
},
};
use foundry_common::evm::Breakpoints;
Expand Down Expand Up @@ -611,7 +610,7 @@ impl<DB: DatabaseExt> Inspector<DB> for Cheatcodes {
// Handle mocked calls
if let Some(mocks) = self.mocked_calls.get(&b160_to_h160(call.contract)) {
let ctx = MockCallDataContext {
calldata: ethers::types::Bytes::from(call.input.clone().0),
calldata: call.input.clone().0.into(),
value: Some(call.transfer.value).map(ru256_to_u256),
};
if let Some(mock_retdata) = mocks.get(&ctx) {
Expand Down Expand Up @@ -792,7 +791,7 @@ impl<DB: DatabaseExt> Inspector<DB> for Cheatcodes {
false,
expected_revert.reason.as_ref(),
status,
ethers::types::Bytes(retdata.0),
retdata,
) {
Err(error) => {
trace!(expected=?expected_revert, ?error, ?status, "Expected revert mismatch");
Expand Down Expand Up @@ -1093,7 +1092,7 @@ impl<DB: DatabaseExt> Inspector<DB> for Cheatcodes {
true,
expected_revert.reason.as_ref(),
status,
ethers::types::Bytes(retdata.0),
retdata,
) {
Ok((address, retdata)) => (
InstructionResult::Return,
Expand Down
1 change: 1 addition & 0 deletions crates/utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ ethers-providers.workspace = true
ethers-solc.workspace = true

alloy-primitives = { workspace = true, features = ["std"]}
alloy-dyn-abi = { workspace = true, features = ["std"]}

eyre = { version = "0.6", default-features = false }
futures = "0.3"
Expand Down
10 changes: 7 additions & 3 deletions crates/utils/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! error handling and support

use ethers_core::{abi::AbiEncode, types::Bytes};
use alloy_dyn_abi::DynSolValue;
use alloy_primitives::Bytes;
use std::fmt::Display;

/// Solidity revert prefix.
Expand All @@ -26,11 +27,14 @@ pub trait SolError: std::error::Error {
///
/// See also [`AbiEncode`](ethers::abi::AbiEncode)
fn encode_string(&self) -> Bytes {
self.to_string().encode().into()
let err = DynSolValue::from(self.to_string());
err.encode_single().into()
}
}

/// Encodes the given messages as solidity custom error
pub fn encode_error(reason: impl Display) -> Bytes {
[ERROR_PREFIX.as_slice(), reason.to_string().encode().as_slice()].concat().into()
[ERROR_PREFIX.as_slice(), DynSolValue::String(reason.to_string()).encode_single().as_slice()]
.concat()
.into()
}
8 changes: 8 additions & 0 deletions crates/utils/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ impl ToAlloy for U256 {
}
}

impl ToAlloy for u64 {
type To = AlloyU256;

fn to_alloy(self) -> Self::To {
AlloyU256::from(self)
}
}

/// Conversion trait to easily convert from alloy primitive types to ethers-rs types.
pub trait ToEthers {
type To;
Expand Down