diff --git a/crates/blockifier/feature_contracts/cairo0/compiled/test_contract_compiled.json b/crates/blockifier/feature_contracts/cairo0/compiled/test_contract_compiled.json index a2fe7d15f7..b3f621d7e7 100644 --- a/crates/blockifier/feature_contracts/cairo0/compiled/test_contract_compiled.json +++ b/crates/blockifier/feature_contracts/cairo0/compiled/test_contract_compiled.json @@ -792,7 +792,26 @@ "L1_HANDLER": [] }, "program": { - "attributes": [], + "attributes": [ + { + "accessible_scopes": [ + "__main__", + "__main__", + "__main__.fail" + ], + "end_pc": 1186, + "flow_tracking_data": { + "ap_tracking": { + "group": 95, + "offset": 0 + }, + "reference_ids": {} + }, + "name": "error_message", + "start_pc": 1182, + "value": "You shall not pass!" + } + ], "builtins": [ "pedersen", "range_check", diff --git a/crates/blockifier/feature_contracts/cairo0/test_contract.cairo b/crates/blockifier/feature_contracts/cairo0/test_contract.cairo index 7354464f7a..646aeca672 100644 --- a/crates/blockifier/feature_contracts/cairo0/test_contract.cairo +++ b/crates/blockifier/feature_contracts/cairo0/test_contract.cairo @@ -274,7 +274,9 @@ func invoke_call_chain{syscall_ptr: felt*}(calldata_len: felt, calldata: felt*) @external func fail() { - assert 0 = 1; + with_attr error_message("You shall not pass!") { + assert 0 = 1; + } return (); } diff --git a/crates/blockifier/src/execution/stack_trace.rs b/crates/blockifier/src/execution/stack_trace.rs index c6a15e6a68..8028958b22 100644 --- a/crates/blockifier/src/execution/stack_trace.rs +++ b/crates/blockifier/src/execution/stack_trace.rs @@ -66,18 +66,24 @@ impl From<&EntryPointErrorFrame> for String { pub struct VmExceptionFrame { pc: Relocatable, + error_attr_value: Option, traceback: Option, } impl From<&VmExceptionFrame> for String { fn from(value: &VmExceptionFrame) -> Self { + let error_msg = match &value.error_attr_value { + Some(error_msg) => error_msg.clone(), + None => String::new(), + }; let vm_exception_preamble = format!("Error at pc={}:", value.pc); let vm_exception_traceback = if let Some(traceback) = &value.traceback { format!("\n{}", traceback) } else { "".to_string() }; - format!("{vm_exception_preamble}{vm_exception_traceback}") + // TODO(Aner): add test for error message in intermediate call" + format!("{error_msg}{vm_exception_preamble}{vm_exception_traceback}") } } @@ -217,8 +223,12 @@ fn extract_cairo_run_error_into_stack_trace( ) { if let CairoRunError::VmException(vm_exception) = error { error_stack.push( - VmExceptionFrame { pc: vm_exception.pc, traceback: vm_exception.traceback.clone() } - .into(), + VmExceptionFrame { + pc: vm_exception.pc, + error_attr_value: vm_exception.error_attr_value.clone(), + traceback: vm_exception.traceback.clone(), + } + .into(), ); extract_virtual_machine_error_into_stack_trace(error_stack, depth, &vm_exception.inner_exc); } else { diff --git a/crates/blockifier/src/execution/stack_trace_test.rs b/crates/blockifier/src/execution/stack_trace_test.rs index 6aa7523507..2361285166 100644 --- a/crates/blockifier/src/execution/stack_trace_test.rs +++ b/crates/blockifier/src/execution/stack_trace_test.rs @@ -118,6 +118,7 @@ Unknown location (pc=0:{entry_point_location}) 2: Error in the called contract (contract address: {test_contract_address_2_felt:#064x}, class \ hash: {test_contract_hash:#064x}, selector: {inner_entry_point_selector_felt:#064x}): +Error message: You shall not pass! Error at pc=0:1184: Cairo traceback (most recent call last): Unknown location (pc=0:1188) @@ -160,6 +161,10 @@ fn test_trace_callchain_ends_with_regular_call( #[case] expected_error: &str, #[case] expected_pc_locations: (u16, u16), ) { + let expected_with_attr_error_msg = match (cairo_version, last_func_name) { + (CairoVersion::Cairo0, "fail") => "Error message: You shall not pass!\n".to_string(), + _ => String::new(), + }; let chain_info = ChainInfo::create_for_testing(); let account_contract = FeatureContract::AccountWithoutValidations(cairo_version); let test_contract = FeatureContract::TestContract(cairo_version); @@ -234,7 +239,7 @@ Unknown location (pc=0:{entry_point_location}) 2: Error in the called contract (contract address: {contract_address_felt:#064x}, class hash: \ {test_contract_hash:#064x}, selector: {invoke_call_chain_selector_felt:#064x}): -Error at pc=0:{expected_pc0}: +{expected_with_attr_error_msg}Error at pc=0:{expected_pc0}: Cairo traceback (most recent call last): Unknown location (pc=0:{call_location}) Unknown location (pc=0:{expected_pc1}) @@ -285,6 +290,10 @@ fn test_trace_call_chain_with_syscalls( #[case] call_type: u8, #[case] expected_pcs: (u16, u16, u16, u16), ) { + let expected_with_attr_error_msg = match (cairo_version, last_func_name) { + (CairoVersion::Cairo0, "fail") => "Error message: You shall not pass!\n".to_string(), + _ => String::new(), + }; let chain_info = ChainInfo::create_for_testing(); let account_contract = FeatureContract::AccountWithoutValidations(cairo_version); let test_contract = FeatureContract::TestContract(cairo_version); @@ -387,7 +396,7 @@ Unknown location (pc=0:{call_location}) Unknown location (pc=0:{expected_pc1}) 3: {last_call_preamble}: -Error at pc=0:{expected_pc2}: +{expected_with_attr_error_msg}Error at pc=0:{expected_pc2}: Cairo traceback (most recent call last): Unknown location (pc=0:{expected_pc3})