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

Add verify command to allow verifying deployed contracts against local source code #948

Merged
merged 2 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
791 changes: 782 additions & 9 deletions Cargo.lock

Large diffs are not rendered by default.

46 changes: 37 additions & 9 deletions crates/driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ pub struct CompiledModule {
pub struct CompiledContract {
pub json_abi: String,
pub yul: String,
pub origin: ContractId,
#[cfg(feature = "solc-backend")]
pub bytecode: String,
#[cfg(feature = "solc-backend")]
pub runtime_bytecode: String,
}

#[cfg(feature = "solc-backend")]
Expand Down Expand Up @@ -111,13 +114,14 @@ pub fn compile_single_file(
path: &str,
src: &str,
with_bytecode: bool,
with_runtime_bytecode: bool,
optimize: bool,
) -> Result<CompiledModule, CompileError> {
let module = ModuleId::new_standalone(db, path, src);
let diags = module.diagnostics(db);

if diags.is_empty() {
compile_module(db, module, with_bytecode, optimize)
compile_module(db, module, with_bytecode, with_runtime_bytecode, optimize)
} else {
Err(CompileError(diags))
}
Expand Down Expand Up @@ -158,6 +162,7 @@ pub fn compile_ingot(
db: &mut Db,
build_files: &BuildFiles,
with_bytecode: bool,
with_runtime_bytecode: bool,
optimize: bool,
) -> Result<CompiledModule, CompileError> {
let ingot = IngotId::from_build_files(db, build_files);
Expand All @@ -170,7 +175,13 @@ pub fn compile_ingot(
let main_module = ingot
.root_module(db)
.expect("missing root module, with no diagnostic");
compile_module(db, main_module, with_bytecode, optimize)
compile_module(
db,
main_module,
with_bytecode,
with_runtime_bytecode,
optimize,
)
}

#[cfg(feature = "solc-backend")]
Expand Down Expand Up @@ -220,7 +231,7 @@ fn compile_test(db: &mut Db, test: FunctionId, optimize: bool) -> CompiledTest {
let yul_test = fe_codegen::yul::isel::lower_test(db, test)
.to_string()
.replace('"', "\\\"");
let bytecode = compile_to_evm("test", &yul_test, optimize);
let bytecode = compile_to_evm("test", &yul_test, optimize, false).bytecode;
let events = db.codegen_abi_module_events(test.module(db));
CompiledTest::new(test.name(db), events, bytecode)
}
Expand All @@ -239,6 +250,7 @@ fn compile_module(
db: &mut Db,
module_id: ModuleId,
with_bytecode: bool,
with_runtime_bytecode: bool,
optimize: bool,
) -> Result<CompiledModule, CompileError> {
let mut contracts = IndexMap::default();
Expand All @@ -248,19 +260,28 @@ fn compile_module(
let abi = db.codegen_abi_contract(contract);
let yul_contract = compile_to_yul(db, contract);

let bytecode = if with_bytecode {
let (bytecode, runtime_bytecode) = if with_bytecode || with_runtime_bytecode {
let deployable_name = db.codegen_contract_deployer_symbol_name(contract);
compile_to_evm(deployable_name.as_str(), &yul_contract, optimize)
let bytecode = compile_to_evm(
deployable_name.as_str(),
&yul_contract,
optimize,
with_runtime_bytecode,
);
(bytecode.bytecode, bytecode.runtime_bytecode)
} else {
"".to_string()
("".to_string(), "".to_string())
};

contracts.insert(
name.to_string(),
// Maybe put the ContractID here so we can trace it back to the source file
CompiledContract {
json_abi: serde_json::to_string_pretty(&abi).unwrap(),
yul: yul_contract,
origin: contract,
bytecode,
runtime_bytecode,
},
);
}
Expand All @@ -277,6 +298,7 @@ fn compile_module(
db: &mut Db,
module_id: ModuleId,
_with_bytecode: bool,
_with_runtime_bytecode: bool,
_optimize: bool,
) -> Result<CompiledModule, CompileError> {
let mut contracts = IndexMap::default();
Expand All @@ -290,6 +312,7 @@ fn compile_module(
CompiledContract {
json_abi: serde_json::to_string_pretty(&abi).unwrap(),
yul: yul_contract,
origin: contract,
},
);
}
Expand All @@ -307,9 +330,14 @@ fn compile_to_yul(db: &mut Db, contract: ContractId) -> String {
}

#[cfg(feature = "solc-backend")]
fn compile_to_evm(name: &str, yul_object: &str, optimize: bool) -> String {
match fe_yulc::compile_single_contract(name, yul_object, optimize) {
Ok(contracts) => contracts,
fn compile_to_evm(
name: &str,
yul_object: &str,
optimize: bool,
verify_runtime_bytecode: bool,
) -> fe_yulc::ContractBytecode {
match fe_yulc::compile_single_contract(name, yul_object, optimize, verify_runtime_bytecode) {
Ok(bytecode) => bytecode,

Err(error) => {
for error in serde_json::from_str::<Value>(&error.0)
Expand Down
3 changes: 3 additions & 0 deletions crates/fe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ solc-backend = ["fe-driver/solc-backend"]

[dependencies]
clap = {version="3.1.18", features = ["derive"]}
reqwest = { version = "0.11", features = ["json", "blocking"] }
serde = { version = "1", features = ["derive"] }
url = "2"
fs_extra = "1.2.0"
walkdir = "2"
indexmap = "1.6.2"
Expand Down
4 changes: 4 additions & 0 deletions crates/fe/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ fn main() {
task::create_new_project(arg);
}
#[cfg(feature = "solc-backend")]
Commands::Verify(arg) => {
task::verify(arg);
}
#[cfg(feature = "solc-backend")]
Commands::Test(arg) => {
task::test(arg);
}
Expand Down
35 changes: 26 additions & 9 deletions crates/fe/src/task/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ enum Emit {
Ast,
LoweredAst,
Bytecode,
RuntimeBytecode,
Tokens,
Yul,
}
Expand Down Expand Up @@ -45,6 +46,7 @@ pub struct BuildArgs {
fn build_single_file(compile_arg: &BuildArgs) -> (String, CompiledModule) {
let emit = &compile_arg.emit;
let with_bytecode = emit.contains(&Emit::Bytecode);
let with_runtime_bytecode = emit.contains(&Emit::RuntimeBytecode);
let input_path = &compile_arg.input_path;
let optimize = compile_arg.optimize.unwrap_or(true);

Expand All @@ -62,6 +64,7 @@ fn build_single_file(compile_arg: &BuildArgs) -> (String, CompiledModule) {
input_path,
&content,
with_bytecode,
with_runtime_bytecode,
optimize,
) {
Ok(module) => module,
Expand All @@ -77,6 +80,7 @@ fn build_single_file(compile_arg: &BuildArgs) -> (String, CompiledModule) {
fn build_ingot(compile_arg: &BuildArgs) -> (String, CompiledModule) {
let emit = &compile_arg.emit;
let with_bytecode = emit.contains(&Emit::Bytecode);
let with_runtime_bytecode = emit.contains(&Emit::RuntimeBytecode);
let input_path = &compile_arg.input_path;
let optimize = compile_arg.optimize.unwrap_or(true);

Expand All @@ -100,15 +104,20 @@ fn build_ingot(compile_arg: &BuildArgs) -> (String, CompiledModule) {
}

let mut db = fe_driver::Db::default();
let compiled_module =
match fe_driver::compile_ingot(&mut db, &build_files, with_bytecode, optimize) {
Ok(module) => module,
Err(error) => {
eprintln!("Unable to compile {input_path}.");
print_diagnostics(&db, &error.0);
std::process::exit(1)
}
};
let compiled_module = match fe_driver::compile_ingot(
&mut db,
&build_files,
with_bytecode,
with_runtime_bytecode,
optimize,
) {
Ok(module) => module,
Err(error) => {
eprintln!("Unable to compile {input_path}.");
print_diagnostics(&db, &error.0);
std::process::exit(1)
}
};

// no file content for ingots
("".to_string(), compiled_module)
Expand Down Expand Up @@ -202,6 +211,14 @@ fn write_compiled_module(
let file_name = format!("{}.bin", &name);
write_output(&contract_output_dir.join(file_name), &contract.bytecode)?;
}
#[cfg(feature = "solc-backend")]
if targets.contains(&Emit::RuntimeBytecode) {
let file_name = format!("{}.runtime.bin", &name);
write_output(
&contract_output_dir.join(file_name),
&contract.runtime_bytecode,
)?;
}
}

Ok(())
Expand Down
5 changes: 5 additions & 0 deletions crates/fe/src/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@ mod check;
mod new;
#[cfg(feature = "solc-backend")]
mod test;
mod verify;

pub use build::{build, BuildArgs};
pub use check::{check, CheckArgs};
use clap::Subcommand;
pub use new::{create_new_project, NewProjectArgs};
#[cfg(feature = "solc-backend")]
pub use test::{test, TestArgs};
#[cfg(feature = "solc-backend")]
pub use verify::{verify, VerifyArgs};

#[derive(Subcommand)]
pub enum Commands {
Build(BuildArgs),
Check(CheckArgs),
New(NewProjectArgs),
#[cfg(feature = "solc-backend")]
Verify(VerifyArgs),
#[cfg(feature = "solc-backend")]
Test(TestArgs),
}
Loading