Skip to content

Commit

Permalink
fix: fix etherscan api parsing again
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse committed Feb 1, 2024
1 parent ceb739a commit b8e03c3
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 9 deletions.
20 changes: 20 additions & 0 deletions crates/cast/bin/cmd/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,23 @@ fn is_storage_layout_empty(storage_layout: &Option<StorageLayout>) -> bool {
true
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn parse_storage_etherscan_api_key() {
let args =
StorageArgs::parse_from(["foundry-cli", "addr", "--etherscan-api-key", "dummykey"]);
assert_eq!(args.etherscan.key(), Some("dummykey".to_string()));

std::env::set_var("ETHERSCAN_API_KEY", "FXY");
let config = Config::from(&args);
std::env::remove_var("ETHERSCAN_API_KEY");
assert_eq!(config.etherscan_api_key, Some("dummykey".to_string()));

let key = config.get_etherscan_api_key(None).unwrap();
assert_eq!(key, "dummykey".to_string());
}
}
30 changes: 30 additions & 0 deletions crates/config/src/etherscan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ use crate::{
resolve::{interpolate, UnresolvedEnvVarError, RE_PLACEHOLDER},
Chain, Config, NamedChain,
};
use figment::{
providers::Env,
value::{Dict, Map},
Error, Metadata, Profile, Provider,
};
use inflector::Inflector;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::{
Expand All @@ -16,6 +21,31 @@ use std::{
/// The user agent to use when querying the etherscan API.
pub const ETHERSCAN_USER_AGENT: &str = concat!("foundry/", env!("CARGO_PKG_VERSION"));

/// A [Provider] that provides Etherscan API key from the environment if it's not empty.
///
/// This prevents `ETHERSCAN_API_KEY=""` if it's set but empty
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[non_exhaustive]
pub(crate) struct EtherscanEnvProvider;

impl Provider for EtherscanEnvProvider {
fn metadata(&self) -> Metadata {
Env::raw().metadata()
}

fn data(&self) -> Result<Map<Profile, Dict>, Error> {
let mut dict = Dict::default();
let env_provider = Env::raw().only(&["ETHERSCAN_API_KEY"]);
if let Some((key, value)) = env_provider.iter().next() {
if !value.trim().is_empty() {
dict.insert(key.as_str().to_string(), value.into());
}
}

Ok(Map::from([(Config::selected_profile(), dict)]))
}
}

/// Errors that can occur when creating an `EtherscanConfig`
#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
pub enum EtherscanConfigError {
Expand Down
33 changes: 24 additions & 9 deletions crates/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub use invariant::InvariantConfig;
use providers::remappings::RemappingsProvider;

mod inline;
use crate::etherscan::EtherscanEnvProvider;
pub use inline::{validate_profiles, InlineConfig, InlineConfigError, InlineConfigParser, NatSpec};

/// Foundry configuration
Expand Down Expand Up @@ -1587,6 +1588,7 @@ impl From<Config> for Figment {
.global(),
)
.merge(DappEnvCompatProvider)
.merge(EtherscanEnvProvider::default())
.merge(
Env::prefixed("FOUNDRY_")
.ignore(&["PROFILE", "REMAPPINGS", "LIBRARIES", "FFI", "FS_PERMISSIONS"])
Expand All @@ -1604,15 +1606,6 @@ impl From<Config> for Figment {
)
.select(profile.clone());

// Ensure only non empty etherscan var is merged
// This prevents `ETHERSCAN_API_KEY=""` if it's set but empty
let env_provider = Env::raw().only(&["ETHERSCAN_API_KEY"]);
if let Some((key, value)) = env_provider.iter().next() {
if !value.trim().is_empty() {
figment = figment.merge((key.as_str(), value));
}
}

// we try to merge remappings after we've merged all other providers, this prevents
// redundant fs lookups to determine the default remappings that are eventually updated by
// other providers, like the toml file
Expand Down Expand Up @@ -4362,6 +4355,28 @@ mod tests {
});
}

#[test]
fn test_etherscan_api_key_figment() {
figment::Jail::expect_with(|jail| {
jail.create_file(
"foundry.toml",
r"
[default]
etherscan_api_key = 'DUMMY'
",
)?;
jail.set_env("ETHERSCAN_API_KEY", "ETHER");

let figment = Config::figment_with_root(jail.directory())
.merge(("etherscan_api_key", "USER_KEY"));

let loaded = Config::from_provider(figment);
assert_eq!(loaded.etherscan_api_key, Some("USER_KEY".into()));

Ok(())
});
}

// a test to print the config, mainly used to update the example config in the README
#[test]
#[ignore]
Expand Down

0 comments on commit b8e03c3

Please sign in to comment.