Skip to content

Commit 0298724

Browse files
committed
Raise error in interact_with_state if address not exists
Towards #3331 commit-id:0a0b856d
1 parent 552b650 commit 0298724

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-5
lines changed

crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/execution/cheated_syscalls.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ pub fn storage_read(
257257
_remaining_gas: &mut u64,
258258
) -> SyscallResult<StorageReadResponse> {
259259
let original_storage_address = syscall_handler.base.call.storage_address;
260-
maybe_modify_storage_address(syscall_handler, cheatnet_state);
260+
maybe_modify_storage_address(syscall_handler, cheatnet_state)?;
261261

262262
let value = syscall_handler
263263
.base
@@ -282,7 +282,7 @@ pub fn storage_write(
282282
_remaining_gas: &mut u64,
283283
) -> SyscallResult<StorageWriteResponse> {
284284
let original_storage_address = syscall_handler.base.call.storage_address;
285-
maybe_modify_storage_address(syscall_handler, cheatnet_state);
285+
maybe_modify_storage_address(syscall_handler, cheatnet_state)?;
286286

287287
syscall_handler
288288
.base
@@ -303,19 +303,33 @@ pub fn storage_write(
303303
fn maybe_modify_storage_address(
304304
syscall_handler: &mut SyscallHintProcessor<'_>,
305305
cheatnet_state: &mut CheatnetState,
306-
) {
306+
) -> Result<(), StateError> {
307307
let contract_address = syscall_handler.storage_address();
308308
let test_address =
309309
TryFromHexStr::try_from_hex_str(TEST_ADDRESS).expect("Failed to parse `TEST_ADDRESS`");
310310

311311
if contract_address != test_address {
312-
return;
312+
return Ok(());
313313
}
314314

315315
let cheated_data = cheatnet_state.get_cheated_data(contract_address);
316316
if let Some(actual_address) = cheated_data.contract_address {
317+
let class_hash = syscall_handler
318+
.base
319+
.state
320+
.get_class_hash_at(actual_address)
321+
.expect("`get_class_hash_at` should never fail");
322+
323+
if class_hash == ClassHash::default() {
324+
return Err(StateError::StateReadError(format!(
325+
"Failed to interact with contract state because no contract is deployed at address {actual_address}"
326+
)));
327+
}
328+
317329
syscall_handler.base.call.storage_address = actual_address;
318330
}
331+
332+
Ok(())
319333
}
320334

321335
#[derive(Debug)]

crates/forge/tests/integration/interact_with_state.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use forge_runner::forge_config::ForgeTrackedResource;
22
use indoc::indoc;
3-
use test_utils::runner::{Contract, assert_passed};
3+
use test_utils::runner::{Contract, assert_case_output_contains, assert_failed, assert_passed};
44
use test_utils::running_tests::run_test_case;
55
use test_utils::test_case;
66

@@ -82,3 +82,40 @@ fn get_contract_address_in_interact_with_state() {
8282

8383
assert_passed(&result);
8484
}
85+
86+
#[test]
87+
fn raise_error_if_non_existent_address() {
88+
let test = test_case!(indoc!(
89+
r"
90+
use snforge_std::interact_with_state;
91+
92+
#[starknet::contract]
93+
mod SingleFelt {
94+
#[storage]
95+
pub struct Storage {
96+
pub field: felt252,
97+
}
98+
}
99+
100+
#[test]
101+
fn test_single_felt() {
102+
interact_with_state(
103+
0x123.try_into().unwrap(),
104+
|| {
105+
let mut state = SingleFelt::contract_state_for_testing();
106+
state.field.write(1);
107+
},
108+
)
109+
}
110+
"
111+
));
112+
113+
let result = run_test_case(&test, ForgeTrackedResource::CairoSteps);
114+
115+
assert_failed(&result);
116+
assert_case_output_contains(
117+
&result,
118+
"test_single_felt",
119+
"Failed to interact with contract state because no contract is deployed at address 0x0000000000000000000000000000000000000000000000000000000000000123",
120+
);
121+
}

0 commit comments

Comments
 (0)