Skip to content
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

chore(cairo_native): add native to stack trace test #2633

Merged
merged 1 commit into from
Dec 25, 2024
Merged
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
78 changes: 62 additions & 16 deletions crates/blockifier/src/execution/native/syscall_handler.rs
Original file line number Diff line number Diff line change
@@ -36,6 +36,8 @@ use crate::state::state_api::State;
use crate::transaction::objects::TransactionInfo;
use crate::versioned_constants::GasCosts;

pub const CALL_CONTRACT_SELECTOR_NAME: &str = "call_contract";
pub const LIBRARY_CALL_SELECTOR_NAME: &str = "library_call";
pub struct NativeSyscallHandler<'state> {
pub base: Box<SyscallHandlerBase<'state>>,

@@ -55,19 +57,6 @@ impl<'state> NativeSyscallHandler<'state> {
}
}

fn execute_inner_call(
&mut self,
entry_point: CallEntryPoint,
remaining_gas: &mut u64,
) -> SyscallResult<Retdata> {
let raw_retdata = self
.base
.execute_inner_call(entry_point, remaining_gas)
.map_err(|e| self.handle_error(remaining_gas, e))?;

Ok(Retdata(raw_retdata))
}

pub fn gas_costs(&self) -> &GasCosts {
self.base.context.gas_costs()
}
@@ -129,6 +118,36 @@ impl<'state> NativeSyscallHandler<'state> {
}
}

fn execute_inner_call(
&mut self,
entry_point: CallEntryPoint,
remaining_gas: &mut u64,
class_hash: ClassHash,
error_wrapper_fn: impl Fn(
SyscallExecutionError,
ClassHash,
ContractAddress,
EntryPointSelector,
) -> SyscallExecutionError,
) -> SyscallResult<Retdata> {
let entry_point_clone = entry_point.clone();
let raw_data = self.base.execute_inner_call(entry_point, remaining_gas).map_err(|e| {
self.handle_error(
remaining_gas,
match e {
SyscallExecutionError::Revert { .. } => e,
_ => error_wrapper_fn(
e,
class_hash,
entry_point_clone.storage_address,
entry_point_clone.entry_point_selector,
),
},
)
})?;
Ok(Retdata(raw_data))
}

