-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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(cheatcodes): mark unmatched expectedEmits as unemitted #8686
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ use crate::{ | |
use alloy_dyn_abi::{DecodedEvent, DynSolValue, EventExt, FunctionExt, JsonAbiExt}; | ||
use alloy_json_abi::{Error, Event, Function, JsonAbi}; | ||
use alloy_primitives::{Address, LogData, Selector, B256}; | ||
use alloy_sol_types::SolError; | ||
use foundry_common::{ | ||
abi::get_indexed_event, fmt::format_token, get_contract_name, ContractsByArtifact, SELECTOR_LEN, | ||
}; | ||
|
@@ -24,6 +25,7 @@ use foundry_evm_core::{ | |
}, | ||
}; | ||
use itertools::Itertools; | ||
use owo_colors::OwoColorize; | ||
use revm_inspectors::tracing::types::{DecodedCallLog, DecodedCallTrace}; | ||
use rustc_hash::FxHashMap; | ||
use std::{ | ||
|
@@ -327,10 +329,23 @@ impl CallTraceDecoder { | |
pub async fn populate_traces(&self, traces: &mut Vec<CallTraceNode>) { | ||
for node in traces { | ||
node.trace.decoded = self.decode_function(&node.trace).await; | ||
|
||
for log in node.logs.iter_mut() { | ||
log.decoded = self.decode_event(&log.raw_log).await; | ||
} | ||
|
||
if let Ok(e) = Vm::UnemittedEventError::abi_decode(&node.trace.output, false) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could actually add the unmatched event name to the revert error here, if that's desirable. |
||
let log_name = node.logs[e.positionExpected as usize] | ||
.decoded | ||
.name | ||
.as_mut() | ||
.expect("already decoded"); | ||
|
||
// set color to red fo the given event Id | ||
node.logs[e.positionExpected as usize].decoded.name = | ||
Some(log_name.red().to_string()); | ||
} | ||
|
||
if let Some(debug) = self.debug_identifier.as_ref() { | ||
if let Some(identified) = self.contracts.get(&node.trace.address) { | ||
debug.identify_node_steps(node, get_contract_name(identified)) | ||
|
@@ -475,7 +490,7 @@ impl CallTraceDecoder { | |
"parseJsonBytes32Array" | | ||
"writeJson" | | ||
// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions. | ||
"keyExists" | | ||
"keyExists" | | ||
"keyExistsJson" | | ||
"serializeBool" | | ||
"serializeUint" | | ||
|
@@ -491,7 +506,7 @@ impl CallTraceDecoder { | |
let mut decoded = func.abi_decode_input(&data[SELECTOR_LEN..], false).ok()?; | ||
let token = if func.name.as_str() == "parseJson" || | ||
// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions. | ||
func.name.as_str() == "keyExists" || | ||
func.name.as_str() == "keyExists" || | ||
func.name.as_str() == "keyExistsJson" | ||
{ | ||
"<JSON file>" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is incorrect as
sequence
only knows about events which came afterexpectEmit
which might not always be the only events emitted during executionI think we'd want to directly use tracing inspector indexes here, which should be possible after #8696
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey @topocount #8696 just got merged and
CheatcodesExecutor
was extended withtracing_inspector
fn which provides a reference to a tracing inspector from which you can check the log indicies directlythat way
sequence
value can be just set to something liketracer.traces().nodes().last().expect("no trace nodes").logs.len()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should have time to work on this this week
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@klkvr I've added
tracer.traces().nodes().last().expect("no trace nodes").logs.len()
toexpect_emit
but still need the offset to cover an edge case where a prior call completes successfully, otherwise that prior call is erroneously highlighted red instead.not_found.sequence
holds the tracer length call from from when the expected emit payload is initially pushed onto the stack.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is incorrect after my debugging outline below
hmm there are still edge cases that aren't satisfied by this, namely if multiple expectedEmits are added for a given call, the incorrect one (the one that is matched) is highlighted. I need to dig into this more.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it doesn't look like this is incrementing. Is this array lazily constructed then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a debug trace where we're expecting the same event twice:
Click here