Skip to content
Closed
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
21 changes: 21 additions & 0 deletions lib/dvf/parse.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::HashSet;
use std::env::VarError;
use std::error::Error;
use std::fmt;
use std::fs::File;
use std::io;
Expand Down Expand Up @@ -126,6 +127,26 @@ 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);

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

// Print source chain (if available)
let mut source = error.source();
while let Some(s) = source {
eprintln!("Caused by: {}", s);
source = s.source();
}
ValidationError::Error(format!("Communication error occurred: {}", error))
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/state/forge_inspect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ impl ForgeInspect {
contract = format!("{}:{}", path, contract_name);
}
let forge_inspect = Command::new("forge")
.env("RUST_LOG", "error") // prevents `forge inspect` from contaminating the JSON with logs
.current_dir(project_path)
.arg("inspect")
.arg("--force")
Expand Down
116 changes: 77 additions & 39 deletions src/dvf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,53 +196,91 @@ fn validate_dvf(
// Validate events
print_progress("Validating Critical Events.", &mut pc, &progress_mode);
let pb = ProgressBar::new(filled.critical_events.len().try_into().unwrap());

let start_block = filled.deployment_block_num;
let end_block = validation_block_num;
print!("max_block per event {}", config.max_blocks_per_event_query);

// For each critical event
for critical_event in &filled.critical_events {
let seen_events = web3::get_eth_events(
config,
&filled.address,
filled.deployment_block_num,
validation_block_num,
&vec![critical_event.topic0],
)?;
if seen_events.len() != critical_event.occurrences.len() {
return Err(ValidationError::Invalid(format!(
"Found {} occurrences of event {}, but expected {}.",
seen_events.len(),
critical_event.sig,
critical_event.occurrences.len()
)));
}
let mut num_occurrences = 0;
let num_occurrences_expected = critical_event.occurrences.len();

#[allow(clippy::needless_range_loop)]
for i in 0..seen_events.len() {
let log_inner = &seen_events[i].inner;
if log_inner.topics() != critical_event.occurrences[i].topics {
let message = format!(
"Mismatching topics for event occurrence {} of {}.",
i, critical_event.sig
);
if continue_on_mismatch {
mismatch_found = true;
println!("{}", message);
} else {
return Err(ValidationError::Invalid(message));
}
let mut current_from = start_block;

// For each block range of at most config.max_blocks_per_event_query
while current_from <= end_block {
let current_to = std::cmp::min(
current_from + config.max_blocks_per_event_query - 1,
end_block,
);

// Get event logs from `current_from` to `current_to`
let seen_events = web3::get_eth_events(
config,
&filled.address,
current_from,
current_to,
&vec![critical_event.topic0],
)?;

// Early quit if num. of occurrences observed so far is already greater than the num. of occurrences expected
if num_occurrences + seen_events.len() > num_occurrences_expected {
return Err(ValidationError::Invalid(format!(
"Found at least {} occurrences of event {}, but expected {}.",
num_occurrences + seen_events.len(),
critical_event.sig,
num_occurrences_expected
)));
}
if log_inner.data.data != critical_event.occurrences[i].data {
let message = format!(
"Mismatching data for event occurrence {} of {}.",
i, critical_event.sig
);
if continue_on_mismatch {
mismatch_found = true;
println!("{}", message);
} else {
return Err(ValidationError::Invalid(message));

// For each occurrence of critical event
for event in seen_events {
let expected = &critical_event.occurrences[num_occurrences];
let log_inner = &event.inner;

if log_inner.topics() != expected.topics {
let message = format!(
"Mismatching topics for event occurrence {} of {}.",
num_occurrences, critical_event.sig
);
if continue_on_mismatch {
mismatch_found = true;
println!("{}", message);
} else {
return Err(ValidationError::Invalid(message));
}
}

if log_inner.data.data != expected.data {
let message = format!(
"Mismatching data for event occurrence {} of {}.",
num_occurrences, critical_event.sig
);
if continue_on_mismatch {
mismatch_found = true;
println!("{}", message);
} else {
return Err(ValidationError::Invalid(message));
}
}

num_occurrences += 1;
}

current_from = current_to + 1;
}

// if num_occurrences != num_occurrences_expected {
// return Err(ValidationError::Invalid(format!(
// "Found {} occurrences of event {}, but expected {}.",
// num_occurrences, critical_event.sig, num_occurrences_expected
// )));
// }

pb.inc(1);
}

pb.finish_and_clear();

if mismatch_found {
Expand Down
118 changes: 118 additions & 0 deletions tests/expected_dvfs/Deploy_3_wrong_event_Anvil.dvf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
{
"version": "0.9.1",
"id": "0x7bacfebc44215371ee7305a45ff0faad48cde0f1de062748c6299953b9ddcb5b",
"contract_name": "StructInEvent",
"address": "0x5fbdb2315678afecb367f032d93f642f64180aa3",
"chain_id": 31337,
"deployment_block_num": 2,
"init_block_num": 4,
"deployment_tx": "0x6e3482192028814aaf7d25796faf2cae5dc51e34f8cab42633f330b6b76e35b7",
"codehash": "0x5948787aac497637d2b6ede7bb077e2b1a14822d661e2fcf5cee4b79c4a81898",
"insecure": false,
"immutables": [],
"constructor_args": [],
"critical_storage_variables": [
{
"slot": "0x0",
"offset": 0,
"var_name": "x",
"var_type": "t_uint256",
"value": "0x00000000000000000000000000000000000000000000000000000000000001c8",
"value_hint": "456",
"comparison_operator": "Equal"
},
{
"slot": "0x1",
"offset": 0,
"var_name": "S.A",
"var_type": "t_uint256",
"value": "0x0000000000000000000000000000000000000000000000000000000000000040",
"value_hint": "64",
"comparison_operator": "Equal"
},
{
"slot": "0x2",
"offset": 0,
"var_name": "S.B",
"var_type": "t_address",
"value": "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce",
"comparison_operator": "Equal"
},
{
"slot": "0x2",
"offset": 20,
"var_name": "S.C",
"var_type": "t_bool",
"value": "0x01",
"value_hint": "true",
"comparison_operator": "Equal"
},
{
"slot": "0x3",
"offset": 8,
"var_name": "S.D[1]",
"var_type": "t_uint64",
"value": "0x000000000000002a",
"value_hint": "42",
"comparison_operator": "Equal"
},
{
"slot": "0x3",
"offset": 24,
"var_name": "S.D[3]",
"var_type": "t_uint64",
"value": "0x0000000000000003",
"value_hint": "3",
"comparison_operator": "Equal"
},
{
"slot": "0x4",
"offset": 8,
"var_name": "S.D[5]",
"var_type": "t_uint64",
"value": "0x000000000000007c",
"value_hint": "124",
"comparison_operator": "Equal"
},
{
"slot": "0x5",
"offset": 0,
"var_name": "S.E",
"var_type": "t_uint128",
"value": "0x00000000000000000000000000000080",
"value_hint": "128",
"comparison_operator": "Equal"
}
],
"critical_events": [
{
"sig": "Huh((uint256,address,bool,uint64[6],uint128))",
"topic0": "0x5958d02c6f25c2638c5ceaf6c12d534c7ba06054374767984e828e32ddd5927a",
"occurrences": [
{
"topics": [
"0x5958d02c6f25c2638c5ceaf6c12d534c7ba06054374767984e828e32ddd5927a"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000004100000000000000000000000095ad61b0a150d79219dcf64e1e6cc01f0b64c4ce00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007c0000000000000000000000000000000000000000000000000000000000000080"
},
{
"topics": [
"0x5958d02c6f25c2638c5ceaf6c12d534c7ba06054374767984e828e32ddd5927a"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000095ad61b0a150d79219dcf64e1e6cc01f0b64c4ce00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007c0000000000000000000000000000000000000000000000000000000000000080"
}
]
}
],
"unvalidated_metadata": {
"author_name": "Author",
"description": "System Description",
"hardfork": [
"paris",
"shanghai"
],
"audit_report": "https://example.org/report.pdf",
"source_url": "https://github.com/source/code",
"security_contact": "security@example.org"
}
}
Loading
Loading