Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cast run): add --etherscan-api-key to resolve contract names #9295

Merged
merged 3 commits into from
Nov 11, 2024
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
11 changes: 9 additions & 2 deletions crates/cast/bin/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use cast::revm::primitives::EnvWithHandlerCfg;
use clap::Parser;
use eyre::{Result, WrapErr};
use foundry_cli::{
opts::RpcOpts,
opts::{EtherscanOpts, RpcOpts},
utils::{handle_traces, init_progress, TraceResult},
};
use foundry_common::{is_known_system_sender, SYSTEM_TRANSACTION_TYPE};
Expand Down Expand Up @@ -58,13 +58,16 @@ pub struct RunArgs {
#[arg(long, short)]
label: Vec<String>,

#[command(flatten)]
etherscan: EtherscanOpts,

#[command(flatten)]
rpc: RpcOpts,

/// The EVM version to use.
///
/// Overrides the version specified in the config.
#[arg(long, short)]
#[arg(long)]
evm_version: Option<EvmVersion>,

/// Sets the number of assumed available compute units per second for this provider
Expand Down Expand Up @@ -269,6 +272,10 @@ impl figment::Provider for RunArgs {
map.insert("alphanet".into(), self.alphanet.into());
}

if let Some(api_key) = &self.etherscan.key {
map.insert("etherscan_api_key".into(), api_key.as_str().into());
}

if let Some(evm_version) = self.evm_version {
map.insert("evm_version".into(), figment::value::Value::serialize(evm_version)?);
}
Expand Down
29 changes: 27 additions & 2 deletions crates/cast/tests/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use anvil::{EthereumHardfork, NodeConfig};
use foundry_test_utils::{
casttest, file,
rpc::{
next_http_rpc_endpoint, next_mainnet_etherscan_api_key, next_rpc_endpoint,
next_ws_rpc_endpoint,
next_etherscan_api_key, next_http_rpc_endpoint, next_mainnet_etherscan_api_key,
next_rpc_endpoint, next_ws_rpc_endpoint,
},
str,
util::OutputExt,
Expand Down Expand Up @@ -1503,3 +1503,28 @@ casttest!(fetch_constructor_args_from_etherscan, |_prj, cmd| {

"#]]);
});

// <https://github.com/foundry-rs/foundry/issues/3473>
casttest!(test_non_mainnet_traces, |prj, cmd| {
prj.clear();
cmd.args([
"run",
"0xa003e419e2d7502269eb5eda56947b580120e00abfd5b5460d08f8af44a0c24f",
"--rpc-url",
next_rpc_endpoint(NamedChain::Optimism).as_str(),
"--etherscan-api-key",
next_etherscan_api_key(NamedChain::Optimism).as_str(),
])
.assert_success()
.stdout_eq(str![[r#"
Executing previous transactions from the block.
Traces:
[33841] FiatTokenProxy::fallback(0x111111125421cA6dc452d289314280a0f8842A65, 164054805 [1.64e8])
├─ [26673] FiatTokenV2_2::approve(0x111111125421cA6dc452d289314280a0f8842A65, 164054805 [1.64e8]) [delegatecall]
│ ├─ emit Approval(owner: 0x9a95Af47C51562acfb2107F44d7967DF253197df, spender: 0x111111125421cA6dc452d289314280a0f8842A65, value: 164054805 [1.64e8])
│ └─ ← [Return] true
└─ ← [Return] true
...

"#]]);
});
12 changes: 8 additions & 4 deletions crates/evm/core/src/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,6 @@ impl EvmOpts {
/// Returns the chain ID from the RPC, if any.
pub async fn get_remote_chain_id(&self) -> Option<Chain> {
if let Some(ref url) = self.fork_url {
if url.contains("mainnet") {
trace!(?url, "auto detected mainnet chain");
return Some(Chain::mainnet());
}
trace!(?url, "retrieving chain via eth_chainId");
let provider = ProviderBuilder::new(url.as_str())
.compute_units_per_second(self.get_compute_units_per_second())
Expand All @@ -206,6 +202,14 @@ impl EvmOpts {
if let Ok(id) = provider.get_chain_id().await {
return Some(Chain::from(id));
}

// Provider URLs could be of the format `{CHAIN_IDENTIFIER}-mainnet`
// (e.g. Alchemy `opt-mainnet`, `arb-mainnet`), fallback to this method only
// if we're not able to retrieve chain id from `RetryProvider`.
if url.contains("mainnet") {
trace!(?url, "auto detected mainnet chain");
return Some(Chain::mainnet());
}
}

None
Expand Down
16 changes: 15 additions & 1 deletion crates/test-utils/src/rpc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! RPC API keys utilities.

use foundry_config::NamedChain;
use foundry_config::{NamedChain, NamedChain::Optimism};
use rand::seq::SliceRandom;
use std::sync::{
atomic::{AtomicUsize, Ordering},
Expand Down Expand Up @@ -75,6 +75,10 @@ static ETHERSCAN_MAINNET_KEYS: LazyLock<Vec<&'static str>> = LazyLock::new(|| {
keys
});

// List of etherscan keys for Optimism.
static ETHERSCAN_OPTIMISM_KEYS: LazyLock<Vec<&'static str>> =
LazyLock::new(|| vec!["JQNGFHINKS1W7Y5FRXU4SPBYF43J3NYK46"]);

/// Returns the next index to use.
fn next() -> usize {
static NEXT_INDEX: AtomicUsize = AtomicUsize::new(0);
Expand Down Expand Up @@ -127,6 +131,16 @@ pub fn next_mainnet_etherscan_api_key() -> String {
ETHERSCAN_MAINNET_KEYS[idx].to_string()
}

/// Returns the next etherscan api key for given chain.
pub fn next_etherscan_api_key(chain: NamedChain) -> String {
let keys = match chain {
Optimism => &ETHERSCAN_OPTIMISM_KEYS,
_ => &ETHERSCAN_MAINNET_KEYS,
};
let idx = next() % keys.len();
keys[idx].to_string()
}

fn next_url(is_ws: bool, chain: NamedChain) -> String {
use NamedChain::*;

Expand Down
Loading