Skip to main content

cast/cmd/
artifact.rs

1use super::creation_code::{fetch_creation_code, load_abi, parse_code_output};
2use alloy_primitives::Address;
3use clap::Parser;
4use eyre::Result;
5use foundry_cli::{
6    opts::{EtherscanOpts, RpcOpts},
7    utils::LoadConfig,
8};
9use foundry_common::fs;
10use serde_json::json;
11use std::path::PathBuf;
12
13foundry_config::impl_figment_convert!(ArtifactArgs, etherscan, rpc);
14
15/// CLI arguments for `cast artifact`.
16#[derive(Parser)]
17pub struct ArtifactArgs {
18    /// An Ethereum address, for which the artifact will be produced.
19    contract: Address,
20
21    /// Path to file containing the contract's JSON ABI. It's necessary if the target contract is
22    /// not verified on Etherscan.
23    #[arg(long)]
24    abi_path: Option<String>,
25
26    /// The path to the output file.
27    ///
28    /// If not specified, the artifact will be output to stdout.
29    #[arg(
30        short,
31        long,
32        value_hint = clap::ValueHint::FilePath,
33        value_name = "PATH",
34    )]
35    output: Option<PathBuf>,
36
37    #[command(flatten)]
38    etherscan: EtherscanOpts,
39
40    #[command(flatten)]
41    rpc: RpcOpts,
42}
43
44impl ArtifactArgs {
45    pub async fn run(self) -> Result<()> {
46        let mut config = self.load_config()?;
47        let Self { contract, output, abi_path, .. } = self;
48
49        let bytecode = fetch_creation_code(&mut config, contract).await?;
50        let abi_path = abi_path.as_deref();
51        let abi = load_abi(contract, &config, abi_path).await?;
52        let bytecode =
53            parse_code_output(bytecode, contract, &config, abi_path, true, false).await?;
54
55        let artifact = json!({ "abi": abi, "bytecode": { "object": bytecode } });
56        let artifact = serde_json::to_string_pretty(&artifact)?;
57
58        if let Some(loc) = output {
59            if let Some(parent) = loc.parent() {
60                fs::create_dir_all(parent)?;
61            }
62            fs::write(&loc, artifact)?;
63            sh_status!("Saved artifact at {}", loc.display())?;
64        } else {
65            sh_println!("{artifact}")?;
66        }
67        Ok(())
68    }
69}