Skip to content

Commit f21e510

Browse files
committed
feat(cheatnet): add "dynamic" return value fir mock_call
1 parent 0ff1663 commit f21e510

File tree

7 files changed

+61
-17
lines changed

7 files changed

+61
-17
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cheatnet/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ bimap.workspace = true
1313
camino.workspace = true
1414
starknet_api.workspace = true
1515
starknet-types-core.workspace = true
16+
starknet-crypto.workspace = true
1617
cairo-lang-casm.workspace = true
1718
cairo-lang-runner.workspace = true
1819
cairo-lang-utils.workspace = true

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ use blockifier::{
1818
state::state_api::State,
1919
};
2020
use cairo_vm::vm::runners::cairo_runner::{CairoRunner, ExecutionResources};
21+
use num_traits::Zero;
2122
use starknet_api::{
2223
core::ClassHash,
2324
deprecated_contract_class::EntryPointType,
2425
transaction::{Calldata, TransactionVersion},
2526
};
27+
use starknet_crypto::poseidon_hash_many;
2628
use std::collections::HashSet;
2729
use std::rc::Rc;
2830
use blockifier::execution::deprecated_syscalls::hint_processor::SyscallCounter;
@@ -268,11 +270,22 @@ fn get_mocked_function_cheat_status<'a>(
268270
if call.call_type == CallType::Delegate {
269271
return None;
270272
}
271-
272-
cheatnet_state
273+
match cheatnet_state
273274
.mocked_functions
274275
.get_mut(&call.storage_address)
275-
.and_then(|contract_functions| contract_functions.get_mut(&call.entry_point_selector))
276+
{
277+
None => None,
278+
Some(contract_functions) => {
279+
let call_data_hash = poseidon_hash_many(call.calldata.0.iter());
280+
let key = (call.entry_point_selector, call_data_hash);
281+
if contract_functions.contains_key(&key) {
282+
contract_functions.get_mut(&key)
283+
} else {
284+
let key_zero = (call.entry_point_selector, Felt::zero());
285+
contract_functions.get_mut(&key_zero)
286+
}
287+
}
288+
}
276289
}
277290

