forge_verify/etherscan/
standard_json.rs

1use super::{EtherscanSourceProvider, VerifyArgs};
2use crate::{provider::VerificationContext, verify::ContractLanguage};
3use eyre::{Context, Result};
4use foundry_block_explorers::verify::CodeFormat;
5use foundry_compilers::{
6    artifacts::{Source, StandardJsonCompilerInput, vyper::VyperInput},
7    solc::SolcLanguage,
8};
9use std::path::Path;
10
11#[derive(Debug)]
12pub struct EtherscanStandardJsonSource;
13impl EtherscanSourceProvider for EtherscanStandardJsonSource {
14    fn source(
15        &self,
16        args: &VerifyArgs,
17        context: &VerificationContext,
18    ) -> Result<(String, String, CodeFormat)> {
19        let mut input: StandardJsonCompilerInput = context
20            .project
21            .standard_json_input(&context.target_path)
22            .wrap_err("Failed to get standard json input")?
23            .normalize_evm_version(&context.compiler_version);
24
25        let lang = args.detect_language(context);
26
27        let code_format = match lang {
28            ContractLanguage::Solidity => CodeFormat::StandardJsonInput,
29            ContractLanguage::Vyper => CodeFormat::VyperJson,
30        };
31
32        let mut settings = context.compiler_settings.solc.settings.clone();
33        settings.libraries.libs = input
34            .settings
35            .libraries
36            .libs
37            .into_iter()
38            .map(|(f, libs)| {
39                (f.strip_prefix(context.project.root()).unwrap_or(&f).to_path_buf(), libs)
40            })
41            .collect();
42
43        settings.remappings = input.settings.remappings;
44
45        // remove all incompatible settings
46        settings.sanitize(&context.compiler_version, SolcLanguage::Solidity);
47
48        input.settings = settings;
49
50        let source = match lang {
51            ContractLanguage::Solidity => {
52                serde_json::to_string(&input).wrap_err("Failed to parse standard json input")?
53            }
54            ContractLanguage::Vyper => {
55                let path = Path::new(&context.target_path);
56                let sources = Source::read_all_from(path, &["vy", "vyi"])?;
57                let input = VyperInput::new(
58                    sources,
59                    context.clone().compiler_settings.vyper,
60                    &context.compiler_version,
61                );
62
63                serde_json::to_string(&input).wrap_err("Failed to parse vyper json input")?
64            }
65        };
66
67        trace!(target: "forge::verify", standard_json=source, "determined standard json input");
68
69        let name = format!(
70            "{}:{}",
71            context
72                .target_path
73                .strip_prefix(context.project.root())
74                .unwrap_or(context.target_path.as_path())
75                .display(),
76            context.target_name.clone()
77        );
78        Ok((source, name, code_format))
79    }
80}