Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(forge verify-bytecode): support alternative block explorers + predeploys #8510

Merged
merged 42 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
1fd7cac
major refactor, include multi-verifier
zerosnacks Jul 24, 2024
efc847b
fix build issues
zerosnacks Jul 24, 2024
cce169b
clarify preflight check applies to `verify` not `verify_bytecode`, fu…
zerosnacks Jul 24, 2024
6b258a2
update message indicating lack of Sourcify support for the time being
zerosnacks Jul 24, 2024
7b9ddd5
use get_provider abstraction
zerosnacks Jul 24, 2024
9989250
clean up
zerosnacks Jul 24, 2024
d12f925
clean up
zerosnacks Jul 24, 2024
a221bd1
do not println in json mode
zerosnacks Jul 24, 2024
b192f4b
merge in changes of https://github.com/foundry-rs/foundry/pull/8513
zerosnacks Jul 25, 2024
0a93dee
clean up
zerosnacks Jul 25, 2024
71736bf
prepare -> helpers
zerosnacks Jul 29, 2024
d9efb20
pull in master incl. #8547
zerosnacks Jul 29, 2024
336b8fc
fix merge conflict
zerosnacks Jul 30, 2024
8bfebbe
fix regression
zerosnacks Jul 30, 2024
0e74348
fix clippy
zerosnacks Jul 30, 2024
199cf58
forge(`vb`): test blockscout for non-CREATE2 tx
yash-atreya Aug 2, 2024
f5028fb
feat(`verify-bytecode`): `--ignore <BytecodeType>` while verifying by…
yash-atreya Aug 2, 2024
e74a26d
nit
yash-atreya Aug 2, 2024
047a9ec
feat(`verify-bytecode`): support verifying predeployed contracts with…
yash-atreya Aug 2, 2024
efca135
cleanup nits
yash-atreya Aug 3, 2024
e9b6765
fix(`forge vb`): resolve blockscout discrepancy by using `tx.from`
yash-atreya Aug 3, 2024
4961be1
nit
yash-atreya Aug 3, 2024
92ad930
nit
yash-atreya Aug 5, 2024
6cecc48
Merge branch 'master' into zerosnacks/support-blockscout-in-verify-by…
yash-atreya Aug 5, 2024
14916d1
Merge branch 'master' into zerosnacks/support-blockscout-in-verify-by…
yash-atreya Aug 7, 2024
7e1491d
Merge branch 'master' into zerosnacks/support-blockscout-in-verify-by…
yash-atreya Aug 8, 2024
f69d5a4
refac(`forge vb`)
yash-atreya Aug 8, 2024
f0b1668
rm verify_bytecode from VerificationProvider
yash-atreya Aug 8, 2024
4559a34
feat(`forge vb`): support vb for predeploys using genesis sim
yash-atreya Aug 8, 2024
d91ecbd
use Option in maybe_predeploy_contract
yash-atreya Aug 9, 2024
b5712a3
clippy
yash-atreya Aug 9, 2024
2ea3283
fix: constructor_args retrieval order and checks.
yash-atreya Aug 9, 2024
394acf6
nit
yash-atreya Aug 9, 2024
39f89ff
nit
yash-atreya Aug 9, 2024
6fcb545
refac: use util methods
yash-atreya Aug 9, 2024
e44b40a
Merge branch 'master' into zerosnacks/support-blockscout-in-verify-by…
yash-atreya Aug 9, 2024
c601f42
Merge branch 'master' into zerosnacks/support-blockscout-in-verify-by…
yash-atreya Aug 12, 2024
061648e
fix: use sourcify definitions for match types i.e always Partial if b…
yash-atreya Aug 13, 2024
bfb9ccb
Merge branch 'master' into zerosnacks/support-blockscout-in-verify-by…
yash-atreya Aug 13, 2024
4a55f27
resolve conflicts
yash-atreya Aug 20, 2024
b9f79ae
test(forge vb): test provided constructor-args
yash-atreya Aug 21, 2024
0219cc4
nit
yash-atreya Aug 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/forge/bin/cmd/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ impl CreateArgs {

let context = verify.resolve_context().await?;

verify.verification_provider()?.preflight_check(verify, context).await?;
verify.verification_provider()?.preflight_verify_check(verify, context).await?;
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion crates/forge/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ fn main() -> Result<()> {
ForgeSubcommand::Debug(cmd) => utils::block_on(cmd.run()),
ForgeSubcommand::VerifyContract(args) => utils::block_on(args.run()),
ForgeSubcommand::VerifyCheck(args) => utils::block_on(args.run()),
ForgeSubcommand::VerifyBytecode(cmd) => utils::block_on(cmd.run()),
ForgeSubcommand::Clone(cmd) => utils::block_on(cmd.run()),
ForgeSubcommand::Cache(cmd) => match cmd.sub {
CacheSubcommands::Clean(cmd) => cmd.run(),
Expand Down Expand Up @@ -117,7 +118,6 @@ fn main() -> Result<()> {
ForgeSubcommand::Generate(cmd) => match cmd.sub {
GenerateSubcommands::Test(cmd) => cmd.run(),
},
ForgeSubcommand::VerifyBytecode(cmd) => utils::block_on(cmd.run()),
ForgeSubcommand::Soldeer(cmd) => cmd.run(),
ForgeSubcommand::Eip712(cmd) => cmd.run(),
ForgeSubcommand::BindJson(cmd) => cmd.run(),
Expand Down
10 changes: 5 additions & 5 deletions crates/forge/bin/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::cmd::{
};
use clap::{Parser, Subcommand, ValueHint};
use forge_script::ScriptArgs;
use forge_verify::{bytecode::VerifyBytecodeArgs, VerifyArgs, VerifyCheckArgs};
use forge_verify::{VerifyArgs, VerifyBytecodeArgs, VerifyCheckArgs};
use std::path::PathBuf;

const VERSION_MESSAGE: &str = concat!(
Expand Down Expand Up @@ -87,6 +87,10 @@ pub enum ForgeSubcommand {
#[command(visible_alias = "vc")]
VerifyCheck(VerifyCheckArgs),

/// Verify the deployed bytecode against its source on Etherscan.
#[clap(visible_alias = "vb")]
VerifyBytecode(VerifyBytecodeArgs),

/// Deploy a smart contract.
#[command(visible_alias = "c")]
Create(CreateArgs),
Expand Down Expand Up @@ -158,10 +162,6 @@ pub enum ForgeSubcommand {
/// Generate scaffold files.
Generate(generate::GenerateArgs),

/// Verify the deployed bytecode against its source.
#[clap(visible_alias = "vb")]
VerifyBytecode(VerifyBytecodeArgs),

/// Soldeer dependency manager.
Soldeer(soldeer::SoldeerArgs),

Expand Down
239 changes: 233 additions & 6 deletions crates/forge/tests/cli/verify_bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ use foundry_test_utils::{
TestCommand, TestProject,
};

#[allow(clippy::too_many_arguments)]
fn test_verify_bytecode(
prj: TestProject,
mut cmd: TestCommand,
addr: &str,
contract_name: &str,
constructor_args: Option<Vec<&str>>,
config: Config,
verifier: &str,
verifier_url: &str,
expected_matches: (&str, &str),
) {
let etherscan_key = next_etherscan_api_key();
Expand All @@ -29,6 +33,68 @@ fn test_verify_bytecode(
prj.add_source(contract_name, &source_code).unwrap();
prj.write_config(config);

let mut args = vec![
"verify-bytecode",
addr,
contract_name,
"--etherscan-api-key",
&etherscan_key,
"--verifier",
verifier,
"--verifier-url",
verifier_url,
"--rpc-url",
&rpc_url,
];

if let Some(constructor_args) = constructor_args {
args.push("--constructor-args");
args.extend(constructor_args.iter());
}

let output = cmd.forge_fuse().args(args).assert_success().get_output().stdout_lossy();

assert!(output
.contains(format!("Creation code matched with status {}", expected_matches.0).as_str()));
assert!(output
.contains(format!("Runtime code matched with status {}", expected_matches.1).as_str()));
}

#[allow(clippy::too_many_arguments)]
fn test_verify_bytecode_with_ignore(
prj: TestProject,
mut cmd: TestCommand,
addr: &str,
contract_name: &str,
config: Config,
verifier: &str,
verifier_url: &str,
expected_matches: (&str, &str),
ignore: &str,
chain: &str,
) {
let etherscan_key = next_etherscan_api_key();
let rpc_url = next_http_archive_rpc_endpoint();

// fetch and flatten source code
let source_code = cmd
.cast_fuse()
.args([
"etherscan-source",
addr,
"--flatten",
"--etherscan-api-key",
&etherscan_key,
"--chain",
chain,
])
.assert_success()
.get_output()
.stdout_lossy();

prj.add_source(contract_name, &source_code).unwrap();
prj.write_config(config);

let output = cmd
.forge_fuse()
.args([
Expand All @@ -37,25 +103,44 @@ fn test_verify_bytecode(
contract_name,
"--etherscan-api-key",
&etherscan_key,
"--verifier",
verifier,
"--verifier-url",
verifier_url,
"--rpc-url",
&rpc_url,
"--ignore",
ignore,
])
.assert_success()
.get_output()
.stdout_lossy();

assert!(output
.contains(format!("Creation code matched with status {}", expected_matches.0).as_str()));
assert!(output
.contains(format!("Runtime code matched with status {}", expected_matches.1).as_str()));
}
if ignore == "creation" {
assert!(!output.contains(
format!("Creation code matched with status {}", expected_matches.0).as_str()
));
} else {
assert!(output.contains(
format!("Creation code matched with status {}", expected_matches.0).as_str()
));
}

if ignore == "runtime" {
assert!(!output
.contains(format!("Runtime code matched with status {}", expected_matches.1).as_str()));
} else {
assert!(output
.contains(format!("Runtime code matched with status {}", expected_matches.1).as_str()));
}
}
forgetest_async!(can_verify_bytecode_no_metadata, |prj, cmd| {
test_verify_bytecode(
prj,
cmd,
"0xba2492e52F45651B60B8B38d4Ea5E2390C64Ffb1",
"SystemConfig",
None,
Config {
evm_version: EvmVersion::London,
optimizer_runs: 999999,
Expand All @@ -64,7 +149,9 @@ forgetest_async!(can_verify_bytecode_no_metadata, |prj, cmd| {
bytecode_hash: BytecodeHash::None,
..Default::default()
},
("full", "full"),
"etherscan",
"https://api.etherscan.io/api",
("partial", "partial"),
);
});

Expand All @@ -74,12 +161,152 @@ forgetest_async!(can_verify_bytecode_with_metadata, |prj, cmd| {
cmd,
"0xb8901acb165ed027e32754e0ffe830802919727f",
"L1_ETH_Bridge",
None,
Config {
evm_version: EvmVersion::Paris,
optimizer_runs: 50000,
optimizer: true,
..Default::default()
},
"etherscan",
"https://api.etherscan.io/api",
("partial", "partial"),
);
});

// Test non-CREATE2 deployed contract with blockscout
forgetest_async!(can_verify_bytecode_with_blockscout, |prj, cmd| {
test_verify_bytecode(
prj,
cmd,
"0x70f44C13944d49a236E3cD7a94f48f5daB6C619b",
"StrategyManager",
None,
Config {
evm_version: EvmVersion::London,
optimizer: true,
optimizer_runs: 200,
..Default::default()
},
"blockscout",
"https://eth.blockscout.com/api",
("partial", "partial"),
);
});

// Test CREATE2 deployed contract with blockscout
forgetest_async!(can_vb_create2_with_blockscout, |prj, cmd| {
test_verify_bytecode(
prj,
cmd,
"0xba2492e52F45651B60B8B38d4Ea5E2390C64Ffb1",
"SystemConfig",
None,
Config {
evm_version: EvmVersion::London,
optimizer_runs: 999999,
optimizer: true,
cbor_metadata: false,
bytecode_hash: BytecodeHash::None,
..Default::default()
},
"blockscout",
"https://eth.blockscout.com/api",
("partial", "partial"),
);
});

// Test `--constructor-args`
forgetest_async!(can_verify_bytecode_with_constructor_args, |prj, cmd| {
let constructor_args = vec![
"0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A",
"0x91E677b07F7AF907ec9a428aafA9fc14a0d3A338",
"0xD92145c07f8Ed1D392c1B88017934E301CC1c3Cd",
];
test_verify_bytecode(
prj,
cmd,
"0x70f44C13944d49a236E3cD7a94f48f5daB6C619b",
"StrategyManager",
Some(constructor_args),
Config {
evm_version: EvmVersion::London,
optimizer: true,
optimizer_runs: 200,
..Default::default()
},
"etherscan",
"https://api.etherscan.io/api",
("partial", "partial"),
);
});

// `--ignore` tests
forgetest_async!(can_ignore_creation, |prj, cmd| {
test_verify_bytecode_with_ignore(
prj,
cmd,
"0xba2492e52F45651B60B8B38d4Ea5E2390C64Ffb1",
"SystemConfig",
Config {
evm_version: EvmVersion::London,
optimizer_runs: 999999,
optimizer: true,
cbor_metadata: false,
bytecode_hash: BytecodeHash::None,
..Default::default()
},
"etherscan",
"https://api.etherscan.io/api",
("ignored", "partial"),
"creation",
"1",
);
});

forgetest_async!(can_ignore_runtime, |prj, cmd| {
test_verify_bytecode_with_ignore(
prj,
cmd,
"0xba2492e52F45651B60B8B38d4Ea5E2390C64Ffb1",
"SystemConfig",
Config {
evm_version: EvmVersion::London,
optimizer_runs: 999999,
optimizer: true,
cbor_metadata: false,
bytecode_hash: BytecodeHash::None,
..Default::default()
},
"etherscan",
"https://api.etherscan.io/api",
("partial", "ignored"),
"runtime",
"1",
);
});

// Test predeploy contracts
// TODO: Add test utils for base such as basescan keys and alchemy keys.
// WETH9 Predeploy
// forgetest_async!(can_verify_predeploys, |prj, cmd| {
// test_verify_bytecode_with_ignore(
// prj,
// cmd,
// "0x4200000000000000000000000000000000000006",
// "WETH9",
// Config {
// evm_version: EvmVersion::default(),
// optimizer: true,
// optimizer_runs: 10000,
// cbor_metadata: true,
// bytecode_hash: BytecodeHash::Bzzr1,
// ..Default::default()
// },
// "etherscan",
// "https://api.basescan.org/api",
// ("ignored", "partial"),
// "creation",
// "base",
// );
// });
Loading
Loading