diff --git a/Cargo.lock b/Cargo.lock index a0858fe08d58..a3a5b14d20b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,10 +76,20 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "alloy-chains" +version = "0.1.1" +source = "git+https://github.com/alloy-rs/chains/?branch=dani/fix-serde#bd022b904897cf71333db9e96e73f6abb363688e" +dependencies = [ + "num_enum", + "serde", + "strum", +] + [[package]] name = "alloy-dyn-abi" version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#89f07abf7837f63d22e30d2076e860dac6acef57" +source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -99,7 +109,7 @@ dependencies = [ [[package]] name = "alloy-json-abi" version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#89f07abf7837f63d22e30d2076e860dac6acef57" +source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -110,7 +120,7 @@ dependencies = [ [[package]] name = "alloy-primitives" version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#89f07abf7837f63d22e30d2076e860dac6acef57" +source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" dependencies = [ "alloy-rlp", "arbitrary", @@ -157,7 +167,7 @@ dependencies = [ [[package]] name = "alloy-sol-macro" version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#89f07abf7837f63d22e30d2076e860dac6acef57" +source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" dependencies = [ "const-hex", "dunce", @@ -174,7 +184,7 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#89f07abf7837f63d22e30d2076e860dac6acef57" +source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" dependencies = [ "winnow", ] @@ -182,7 +192,7 @@ dependencies = [ [[package]] name = "alloy-sol-types" version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#89f07abf7837f63d22e30d2076e860dac6acef57" +source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -1562,9 +1572,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" +checksum = "28f85c3514d2a6e64160359b45a3918c3b4178bcbf4ae5d03ab2d02e521c479a" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -2619,11 +2629,12 @@ dependencies = [ [[package]] name = "foundry-block-explorers" version = "0.1.0" -source = "git+https://github.com/foundry-rs/block-explorers#6e040684a6b6dfccee52eee02c0958a8436d7bc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc59cf4c18884c485b20f376e98946774b76f3b8e2e71e4f35723ffb34b8544" dependencies = [ + "alloy-chains", "alloy-json-abi", "alloy-primitives", - "ethers-core", "foundry-compilers", "reqwest", "semver 1.0.20", @@ -2793,9 +2804,9 @@ name = "foundry-config" version = "0.2.0" dependencies = [ "Inflector", + "alloy-chains", "alloy-primitives", "dirs-next", - "ethers-core", "eyre", "figment", "foundry-block-explorers", @@ -3696,9 +3707,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f95b9abcae896730d42b78e09c155ed4ddf82c07b4de772c64aee5b2d8b7c150" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -4700,7 +4711,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" dependencies = [ - "proc-macro-crate 2.0.0", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.39", @@ -4875,7 +4886,7 @@ version = "3.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -5331,15 +5342,6 @@ dependencies = [ "toml_edit 0.19.15", ] -[[package]] -name = "proc-macro-crate" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" -dependencies = [ - "toml_edit 0.20.7", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -6056,9 +6058,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234" dependencies = [ "bitflags 2.4.1", "errno", @@ -6205,7 +6207,7 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -6852,7 +6854,7 @@ dependencies = [ [[package]] name = "syn-solidity" version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#89f07abf7837f63d22e30d2076e860dac6acef57" +source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" dependencies = [ "paste", "proc-macro2", @@ -6942,9 +6944,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" dependencies = [ "winapi-util", ] @@ -7233,17 +7235,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "toml_edit" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" -dependencies = [ - "indexmap 2.1.0", - "toml_datetime", - "winnow", -] - [[package]] name = "toml_edit" version = "0.21.0" @@ -7384,9 +7375,9 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ "log", "once_cell", @@ -7395,9 +7386,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -7561,9 +7552,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-bom" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98e90c70c9f0d4d1ee6d0a7d04aa06cb9bbd53d8cfbdd62a0269a7c2eb640552" +checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" [[package]] name = "unicode-ident" @@ -8143,18 +8134,18 @@ checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377" [[package]] name = "zerocopy" -version = "0.7.25" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.25" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 836b5cc4550a..35f4ad47fd30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -158,6 +158,7 @@ alloy-json-abi = "0.4.1" alloy-sol-types = "0.4.1" syn-solidity = "0.4.1" +alloy-chains = "0.1.0" alloy-rlp = "0.3.3" solang-parser = "=0.3.3" @@ -200,7 +201,7 @@ ethers-middleware = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e ethers-etherscan = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e1ccbaab70996ab21b5ceeff2fe599728b74" } ethers-solc = { git = "https://github.com/gakonst/ethers-rs", rev = "0543e1ccbaab70996ab21b5ceeff2fe599728b74" } -foundry-block-explorers = { git = "https://github.com/foundry-rs/block-explorers" } +alloy-chains = { git = "https://github.com/alloy-rs/chains/", branch = "dani/fix-serde" } alloy-dyn-abi = { git = "https://github.com/alloy-rs/core/" } alloy-primitives = { git = "https://github.com/alloy-rs/core/" } diff --git a/crates/cast/bin/cmd/access_list.rs b/crates/cast/bin/cmd/access_list.rs index 9ac265660764..171853faf782 100644 --- a/crates/cast/bin/cmd/access_list.rs +++ b/crates/cast/bin/cmd/access_list.rs @@ -61,7 +61,7 @@ impl AccessListArgs { let config = Config::from(ð); let provider = utils::get_provider(&config)?; - let chain = utils::get_chain(config.chain_id, &provider).await?; + let chain = utils::get_chain(config.chain, &provider).await?; let sender = eth.wallet.sender().await; access_list(&provider, sender.to_ethers(), to, sig, args, data, tx, chain, block, to_json) diff --git a/crates/cast/bin/cmd/bind.rs b/crates/cast/bin/cmd/bind.rs index a0716f3cd1a6..349630291739 100644 --- a/crates/cast/bin/cmd/bind.rs +++ b/crates/cast/bin/cmd/bind.rs @@ -79,9 +79,8 @@ impl BindArgs { async fn abigen_etherscan(&self) -> Result { let config = Config::from(&self.etherscan); - let chain = config.chain_id.unwrap_or_default(); + let chain = config.chain.unwrap_or_default(); let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); - let chain = chain.named()?; let client = Client::new(chain, api_key)?; let address = self.path_or_address.parse()?; diff --git a/crates/cast/bin/cmd/call.rs b/crates/cast/bin/cmd/call.rs index a394c6421941..6c9fc22aa64f 100644 --- a/crates/cast/bin/cmd/call.rs +++ b/crates/cast/bin/cmd/call.rs @@ -126,7 +126,7 @@ impl CallArgs { let config = Config::from(ð); let provider = utils::get_provider(&config)?; - let chain = utils::get_chain(config.chain_id, &provider).await?; + let chain = utils::get_chain(config.chain, &provider).await?; let sender = eth.wallet.sender().await; let mut builder: TxBuilder<'_, Provider> = diff --git a/crates/cast/bin/cmd/estimate.rs b/crates/cast/bin/cmd/estimate.rs index 94493c3c76bd..c3352cab35b8 100644 --- a/crates/cast/bin/cmd/estimate.rs +++ b/crates/cast/bin/cmd/estimate.rs @@ -83,7 +83,7 @@ impl EstimateArgs { let config = Config::from_provider(figment); let provider = utils::get_provider(&config)?; - let chain = utils::get_chain(config.chain_id, &provider).await?; + let chain = utils::get_chain(config.chain, &provider).await?; let api_key = config.get_etherscan_api_key(Some(chain)); let mut builder = TxBuilder::new(&provider, from, to, chain, false).await?; diff --git a/crates/cast/bin/cmd/interface.rs b/crates/cast/bin/cmd/interface.rs index b49667ce8319..cc2b7290cc97 100644 --- a/crates/cast/bin/cmd/interface.rs +++ b/crates/cast/bin/cmd/interface.rs @@ -56,9 +56,8 @@ impl InterfaceArgs { AbiPath::Local { path: path_or_address, name } } else { let config = Config::from(ðerscan); - let chain = config.chain_id.unwrap_or_default(); + let chain = config.chain.unwrap_or_default(); let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); - let chain = chain.named()?; AbiPath::Etherscan { chain, api_key, diff --git a/crates/cast/bin/cmd/logs.rs b/crates/cast/bin/cmd/logs.rs index 65643968d959..e7e6aed5d9b7 100644 --- a/crates/cast/bin/cmd/logs.rs +++ b/crates/cast/bin/cmd/logs.rs @@ -169,8 +169,7 @@ fn build_filter_event_sig(event: Event, args: Vec) -> Result>(), true)?; + let indexed_tokens = parse_params(with_args.iter().map(|(_, p)| *p), true)?; // Merge the inputs restoring the original ordering let mut tokens = with_args @@ -217,7 +216,7 @@ fn parse_params<'a, I: IntoIterator>( ) -> eyre::Result> { let mut tokens = Vec::new(); - for (param, value) in params.into_iter() { + for (param, value) in params { let mut token = if lenient { LenientTokenizer::tokenize(param, value) } else { diff --git a/crates/cast/bin/cmd/send.rs b/crates/cast/bin/cmd/send.rs index f30221ddb033..725e540fce18 100644 --- a/crates/cast/bin/cmd/send.rs +++ b/crates/cast/bin/cmd/send.rs @@ -112,7 +112,7 @@ impl SendTxArgs { let config = Config::from(ð); let provider = utils::get_provider(&config)?; - let chain = utils::get_chain(config.chain_id, &provider).await?; + let chain = utils::get_chain(config.chain, &provider).await?; let api_key = config.get_etherscan_api_key(Some(chain)); // Case 1: @@ -121,7 +121,7 @@ impl SendTxArgs { // or remote RPC with unlocked accounts. if unlocked { // only check current chain id if it was specified in the config - if let Some(config_chain) = config.chain_id { + if let Some(config_chain) = config.chain { let current_chain_id = provider.get_chainid().await?.as_u64(); let config_chain_id = config_chain.id(); // switch chain if current chain id is not the same as the one specified in the diff --git a/crates/cast/bin/cmd/storage.rs b/crates/cast/bin/cmd/storage.rs index 9981b96f2c09..ba372b95871c 100644 --- a/crates/cast/bin/cmd/storage.rs +++ b/crates/cast/bin/cmd/storage.rs @@ -126,9 +126,9 @@ impl StorageArgs { eyre::bail!("You must provide an Etherscan API key if you're fetching a remote contract's storage."); } - let chain = utils::get_chain(config.chain_id, &provider).await?; + let chain = utils::get_chain(config.chain, &provider).await?; let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); - let client = Client::new(chain.named()?, api_key)?; + let client = Client::new(chain, api_key)?; let addr = address .as_address() .ok_or_else(|| eyre::eyre!("Could not resolve address"))? diff --git a/crates/cast/bin/cmd/wallet/mod.rs b/crates/cast/bin/cmd/wallet/mod.rs index bbbdf0e8deca..abe4df5d4704 100644 --- a/crates/cast/bin/cmd/wallet/mod.rs +++ b/crates/cast/bin/cmd/wallet/mod.rs @@ -3,7 +3,6 @@ use clap::Parser; use ethers_core::{ rand::thread_rng, types::{transaction::eip712::TypedData, Signature}, - utils::to_checksum, }; use ethers_signers::{ coins_bip39::{English, Mnemonic}, @@ -226,7 +225,7 @@ impl WalletSubcommands { println!("\nAccounts:"); for (i, wallet) in wallets.iter().enumerate() { println!("- Account {i}:"); - println!("Address: {}", to_checksum(&wallet.address(), None)); + println!("Address: {}", wallet.address().to_alloy()); println!("Private key: 0x{}\n", hex::encode(wallet.signer().to_bytes())); } } diff --git a/crates/cast/bin/main.rs b/crates/cast/bin/main.rs index d4a11421e31b..edbe9d9804c2 100644 --- a/crates/cast/bin/main.rs +++ b/crates/cast/bin/main.rs @@ -462,9 +462,8 @@ async fn main() -> Result<()> { } Subcommands::EtherscanSource { address, directory, etherscan } => { let config = Config::from(ðerscan); - let chain = config.chain_id.unwrap_or_default(); + let chain = config.chain.unwrap_or_default(); let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); - let chain = chain.named()?; match directory { Some(dir) => { SimpleCast::expand_etherscan_source_to_directory(chain, address, api_key, dir) diff --git a/crates/cast/src/lib.rs b/crates/cast/src/lib.rs index c66edd80477d..fee1f7d28900 100644 --- a/crates/cast/src/lib.rs +++ b/crates/cast/src/lib.rs @@ -5,7 +5,7 @@ use alloy_rlp::Decodable; use base::{Base, NumberWithBase, ToBase}; use chrono::NaiveDateTime; use ethers_core::{ - types::{transaction::eip2718::TypedTransaction, Chain, *}, + types::{transaction::eip2718::TypedTransaction, *}, utils::{ format_bytes32_string, format_units, keccak256, parse_bytes32_string, parse_units, rlp, Units, @@ -16,6 +16,7 @@ use evm_disassembler::{disassemble_bytes, disassemble_str, format_operations}; use eyre::{Context, ContextCompat, Result}; use foundry_block_explorers::Client; use foundry_common::{abi::encode_function_args, fmt::*, TransactionReceiptWithRevertReason}; +use foundry_config::Chain; use foundry_utils::types::{ToAlloy, ToEthers}; use futures::{future::Either, FutureExt, StreamExt}; use rayon::prelude::*; @@ -75,9 +76,9 @@ where /// /// # Example /// - /// ``` + /// ```ignore /// use cast::{Cast, TxBuilder}; - /// use ethers_core::types::{Address, Chain}; + /// use ethers_core::types::Address; /// use ethers_providers::{Http, Provider}; /// use std::str::FromStr; /// @@ -142,9 +143,9 @@ where /// /// # Example /// - /// ```no_run + /// ```ignore /// use cast::{Cast, TxBuilder}; - /// use ethers_core::types::{Address, Chain}; + /// use ethers_core::types::Address; /// use ethers_providers::{Http, Provider}; /// use std::str::FromStr; /// @@ -203,10 +204,9 @@ where /// /// # Example /// - /// ```no_run - /// use alloy_primitives::{Address, U256}; + /// ```ignore /// use cast::{Cast, TxBuilder}; - /// use ethers_core::types::{Address as eAddress, Chain}; + /// use ethers_core::types::{Address, U256}; /// use ethers_providers::{Http, Provider}; /// use std::str::FromStr; /// @@ -242,7 +242,7 @@ where /// /// # Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_providers::{Http, Provider}; /// @@ -269,10 +269,10 @@ where /// /// # Example /// - /// ```no_run + /// ```ignore /// use alloy_primitives::U256; /// use cast::{Cast, TxBuilder}; - /// use ethers_core::types::{Address, Chain}; + /// use ethers_core::types::Address; /// use ethers_providers::{Http, Provider}; /// use std::str::FromStr; /// @@ -302,7 +302,7 @@ where /// # Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_providers::{Http, Provider}; /// @@ -469,7 +469,7 @@ where /// # Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_core::types::Address; /// use ethers_providers::{Http, Provider}; @@ -494,7 +494,7 @@ where /// # Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_core::types::Address; /// use ethers_providers::{Http, Provider}; @@ -523,7 +523,7 @@ where /// # Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_core::types::Address; /// use ethers_providers::{Http, Provider}; @@ -552,7 +552,7 @@ where /// # Example /// - /// ```no_run + /// ```ignore /// use alloy_primitives::{Address, U256}; /// use cast::Cast; /// use ethers_providers::{Http, Provider}; @@ -575,7 +575,7 @@ where /// # Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_core::types::Address; /// use ethers_providers::{Http, Provider}; @@ -606,7 +606,7 @@ where /// Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_core::types::Address; /// use ethers_providers::{Http, Provider}; @@ -632,7 +632,7 @@ where /// # Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_providers::{Http, Provider}; /// @@ -674,7 +674,7 @@ where /// # Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_providers::{Http, Provider}; /// @@ -736,7 +736,7 @@ where /// /// # Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_providers::{Http, Provider}; /// @@ -762,7 +762,7 @@ where /// /// # Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_core::types::{Address, H256}; /// use ethers_providers::{Http, Provider}; @@ -814,7 +814,7 @@ where /// /// # Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_core::types::{BlockId, BlockNumber}; /// use ethers_providers::{Http, Provider}; @@ -857,7 +857,7 @@ where /// /// # Example /// - /// ```no_run + /// ```ignore /// use cast::Cast; /// use ethers_core::{abi::Address, types::Filter}; /// use ethers_providers::{Provider, Ws}; @@ -1593,7 +1593,7 @@ impl SimpleCast { /// Generates an interface in solidity from either a local file ABI or a verified contract on /// Etherscan. It returns a vector of [`InterfaceSource`] structs that contain the source of the /// interface and their name. - /// ```no_run + /// ```ignore /// use cast::{AbiPath, SimpleCast as Cast}; /// # async fn foo() -> eyre::Result<()> { /// let path = @@ -1810,15 +1810,14 @@ impl SimpleCast { /// /// ``` /// # use cast::SimpleCast as Cast; - /// # use ethers_core::types::Chain; - /// + /// # use foundry_config::NamedChain; /// # async fn foo() -> eyre::Result<()> { /// assert_eq!( /// "/* /// - Bytecode Verification performed was compared on second iteration - /// This file is part of the DAO.....", /// Cast::etherscan_source( - /// Chain::Mainnet, + /// NamedChain::Mainnet.into(), /// "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".to_string(), /// "".to_string() /// ) @@ -1850,7 +1849,7 @@ impl SimpleCast { /// # use std::path::PathBuf; /// # async fn expand() -> eyre::Result<()> { /// Cast::expand_etherscan_source_to_directory( - /// NamedChain::Mainnet, + /// NamedChain::Mainnet.into(), /// "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413".to_string(), /// "".to_string(), /// PathBuf::from("output_dir"), @@ -1876,7 +1875,7 @@ impl SimpleCast { /// /// # Example /// - /// ```no_run + /// ```ignore /// use cast::SimpleCast as Cast; /// /// # async fn foo() -> eyre::Result<()> { diff --git a/crates/cast/src/tx.rs b/crates/cast/src/tx.rs index 9da0c20b2274..67d12e9efcb8 100644 --- a/crates/cast/src/tx.rs +++ b/crates/cast/src/tx.rs @@ -183,15 +183,11 @@ impl<'a, M: Middleware> TxBuilder<'a, M> { // if only calldata is provided, returning a dummy function get_func("x()")? } else { - let chain = self - .chain - .try_into() - .map_err(|_| FunctionSignatureError::UnknownChain(self.chain))?; get_func_etherscan( sig, self.to.ok_or(FunctionSignatureError::MissingToAddress)?, &args, - chain, + self.chain, self.etherscan_api_key.as_ref().ok_or_else(|| { FunctionSignatureError::MissingEtherscan { sig: sig.to_string() } })?, @@ -278,8 +274,9 @@ mod tests { use crate::TxBuilder; use alloy_primitives::{Address, U256}; use async_trait::async_trait; - use ethers_core::types::{transaction::eip2718::TypedTransaction, Chain, NameOrAddress, H160}; + use ethers_core::types::{transaction::eip2718::TypedTransaction, NameOrAddress, H160}; use ethers_providers::{JsonRpcClient, Middleware, ProviderError}; + use foundry_config::NamedChain; use foundry_utils::types::ToEthers; use serde::{de::DeserializeOwned, Serialize}; use std::str::FromStr; @@ -326,7 +323,7 @@ mod tests { async fn builder_new_non_legacy() -> eyre::Result<()> { let provider = MyProvider {}; let builder = - TxBuilder::new(&provider, "a.eth", Some("b.eth"), Chain::Mainnet, false).await?; + TxBuilder::new(&provider, "a.eth", Some("b.eth"), NamedChain::Mainnet, false).await?; let (tx, args) = builder.build(); assert_eq!(*tx.from().unwrap(), Address::from_str(ADDR_1).unwrap().to_ethers()); assert_eq!( @@ -348,7 +345,7 @@ mod tests { async fn builder_new_legacy() -> eyre::Result<()> { let provider = MyProvider {}; let builder = - TxBuilder::new(&provider, "a.eth", Some("b.eth"), Chain::Mainnet, true).await?; + TxBuilder::new(&provider, "a.eth", Some("b.eth"), NamedChain::Mainnet, true).await?; // don't check anything other than the tx type - the rest is covered in the non-legacy case let (tx, _) = builder.build(); match tx { @@ -364,7 +361,9 @@ mod tests { async fn builder_fields() -> eyre::Result<()> { let provider = MyProvider {}; let mut builder = - TxBuilder::new(&provider, "a.eth", Some("b.eth"), Chain::Mainnet, false).await.unwrap(); + TxBuilder::new(&provider, "a.eth", Some("b.eth"), NamedChain::Mainnet, false) + .await + .unwrap(); builder .gas(Some(U256::from(12u32))) .gas_price(Some(U256::from(34u32))) @@ -386,7 +385,9 @@ mod tests { async fn builder_args() -> eyre::Result<()> { let provider = MyProvider {}; let mut builder = - TxBuilder::new(&provider, "a.eth", Some("b.eth"), Chain::Mainnet, false).await.unwrap(); + TxBuilder::new(&provider, "a.eth", Some("b.eth"), NamedChain::Mainnet, false) + .await + .unwrap(); builder.args(Some(("what_a_day(int)", vec![String::from("31337")]))).await?; let (_, function_maybe) = builder.build(); diff --git a/crates/cheatcodes/src/evm.rs b/crates/cheatcodes/src/evm.rs index c1cdcc1b2269..8585c5410ce0 100644 --- a/crates/cheatcodes/src/evm.rs +++ b/crates/cheatcodes/src/evm.rs @@ -82,7 +82,7 @@ impl Cheatcode for loadAllocsCall { ccx.data .db .load_allocs(&allocs, &mut ccx.data.journaled_state) - .map(|_| Vec::default()) + .map(|()| Vec::default()) .map_err(|e| fmt_err!("failed to load allocs: {e}")) } } diff --git a/crates/cli/src/opts/chain.rs b/crates/cli/src/opts/chain.rs index 26d63987d9c8..2762481e08e8 100644 --- a/crates/cli/src/opts/chain.rs +++ b/crates/cli/src/opts/chain.rs @@ -30,7 +30,7 @@ impl TypedValueParser for ChainValueParser { let s = value.to_str().ok_or_else(|| clap::Error::new(clap::error::ErrorKind::InvalidUtf8))?; if let Ok(id) = s.parse() { - Ok(Chain::Id(id)) + Ok(Chain::from_id(id)) } else { // NamedChain::VARIANTS is a subset of all possible variants, since there are aliases: // mumbai instead of polygon-mumbai etc @@ -39,7 +39,7 @@ impl TypedValueParser for ChainValueParser { // the error to the user s.parse() .map_err(|_| self.inner.parse_ref(cmd, arg, value).unwrap_err()) - .map(Chain::Named) + .map(Chain::from_named) } } } diff --git a/crates/cli/src/opts/ethereum.rs b/crates/cli/src/opts/ethereum.rs index 78504e584800..17319952b01a 100644 --- a/crates/cli/src/opts/ethereum.rs +++ b/crates/cli/src/opts/ethereum.rs @@ -85,12 +85,12 @@ impl RpcOpts { #[derive(Clone, Debug, Default, Parser, Serialize)] pub struct EtherscanOpts { - /// The Etherscan (or equivalent) API key + /// The Etherscan (or equivalent) API key. #[clap(short = 'e', long = "etherscan-api-key", alias = "api-key", env = "ETHERSCAN_API_KEY")] #[serde(rename = "etherscan_api_key", skip_serializing_if = "Option::is_none")] pub key: Option, - /// The chain name or EIP-155 chain ID + /// The chain name or EIP-155 chain ID. #[clap( short, long, diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index 466c3908d7bc..309e4d295606 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -163,8 +163,8 @@ macro_rules! update_progress { } /// True if the network calculates gas costs differently. -pub fn has_different_gas_calc(chain: u64) -> bool { - if let Chain::Named(chain) = Chain::from(chain) { +pub fn has_different_gas_calc(chain_id: u64) -> bool { + if let Some(chain) = Chain::from(chain_id).named() { return matches!( chain, NamedChain::Arbitrum | @@ -177,8 +177,8 @@ pub fn has_different_gas_calc(chain: u64) -> bool { } /// True if it supports broadcasting in batches. -pub fn has_batch_support(chain: u64) -> bool { - if let Chain::Named(chain) = Chain::from(chain) { +pub fn has_batch_support(chain_id: u64) -> bool { + if let Some(chain) = Chain::from(chain_id).named() { return !matches!( chain, NamedChain::Arbitrum | @@ -368,7 +368,7 @@ impl TryFrom for TraceResult { pub async fn handle_traces( mut result: TraceResult, config: &Config, - chain: Option, + chain: Option, labels: Vec, verbose: bool, debug: bool, diff --git a/crates/cli/src/utils/mod.rs b/crates/cli/src/utils/mod.rs index f27054b4839e..124df64537cc 100644 --- a/crates/cli/src/utils/mod.rs +++ b/crates/cli/src/utils/mod.rs @@ -91,7 +91,7 @@ pub fn get_provider_builder(config: &Config) -> Result Ok(chain), - None => Ok(Chain::Id(provider.get_chainid().await?.as_u64())), + None => Ok(Chain::from_id(provider.get_chainid().await?.as_u64())), } } diff --git a/crates/common/src/abi.rs b/crates/common/src/abi.rs index 1961a010abcf..5a166a20f09e 100644 --- a/crates/common/src/abi.rs +++ b/crates/common/src/abi.rs @@ -5,7 +5,7 @@ use alloy_json_abi::{AbiItem, Event, Function}; use alloy_primitives::{hex, Address, Log}; use eyre::{ContextCompat, Result}; use foundry_block_explorers::{contract::ContractMetadata, errors::EtherscanError, Client}; -use foundry_config::NamedChain; +use foundry_config::Chain; use std::{future::Future, pin::Pin}; /// Given a function and a vector of string arguments, it proceeds to convert the args to alloy @@ -132,7 +132,7 @@ pub async fn get_func_etherscan( function_name: &str, contract: Address, args: &[String], - chain: NamedChain, + chain: Chain, etherscan_api_key: &str, ) -> Result { let client = Client::new(chain, etherscan_api_key)?; diff --git a/crates/common/src/evm.rs b/crates/common/src/evm.rs index 74ab6a2ddc7c..b721d6aafd91 100644 --- a/crates/common/src/evm.rs +++ b/crates/common/src/evm.rs @@ -192,10 +192,10 @@ pub struct EnvArgs { #[serde(skip_serializing_if = "Option::is_none")] pub code_size_limit: Option, - /// The chain ID. - #[clap(long, alias = "chain", value_name = "CHAIN_ID")] - #[serde(skip_serializing_if = "Option::is_none")] - pub chain_id: Option, + /// The chain name or EIP-155 chain ID. + #[clap(long, visible_alias = "chain-id", value_name = "CHAIN")] + #[serde(rename = "chain_id", skip_serializing_if = "Option::is_none", serialize_with = "id")] + pub chain: Option, /// The gas price. #[clap(long, value_name = "GAS_PRICE")] @@ -255,6 +255,18 @@ impl EvmArgs { } } +/// We have to serialize chain IDs and not names because when extracting an EVM `Env`, it expects +/// `chain_id` to be `u64`. +#[allow(clippy::trivially_copy_pass_by_ref)] +fn id(chain: &Option, s: S) -> Result { + if let Some(chain) = chain { + s.serialize_u64(chain.id()) + } else { + // skip_serializing_if = "Option::is_none" should prevent this branch from being taken + unreachable!() + } +} + #[cfg(test)] mod tests { use super::*; @@ -263,20 +275,20 @@ mod tests { #[test] fn can_parse_chain_id() { let args = EvmArgs { - env: EnvArgs { chain_id: Some(NamedChain::Mainnet.into()), ..Default::default() }, + env: EnvArgs { chain: Some(NamedChain::Mainnet.into()), ..Default::default() }, ..Default::default() }; let config = Config::from_provider(Config::figment().merge(args)); - assert_eq!(config.chain_id, Some(NamedChain::Mainnet.into())); + assert_eq!(config.chain, Some(NamedChain::Mainnet.into())); let env = EnvArgs::parse_from(["foundry-common", "--chain-id", "goerli"]); - assert_eq!(env.chain_id, Some(NamedChain::Goerli.into())); + assert_eq!(env.chain, Some(NamedChain::Goerli.into())); } #[test] fn test_memory_limit() { let args = EvmArgs { - env: EnvArgs { chain_id: Some(NamedChain::Mainnet.into()), ..Default::default() }, + env: EnvArgs { chain: Some(NamedChain::Mainnet.into()), ..Default::default() }, ..Default::default() }; let config = Config::from_provider(Config::figment().merge(args)); @@ -285,4 +297,16 @@ mod tests { let env = EnvArgs::parse_from(["foundry-common", "--memory-limit", "100"]); assert_eq!(env.memory_limit, Some(100)); } + + #[test] + fn test_chain_id() { + let env = EnvArgs::parse_from(["foundry-common", "--chain-id", "1"]); + assert_eq!(env.chain, Some(Chain::mainnet())); + + let env = EnvArgs::parse_from(["foundry-common", "--chain-id", "mainnet"]); + assert_eq!(env.chain, Some(Chain::mainnet())); + let args = EvmArgs { env, ..Default::default() }; + let config = Config::from_provider(Config::figment().merge(args)); + assert_eq!(config.chain, Some(Chain::mainnet())); + } } diff --git a/crates/common/src/provider.rs b/crates/common/src/provider.rs index e4cc8bbd695b..d437f92451a3 100644 --- a/crates/common/src/provider.rs +++ b/crates/common/src/provider.rs @@ -204,7 +204,7 @@ impl ProviderBuilder { pub async fn connect(self) -> Result { let mut provider = self.build()?; if let Some(blocktime) = provider.get_chainid().await.ok().and_then(|id| { - NamedChain::try_from(id).ok().and_then(|chain| chain.average_blocktime_hint()) + NamedChain::try_from(id.as_u64()).ok().and_then(|chain| chain.average_blocktime_hint()) }) { provider = provider.interval(blocktime / 2); } @@ -274,6 +274,12 @@ where // handle chains that deviate from `eth_feeHistory` and have their own oracle match chain { NamedChain::Polygon | NamedChain::PolygonMumbai => { + // TODO: phase this out somehow + let chain = match chain { + NamedChain::Polygon => ethers_core::types::Chain::Polygon, + NamedChain::PolygonMumbai => ethers_core::types::Chain::PolygonMumbai, + _ => unreachable!(), + }; let estimator = Polygon::new(chain)?.category(GasCategory::Standard); return Ok(estimator.estimate_eip1559_fees().await?) } diff --git a/crates/config/Cargo.toml b/crates/config/Cargo.toml index 7b05880d38db..2a29c112c906 100644 --- a/crates/config/Cargo.toml +++ b/crates/config/Cargo.toml @@ -14,11 +14,10 @@ repository.workspace = true foundry-block-explorers = { workspace = true, features = ["foundry-compilers"] } foundry-compilers = { workspace = true, features = ["async", "svm-solc"] } -alloy-primitives = { workspace = true, features = ["std", "serde"] } +alloy-chains = { workspace = true, features = ["serde"] } +alloy-primitives = { workspace = true, features = ["serde"] } revm-primitives = { workspace = true, default-features = false, features = ["std"] } -ethers-core.workspace = true - dirs-next = "2" eyre.workspace = true figment = { version = "0.10", features = ["toml", "env"] } diff --git a/crates/config/src/cache.rs b/crates/config/src/cache.rs index 1355a3c54d43..bebb3e5284cc 100644 --- a/crates/config/src/cache.rs +++ b/crates/config/src/cache.rs @@ -1,6 +1,6 @@ //! Support types for configuring storage caching -use crate::chain::Chain; +use crate::Chain; use number_prefix::NumberPrefix; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::{fmt, fmt::Formatter, str::FromStr}; @@ -230,7 +230,6 @@ pub struct ChainCache { #[cfg(test)] mod tests { use super::*; - use crate::chain::NamedChain; use pretty_assertions::assert_str_eq; #[test] @@ -255,9 +254,9 @@ mod tests { w.rpc_storage_caching, StorageCachingConfig { chains: CachedChains::Chains(vec![ - Chain::Named(NamedChain::Mainnet), - Chain::Named(NamedChain::Optimism), - Chain::Id(999999) + Chain::mainnet(), + Chain::optimism_mainnet(), + Chain::from_id(999999) ]), endpoints: CachedEndpoints::All } diff --git a/crates/config/src/chain.rs b/crates/config/src/chain.rs deleted file mode 100644 index b7ce1ba0ed40..000000000000 --- a/crates/config/src/chain.rs +++ /dev/null @@ -1,157 +0,0 @@ -use crate::U256; -use alloy_primitives::U64; -use eyre::Result; -use serde::{Deserialize, Deserializer, Serialize}; -use std::{fmt, str::FromStr}; - -pub use ethers_core::types::Chain as NamedChain; - -/// Either a named or chain id or the actual id value -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)] -#[serde(untagged)] -pub enum Chain { - /// Contains a known chain - #[serde(serialize_with = "super::from_str_lowercase::serialize")] - Named(NamedChain), - /// Contains the id of a chain - Id(u64), -} - -impl Chain { - /// The id of the chain. - pub const fn id(&self) -> u64 { - match self { - Chain::Named(chain) => *chain as u64, - Chain::Id(id) => *id, - } - } - - /// Returns the wrapped named chain or tries converting the ID into one. - pub fn named(&self) -> Result { - match self { - Self::Named(chain) => Ok(*chain), - Self::Id(id) => { - NamedChain::try_from(*id).map_err(|_| eyre::eyre!("Unsupported chain: {id}")) - } - } - } - - /// Helper function for checking if a chainid corresponds to a legacy chainid - /// without eip1559 - pub fn is_legacy(&self) -> bool { - self.named().map_or(false, |c| c.is_legacy()) - } - - /// Returns the corresponding etherscan URLs - pub fn etherscan_urls(&self) -> Option<(&'static str, &'static str)> { - self.named().ok().and_then(|c| c.etherscan_urls()) - } -} - -impl fmt::Display for Chain { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Chain::Named(chain) => chain.fmt(f), - Chain::Id(id) => { - if let Ok(chain) = NamedChain::try_from(*id) { - chain.fmt(f) - } else { - id.fmt(f) - } - } - } - } -} - -impl From for Chain { - fn from(id: NamedChain) -> Self { - Chain::Named(id) - } -} - -impl From for Chain { - fn from(id: u64) -> Self { - NamedChain::try_from(id).map(Chain::Named).unwrap_or_else(|_| Chain::Id(id)) - } -} - -impl From for Chain { - fn from(id: U256) -> Self { - id.to::().into() - } -} - -impl From for u64 { - fn from(c: Chain) -> Self { - match c { - Chain::Named(c) => c as u64, - Chain::Id(id) => id, - } - } -} - -impl From for U64 { - fn from(c: Chain) -> Self { - U64::from(u64::from(c)) - } -} - -impl From for U256 { - fn from(c: Chain) -> Self { - U256::from(u64::from(c)) - } -} - -impl TryFrom for NamedChain { - type Error = >::Error; - - fn try_from(chain: Chain) -> Result { - match chain { - Chain::Named(chain) => Ok(chain), - Chain::Id(id) => id.try_into(), - } - } -} - -impl FromStr for Chain { - type Err = String; - - fn from_str(s: &str) -> Result { - if let Ok(chain) = NamedChain::from_str(s) { - Ok(Chain::Named(chain)) - } else { - s.parse::() - .map(Chain::Id) - .map_err(|_| format!("Expected known chain or integer, found: {s}")) - } - } -} - -impl<'de> Deserialize<'de> for Chain { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - #[derive(Deserialize)] - #[serde(untagged)] - enum ChainId { - Named(String), - Id(u64), - } - - match ChainId::deserialize(deserializer)? { - ChainId::Named(s) => { - s.to_lowercase().parse().map(Chain::Named).map_err(serde::de::Error::custom) - } - ChainId::Id(id) => { - Ok(NamedChain::try_from(id).map(Chain::Named).unwrap_or_else(|_| Chain::Id(id))) - } - } - } -} - -impl Default for Chain { - fn default() -> Self { - NamedChain::Mainnet.into() - } -} diff --git a/crates/config/src/etherscan.rs b/crates/config/src/etherscan.rs index 36e1dbba976e..01e0f3b92450 100644 --- a/crates/config/src/etherscan.rs +++ b/crates/config/src/etherscan.rs @@ -140,7 +140,7 @@ impl DerefMut for ResolvedEtherscanConfigs { /// Represents all info required to create an etherscan client #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct EtherscanConfig { - /// Chain name/id that can be used to derive the api url + /// The chain name or EIP-155 chain ID used to derive the API URL. #[serde(default, skip_serializing_if = "Option::is_none")] pub chain: Option, /// Etherscan API URL @@ -204,15 +204,15 @@ impl EtherscanConfig { /// Contains required url + api key to set up an etherscan client #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct ResolvedEtherscanConfig { - /// Etherscan API URL + /// Etherscan API URL. #[serde(rename = "url")] pub api_url: String, - /// Optional browser url + /// Optional browser URL. #[serde(default, skip_serializing_if = "Option::is_none")] pub browser_url: Option, - /// Resolved api key + /// The resolved API key. pub key: String, - /// The chain if set + /// The chain name or EIP-155 chain ID. #[serde(default, skip_serializing_if = "Option::is_none")] pub chain: Option, } diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index afe750e9bbbb..cb1d76d9fc03 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -13,12 +13,11 @@ use figment::{ value::{Dict, Map, Value}, Error, Figment, Metadata, Profile, Provider, }; -pub use foundry_compilers::{self, artifacts::OptimizerDetails}; use foundry_compilers::{ artifacts::{ output_selection::ContractOutputSelection, serde_helpers, BytecodeHash, DebuggingSettings, - Libraries, ModelCheckerSettings, ModelCheckerTarget, Optimizer, RevertStrings, Settings, - SettingsMetadata, Severity, + Libraries, ModelCheckerSettings, ModelCheckerTarget, Optimizer, OptimizerDetails, + RevertStrings, Settings, SettingsMetadata, Severity, }, cache::SOLIDITY_FILES_CACHE_FILENAME, error::SolcError, @@ -28,6 +27,7 @@ use foundry_compilers::{ use inflector::Inflector; use once_cell::sync::Lazy; use regex::Regex; +use revm_primitives::SpecId; use semver::Version; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::{ @@ -55,9 +55,6 @@ pub use resolve::UnresolvedEnvVarError; pub mod cache; use cache::{Cache, ChainCache}; -mod chain; -pub use chain::{Chain, NamedChain}; - pub mod fmt; pub use fmt::FormatterConfig; @@ -77,8 +74,8 @@ pub use warning::*; pub mod fix; // reexport so cli types can implement `figment::Provider` to easily merge compiler arguments +pub use alloy_chains::{Chain, NamedChain}; pub use figment; -use revm_primitives::SpecId; /// config providers pub mod providers; @@ -252,8 +249,9 @@ pub struct Config { pub block_number: u64, /// pins the block number for the state fork pub fork_block_number: Option, - /// The chain id to use - pub chain_id: Option, + /// The chain name or EIP-155 chain ID. + #[serde(rename = "chain_id", alias = "chain")] + pub chain: Option, /// Block gas limit pub gas_limit: GasLimit, /// EIP-170: Contract code size limit in bytes. Useful to increase this because of tests. @@ -895,7 +893,7 @@ impl Config { // we treat the `etherscan_api_key` as actual API key // if no chain provided, we assume mainnet - let chain = self.chain_id.unwrap_or(Chain::Named(NamedChain::Mainnet)); + let chain = self.chain.unwrap_or(Chain::mainnet()); let api_key = self.etherscan_api_key.as_ref()?; ResolvedEtherscanConfig::create(api_key, chain).map(Ok) } @@ -908,9 +906,8 @@ impl Config { /// over the chain's entry in the table. pub fn get_etherscan_config_with_chain( &self, - chain: Option>, + chain: Option, ) -> Result, EtherscanConfigError> { - let chain = chain.map(Into::into); if let Some(maybe_alias) = self.etherscan_api_key.as_ref().or(self.eth_rpc_url.as_ref()) { if self.etherscan.contains_key(maybe_alias) { return self.etherscan.clone().resolved().remove(maybe_alias).transpose() @@ -938,7 +935,7 @@ impl Config { // etherscan fallback via API key if let Some(key) = self.etherscan_api_key.as_ref() { - let chain = chain.or(self.chain_id).unwrap_or_default(); + let chain = chain.or(self.chain).unwrap_or_default(); return Ok(ResolvedEtherscanConfig::create(key, chain)) } @@ -946,7 +943,7 @@ impl Config { } /// Helper function to just get the API key - pub fn get_etherscan_api_key(&self, chain: Option>) -> Option { + pub fn get_etherscan_api_key(&self, chain: Option) -> Option { self.get_etherscan_config_with_chain(chain).ok().flatten().map(|c| c.key) } @@ -1132,7 +1129,7 @@ impl Config { /// Returns the default config that uses dapptools style paths pub fn dapptools() -> Self { Config { - chain_id: Some(Chain::Id(99)), + chain: Some(Chain::from_id(99)), block_timestamp: 0, block_number: 0, ..Config::default() @@ -1788,7 +1785,7 @@ impl Default for Config { initial_balance: U256::from(0xffffffffffffffffffffffffu128), block_number: 1, fork_block_number: None, - chain_id: None, + chain: None, gas_limit: i64::MAX.into(), code_size_limit: None, gas_price: None, @@ -2922,16 +2919,15 @@ mod tests { )?; let config = Config::load(); - assert!(config.get_etherscan_config_with_chain(None::).unwrap().is_none()); assert!(config - .get_etherscan_config_with_chain(Some(NamedChain::BinanceSmartChain)) + .get_etherscan_config_with_chain(Some(NamedChain::BinanceSmartChain.into())) .is_err()); std::env::set_var(env_key, env_value); assert_eq!( config - .get_etherscan_config_with_chain(Some(NamedChain::BinanceSmartChain)) + .get_etherscan_config_with_chain(Some(NamedChain::BinanceSmartChain.into())) .unwrap() .unwrap() .key, @@ -2943,7 +2939,7 @@ mod tests { assert_eq!( with_key - .get_etherscan_config_with_chain(Some(NamedChain::BinanceSmartChain)) + .get_etherscan_config_with_chain(Some(NamedChain::BinanceSmartChain.into())) .unwrap() .unwrap() .key, @@ -3159,12 +3155,12 @@ mod tests { let mut config = Config::load(); - let optimism = config.get_etherscan_api_key(Some(NamedChain::Optimism)); + let optimism = config.get_etherscan_api_key(Some(NamedChain::Optimism.into())); assert_eq!(optimism, Some("https://etherscan-optimism.com/".to_string())); config.etherscan_api_key = Some("mumbai".to_string()); - let mumbai = config.get_etherscan_api_key(Some(NamedChain::PolygonMumbai)); + let mumbai = config.get_etherscan_api_key(Some(NamedChain::PolygonMumbai.into())); assert_eq!(mumbai, Some("https://etherscan-mumbai.com/".to_string())); Ok(()) @@ -3187,7 +3183,7 @@ mod tests { let config = Config::load(); let mumbai = config - .get_etherscan_config_with_chain(Some(NamedChain::PolygonMumbai)) + .get_etherscan_config_with_chain(Some(NamedChain::PolygonMumbai.into())) .unwrap() .unwrap(); assert_eq!(mumbai.key, "https://etherscan-mumbai.com/".to_string()); @@ -3212,7 +3208,7 @@ mod tests { let config = Config::load(); let mumbai = config - .get_etherscan_config_with_chain(Some(NamedChain::PolygonMumbai)) + .get_etherscan_config_with_chain(Some(NamedChain::PolygonMumbai.into())) .unwrap() .unwrap(); assert_eq!(mumbai.key, "https://etherscan-mumbai.com/".to_string()); @@ -3241,8 +3237,7 @@ mod tests { let config = Config::load(); - let mumbai = - config.get_etherscan_config_with_chain(Option::::None).unwrap().unwrap(); + let mumbai = config.get_etherscan_config_with_chain(None).unwrap().unwrap(); assert_eq!(mumbai.key, "https://etherscan-mumbai.com/".to_string()); let mumbai_rpc = config.get_rpc_url().unwrap().unwrap(); @@ -3294,9 +3289,9 @@ mod tests { via_ir: true, rpc_storage_caching: StorageCachingConfig { chains: CachedChains::Chains(vec![ - Chain::Named(NamedChain::Mainnet), - Chain::Named(NamedChain::Optimism), - Chain::Id(999999) + Chain::mainnet(), + Chain::optimism_mainnet(), + Chain::from_id(999999) ]), endpoints: CachedEndpoints::All }, diff --git a/crates/evm/core/src/opts.rs b/crates/evm/core/src/opts.rs index 09f33d0a1fe2..bc364bc51b45 100644 --- a/crates/evm/core/src/opts.rs +++ b/crates/evm/core/src/opts.rs @@ -1,12 +1,12 @@ use super::fork::environment; use crate::fork::CreateFork; use alloy_primitives::{Address, B256, U256}; -use ethers_core::types::{Block, Chain, TxHash}; +use ethers_core::types::{Block, TxHash}; use ethers_providers::{Middleware, Provider}; use eyre::WrapErr; use foundry_common::{self, ProviderBuilder, RpcUrl, ALCHEMY_FREE_TIER_CUPS}; use foundry_compilers::utils::RuntimeOrHandle; -use foundry_config::Config; +use foundry_config::{Chain, Config}; use revm::primitives::{BlockEnv, CfgEnv, SpecId, TxEnv}; use serde::{Deserialize, Deserializer, Serialize}; @@ -156,7 +156,7 @@ impl EvmOpts { if let Some(id) = self.env.chain_id { return id } - self.get_remote_chain_id().map_or(Chain::Mainnet as u64, |id| id as u64) + self.get_remote_chain_id().unwrap_or(Chain::mainnet()).id() } /// Returns the available compute units per second, which will be @@ -178,14 +178,14 @@ impl EvmOpts { if let Some(ref url) = self.fork_url { if url.contains("mainnet") { trace!(?url, "auto detected mainnet chain"); - return Some(Chain::Mainnet) + return Some(Chain::mainnet()); } trace!(?url, "retrieving chain via eth_chainId"); let provider = Provider::try_from(url.as_str()) .unwrap_or_else(|_| panic!("Failed to establish provider to {url}")); if let Ok(id) = RuntimeOrHandle::new().block_on(provider.get_chainid()) { - return Chain::try_from(id.as_u64()).ok() + return Some(Chain::from(id.as_u64())); } } @@ -195,11 +195,11 @@ impl EvmOpts { #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct Env { - /// the block gas limit + /// The block gas limit. #[serde(deserialize_with = "string_or_number")] pub gas_limit: u64, - /// the chainid opcode value + /// The `CHAINID` opcode value. pub chain_id: Option, /// the tx.gasprice value during EVM execution diff --git a/crates/evm/evm/src/executors/tracing.rs b/crates/evm/evm/src/executors/tracing.rs index bf94679330c2..19db5fc57755 100644 --- a/crates/evm/evm/src/executors/tracing.rs +++ b/crates/evm/evm/src/executors/tracing.rs @@ -1,6 +1,6 @@ use crate::executors::{Executor, ExecutorBuilder}; use foundry_compilers::EvmVersion; -use foundry_config::{utils::evm_spec_id, Config, NamedChain}; +use foundry_config::{utils::evm_spec_id, Chain, Config}; use foundry_evm_core::{backend::Backend, fork::CreateFork, opts::EvmOpts}; use revm::primitives::Env; use std::ops::{Deref, DerefMut}; @@ -32,7 +32,7 @@ impl TracingExecutor { pub async fn get_fork_material( config: &Config, mut evm_opts: EvmOpts, - ) -> eyre::Result<(Env, Option, Option)> { + ) -> eyre::Result<(Env, Option, Option)> { evm_opts.fork_url = Some(config.get_rpc_url_or_localhost_http()?.into_owned()); evm_opts.fork_block_number = config.fork_block_number; diff --git a/crates/evm/traces/src/identifier/etherscan.rs b/crates/evm/traces/src/identifier/etherscan.rs index 9a92b9ac7ba1..e6e566cc8a4d 100644 --- a/crates/evm/traces/src/identifier/etherscan.rs +++ b/crates/evm/traces/src/identifier/etherscan.rs @@ -40,7 +40,7 @@ pub struct EtherscanIdentifier { impl EtherscanIdentifier { /// Creates a new Etherscan identifier with the given client - pub fn new(config: &Config, chain: Option>) -> eyre::Result { + pub fn new(config: &Config, chain: Option) -> eyre::Result { if let Some(config) = config.get_etherscan_config_with_chain(chain)? { trace!(target: "etherscanidentifier", chain=?config.chain, url=?config.api_url, "using etherscan identifier"); Ok(Self { diff --git a/crates/forge/bin/cmd/script/broadcast.rs b/crates/forge/bin/cmd/script/broadcast.rs index 72d6be2ae5f9..c57e1ec383bc 100644 --- a/crates/forge/bin/cmd/script/broadcast.rs +++ b/crates/forge/bin/cmd/script/broadcast.rs @@ -448,7 +448,7 @@ impl ScriptArgs { // Config is used to initialize the sequence chain, so we need to change when handling a new // sequence. This makes sure we don't lose the original value. - let original_config_chain = config.chain_id; + let original_config_chain = config.chain; // Peeking is used to check if the next rpc url is different. If so, it creates a // [`ScriptSequence`] from all the collected transactions up to this point. @@ -510,7 +510,7 @@ impl ScriptArgs { } } - config.chain_id = Some(provider_info.chain.into()); + config.chain = Some(provider_info.chain.into()); let sequence = ScriptSequence::new( new_sequence, returns.clone(), @@ -527,7 +527,7 @@ impl ScriptArgs { } // Restore previous config chain. - config.chain_id = original_config_chain; + config.chain = original_config_chain; if !self.skip_simulation { // Present gas information on a per RPC basis. diff --git a/crates/forge/bin/cmd/script/mod.rs b/crates/forge/bin/cmd/script/mod.rs index f7a6fd47ebb2..2f39d8fda27d 100644 --- a/crates/forge/bin/cmd/script/mod.rs +++ b/crates/forge/bin/cmd/script/mod.rs @@ -854,7 +854,7 @@ mod tests { ]); let config = args.load_config(); - let mumbai = config.get_etherscan_api_key(Some(NamedChain::PolygonMumbai)); + let mumbai = config.get_etherscan_api_key(Some(NamedChain::PolygonMumbai.into())); assert_eq!(mumbai, Some("https://etherscan-mumbai.com/".to_string())); } @@ -933,9 +933,9 @@ mod tests { evm_opts.fork_url, Some("https://polygon-mumbai.g.alchemy.com/v2/123456".to_string()) ); - let etherscan = config.get_etherscan_api_key(Some(80001u64)); + let etherscan = config.get_etherscan_api_key(Some(80001u64.into())); assert_eq!(etherscan, Some("polygonkey".to_string())); - let etherscan = config.get_etherscan_api_key(Option::::None); + let etherscan = config.get_etherscan_api_key(None); assert_eq!(etherscan, Some("polygonkey".to_string())); } @@ -975,9 +975,9 @@ mod tests { evm_opts.fork_url, Some("https://polygon-mumbai.g.alchemy.com/v2/123456".to_string()) ); - let etherscan = config.get_etherscan_api_key(Some(80001u64)); + let etherscan = config.get_etherscan_api_key(Some(80001u64.into())); assert_eq!(etherscan, Some("polygonkey".to_string())); - let etherscan = config.get_etherscan_api_key(Option::::None); + let etherscan = config.get_etherscan_api_key(None); assert_eq!(etherscan, Some("polygonkey".to_string())); } diff --git a/crates/forge/bin/cmd/script/providers.rs b/crates/forge/bin/cmd/script/providers.rs index d2f6bb17a76d..ab417ca156bb 100644 --- a/crates/forge/bin/cmd/script/providers.rs +++ b/crates/forge/bin/cmd/script/providers.rs @@ -62,7 +62,7 @@ impl ProviderInfo { let provider = Arc::new(get_http_provider(rpc)); let chain = provider.get_chainid().await?.as_u64(); - if let Chain::Named(chain) = Chain::from(chain) { + if let Some(chain) = Chain::from(chain).named() { is_legacy |= chain.is_legacy(); }; diff --git a/crates/forge/bin/cmd/script/sequence.rs b/crates/forge/bin/cmd/script/sequence.rs index 0b612d8fe73b..4d6239dc92ab 100644 --- a/crates/forge/bin/cmd/script/sequence.rs +++ b/crates/forge/bin/cmd/script/sequence.rs @@ -80,7 +80,7 @@ impl ScriptSequence { broadcasted: bool, is_multi: bool, ) -> Result { - let chain = config.chain_id.unwrap_or_default().id(); + let chain = config.chain.unwrap_or_default().id(); let (path, sensitive_path) = ScriptSequence::get_paths( &config.broadcast, diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index 3fc373eafeab..1ad5488701ac 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -544,9 +544,7 @@ fn short_test_result(name: &str, result: &TestResult) { println!("{result} {name} {}", result.kind.report()); } -/** - * Formats the aggregated summary of all test suites into a string (for printing) - */ +/// Formats the aggregated summary of all test suites into a string (for printing). fn format_aggregated_summary( num_test_suites: usize, total_passed: usize, @@ -786,58 +784,38 @@ async fn test( #[cfg(test)] mod tests { use super::*; + use foundry_config::Chain; - // Sanity test that unknown args are rejected #[test] - fn test_verbosity() { - #[derive(Debug, Parser)] - pub struct VerbosityArgs { - #[clap(long, short, action = clap::ArgAction::Count)] - verbosity: u8, - } - let res = VerbosityArgs::try_parse_from(["foundry-cli", "-vw"]); - assert!(res.is_err()); - - let res = VerbosityArgs::try_parse_from(["foundry-cli", "-vv"]); - assert!(res.is_ok()); - } - - #[test] - fn test_verbosity_multi_short() { - #[derive(Debug, Parser)] - pub struct VerbosityArgs { - #[clap(long, short)] - verbosity: bool, - #[clap( - long, - short, - num_args(0..), - value_name = "PATH", - )] - watch: Option>, - } - // this is supported by clap - let res = VerbosityArgs::try_parse_from(["foundry-cli", "-vw"]); - assert!(res.is_ok()) - } - - #[test] - fn test_watch_parse() { + fn watch_parse() { let args: TestArgs = TestArgs::parse_from(["foundry-cli", "-vw"]); assert!(args.watch.watch.is_some()); } #[test] - fn test_fuzz_seed() { + fn fuzz_seed() { let args: TestArgs = TestArgs::parse_from(["foundry-cli", "--fuzz-seed", "0x10"]); assert!(args.fuzz_seed.is_some()); } // #[test] - fn test_5913() { + fn issue_5913() { let args: TestArgs = TestArgs::parse_from(["foundry-cli", "-vvv", "--gas-report", "--fuzz-seed", "0x10"]); assert!(args.fuzz_seed.is_some()); } + + #[test] + fn extract_chain() { + let test = |arg: &str, expected: Chain| { + let args = TestArgs::parse_from(["foundry-cli", arg]); + assert_eq!(args.evm_opts.env.chain, Some(expected)); + let (config, evm_opts) = args.load_config_and_evm_opts().unwrap(); + assert_eq!(config.chain, Some(expected)); + assert_eq!(evm_opts.env.chain_id, Some(expected.id())); + }; + test("--chain-id=1", Chain::mainnet()); + test("--chain-id=42", Chain::from_id(42)); + } } diff --git a/crates/forge/bin/cmd/verify/etherscan/mod.rs b/crates/forge/bin/cmd/verify/etherscan/mod.rs index 533e451e4e9b..2bd045f241bf 100644 --- a/crates/forge/bin/cmd/verify/etherscan/mod.rs +++ b/crates/forge/bin/cmd/verify/etherscan/mod.rs @@ -269,7 +269,7 @@ impl EtherscanVerificationProvider { let base_url = etherscan_config .as_ref() .and_then(|c| c.browser_url.as_deref()) - .or_else(|| chain.etherscan_urls().map(|urls| urls.1)); + .or_else(|| chain.etherscan_urls().map(|(_, url)| url)); let etherscan_key = etherscan_key.or_else(|| etherscan_config.as_ref().map(|c| c.key.as_str())); @@ -279,7 +279,7 @@ impl EtherscanVerificationProvider { builder = if let Some(api_url) = api_url { builder.with_api_url(api_url)?.with_url(base_url.unwrap_or(api_url))? } else { - builder.chain(chain.to_owned().try_into()?)? + builder.chain(chain)? }; builder diff --git a/crates/forge/bin/cmd/verify/mod.rs b/crates/forge/bin/cmd/verify/mod.rs index adf9819fa4ba..5544c12f0508 100644 --- a/crates/forge/bin/cmd/verify/mod.rs +++ b/crates/forge/bin/cmd/verify/mod.rs @@ -128,7 +128,7 @@ impl VerifyArgs { /// Run the verify command to submit the contract's source code for verification on etherscan pub async fn run(mut self) -> Result<()> { let config = self.load_config_emit_warnings(); - let chain = config.chain_id.unwrap_or_default(); + let chain = config.chain.unwrap_or_default(); self.etherscan.chain = Some(chain); self.etherscan.key = config.get_etherscan_config_with_chain(Some(chain))?.map(|c| c.key); diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index a19accee103f..a9eee34f3a52 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -2,9 +2,7 @@ use crate::constants::*; use foundry_compilers::{artifacts::Metadata, remappings::Remapping, ConfigurableContractArtifact}; -use foundry_config::{ - parse_with_profile, BasicConfig, Chain, Config, NamedChain, SolidityErrorCode, -}; +use foundry_config::{parse_with_profile, BasicConfig, Chain, Config, SolidityErrorCode}; use foundry_test_utils::{ foundry_compilers::PathStyle, util::{pretty_err, read_string, OutputExt, TestCommand}, @@ -35,7 +33,7 @@ forgetest!( #[ignore] can_cache_ls, |_prj, cmd| { - let chain = Chain::Named(NamedChain::Mainnet); + let chain = Chain::mainnet(); let block1 = 100; let block2 = 101; @@ -132,7 +130,7 @@ forgetest!( #[ignore] can_cache_clean_chain, |_prj, cmd| { - let chain = Chain::Named(NamedChain::Mainnet); + let chain = Chain::mainnet(); let cache_dir = Config::foundry_chain_cache_dir(chain).unwrap(); let etherscan_cache_dir = Config::foundry_etherscan_chain_cache_dir(chain).unwrap(); let path = cache_dir.as_path(); @@ -155,7 +153,7 @@ forgetest!( #[ignore] can_cache_clean_blocks, |_prj, cmd| { - let chain = Chain::Named(NamedChain::Mainnet); + let chain = Chain::mainnet(); let block1 = 100; let block2 = 101; let block3 = 102; @@ -189,9 +187,9 @@ forgetest!( #[ignore] can_cache_clean_chain_etherscan, |_prj, cmd| { - let cache_dir = Config::foundry_chain_cache_dir(Chain::Named(NamedChain::Mainnet)).unwrap(); + let cache_dir = Config::foundry_chain_cache_dir(Chain::mainnet()).unwrap(); let etherscan_cache_dir = - Config::foundry_etherscan_chain_cache_dir(Chain::Named(NamedChain::Mainnet)).unwrap(); + Config::foundry_etherscan_chain_cache_dir(Chain::mainnet()).unwrap(); let path = cache_dir.as_path(); let etherscan_path = etherscan_cache_dir.as_path(); fs::create_dir_all(path).unwrap(); diff --git a/crates/forge/tests/cli/config.rs b/crates/forge/tests/cli/config.rs index 96140c525585..74aa16e45fc6 100644 --- a/crates/forge/tests/cli/config.rs +++ b/crates/forge/tests/cli/config.rs @@ -2,10 +2,10 @@ use alloy_primitives::{Address, B256, U256}; use foundry_cli::utils as forge_utils; -use foundry_compilers::artifacts::{RevertStrings, YulDetails}; +use foundry_compilers::artifacts::{OptimizerDetails, RevertStrings, YulDetails}; use foundry_config::{ cache::{CachedChains, CachedEndpoints, StorageCachingConfig}, - Config, FuzzConfig, InvariantConfig, OptimizerDetails, SolcReq, + Config, FuzzConfig, InvariantConfig, SolcReq, }; use foundry_evm::opts::EvmOpts; use foundry_test_utils::{ @@ -69,7 +69,7 @@ forgetest!(can_extract_config_values, |prj, cmd| { initial_balance: U256::from(0xffffffffffffffffffffffffu128), block_number: 10, fork_block_number: Some(200), - chain_id: Some(9999.into()), + chain: Some(9999.into()), gas_limit: 99_000_000u64.into(), code_size_limit: Some(100000), gas_price: Some(999),