Skip to content

Commit af9c793

Browse files
Address review
1 parent ef6cc7f commit af9c793

6 files changed

Lines changed: 76 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313

1414
- `#[derive(Fuzzable)]` macro that automatically generates `Fuzzable` trait implementations for structs and enums
1515
- `SNFOUNDRY_CACHE` environment variable to allow to specify a custom cache directory
16-
- Contract debug traces now include emitted Starknet events via the `events` trace component and `detailed` trace verbosity. A dedicated reversed data transformer decodes raw keys and values of an event into a struct-like output.
16+
- Contract debug traces now include emitted Starknet events via the `events` trace component and `detailed` trace verbosity, rendering ABI-decodable events in a struct-like format.
1717

1818
#### Changed
1919

crates/debugging/src/trace/collect.rs

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use cheatnet::runtime_extensions::call_to_blockifier_runtime_extension::rpc::{
1010
};
1111
use cheatnet::trace_data::{CallTrace, CallTraceNode};
1212
use data_transformer::{
13-
ReverseTransformError, reverse_transform_event, reverse_transform_input,
14-
reverse_transform_output,
13+
ReverseTransformError, ReverseTransformEventError, reverse_transform_event,
14+
reverse_transform_input, reverse_transform_output,
1515
};
1616
use starknet_api::core::ClassHash;
1717
use starknet_api::execution_utils::format_panic_data;
@@ -200,7 +200,11 @@ fn collect_event(event: &OrderedEvent, abi: &[AbiEntry]) -> Event {
200200

201201
match reverse_transform_event(&keys, &data, abi) {
202202
Ok(decoded) => Event::Decoded(decoded),
203-
Err(_) => Event::Raw { keys, data },
203+
Err(
204+
ReverseTransformEventError::EventNotFound(_)
205+
| ReverseTransformEventError::UnsupportedUntypedEvent(_),
206+
) => Event::Raw { keys, data },
207+
Err(error) => panic!("Failed to decode event: {error}"),
204208
}
205209
}
206210

