cast/cmd/
artifact.rs
1use super::{
2 creation_code::{fetch_creation_code, parse_code_output},
3 interface::{fetch_abi_from_etherscan, load_abi_from_file},
4};
5use alloy_primitives::Address;
6use alloy_provider::Provider;
7use clap::{command, Parser};
8use eyre::Result;
9use foundry_block_explorers::Client;
10use foundry_cli::{
11 opts::{EtherscanOpts, RpcOpts},
12 utils::{self, LoadConfig},
13};
14use foundry_common::fs;
15use serde_json::json;
16use std::path::PathBuf;
17
18#[derive(Parser)]
20pub struct ArtifactArgs {
21 contract: Address,
23
24 #[arg(long)]
27 abi_path: Option<String>,
28
29 #[arg(
33 short,
34 long,
35 value_hint = clap::ValueHint::FilePath,
36 value_name = "PATH",
37 )]
38 output: Option<PathBuf>,
39
40 #[command(flatten)]
41 etherscan: EtherscanOpts,
42
43 #[command(flatten)]
44 rpc: RpcOpts,
45}
46
47impl ArtifactArgs {
48 pub async fn run(self) -> Result<()> {
49 let Self { contract, etherscan, rpc, output: output_location, abi_path } = self;
50
51 let mut etherscan = etherscan;
52 let config = rpc.load_config()?;
53 let provider = utils::get_provider(&config)?;
54 let api_key = etherscan.key().unwrap_or_default();
55 let chain = provider.get_chain_id().await?;
56 etherscan.chain = Some(chain.into());
57 let client = Client::new(chain.into(), api_key)?;
58
59 let abi = if let Some(ref abi_path) = abi_path {
60 load_abi_from_file(abi_path, None)?
61 } else {
62 fetch_abi_from_etherscan(contract, ðerscan).await?
63 };
64
65 let (abi, _) = abi.first().ok_or_else(|| eyre::eyre!("No ABI found"))?;
66
67 let bytecode = fetch_creation_code(contract, client, provider).await?;
68 let bytecode =
69 parse_code_output(bytecode, contract, ðerscan, abi_path.as_deref(), true, false)
70 .await?;
71
72 let artifact = json!({
73 "abi": abi,
74 "bytecode": {
75 "object": bytecode
76 }
77 });
78
79 let artifact = serde_json::to_string_pretty(&artifact)?;
80
81 if let Some(loc) = output_location {
82 if let Some(parent) = loc.parent() {
83 fs::create_dir_all(parent)?;
84 }
85 fs::write(&loc, artifact)?;
86 sh_println!("Saved artifact at {}", loc.display())?;
87 } else {
88 sh_println!("{artifact}")?;
89 }
90
91 Ok(())
92 }
93}