278291
fn mocked_call_info(call: CallEntryPoint, ret_data: Vec<Felt>) -> CallInfo {
Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::state::{CheatSpan, CheatStatus};
22
use crate::CheatnetState;
3+
use num_traits::Zero;
34
use starknet_api::core::{ContractAddress, EntryPointSelector};
5+
use starknet_crypto::poseidon_hash_many;
46
use starknet_types_core::felt::Felt;
57
use std::collections::hash_map::Entry;
68

@@ -9,26 +11,30 @@ impl CheatnetState {
911
&mut self,
1012
contract_address: ContractAddress,
1113
function_selector: EntryPointSelector,
14+
call_data: Option<Vec<Felt>>,
1215
ret_data: &[Felt],
1316
span: CheatSpan,
1417
) {
1518
let contract_mocked_functions = self.mocked_functions.entry(contract_address).or_default();
16-
17-
contract_mocked_functions.insert(
18-
function_selector,
19-
CheatStatus::Cheated(ret_data.to_vec(), span),
20-
);
19+
let call_data_hash = match call_data {
20+
Some(data) => poseidon_hash_many(data.iter()),
21+
None => Felt::zero(),
22+
};
23+
let key = (function_selector, call_data_hash);
24+
contract_mocked_functions.insert(key, CheatStatus::Cheated(ret_data.to_vec(), span));
2125
}
2226

2327
pub fn start_mock_call(
2428
&mut self,
2529
contract_address: ContractAddress,
2630
function_selector: EntryPointSelector,
31+
call_data: Option<Vec<Felt>>,
2732
ret_data: &[Felt],
2833
) {
2934
self.mock_call(
3035
contract_address,
3136
function_selector,
37+
call_data,
3238
ret_data,
3339
CheatSpan::Indefinite,
3440
);
@@ -38,10 +44,15 @@ impl CheatnetState {
3844
&mut self,
3945
contract_address: ContractAddress,
4046
function_selector: EntryPointSelector,
47+
call_data: Option<Vec<Felt>>,
4148
) {
4249
if let Entry::Occupied(mut e) = self.mocked_functions.entry(contract_address) {
4350
let contract_mocked_functions = e.get_mut();
44-
contract_mocked_functions.remove(&function_selector);
51+
let call_data_hash = match call_data {
52+
Some(data) => poseidon_hash_many(data.iter()),
53+
None => Felt::zero(),
54+
};
55+
contract_mocked_functions.remove(&(function_selector, call_data_hash));
4556
}
4657
}
4758
}

crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,26 +87,31 @@ impl<'a> ExtensionLogic for ForgeExtension<'a> {
8787
"mock_call" => {
8888
let contract_address = input_reader.read()?;
8989
let function_selector = input_reader.read()?;
90+
let call_data = input_reader.read()?;
9091
let span = input_reader.read()?;
91-
9292
let ret_data: Vec<_> = input_reader.read()?;
93-
9493
extended_runtime
9594
.extended_runtime
9695
.extension
9796
.cheatnet_state
98-
.mock_call(contract_address, function_selector, &ret_data, span);
97+
.mock_call(
98+
contract_address,
99+
function_selector,
100+
call_data,
101+
&ret_data,
102+
span,
103+
);
99104
Ok(CheatcodeHandlingResult::from_serializable(()))
100105
}
101106
"stop_mock_call" => {
102107
let contract_address = input_reader.read()?;
103108
let function_selector = input_reader.read()?;
104-
109+
let call_data = input_reader.read()?;
105110
extended_runtime
106111
.extended_runtime
107112
.extension
108113
.cheatnet_state
109-
.stop_mock_call(contract_address, function_selector);
114+
.stop_mock_call(contract_address, function_selector, call_data);
110115
Ok(CheatcodeHandlingResult::from_serializable(()))
111116
}
112117
"replace_bytecode" => {

crates/cheatnet/src/state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ pub struct CheatnetState {
331331
pub global_cheated_execution_info: ExecutionInfoMock,
332332

333333
pub mocked_functions:
334-
HashMap<ContractAddress, HashMap<EntryPointSelector, CheatStatus<Vec<Felt>>>>,
334+
HashMap<ContractAddress, HashMap<(EntryPointSelector, Felt), CheatStatus<Vec<Felt>>>>,
335335
pub replaced_bytecode_contracts: HashMap<ContractAddress, ClassHash>,
336336
pub detected_events: Vec<Event>,
337337
pub detected_messages_to_l1: Vec<MessageToL1>,

crates/cheatnet/tests/cheatcodes/mock_call.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ fn mock_call_simple() {
6868
cheatnet_state.start_mock_call(
6969
contract_address,
7070
felt_selector_from_name("get_thing"),
71+
None,
7172
&ret_data,
7273
);
7374

@@ -100,6 +101,7 @@ fn mock_call_stop() {
100101
cheatnet_state.start_mock_call(
101102
contract_address,
102103
felt_selector_from_name("get_thing"),
104+
None,
103105
&ret_data,
104106
);
105107

@@ -168,10 +170,10 @@ fn mock_call_double() {
168170
let selector = felt_selector_from_name("get_thing");
169171

170172
let ret_data = [Felt::from(123)];
171-
cheatnet_state.start_mock_call(contract_address, selector, &ret_data);
173+
cheatnet_state.start_mock_call(contract_address, selector, None, &ret_data);
172174

173175
let ret_data = [Felt::from(999)];
174-
cheatnet_state.start_mock_call(contract_address, selector, &ret_data);
176+
cheatnet_state.start_mock_call(contract_address, selector, None, &ret_data);
175177

176178
let output = call_contract(
177179
&mut cached_state,
@@ -214,6 +216,7 @@ fn mock_call_double_call() {
214216
cheatnet_state.start_mock_call(
215217
contract_address,
216218
felt_selector_from_name("get_thing"),
219+
None,
217220
&ret_data,
218221
);
219222

@@ -255,6 +258,7 @@ fn mock_call_proxy() {
255258
cheatnet_state.start_mock_call(
256259
contract_address,
257260
felt_selector_from_name("get_thing"),
261+
None,
258262
&ret_data,
259263
);
260264

@@ -303,6 +307,7 @@ fn mock_call_proxy_with_other_syscall() {
303307
cheatnet_state.start_mock_call(
304308
contract_address,
305309
felt_selector_from_name("get_thing"),
310+
None,
306311
&ret_data,
307312
);
308313

@@ -352,6 +357,7 @@ fn mock_call_inner_call_no_effect() {
352357
cheatnet_state.start_mock_call(
353358
contract_address,
354359
felt_selector_from_name("get_thing"),
360+
None,
355361
&ret_data,
356362
);
357363

@@ -407,6 +413,7 @@ fn mock_call_library_call_no_effect() {
407413
cheatnet_state.start_mock_call(
408414
contract_address,
409415
felt_selector_from_name("get_constant_thing"),
416+
None,
410417
&ret_data,
411418
);
412419

@@ -440,6 +447,7 @@ fn mock_call_before_deployment() {
440447
cheatnet_state.start_mock_call(
441448
precalculated_address,
442449
felt_selector_from_name("get_thing"),
450+
None,
443451
&ret_data,
444452
);
445453

@@ -482,6 +490,7 @@ fn mock_call_not_implemented() {
482490
cheatnet_state.start_mock_call(
483491
contract_address,
484492
felt_selector_from_name("get_thing_not_implemented"),
493+
None,
485494
&ret_data,
486495
);
487496

@@ -512,6 +521,7 @@ fn mock_call_in_constructor() {
512521
cheatnet_state.start_mock_call(
513522
balance_contract_address,
514523
felt_selector_from_name("get_balance"),
524+
None,
515525
&ret_data,
516526
);
517527

@@ -559,12 +569,14 @@ fn mock_call_two_methods() {
559569
cheatnet_state.start_mock_call(
560570
contract_address,
561571
felt_selector_from_name("get_thing"),
572+
None,
562573
&ret_data,
563574
);
564575

565576
cheatnet_state.start_mock_call(
566577
contract_address,
567578
felt_selector_from_name("get_constant_thing"),
579+
None,
568580
&ret_data,
569581
);
570582

@@ -602,6 +614,7 @@ fn mock_call_nonexisting_contract() {
602614
cheatnet_state.start_mock_call(
603615
contract_address,
604616
felt_selector_from_name("get_thing"),
617+
None,
605618
&ret_data,
606619
);
607620

0 commit comments

Comments
 (0)