@@ -218,7 +222,11 @@ mod tests {
218222
use cheatnet::trace_data::CallTrace;
219223
use starknet_api::core::{ClassHash, EntryPointSelector};
220224
use starknet_api::transaction::fields::Calldata;
221-
use starknet_rust::core::types::contract::AbiEntry;
225+
use starknet_api::transaction::{EventContent, EventData, EventKey};
226+
use starknet_rust::core::types::contract::{
227+
AbiEntry, AbiEvent, AbiEventEnum, EventField, EventFieldKind, TypedAbiEvent,
228+
};
229+
use starknet_rust::core::utils::get_selector_from_name;
222230
use starknet_types_core::felt::Felt;
223231
use std::collections::{HashMap, HashSet};
224232
use std::sync::Arc;
@@ -250,6 +258,34 @@ mod tests {
250258
Context::for_testing(store, Components::new(HashSet::new()))
251259
}
252260

261+
fn make_ordered_event(keys: Vec<Felt>, data: Vec<Felt>) -> OrderedEvent {
262+
OrderedEvent {
263+
order: 0,
264+
event: EventContent {
265+
keys: keys.into_iter().map(EventKey).collect(),
266+
data: EventData(data),
267+
},
268+
}
269+
}
270+
271+
fn typed_enum_event(name: &str, variants: &[(&str, &str, EventFieldKind)]) -> AbiEntry {
272+
AbiEntry::Event(AbiEvent::Typed(TypedAbiEvent::Enum(AbiEventEnum {
273+
name: name.to_string(),
274+
variants: variants
275+
.iter()
276+
.map(|(name, ty, kind)| EventField {
277+
name: (*name).to_string(),
278+
r#type: (*ty).to_string(),
279+
kind: kind.clone(),
280+
})
281+
.collect(),
282+
})))
283+
}
284+
285+
fn selector(name: &str) -> Felt {
286+
get_selector_from_name(name).unwrap()
287+
}
288+
253289
#[test]
254290
fn collect_selector_falls_back_to_hex_when_not_in_map() {
255291
let class_hash = ClassHash::default();
@@ -333,4 +369,31 @@ mod tests {
333369
let result = collector.collect_transformed_call_result(&[]);
334370
assert_eq!(result.0, "success: 0x1, 0x2a, 0xff");
335371
}
372+
373+
#[test]
374+
fn collect_event_falls_back_to_raw_when_event_not_in_abi() {
375+
let event = make_ordered_event(vec![Felt::from(0x123)], vec![Felt::from(0x456)]);
376+
377+
let result = collect_event(&event, &[]);
378+
379+
match result {
380+
Event::Raw { keys, data } => {
381+
assert_eq!(keys, vec![Felt::from(0x123)]);
382+
assert_eq!(data, vec![Felt::from(0x456)]);
383+
}
384+
Event::Decoded(decoded) => panic!("expected raw event fallback, got {decoded}"),
385+
}
386+
}
387+
388+
#[test]
389+
#[should_panic(expected = "Failed to decode event: abi is invalid")]
390+
fn collect_event_panics_on_invalid_event_abi() {
391+
let abi = vec![typed_enum_event(
392+
"test::Event",
393+
&[("Missing", "test::MissingEvent", EventFieldKind::Nested)],
394+
)];
395+
let event = make_ordered_event(vec![selector("Missing")], vec![]);
396+
397+
collect_event(&event, &abi);
398+
}
336399
}

crates/debugging/src/trace/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ pub struct Events(pub Vec<Event>);
7070
pub enum Event {
7171
/// A successfully reverse-transformed event, pretty-formatted as a human-readable struct.
7272
Decoded(String),
73-
/// A fallback for legacy Cairo1 events, events from contract which is missing an ABI, etc.
73+
/// A fallback for legacy Cairo1 events, events without matching ABI entries, or non-standard raw events.
7474
Raw { keys: Vec<Felt>, data: Vec<Felt> },
7575
}
7676

crates/forge/tests/e2e/debugging.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ fn detailed_debugging_trace_message(test_name: &str, package_name: &str) -> Stri
256256
│ ├─ [caller address] [..]
257257
│ ├─ [call type] Call
258258
│ ├─ [call result] success: array![RecursiveCall {{ contract_address: ContractAddress([..]), payload: array![RecursiveCall {{ contract_address: ContractAddress([..]), payload: array![] }}, RecursiveCall {{ contract_address: ContractAddress([..]), payload: array![] }}] }}, RecursiveCall {{ contract_address: ContractAddress([..]), payload: array![] }}]
259-
│ ├─ [events] [Event::CallsExecuted(CallsExecuted {{ calls_len: 0x2 }})]
259+
│ ├─ [events] [CallsExecuted {{ calls_len: 0x2 }}]
260260
│ ├─ [L2 gas] [..]
261261
│ ├─ [selector] execute_calls
262262
│ │ ├─ [contract name] SimpleContract
@@ -266,7 +266,7 @@ fn detailed_debugging_trace_message(test_name: &str, package_name: &str) -> Stri
266266
│ │ ├─ [caller address] [..]
267267
│ │ ├─ [call type] Call
268268
│ │ ├─ [call result] success: array![RecursiveCall {{ contract_address: ContractAddress([..]), payload: array![] }}, RecursiveCall {{ contract_address: ContractAddress([..]), payload: array![] }}]
269-
│ │ ├─ [events] [Event::CallsExecuted(CallsExecuted {{ calls_len: 0x2 }})]
269+
│ │ ├─ [events] [CallsExecuted {{ calls_len: 0x2 }}]
270270
│ │ ├─ [L2 gas] [..]
271271
│ │ ├─ [selector] execute_calls
272272
│ │ │ ├─ [contract name] SimpleContract
@@ -276,7 +276,7 @@ fn detailed_debugging_trace_message(test_name: &str, package_name: &str) -> Stri
276276
│ │ │ ├─ [caller address] [..]
277277
│ │ │ ├─ [call type] Call
278278
│ │ │ ├─ [call result] success: array![]
279-
│ │ │ ├─ [events] [Event::CallsExecuted(CallsExecuted {{ calls_len: 0x0 }})]
279+
│ │ │ ├─ [events] [CallsExecuted {{ calls_len: 0x0 }}]
280280
│ │ │ └─ [L2 gas] [..]
281281
│ │ └─ [selector] execute_calls
282282
│ │ ├─ [contract name] SimpleContract
@@ -286,7 +286,7 @@ fn detailed_debugging_trace_message(test_name: &str, package_name: &str) -> Stri
286286
│ │ ├─ [caller address] [..]
287287
│ │ ├─ [call type] Call
288288
│ │ ├─ [call result] success: array![]
289-
│ │ ├─ [events] [Event::CallsExecuted(CallsExecuted {{ calls_len: 0x0 }})]
289+
│ │ ├─ [events] [CallsExecuted {{ calls_len: 0x0 }}]
290290
│ │ └─ [L2 gas] [..]
291291
│ └─ [selector] execute_calls
292292
│ ├─ [contract name] SimpleContract
@@ -296,7 +296,7 @@ fn detailed_debugging_trace_message(test_name: &str, package_name: &str) -> Stri
296296
│ ├─ [caller address] [..]
297297
│ ├─ [call type] Call
298298
│ ├─ [call result] success: array![]
299-
│ ├─ [events] [Event::CallsExecuted(CallsExecuted {{ calls_len: 0x0 }})]
299+
│ ├─ [events] [CallsExecuted {{ calls_len: 0x0 }}]
300300
│ └─ [L2 gas] [..]
301301
└─ [selector] fail
302302
├─ [contract name] SimpleContract

crates/forge/tests/e2e/snapshots/debugging/main__e2e__debugging__debugging_trace_events_component_only@2.18.0.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ expression: stdout
88
[PASS] debugging_events_integrationtest::test_trace::test_debugging_trace_events_component (l1_gas: ~0, l1_data_gas: ~96, l2_gas: ~304300)
99
[test name] debugging_events_integrationtest::test_trace::test_debugging_trace_events_component
1010
└─ [selector] emit_event
11-
└─ [events] [Event::ValueEmitted(ValueEmitted { value: 0x2a })]
11+
└─ [events] [ValueEmitted { value: 0x2a }]

crates/forge/tests/e2e/snapshots/debugging/main__e2e__debugging__debugging_trace_multiple_events_component@2.18.0.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ expression: stdout
88
[PASS] debugging_events_integrationtest::test_trace::test_debugging_trace_multiple_events (l1_gas: ~0, l1_data_gas: ~96, l2_gas: ~332360)
99
[test name] debugging_events_integrationtest::test_trace::test_debugging_trace_multiple_events
1010
└─ [selector] emit_two_events
11-
└─ [events] [Event::ValueEmitted(ValueEmitted { value: 0x2a }), Event::ValueEmitted(ValueEmitted { value: 0x2b })]
11+
└─ [events] [ValueEmitted { value: 0x2a }, ValueEmitted { value: 0x2b }]

0 commit comments

Comments
 (0)