Skip to content
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
11 changes: 4 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,12 @@ To successfully create DVFs for on-chain smart contracts, you need access to the

**Please note the following restrictions/requirements**:

1. While Blockscout and Etherscan API keys are optional, at least one of them is required to determine the deployment transaction of a contract. If you provide neither, you are limited to local RPC nodes with less than 100 blocks.
2. A Blockscout API key allows for faster execution.
1. The Blockscout API is required to fetch the transaction hashes of a contract. This API can only be omitted if you fetch transactions based on events.
2. The Etherscan API is optional but can be used instead of Blockscout to fetch the deployment transaction of a contract.
3. Your RPC node **must** support either `debug_traceTransaction` or `trace_transaction`.
4. Your RPC node **should** support `debug_traceTransaction` with [opcode logger](https://geth.ethereum.org/docs/developers/evm-tracing/built-in-tracers#struct-opcode-logger) enabled. Otherwise, `dv` won't be able to decode mapping keys.
4. For faster execution, your RPC node **may** support `debug_traceTransaction` with [opcode logger](https://geth.ethereum.org/docs/developers/evm-tracing/built-in-tracers#struct-opcode-logger) enabled. Otherwise, `dv` will locally re-execute all transactions which might increase execution time.
5. For faster execution, your RPC node **may** support `debug_storageRangeAt`.

The RPC provider [QuickNode](https://www.quicknode.com/) supports all aforementioned requirements. A full list of supported RPC providers may be added here at a later point in time.

To run `dv`, you can either [build from source](#building-from-source) it or use the pre-configured [Docker](#using-docker) image.

If you choose to install `dv`, the following dependencies have to be installed on your system:
Expand Down Expand Up @@ -614,9 +612,8 @@ This section will be updated soon.
- Empty-string mapping keys can currently not be decoded correctly.
- Big transaction traces (`debug_traceTransaction` with opcode logger) of multiple GB may cause a crash.
- Proxy Contracts without events when changing the implementation cannot be accurately secured, as implementation changes could be missed.
- Successfully running validation against an non-finalized block at height H does not guarantee, validity at height H.
- Successfully running validation against a non-finalized block at height H does not guarantee validity at height H.
- Missing optimizations can cause longer waiting times than necessary.
- Celoscan.io is currently not supported.

## Supported Networks

Expand Down
2 changes: 1 addition & 1 deletion lib/bytecode_verification/compare_bytecodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ impl CompareInitCode {

for (arg, value) in project_info.constructor_args.iter_mut().zip(&decoded_args) {
let encoded_value = value.abi_encode_packed();
if encoded_value.len() == 0 {
if encoded_value.is_empty() {
// Here we keep the arg.type_string we previous extracted from the ABI
// This happens with empty arrays
arg.value = "0x".to_string();
Expand Down
16 changes: 4 additions & 12 deletions lib/bytecode_verification/verify_bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn print_verification_summary(
contract_address: &Address,
status: CompareBytecode,
project_info: &ProjectInfo,
on_chain_bytecode: &String,
on_chain_bytecode: &str,
) {
let mut table = Table::new();

Expand Down Expand Up @@ -70,11 +70,7 @@ pub fn print_verification_summary(
table.printstd();
}

pub fn write_out_bytecodes(
project_info: &ProjectInfo,
on_chain_bytecode: &String,
table: &mut Table,
) {
pub fn write_out_bytecodes(project_info: &ProjectInfo, on_chain_bytecode: &str, table: &mut Table) {
let mut compiled_file = File::create("compiled_bytecode.txt").expect("Could not create file");
let mut on_chain_file = File::create("on_chain_bytecode.txt").expect("Could not create file");

Expand All @@ -96,11 +92,7 @@ pub fn write_out_bytecodes(
]);
}

pub fn write_out_initcodes(
project_info: &ProjectInfo,
on_chain_initcode: &String,
table: &mut Table,
) {
pub fn write_out_initcodes(project_info: &ProjectInfo, on_chain_initcode: &str, table: &mut Table) {
let mut compiled_file = File::create("compiled_initcode.txt").expect("Could not create file");
let mut on_chain_file = File::create("on_chain_initcode.txt").expect("Could not create file");

Expand All @@ -123,7 +115,7 @@ pub fn print_generation_summary(
contract_address: &Address,
status: CompareBytecode,
project_info: &ProjectInfo,
on_chain_bytecode: &String,
on_chain_bytecode: &str,
pretty_printer: &PrettyPrinter,
) {
let mut table = Table::new();
Expand Down
2 changes: 1 addition & 1 deletion lib/dvf/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ fn default_max_blocks() -> u64 {
}

fn default_web3_timeout() -> u64 {
700
5000
}

impl DVFConfig {
Expand Down
56 changes: 38 additions & 18 deletions lib/dvf/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::utils::pretty::PrettyPrinter;
use crate::utils::progress::{print_progress, ProgressMode};
use crate::utils::read_write_file::get_project_paths;
use crate::web3;
use crate::web3::stop_anvil_instance;

pub struct DiscoveryParams<'a> {
pub config: &'a DVFConfig,
Expand Down Expand Up @@ -79,12 +80,20 @@ pub fn discover_storage_and_events(
let fi_layout = forge_inspect::ForgeInspectLayoutStorage::generate_and_parse_layout(
project_path,
params.contract_name,
project_info.absolute_path.clone(),
if params.env == Environment::Hardhat {
project_info.absolute_path.clone()
} else {
None
},
);
let fi_ir = forge_inspect::ForgeInspectIrOptimized::generate_and_parse_ir_optimized(
project_path,
params.contract_name,
project_info.absolute_path.clone(),
if params.env == Environment::Hardhat {
project_info.absolute_path.clone()
} else {
None
},
);
let mut contract_state = ContractState::new_with_address(params.address, &pretty_printer);
contract_state.add_forge_inspect(&fi_layout, &fi_ir);
Expand Down Expand Up @@ -140,12 +149,20 @@ pub fn discover_storage_and_events(
let fi_impl_layout = forge_inspect::ForgeInspectLayoutStorage::generate_and_parse_layout(
&imp_path,
implementation_name,
tmp_project_info.absolute_path.clone(),
if params.implementation_env == Environment::Hardhat {
tmp_project_info.absolute_path.clone()
} else {
None
},
);
let fi_impl_ir = forge_inspect::ForgeInspectIrOptimized::generate_and_parse_ir_optimized(
&imp_path,
implementation_name,
tmp_project_info.absolute_path.clone(),
if params.implementation_env == Environment::Hardhat {
tmp_project_info.absolute_path.clone()
} else {
None
},
);
contract_state.add_forge_inspect(&fi_impl_layout, &fi_impl_ir);

Expand Down Expand Up @@ -206,22 +223,25 @@ pub fn discover_storage_and_events(
}
seen_transactions.insert(tx_hash);

let mut found_trace = true;
if let Ok(trace) = web3::get_eth_debug_trace(params.config, tx_hash) {
if contract_state
.record_traces(params.config, vec![trace])
.is_err()
{
found_trace = false;
info!("Getting trace for {}", tx_hash);
match web3::get_eth_debug_trace_sim(params.config, tx_hash) {
Ok((trace, anvil_config, anvil_instance)) => {
let record_traces_config = match &anvil_config {
Some(c) => c,
None => params.config,
};
if let Err(err) = contract_state.record_traces(record_traces_config, vec![trace]) {
missing_traces = true;
info!("Warning. The trace for {tx_hash} cannot be obtained. Some mapping slots might not be decodable. You can try to increase the timeout in the config. Error: {}", err);
}
if let Some(anvil_instance) = anvil_instance {
stop_anvil_instance(anvil_instance);
}
}
Err(err) => {
missing_traces = true;
info!("Warning. The trace for {tx_hash} cannot be obtained. Some mapping slots might not be decodable. You can try to increase the timeout in the config. Error: {}", err);
}
} else {
found_trace = false;
missing_traces = true;
}

if !found_trace {
info!("Warning. The trace for {tx_hash} cannot be obtained. Some mapping slots might not be decodable.");
}
}

Expand Down
13 changes: 7 additions & 6 deletions lib/dvf/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::num::ParseIntError;
use std::path::Path;

use ruint;
use tracing::info;

use crate::bytecode_verification::parse_json::ProjectInfo;
use crate::utils::pretty::convert_bytes_to_i256;
Expand Down Expand Up @@ -128,23 +129,23 @@ impl From<serde_json::Error> for ValidationError {
impl From<reqwest::Error> for ValidationError {
fn from(error: reqwest::Error) -> Self {
// Print the full error details
eprintln!("Request failed: {:?}", error);
info!("Request failed: {:?}", error);

// Optionally, print more specific causes
if error.is_timeout() {
eprintln!("Reason: Timeout");
info!("Reason: Timeout");
} else if error.is_connect() {
eprintln!("Reason: Connection error");
info!("Reason: Connection error");
} else if error.is_status() {
eprintln!("Reason: Received bad HTTP status");
info!("Reason: Received bad HTTP status");
} else if error.is_request() {
eprintln!("Reason: Request failed to build");
info!("Reason: Request failed to build");
}

// Print source chain (if available)
let mut source = error.source();
while let Some(s) = source {
eprintln!("Caused by: {}", s);
info!("Caused by: {}", s);
source = s.source();
}
ValidationError::Error(format!("Communication error occurred: {}", error))
Expand Down
Loading
Loading