fn get_tx_info_v1(&self) -> TxInfo {
let tx_info = &self.base.context.tx_context.tx_info;
TxInfo {
@@ -295,11 +314,13 @@ impl StarknetSyscallHandler for &mut NativeSyscallHandler<'_> {

let wrapper_calldata = Calldata(Arc::new(calldata.to_vec()));

let selector = EntryPointSelector(function_selector);

let entry_point = CallEntryPoint {
class_hash: Some(class_hash),
code_address: None,
entry_point_type: EntryPointType::External,
entry_point_selector: EntryPointSelector(function_selector),
entry_point_selector: selector,
calldata: wrapper_calldata,
// The call context remains the same in a library call.
storage_address: self.base.call.storage_address,
@@ -308,7 +329,17 @@ impl StarknetSyscallHandler for &mut NativeSyscallHandler<'_> {
initial_gas: *remaining_gas,
};

Ok(self.execute_inner_call(entry_point, remaining_gas)?.0)
let error_wrapper_function =
|e: SyscallExecutionError,
class_hash: ClassHash,
storage_address: ContractAddress,
selector: EntryPointSelector| {
e.as_lib_call_execution_error(class_hash, storage_address, selector)
};

Ok(self
.execute_inner_call(entry_point, remaining_gas, class_hash, error_wrapper_function)?
.0)
}

fn call_contract(
@@ -322,6 +353,11 @@ impl StarknetSyscallHandler for &mut NativeSyscallHandler<'_> {

let contract_address = ContractAddress::try_from(address)
.map_err(|error| self.handle_error(remaining_gas, error.into()))?;

let class_hash = self
.base
.get_class_hash_at(contract_address)
.map_err(|e| self.handle_error(remaining_gas, e))?;
if self.base.context.execution_mode == ExecutionMode::Validate
&& self.base.call.storage_address != contract_address
{
@@ -346,7 +382,17 @@ impl StarknetSyscallHandler for &mut NativeSyscallHandler<'_> {
initial_gas: *remaining_gas,
};

Ok(self.execute_inner_call(entry_point, remaining_gas)?.0)
let error_wrapper_function =
|e: SyscallExecutionError,
class_hash: ClassHash,
storage_address: ContractAddress,
selector: EntryPointSelector| {
e.as_call_contract_execution_error(class_hash, storage_address, selector)
};

Ok(self
.execute_inner_call(entry_point, remaining_gas, class_hash, error_wrapper_function)?
.0)
}

fn storage_read(
4 changes: 4 additions & 0 deletions crates/blockifier/src/execution/stack_trace.rs
Original file line number Diff line number Diff line change
@@ -709,6 +709,10 @@ fn extract_entry_point_execution_error_into_stack_trace(
EntryPointExecutionError::CairoRunError(cairo_run_error) => {
extract_cairo_run_error_into_stack_trace(error_stack, depth, cairo_run_error)
}
#[cfg(feature = "cairo_native")]
EntryPointExecutionError::NativeUnrecoverableError(error) => {
extract_syscall_execution_error_into_stack_trace(error_stack, depth, error)
}
EntryPointExecutionError::ExecutionFailed { error_trace } => {
error_stack.push(error_trace.clone().into())
}
270 changes: 177 additions & 93 deletions crates/blockifier/src/execution/stack_trace_test.rs
Original file line number Diff line number Diff line change
@@ -145,11 +145,10 @@ An ASSERT_EQ instruction failed: 1 != 0.
}

#[rstest]
fn test_stack_trace(
block_context: BlockContext,
#[values(CairoVersion::Cairo0, CairoVersion::Cairo1(RunnableCairo1::Casm))]
cairo_version: CairoVersion,
) {
#[case(CairoVersion::Cairo0)]
#[case(CairoVersion::Cairo1(RunnableCairo1::Casm))]
#[cfg_attr(feature = "cairo_native", case(CairoVersion::Cairo1(RunnableCairo1::Native)))]
fn test_stack_trace(block_context: BlockContext, #[case] cairo_version: CairoVersion) {
let chain_info = ChainInfo::create_for_testing();
let account = FeatureContract::AccountWithoutValidations(cairo_version);
let test_contract = FeatureContract::TestContract(cairo_version);
@@ -187,71 +186,68 @@ fn test_stack_trace(
)
.unwrap_err();

// Fetch PC locations from the compiled contract to compute the expected PC locations in the
// traceback. Computation is not robust, but as long as the cairo function itself is not edited,
// this computation should be stable.
let account_entry_point_offset =
account.get_entry_point_offset(selector_from_name(EXECUTE_ENTRY_POINT_NAME));
let execute_selector_felt = selector_from_name(EXECUTE_ENTRY_POINT_NAME).0;
let external_entry_point_selector_felt = selector_from_name(call_contract_function_name).0;
let entry_point_offset =
test_contract.get_entry_point_offset(selector_from_name(call_contract_function_name));
// Relative offsets of the test_call_contract entry point and the inner call.
let call_location = entry_point_offset.0 + 14;
let entry_point_location = entry_point_offset.0 - 3;
// Relative offsets of the account contract.
let account_call_location = account_entry_point_offset.0 + 18;
let account_entry_point_location = account_entry_point_offset.0 - 8;

let expected_trace_cairo0 = format!(
"Transaction execution has failed:
let expected_trace = match cairo_version {
CairoVersion::Cairo0 => {
// Fetch PC locations from the compiled contract to compute the expected PC locations in
// the traceback. Computation is not robust, but as long as the cairo
// function itself is not edited, this computation should be stable.
let account_entry_point_offset =
account.get_entry_point_offset(selector_from_name(EXECUTE_ENTRY_POINT_NAME));
let entry_point_offset = test_contract
.get_entry_point_offset(selector_from_name(call_contract_function_name));
// Relative offsets of the test_call_contract entry point and the inner call.
let call_location = entry_point_offset.0 + 14;
let entry_point_location = entry_point_offset.0 - 3;
// Relative offsets of the account contract.
let account_call_location = account_entry_point_offset.0 + 18;
let account_entry_point_location = account_entry_point_offset.0 - 8;
format!(
"Transaction execution has failed:
0: Error in the called contract (contract address: {account_address_felt:#064x}, class hash: \
{account_contract_hash:#064x}, selector: {execute_selector_felt:#064x}):
{account_contract_hash:#064x}, selector: {execute_selector_felt:#064x}):
Error at pc=0:7:
Cairo traceback (most recent call last):
Unknown location (pc=0:{account_call_location})
Unknown location (pc=0:{account_entry_point_location})
1: Error in the called contract (contract address: {test_contract_address_felt:#064x}, class hash: \
{test_contract_hash:#064x}, selector: {external_entry_point_selector_felt:#064x}):
{test_contract_hash:#064x}, selector: \
{external_entry_point_selector_felt:#064x}):
Error at pc=0:37:
Cairo traceback (most recent call last):
Unknown location (pc=0:{call_location})
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}):
hash: {test_contract_hash:#064x}, selector: \
{inner_entry_point_selector_felt:#064x}):
Error message: You shall not pass!
Error at pc=0:1294:
Cairo traceback (most recent call last):
Unknown location (pc=0:1298)
An ASSERT_EQ instruction failed: 1 != 0.
"
);

let expected_trace_cairo1 = format!(
"Transaction execution has failed:
)
.to_string()
}
CairoVersion::Cairo1(_) => format!(
"Transaction execution has failed:
0: Error in the called contract (contract address: {account_address_felt:#064x}, class hash: \
{account_contract_hash:#064x}, selector: {execute_selector_felt:#064x}):
{account_contract_hash:#064x}, selector: {execute_selector_felt:#064x}):
Execution failed. Failure reason:
Error in contract (contract address: {account_address_felt:#064x}, class hash: \
{account_contract_hash:#064x}, selector: {execute_selector_felt:#064x}):
{account_contract_hash:#064x}, selector: {execute_selector_felt:#064x}):
Error in contract (contract address: {test_contract_address_felt:#064x}, class hash: \
{test_contract_hash:#064x}, selector: {external_entry_point_selector_felt:#064x}):
{test_contract_hash:#064x}, selector: {external_entry_point_selector_felt:#064x}):
Error in contract (contract address: {test_contract_address_2_felt:#064x}, class hash: \
{test_contract_hash:#064x}, selector: {inner_entry_point_selector_felt:#064x}):
{test_contract_hash:#064x}, selector: {inner_entry_point_selector_felt:#064x}):
0x6661696c ('fail').
"
);

let expected_trace = match cairo_version {
CairoVersion::Cairo0 => expected_trace_cairo0,
CairoVersion::Cairo1(RunnableCairo1::Casm) => expected_trace_cairo1,
#[cfg(feature = "cairo_native")]
CairoVersion::Cairo1(RunnableCairo1::Native) => {
panic!("Cairo Native is not yet supported")
}
)
.to_string(),
};

assert_eq!(tx_execution_error.to_string(), expected_trace);
@@ -262,6 +258,14 @@ Error in contract (contract address: {test_contract_address_2_felt:#064x}, class
#[case(CairoVersion::Cairo0, "fail", "An ASSERT_EQ instruction failed: 1 != 0.", (1294_u16, 1245_u16))]
#[case(CairoVersion::Cairo1(RunnableCairo1::Casm), "invoke_call_chain", "0x4469766973696f6e2062792030 ('Division by 0')", (0_u16, 0_u16))]
#[case(CairoVersion::Cairo1(RunnableCairo1::Casm), "fail", "0x6661696c ('fail')", (0_u16, 0_u16))]
#[cfg_attr(
feature = "cairo_native",
case(CairoVersion::Cairo1(RunnableCairo1::Native), "invoke_call_chain", "0x4469766973696f6e2062792030 ('Division by 0')", (0_u16, 0_u16))
)]
#[cfg_attr(
feature = "cairo_native",
case(CairoVersion::Cairo1(RunnableCairo1::Native), "fail", "0x6661696c ('fail')", (0_u16, 0_u16))
)]
fn test_trace_callchain_ends_with_regular_call(
block_context: BlockContext,
#[case] cairo_version: CairoVersion,
@@ -315,13 +319,14 @@ fn test_trace_callchain_ends_with_regular_call(
)
.unwrap_err();

let account_entry_point_offset =
account_contract.get_entry_point_offset(selector_from_name(EXECUTE_ENTRY_POINT_NAME));
let entry_point_offset = test_contract.get_entry_point_offset(invoke_call_chain_selector);
let execute_selector_felt = selector_from_name(EXECUTE_ENTRY_POINT_NAME).0;

let expected_trace = match cairo_version {
CairoVersion::Cairo0 => {
let account_entry_point_offset = account_contract
.get_entry_point_offset(selector_from_name(EXECUTE_ENTRY_POINT_NAME));
let entry_point_offset =
test_contract.get_entry_point_offset(invoke_call_chain_selector);
let call_location = entry_point_offset.0 + 12;
let entry_point_location = entry_point_offset.0 - 61;
// Relative offsets of the account contract.
@@ -356,7 +361,7 @@ Unknown location (pc=0:{expected_pc1})
"
)
}
CairoVersion::Cairo1(RunnableCairo1::Casm) => {
CairoVersion::Cairo1(_) => {
format!(
"Transaction execution has failed:
0: Error in the called contract (contract address: {account_address_felt:#064x}, class hash: \
@@ -372,10 +377,6 @@ Error in contract (contract address: {contract_address_felt:#064x}, class hash:
"
)
}
#[cfg(feature = "cairo_native")]
CairoVersion::Cairo1(RunnableCairo1::Native) => {
todo!("Cairo Native is not yet supported here")
}
};

assert_eq!(tx_execution_error.to_string(), expected_trace);
@@ -390,6 +391,22 @@ Error in contract (contract address: {contract_address_felt:#064x}, class hash:
#[case(CairoVersion::Cairo1(RunnableCairo1::Casm), "invoke_call_chain", "0x4469766973696f6e2062792030 ('Division by 0')", 1_u8, 1_u8, (9631_u16, 9700_u16, 0_u16, 0_u16))]
#[case(CairoVersion::Cairo1(RunnableCairo1::Casm), "fail", "0x6661696c ('fail')", 0_u8, 0_u8, (9631_u16, 9631_u16, 0_u16, 0_u16))]
#[case(CairoVersion::Cairo1(RunnableCairo1::Casm), "fail", "0x6661696c ('fail')", 0_u8, 1_u8, (9631_u16, 9700_u16, 0_u16, 0_u16))]
#[cfg_attr(
feature = "cairo_native",
case(CairoVersion::Cairo1(RunnableCairo1::Native), "invoke_call_chain", "0x4469766973696f6e2062792030 ('Division by 0')", 1_u8, 0_u8, (9631_u16, 9631_u16, 0_u16, 0_u16))
)]
#[cfg_attr(
feature = "cairo_native",
case(CairoVersion::Cairo1(RunnableCairo1::Native), "invoke_call_chain", "0x4469766973696f6e2062792030 ('Division by 0')", 1_u8, 1_u8, (9631_u16, 9700_u16, 0_u16, 0_u16))
)]
#[cfg_attr(
feature = "cairo_native",
case(CairoVersion::Cairo1(RunnableCairo1::Native), "fail", "0x6661696c ('fail')", 0_u8, 0_u8, (9631_u16, 9631_u16, 0_u16, 0_u16))
)]
#[cfg_attr(
feature = "cairo_native",
case(CairoVersion::Cairo1(RunnableCairo1::Native), "fail", "0x6661696c ('fail')", 0_u8, 1_u8, (9631_u16, 9700_u16, 0_u16, 0_u16))
)]
fn test_trace_call_chain_with_syscalls(
block_context: BlockContext,
#[case] cairo_version: CairoVersion,
@@ -456,9 +473,6 @@ fn test_trace_call_chain_with_syscalls(
)
.unwrap_err();

let account_entry_point_offset =
account_contract.get_entry_point_offset(selector_from_name(EXECUTE_ENTRY_POINT_NAME));
let entry_point_offset = test_contract.get_entry_point_offset(invoke_call_chain_selector);
let execute_selector_felt = selector_from_name(EXECUTE_ENTRY_POINT_NAME).0;

let last_call_preamble = if call_type == 0 {
@@ -475,6 +489,10 @@ fn test_trace_call_chain_with_syscalls(

let expected_trace = match cairo_version {
CairoVersion::Cairo0 => {
let account_entry_point_offset = account_contract
.get_entry_point_offset(selector_from_name(EXECUTE_ENTRY_POINT_NAME));
let entry_point_offset =
test_contract.get_entry_point_offset(invoke_call_chain_selector);
let call_location = entry_point_offset.0 + 12;
let entry_point_location = entry_point_offset.0 - 61;
// Relative offsets of the account contract.
@@ -513,7 +531,7 @@ Unknown location (pc=0:{expected_pc3})
"
)
}
CairoVersion::Cairo1(RunnableCairo1::Casm) => {
CairoVersion::Cairo1(_) => {
format!(
"Transaction execution has failed:
0: Error in the called contract (contract address: {account_address_felt:#064x}, class hash: \
@@ -531,17 +549,14 @@ Error in contract (contract address: {address_felt:#064x}, class hash: {test_con
"
)
}
#[cfg(feature = "cairo_native")]
CairoVersion::Cairo1(RunnableCairo1::Native) => {
todo!("Cairo Native not yet supported here.")
}
};

assert_eq!(tx_execution_error.to_string(), expected_trace);
}

// TODO(Arni, 1/5/2024): Cover version 0 declare transaction.
// TODO(Arni, 1/5/2024): Consider version 0 invoke.
#[cfg(not(feature = "cairo_native"))]
#[rstest]
#[case::validate_version_1(
TransactionType::InvokeFunction,
@@ -584,6 +599,66 @@ fn test_validate_trace(
#[case] tx_version: TransactionVersion,
#[values(CairoVersion::Cairo0, CairoVersion::Cairo1(RunnableCairo1::Casm))]
cairo_version: CairoVersion,
) {
test_validate_trace_fn(tx_type, entry_point_name, tx_version, cairo_version);
}

#[cfg(feature = "cairo_native")]
#[rstest]
#[case::validate_version_1(
TransactionType::InvokeFunction,
VALIDATE_ENTRY_POINT_NAME,
TransactionVersion::ONE
)]
#[case::validate_version_3(
TransactionType::InvokeFunction,
VALIDATE_ENTRY_POINT_NAME,
TransactionVersion::THREE
)]
#[case::validate_declare_version_1(
TransactionType::Declare,
VALIDATE_DECLARE_ENTRY_POINT_NAME,
TransactionVersion::ONE
)]
#[case::validate_declare_version_2(
TransactionType::Declare,
VALIDATE_DECLARE_ENTRY_POINT_NAME,
TransactionVersion::TWO
)]
#[case::validate_declare_version_3(
TransactionType::Declare,
VALIDATE_DECLARE_ENTRY_POINT_NAME,
TransactionVersion::THREE
)]
#[case::validate_deploy_version_1(
TransactionType::DeployAccount,
VALIDATE_DEPLOY_ENTRY_POINT_NAME,
TransactionVersion::ONE
)]
#[case::validate_deploy_version_3(
TransactionType::DeployAccount,
VALIDATE_DEPLOY_ENTRY_POINT_NAME,
TransactionVersion::THREE
)]
fn test_validate_trace(
#[case] tx_type: TransactionType,
#[case] entry_point_name: &str,
#[case] tx_version: TransactionVersion,
#[values(
CairoVersion::Cairo0,
CairoVersion::Cairo1(RunnableCairo1::Casm),
CairoVersion::Cairo1(RunnableCairo1::Native)
)]
cairo_version: CairoVersion,
) {
test_validate_trace_fn(tx_type, entry_point_name, tx_version, cairo_version);
}

fn test_validate_trace_fn(
tx_type: TransactionType,
entry_point_name: &str,
tx_version: TransactionVersion,
cairo_version: CairoVersion,
) {
let create_for_account_testing = &BlockContext::create_for_account_testing();
let block_context = create_for_account_testing;
@@ -634,18 +709,14 @@ An ASSERT_EQ instruction failed: 1 != 0.
",
class_hash.0
),
CairoVersion::Cairo1(RunnableCairo1::Casm) => format!(
CairoVersion::Cairo1(_) => format!(
"The `validate` entry point panicked with:
Error in contract (contract address: {contract_address:#064x}, class hash: {:#064x}, selector: \
{selector:#064x}):
0x496e76616c6964207363656e6172696f ('Invalid scenario').
",
class_hash.0
),
#[cfg(feature = "cairo_native")]
CairoVersion::Cairo1(RunnableCairo1::Native) => {
todo!("Cairo Native is not yet supported here.")
}
};

// Clean pc locations from the trace.
@@ -661,10 +732,12 @@ Error in contract (contract address: {contract_address:#064x}, class hash: {:#06
#[rstest]
/// Tests that hitting an execution error in an account contract constructor outputs the correct
/// traceback (including correct class hash, contract address and constructor entry point selector).
#[case(CairoVersion::Cairo0)]
#[case(CairoVersion::Cairo1(RunnableCairo1::Casm))]
#[cfg_attr(feature = "cairo_native", case(CairoVersion::Cairo1(RunnableCairo1::Native)))]
fn test_account_ctor_frame_stack_trace(
block_context: BlockContext,
#[values(CairoVersion::Cairo0, CairoVersion::Cairo1(RunnableCairo1::Casm))]
cairo_version: CairoVersion,
#[case] cairo_version: CairoVersion,
) {
let chain_info = &block_context.chain_info;
let faulty_account = FeatureContract::FaultyAccount(cairo_version);
@@ -709,7 +782,7 @@ Unknown location (pc=0:206)
An ASSERT_EQ instruction failed: 1 != 0.
"
.to_string(),
CairoVersion::Cairo1(RunnableCairo1::Casm) => format!(
CairoVersion::Cairo1(_) => format!(
"Execution failed. Failure reason:
Error in contract (contract address: {expected_address:#064x}, class hash: {:#064x}, selector: \
{expected_selector:#064x}):
@@ -718,10 +791,6 @@ Error in contract (contract address: {expected_address:#064x}, class hash: {:#06
class_hash.0
)
.to_string(),
#[cfg(feature = "cairo_native")]
CairoVersion::Cairo1(RunnableCairo1::Native) => {
todo!("Cairo Native not yet supported here.")
}
};

// Compare expected and actual error.
@@ -733,11 +802,13 @@ Error in contract (contract address: {expected_address:#064x}, class hash: {:#06
/// Tests that hitting an execution error in a contract constructor during a deploy syscall outputs
/// the correct traceback (including correct class hash, contract address and constructor entry
/// point selector).
#[case(CairoVersion::Cairo0)]
#[case(CairoVersion::Cairo1(RunnableCairo1::Casm))]
#[cfg_attr(feature = "cairo_native", case(CairoVersion::Cairo1(RunnableCairo1::Native)))]
fn test_contract_ctor_frame_stack_trace(
block_context: BlockContext,
default_all_resource_bounds: ValidResourceBounds,
#[values(CairoVersion::Cairo0, CairoVersion::Cairo1(RunnableCairo1::Casm))]
cairo_version: CairoVersion,
#[case] cairo_version: CairoVersion,
) {
let chain_info = &block_context.chain_info;
let account = FeatureContract::AccountWithoutValidations(cairo_version);
@@ -803,14 +874,14 @@ fn test_contract_ctor_frame_stack_trace(
faulty_class_hash.0, ctor_selector.0
),
);
let (execute_offset, deploy_offset, ctor_offset) = (
account.get_entry_point_offset(execute_selector).0,
account.get_entry_point_offset(deploy_contract_selector).0,
faulty_ctor.get_ctor_offset(Some(ctor_selector)).0,
);

let expected_error = match cairo_version {
CairoVersion::Cairo0 => {
let (execute_offset, deploy_offset, ctor_offset) = (
account.get_entry_point_offset(execute_selector).0,
account.get_entry_point_offset(deploy_contract_selector).0,
faulty_ctor.get_ctor_offset(Some(ctor_selector)).0,
);
format!(
"{frame_0}
Error at pc=0:7:
@@ -840,29 +911,42 @@ An ASSERT_EQ instruction failed: 1 != 0.
ctor_offset - 9
)
}
CairoVersion::Cairo1(RunnableCairo1::Casm) => {
CairoVersion::Cairo1(runnable_version) => {
let final_error = format!(
"Execution failed. Failure reason:
Error in contract (contract address: {expected_address:#064x}, class hash: {:#064x}, selector: \
{:#064x}):
0x496e76616c6964207363656e6172696f ('Invalid scenario').
",
faulty_class_hash.0, ctor_selector.0
);
// TODO(Dori, 1/1/2025): Get lowest level PC locations from Cairo1 errors (ctor offset
// does not appear in the trace).
format!(
"{frame_0}
match runnable_version {
RunnableCairo1::Casm => {
let (execute_offset, deploy_offset) = (
account.get_entry_point_offset(execute_selector).0,
account.get_entry_point_offset(deploy_contract_selector).0,
);
format!(
"{frame_0}
Error at pc=0:{}:
{frame_1}
Error at pc=0:{}:
{frame_2}
Execution failed. Failure reason:
Error in contract (contract address: {expected_address:#064x}, class hash: {:#064x}, selector: \
{:#064x}):
0x496e76616c6964207363656e6172696f ('Invalid scenario').
",
execute_offset + 165,
deploy_offset + 154,
faulty_class_hash.0,
ctor_selector.0
)
}
#[cfg(feature = "cairo_native")]
CairoVersion::Cairo1(RunnableCairo1::Native) => {
todo!("Cairo Native not yet supported here.")
{final_error}",
execute_offset + 165,
deploy_offset + 154,
)
}
#[cfg(feature = "cairo_native")]
RunnableCairo1::Native => format!(
"{frame_0}
{frame_1}
{frame_2}
{final_error}"
),
}
}
};