diff --git a/Cargo.lock b/Cargo.lock index 8c7748906188..e174364f2a74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -313,6 +313,7 @@ dependencies = [ "coins-bip32", "coins-bip39", "elliptic-curve", + "eth-keystore", "k256", "rand 0.8.5", "thiserror", @@ -2978,11 +2979,10 @@ dependencies = [ "alloy-primitives", "alloy-providers", "alloy-rpc-types", + "alloy-signer", "alloy-sol-types", "base64 0.21.7", "const-hex", - "ethers-core", - "ethers-signers", "eyre", "foundry-cheatcodes-spec", "foundry-common", @@ -2991,6 +2991,7 @@ dependencies = [ "foundry-evm-core", "itertools 0.11.0", "jsonpath_lib", + "k256", "p256", "revm", "serde_json", @@ -3200,9 +3201,9 @@ dependencies = [ "alloy-json-abi", "alloy-primitives", "alloy-rpc-types", + "alloy-signer", "alloy-sol-types", "const-hex", - "ethers-signers", "eyre", "foundry-cheatcodes", "foundry-common", diff --git a/Cargo.toml b/Cargo.toml index 077fb93f10b5..11dd5a0e769b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -188,6 +188,7 @@ toml = "0.8" tracing = "0.1" tracing-subscriber = "0.3" evm-disassembler = "0.4" +k256 = "0.13" axum = "0.6" hyper = "0.14" diff --git a/crates/anvil/Cargo.toml b/crates/anvil/Cargo.toml index 6d51daed0877..3a3168ddf723 100644 --- a/crates/anvil/Cargo.toml +++ b/crates/anvil/Cargo.toml @@ -29,7 +29,7 @@ foundry-evm.workspace = true # evm support bytes = "1.4.0" -k256 = "0.13" +k256.workspace = true ethers = { workspace = true, features = ["rustls", "ws", "ipc", "optimism"] } trie-db = "0.23" hash-db = "0.15" diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 14cb26e289d2..4c2e69a36483 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -25,9 +25,8 @@ alloy-genesis.workspace = true alloy-sol-types.workspace = true alloy-providers.workspace = true alloy-rpc-types.workspace = true +alloy-signer = { workspace = true, features = ["mnemonic", "keystore"] } -ethers-core.workspace = true -ethers-signers.workspace = true eyre.workspace = true hex.workspace = true @@ -37,6 +36,7 @@ revm.workspace = true serde_json.workspace = true base64.workspace = true tracing.workspace = true +k256.workspace = true walkdir = "2" p256 = "0.13.2" thiserror = "1" diff --git a/crates/cheatcodes/src/error.rs b/crates/cheatcodes/src/error.rs index 80ab7324a793..19475982f3ed 100644 --- a/crates/cheatcodes/src/error.rs +++ b/crates/cheatcodes/src/error.rs @@ -1,11 +1,11 @@ use crate::Vm; use alloy_primitives::{Address, Bytes}; +use alloy_signer::{Error as SignerError, WalletError}; use alloy_sol_types::SolError; -use ethers_core::k256::ecdsa::signature::Error as SignatureError; -use ethers_signers::WalletError; use foundry_common::errors::FsPathError; use foundry_config::UnresolvedEnvVarError; use foundry_evm_core::backend::DatabaseError; +use k256::ecdsa::signature::Error as SignatureError; use std::{borrow::Cow, fmt}; /// Cheatcode result type. @@ -283,7 +283,7 @@ macro_rules! impl_from { impl_from!( alloy_sol_types::Error, - ethers_core::types::SignatureError, + alloy_primitives::SignatureError, FsPathError, hex::FromHexError, eyre::Error, @@ -297,6 +297,7 @@ impl_from!( std::string::FromUtf8Error, UnresolvedEnvVarError, WalletError, + SignerError, ); #[cfg(test)] diff --git a/crates/cheatcodes/src/evm.rs b/crates/cheatcodes/src/evm.rs index f2e5b2026b0d..5bd7750cfe29 100644 --- a/crates/cheatcodes/src/evm.rs +++ b/crates/cheatcodes/src/evm.rs @@ -3,12 +3,9 @@ use crate::{Cheatcode, Cheatcodes, CheatsCtxt, Result, Vm::*}; use alloy_genesis::{Genesis, GenesisAccount}; use alloy_primitives::{Address, Bytes, B256, U256}; +use alloy_signer::Signer; use alloy_sol_types::SolValue; -use ethers_signers::Signer; -use foundry_common::{ - fs::{read_json_file, write_json_file}, - types::ToAlloy, -}; +use foundry_common::fs::{read_json_file, write_json_file}; use foundry_evm_core::{ backend::{DatabaseExt, RevertSnapshotAction}, constants::{CALLER, CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS, TEST_CONTRACT_ADDRESS}, @@ -48,7 +45,7 @@ impl Cheatcode for addrCall { fn apply(&self, _state: &mut Cheatcodes) -> Result { let Self { privateKey } = self; let wallet = super::utils::parse_wallet(privateKey)?; - Ok(wallet.address().to_alloy().abi_encode()) + Ok(wallet.address().abi_encode()) } } @@ -140,9 +137,9 @@ impl Cheatcode for dumpStateCall { } impl Cheatcode for sign_0Call { - fn apply_full(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_full(&self, _: &mut CheatsCtxt) -> Result { let Self { privateKey, digest } = self; - super::utils::sign(privateKey, digest, ccx.data.env.cfg.chain_id) + super::utils::sign(privateKey, digest) } } diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 3f856c5586c1..4e48c5e9e28d 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -16,8 +16,8 @@ use crate::{ }; use alloy_primitives::{Address, Bytes, B256, U256, U64}; use alloy_rpc_types::request::TransactionRequest; +use alloy_signer::LocalWallet; use alloy_sol_types::{SolInterface, SolValue}; -use ethers_signers::LocalWallet; use foundry_common::{evm::Breakpoints, provider::alloy::RpcUrl}; use foundry_evm_core::{ backend::{DatabaseError, DatabaseExt, RevertDiagnostic}, diff --git a/crates/cheatcodes/src/script.rs b/crates/cheatcodes/src/script.rs index f4530b9fb5af..820d3ffd9a18 100644 --- a/crates/cheatcodes/src/script.rs +++ b/crates/cheatcodes/src/script.rs @@ -2,8 +2,7 @@ use crate::{Cheatcode, CheatsCtxt, DatabaseExt, Result, Vm::*}; use alloy_primitives::{Address, U256}; -use ethers_signers::Signer; -use foundry_common::types::ToAlloy; +use alloy_signer::Signer; use foundry_config::Config; impl Cheatcode for broadcast_0Call { @@ -107,8 +106,9 @@ fn broadcast_key( private_key: &U256, single_call: bool, ) -> Result { - let wallet = super::utils::parse_wallet(private_key)?.with_chain_id(ccx.data.env.cfg.chain_id); - let new_origin = &wallet.address().to_alloy(); + let mut wallet = super::utils::parse_wallet(private_key)?; + wallet.set_chain_id(Some(ccx.data.env.cfg.chain_id)); + let new_origin = &wallet.address(); let result = broadcast(ccx, Some(new_origin), single_call); if result.is_ok() { diff --git a/crates/cheatcodes/src/utils.rs b/crates/cheatcodes/src/utils.rs index 68c88da76be9..bb4726431188 100644 --- a/crates/cheatcodes/src/utils.rs +++ b/crates/cheatcodes/src/utils.rs @@ -2,21 +2,20 @@ use crate::{Cheatcode, Cheatcodes, CheatsCtxt, DatabaseExt, Result, Vm::*}; use alloy_primitives::{keccak256, B256, U256}; -use alloy_sol_types::SolValue; -use ethers_core::k256::{ - ecdsa::SigningKey, - elliptic_curve::{sec1::ToEncodedPoint, Curve}, - Secp256k1, -}; -use ethers_signers::{ +use alloy_signer::{ coins_bip39::{ ChineseSimplified, ChineseTraditional, Czech, English, French, Italian, Japanese, Korean, Portuguese, Spanish, Wordlist, }, - LocalWallet, MnemonicBuilder, Signer, + LocalWallet, MnemonicBuilder, Signer, SignerSync, }; -use foundry_common::types::{ToAlloy, ToEthers}; +use alloy_sol_types::SolValue; use foundry_evm_core::constants::DEFAULT_CREATE2_DEPLOYER; +use k256::{ + ecdsa::SigningKey, + elliptic_curve::{sec1::ToEncodedPoint, Curve}, + Secp256k1, +}; use p256::ecdsa::{signature::hazmat::PrehashSigner, Signature, SigningKey as P256SigningKey}; /// The BIP32 default derivation path prefix. @@ -51,9 +50,9 @@ impl Cheatcode for getNonce_1Call { } impl Cheatcode for sign_1Call { - fn apply_full(&self, ccx: &mut CheatsCtxt) -> Result { + fn apply_full(&self, _: &mut CheatsCtxt) -> Result { let Self { wallet, digest } = self; - sign(&wallet.privateKey, digest, ccx.data.env.cfg.chain_id) + sign(&wallet.privateKey, digest) } } @@ -88,10 +87,10 @@ impl Cheatcode for deriveKey_3Call { impl Cheatcode for rememberKeyCall { fn apply_full(&self, ccx: &mut CheatsCtxt) -> Result { let Self { privateKey } = self; - let wallet = parse_wallet(privateKey)?.with_chain_id(ccx.data.env.cfg.chain_id); + let wallet = parse_wallet(privateKey)?.with_chain_id(Some(ccx.data.env.cfg.chain_id)); let address = wallet.address(); ccx.state.script_wallets.push(wallet); - Ok(address.to_alloy().abi_encode()) + Ok(address.abi_encode()) } } @@ -141,7 +140,7 @@ impl Cheatcode for computeCreate2Address_1Call { /// If 'label' is set to 'Some()', assign that label to the associated ETH address in state fn create_wallet(private_key: &U256, label: Option<&str>, state: &mut Cheatcodes) -> Result { let key = parse_private_key(private_key)?; - let addr = ethers_core::utils::secret_key_to_address(&key).to_alloy(); + let addr = alloy_signer::utils::secret_key_to_address(&key); let pub_key = key.verifying_key().as_affine().to_encoded_point(false); let pub_key_x = U256::from_be_bytes((*pub_key.x().unwrap()).into()); @@ -155,21 +154,20 @@ fn create_wallet(private_key: &U256, label: Option<&str>, state: &mut Cheatcodes .abi_encode()) } -pub(super) fn sign(private_key: &U256, digest: &B256, chain_id: u64) -> Result { - let wallet = parse_wallet(private_key)?.with_chain_id(chain_id); +pub(super) fn sign(private_key: &U256, digest: &B256) -> Result { + // The `ecrecover` precompile does not use EIP-155. No chain ID is needed. + let wallet = parse_wallet(private_key)?; - // The `ecrecover` precompile does not use EIP-155 - let sig = wallet.sign_hash(digest.to_ethers())?; - let recovered = sig.recover(digest.to_ethers())?.to_alloy(); + let sig = wallet.sign_hash_sync(*digest)?; + let recovered = sig.recover_address_from_prehash(digest)?; - assert_eq!(recovered, wallet.address().to_alloy()); + assert_eq!(recovered, wallet.address()); - let mut r_bytes = [0u8; 32]; - let mut s_bytes = [0u8; 32]; - sig.r.to_big_endian(&mut r_bytes); - sig.s.to_big_endian(&mut s_bytes); + let v = U256::from(sig.v().y_parity_byte_non_eip155().unwrap_or(sig.v().y_parity_byte())); + let r = B256::from(sig.r()); + let s = B256::from(sig.s()); - Ok((sig.v, r_bytes, s_bytes).abi_encode()) + Ok((v, r, s).abi_encode()) } pub(super) fn sign_p256(private_key: &U256, digest: &B256, _state: &mut Cheatcodes) -> Result { @@ -231,7 +229,7 @@ fn derive_key(mnemonic: &str, path: &str, index: u32) -> Result { let wallet = MnemonicBuilder::::default() .phrase(mnemonic) - .derivation_path(&derive_key_path(path, index))? + .derivation_path(derive_key_path(path, index))? .build()?; let private_key = U256::from_be_bytes(wallet.signer().to_bytes().into()); Ok(private_key.abi_encode()) diff --git a/crates/evm/evm/Cargo.toml b/crates/evm/evm/Cargo.toml index 0ad1d709e05f..9ea7dd0fa51e 100644 --- a/crates/evm/evm/Cargo.toml +++ b/crates/evm/evm/Cargo.toml @@ -25,6 +25,7 @@ alloy-json-abi.workspace = true alloy-primitives = { workspace = true, features = ["serde", "getrandom", "arbitrary", "rlp"] } alloy-sol-types.workspace = true alloy-rpc-types.workspace = true +alloy-signer.workspace = true hashbrown = { version = "0.14", features = ["serde"] } revm = { workspace = true, default-features = false, features = [ "std", @@ -37,7 +38,6 @@ revm = { workspace = true, default-features = false, features = [ ] } revm-inspectors.workspace = true -ethers-signers.workspace = true itertools.workspace = true eyre = "0.6" diff --git a/crates/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index e8bcbaf879c1..092e0641e546 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -12,7 +12,7 @@ use crate::inspectors::{ use alloy_dyn_abi::{DynSolValue, FunctionExt, JsonAbiExt}; use alloy_json_abi::{Function, JsonAbi}; use alloy_primitives::{Address, Bytes, Log, U256}; -use ethers_signers::LocalWallet; +use alloy_signer::LocalWallet; use foundry_common::{abi::IntoFunction, evm::Breakpoints}; use foundry_evm_core::{ backend::{Backend, DatabaseError, DatabaseExt, DatabaseResult, FuzzBackendWrapper}, diff --git a/crates/evm/evm/src/inspectors/stack.rs b/crates/evm/evm/src/inspectors/stack.rs index 48ac5a8df5ab..6ece0f2da4ff 100644 --- a/crates/evm/evm/src/inspectors/stack.rs +++ b/crates/evm/evm/src/inspectors/stack.rs @@ -3,7 +3,7 @@ use super::{ StackSnapshotType, TracePrinter, TracingInspector, TracingInspectorConfig, }; use alloy_primitives::{Address, Bytes, Log, B256, U256}; -use ethers_signers::LocalWallet; +use alloy_signer::LocalWallet; use foundry_evm_core::{backend::DatabaseExt, debug::DebugArena}; use foundry_evm_coverage::HitMaps; use foundry_evm_traces::CallTraceArena; diff --git a/crates/forge/bin/cmd/script/runner.rs b/crates/forge/bin/cmd/script/runner.rs index 4893c21fa9ea..6afb1a4441b0 100644 --- a/crates/forge/bin/cmd/script/runner.rs +++ b/crates/forge/bin/cmd/script/runner.rs @@ -7,6 +7,7 @@ use forge::{ revm::interpreter::{return_ok, InstructionResult}, traces::{TraceKind, Traces}, }; +use foundry_common::types::ToEthers; /// Represents which simulation stage is the script execution at. pub enum SimulationStage { @@ -170,7 +171,7 @@ impl ScriptRunner { traces, debug, address: None, - script_wallets, + script_wallets: script_wallets.to_ethers(), ..Default::default() }, )) @@ -305,7 +306,7 @@ impl ScriptRunner { labeled_addresses: labels, transactions, address: None, - script_wallets, + script_wallets: script_wallets.to_ethers(), breakpoints, }) }