Skip to content

Commit

Permalink
Merge branch 'foundry-rs:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Dargon789 authored Nov 14, 2024
2 parents 582278d + a65a5b1 commit 9fc25b8
Show file tree
Hide file tree
Showing 30 changed files with 588 additions and 251 deletions.
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ semver = "1"
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["arbitrary_precision"] }
similar-asserts = "1.6"
soldeer-commands = "=0.5.0"
soldeer-commands = "=0.5.1"
strum = "0.26"
tempfile = "3.13"
tikv-jemallocator = "0.6"
Expand Down
10 changes: 7 additions & 3 deletions crates/cast/bin/args.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::cmd::{
access_list::AccessListArgs, bind::BindArgs, call::CallArgs,
access_list::AccessListArgs, artifact::ArtifactArgs, bind::BindArgs, call::CallArgs,
constructor_args::ConstructorArgsArgs, create2::Create2Args, creation_code::CreationCodeArgs,
estimate::EstimateArgs, find_block::FindBlockArgs, interface::InterfaceArgs, logs::LogsArgs,
mktx::MakeTxArgs, rpc::RpcArgs, run::RunArgs, send::SendTxArgs, storage::StorageArgs,
Expand Down Expand Up @@ -793,7 +793,7 @@ pub enum CastSubcommand {
who: Option<String>,

/// Perform a reverse lookup to verify that the name is correct.
#[arg(long, short)]
#[arg(long)]
verify: bool,

#[command(flatten)]
Expand All @@ -807,7 +807,7 @@ pub enum CastSubcommand {
who: Option<Address>,

/// Perform a normal lookup to verify that the address is correct.
#[arg(long, short)]
#[arg(long)]
verify: bool,

#[command(flatten)]
Expand Down Expand Up @@ -927,6 +927,10 @@ pub enum CastSubcommand {
#[command(visible_alias = "cc")]
CreationCode(CreationCodeArgs),

/// Generate an artifact file, that can be used to deploy a contract locally.
#[command(visible_alias = "ar")]
Artifact(ArtifactArgs),

/// Display constructor arguments used for the contract initialization.
#[command(visible_alias = "cra")]
ConstructorArgs(ConstructorArgsArgs),
Expand Down
95 changes: 95 additions & 0 deletions crates/cast/bin/cmd/artifact.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use alloy_primitives::Address;
use alloy_provider::Provider;
use clap::{command, Parser};
use eyre::Result;
use foundry_block_explorers::Client;
use foundry_cli::{
opts::{EtherscanOpts, RpcOpts},
utils,
};
use foundry_common::fs;
use foundry_config::Config;
use serde_json::json;
use std::path::PathBuf;

use super::{
creation_code::{fetch_creation_code, parse_code_output},
interface::{fetch_abi_from_etherscan, load_abi_from_file},
};

/// CLI arguments for `cast artifact`.
#[derive(Parser)]
pub struct ArtifactArgs {
/// An Ethereum address, for which the artifact will be produced.
contract: Address,

/// Path to file containing the contract's JSON ABI. It's necessary if the target contract is
/// not verified on Etherscan.
#[arg(long)]
abi_path: Option<String>,

/// The path to the output file.
///
/// If not specified, the artifact will be output to stdout.
#[arg(
short,
long,
value_hint = clap::ValueHint::FilePath,
value_name = "PATH",
)]
output: Option<PathBuf>,

#[command(flatten)]
etherscan: EtherscanOpts,

#[command(flatten)]
rpc: RpcOpts,
}

impl ArtifactArgs {
pub async fn run(self) -> Result<()> {
let Self { contract, etherscan, rpc, output: output_location, abi_path } = self;

let mut etherscan = etherscan;
let config = Config::from(&rpc);
let provider = utils::get_provider(&config)?;
let api_key = etherscan.key().unwrap_or_default();
let chain = provider.get_chain_id().await?;
etherscan.chain = Some(chain.into());
let client = Client::new(chain.into(), api_key)?;

let abi = if let Some(ref abi_path) = abi_path {
load_abi_from_file(abi_path, None)?
} else {
fetch_abi_from_etherscan(contract, &etherscan).await?
};

let (abi, _) = abi.first().ok_or_else(|| eyre::eyre!("No ABI found"))?;

let bytecode = fetch_creation_code(contract, client, provider).await?;
let bytecode =
parse_code_output(bytecode, contract, &etherscan, abi_path.as_deref(), true, false)
.await?;

let artifact = json!({
"abi": abi,
"bytecode": {
"object": bytecode
}
});

let artifact = serde_json::to_string_pretty(&artifact)?;

if let Some(loc) = output_location {
if let Some(parent) = loc.parent() {
fs::create_dir_all(parent)?;
}
fs::write(&loc, artifact)?;
sh_println!("Saved artifact at {}", loc.display())?;
} else {
sh_println!("{artifact}")?;
}

Ok(())
}
}
11 changes: 6 additions & 5 deletions crates/cast/bin/cmd/constructor_args.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use alloy_dyn_abi::DynSolType;
use alloy_primitives::{Address, Bytes};
use alloy_provider::Provider;
use clap::{command, Parser};
use eyre::{eyre, OptionExt, Result};
use foundry_block_explorers::Client;
Expand Down Expand Up @@ -36,13 +37,13 @@ impl ConstructorArgsArgs {
pub async fn run(self) -> Result<()> {
let Self { contract, etherscan, rpc, abi_path } = self;

let config = Config::from(&etherscan);
let chain = config.chain.unwrap_or_default();
let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default();
let client = Client::new(chain, api_key)?;

let mut etherscan = etherscan;
let config = Config::from(&rpc);
let provider = utils::get_provider(&config)?;
let api_key = etherscan.key().unwrap_or_default();
let chain = provider.get_chain_id().await?;
etherscan.chain = Some(chain.into());
let client = Client::new(chain.into(), api_key)?;

let bytecode = fetch_creation_code(contract, client, provider).await?;

Expand Down
28 changes: 17 additions & 11 deletions crates/cast/bin/cmd/creation_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,25 @@ impl CreationCodeArgs {
let Self { contract, etherscan, rpc, disassemble, without_args, only_args, abi_path } =
self;

let config = Config::from(&etherscan);
let chain = config.chain.unwrap_or_default();
let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default();
let client = Client::new(chain, api_key)?;

let mut etherscan = etherscan;
let config = Config::from(&rpc);
let provider = utils::get_provider(&config)?;
let api_key = etherscan.key().unwrap_or_default();
let chain = provider.get_chain_id().await?;
etherscan.chain = Some(chain.into());
let client = Client::new(chain.into(), api_key)?;

let bytecode = fetch_creation_code(contract, client, provider).await?;

let bytecode =
parse_code_output(bytecode, contract, &etherscan, abi_path, without_args, only_args)
.await?;
let bytecode = parse_code_output(
bytecode,
contract,
&etherscan,
abi_path.as_deref(),
without_args,
only_args,
)
.await?;

if disassemble {
let _ = sh_println!("{}", SimpleCast::disassemble(&bytecode)?);
Expand All @@ -77,11 +83,11 @@ impl CreationCodeArgs {
/// - The complete bytecode
/// - The bytecode without constructor arguments
/// - Only the constructor arguments
async fn parse_code_output(
pub async fn parse_code_output(
bytecode: Bytes,
contract: Address,
etherscan: &EtherscanOpts,
abi_path: Option<String>,
abi_path: Option<&str>,
without_args: bool,
only_args: bool,
) -> Result<Bytes> {
Expand All @@ -90,7 +96,7 @@ async fn parse_code_output(
}

let abi = if let Some(abi_path) = abi_path {
load_abi_from_file(&abi_path, None)?
load_abi_from_file(abi_path, None)?
} else {
fetch_abi_from_etherscan(contract, etherscan).await?
};
Expand Down
1 change: 1 addition & 0 deletions crates/cast/bin/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//! [`foundry_config::Config`].
pub mod access_list;
pub mod artifact;
pub mod bind;
pub mod call;
pub mod constructor_args;
Expand Down
19 changes: 11 additions & 8 deletions crates/cast/bin/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ 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};
use foundry_common::{is_known_system_sender, shell, SYSTEM_TRANSACTION_TYPE};
use foundry_compilers::artifacts::EvmVersion;
use foundry_config::{
figment::{
Expand Down Expand Up @@ -48,23 +48,22 @@ pub struct RunArgs {
#[arg(long)]
quick: bool,

/// Prints the full address of the contract.
#[arg(long, short)]
verbose: bool,

/// Label addresses in the trace.
///
/// Example: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045:vitalik.eth
#[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 @@ -249,7 +248,7 @@ impl RunArgs {
self.label,
self.debug,
self.decode_internal,
self.verbose,
shell::verbosity() > 0,
)
.await?;

Expand All @@ -269,6 +268,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
7 changes: 1 addition & 6 deletions crates/cast/bin/cmd/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,6 @@ pub enum WalletSubcommands {
#[arg(value_name = "MNEMONIC_INDEX_OR_DERIVATION_PATH")]
mnemonic_index_or_derivation_path_override: Option<String>,

/// Verbose mode, print the address and private key.
#[arg(short = 'v', long)]
verbose: bool,

#[command(flatten)]
wallet: WalletOpts,
},
Expand Down Expand Up @@ -462,7 +458,6 @@ flag to set your key via:
wallet,
mnemonic_override,
mnemonic_index_or_derivation_path_override,
verbose,
} => {
let (index_override, derivation_path_override) =
match mnemonic_index_or_derivation_path_override {
Expand All @@ -485,7 +480,7 @@ flag to set your key via:
.await?;
match wallet {
WalletSigner::Local(wallet) => {
if verbose {
if shell::verbosity() > 0 {
sh_println!("Address: {}", wallet.address())?;
sh_println!(
"Private key: 0x{}",
Expand Down
1 change: 1 addition & 0 deletions crates/cast/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ async fn main_args(args: CastArgs) -> Result<()> {
CastSubcommand::Interface(cmd) => cmd.run().await?,
CastSubcommand::CreationCode(cmd) => cmd.run().await?,
CastSubcommand::ConstructorArgs(cmd) => cmd.run().await?,
CastSubcommand::Artifact(cmd) => cmd.run().await?,
CastSubcommand::Bind(cmd) => cmd.run().await?,
CastSubcommand::PrettyCalldata { calldata, offline } => {
let calldata = stdin::unwrap_line(calldata)?;
Expand Down
Loading

0 comments on commit 9fc25b8

Please sign in to comment.