foundry_cheatcodes/test/
expect.rs

1use std::{
2    collections::VecDeque,
3    fmt::{self, Display},
4};
5
6use crate::{Cheatcode, Cheatcodes, CheatsCtxt, Error, Result, Vm::*};
7use alloy_primitives::{
8    map::{hash_map::Entry, AddressHashMap, HashMap},
9    Address, Bytes, LogData as RawLog, U256,
10};
11use revm::interpreter::{InstructionResult, Interpreter, InterpreterAction, InterpreterResult};
12
13use super::revert_handlers::RevertParameters;
14/// Tracks the expected calls per address.
15///
16/// For each address, we track the expected calls per call data. We track it in such manner
17/// so that we don't mix together calldatas that only contain selectors and calldatas that contain
18/// selector and arguments (partial and full matches).
19///
20/// This then allows us to customize the matching behavior for each call data on the
21/// `ExpectedCallData` struct and track how many times we've actually seen the call on the second
22/// element of the tuple.
23pub type ExpectedCallTracker = HashMap<Address, HashMap<Bytes, (ExpectedCallData, u64)>>;
24
25#[derive(Clone, Debug)]
26pub struct ExpectedCallData {
27    /// The expected value sent in the call
28    pub value: Option<U256>,
29    /// The expected gas supplied to the call
30    pub gas: Option<u64>,
31    /// The expected *minimum* gas supplied to the call
32    pub min_gas: Option<u64>,
33    /// The number of times the call is expected to be made.
34    /// If the type of call is `NonCount`, this is the lower bound for the number of calls
35    /// that must be seen.
36    /// If the type of call is `Count`, this is the exact number of calls that must be seen.
37    pub count: u64,
38    /// The type of expected call.
39    pub call_type: ExpectedCallType,
40}
41
42/// The type of expected call.
43#[derive(Clone, Debug, PartialEq, Eq)]
44pub enum ExpectedCallType {
45    /// The call is expected to be made at least once.
46    NonCount,
47    /// The exact number of calls expected.
48    Count,
49}
50
51/// The type of expected revert.
52#[derive(Clone, Debug)]
53pub enum ExpectedRevertKind {
54    /// Expects revert from the next non-cheatcode call.
55    Default,
56    /// Expects revert from the next cheatcode call.
57    ///
58    /// The `pending_processing` flag is used to track whether we have exited
59    /// `expectCheatcodeRevert` context or not.
60    /// We have to track it to avoid expecting `expectCheatcodeRevert` call to revert itself.
61    Cheatcode { pending_processing: bool },
62}
63
64#[derive(Clone, Debug)]
65pub struct ExpectedRevert {
66    /// The expected data returned by the revert, None being any.
67    pub reason: Option<Vec<u8>>,
68    /// The depth at which the revert is expected.
69    pub depth: u64,
70    /// The type of expected revert.
71    pub kind: ExpectedRevertKind,
72    /// If true then only the first 4 bytes of expected data returned by the revert are checked.
73    pub partial_match: bool,
74    /// Contract expected to revert next call.
75    pub reverter: Option<Address>,
76    /// Address that reverted the call.
77    pub reverted_by: Option<Address>,
78    /// Max call depth reached during next call execution.
79    pub max_depth: u64,
80    /// Number of times this revert is expected.
81    pub count: u64,
82    /// Actual number of times this revert has been seen.
83    pub actual_count: u64,
84}
85
86#[derive(Clone, Debug)]
87pub struct ExpectedEmit {
88    /// The depth at which we expect this emit to have occurred
89    pub depth: u64,
90    /// The log we expect
91    pub log: Option<RawLog>,
92    /// The checks to perform:
93    /// ```text
94    /// ┌───────┬───────┬───────┬───────┬────┐
95    /// │topic 0│topic 1│topic 2│topic 3│data│
96    /// └───────┴───────┴───────┴───────┴────┘
97    /// ```
98    pub checks: [bool; 5],
99    /// If present, check originating address against this
100    pub address: Option<Address>,
101    /// If present, relax the requirement that topic 0 must be present. This allows anonymous
102    /// events with no indexed topics to be matched.
103    pub anonymous: bool,
104    /// Whether the log was actually found in the subcalls
105    pub found: bool,
106    /// Number of times the log is expected to be emitted
107    pub count: u64,
108}
109
110#[derive(Clone, Debug)]
111pub struct ExpectedCreate {
112    /// The address that deployed the contract
113    pub deployer: Address,
114    /// Runtime bytecode of the contract
115    pub bytecode: Bytes,
116    /// Whether deployed with CREATE or CREATE2
117    pub create_scheme: CreateScheme,
118}
119
120#[derive(Clone, Debug)]
121pub enum CreateScheme {
122    Create,
123    Create2,
124}
125
126impl Display for CreateScheme {
127    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
128        match self {
129            Self::Create => write!(f, "CREATE"),
130            Self::Create2 => write!(f, "CREATE2"),
131        }
132    }
133}
134
135impl CreateScheme {
136    pub fn eq(&self, create_scheme: revm::primitives::CreateScheme) -> bool {
137        matches!(
138            (self, create_scheme),
139            (Self::Create, revm::primitives::CreateScheme::Create) |
140                (Self::Create2, revm::primitives::CreateScheme::Create2 { .. })
141        )
142    }
143}
144
145impl Cheatcode for expectCall_0Call {
146    fn apply(&self, state: &mut Cheatcodes) -> Result {
147        let Self { callee, data } = self;
148        expect_call(state, callee, data, None, None, None, 1, ExpectedCallType::NonCount)
149    }
150}
151
152impl Cheatcode for expectCall_1Call {
153    fn apply(&self, state: &mut Cheatcodes) -> Result {
154        let Self { callee, data, count } = self;
155        expect_call(state, callee, data, None, None, None, *count, ExpectedCallType::Count)
156    }
157}
158
159impl Cheatcode for expectCall_2Call {
160    fn apply(&self, state: &mut Cheatcodes) -> Result {
161        let Self { callee, msgValue, data } = self;
162        expect_call(state, callee, data, Some(msgValue), None, None, 1, ExpectedCallType::NonCount)
163    }
164}
165
166impl Cheatcode for expectCall_3Call {
167    fn apply(&self, state: &mut Cheatcodes) -> Result {
168        let Self { callee, msgValue, data, count } = self;
169        expect_call(
170            state,
171            callee,
172            data,
173            Some(msgValue),
174            None,
175            None,
176            *count,
177            ExpectedCallType::Count,
178        )
179    }
180}
181
182impl Cheatcode for expectCall_4Call {
183    fn apply(&self, state: &mut Cheatcodes) -> Result {
184        let Self { callee, msgValue, gas, data } = self;
185        expect_call(
186            state,
187            callee,
188            data,
189            Some(msgValue),
190            Some(*gas),
191            None,
192            1,
193            ExpectedCallType::NonCount,
194        )
195    }
196}
197
198impl Cheatcode for expectCall_5Call {
199    fn apply(&self, state: &mut Cheatcodes) -> Result {
200        let Self { callee, msgValue, gas, data, count } = self;
201        expect_call(
202            state,
203            callee,
204            data,
205            Some(msgValue),
206            Some(*gas),
207            None,
208            *count,
209            ExpectedCallType::Count,
210        )
211    }
212}
213
214impl Cheatcode for expectCallMinGas_0Call {
215    fn apply(&self, state: &mut Cheatcodes) -> Result {
216        let Self { callee, msgValue, minGas, data } = self;
217        expect_call(
218            state,
219            callee,
220            data,
221            Some(msgValue),
222            None,
223            Some(*minGas),
224            1,
225            ExpectedCallType::NonCount,
226        )
227    }
228}
229
230impl Cheatcode for expectCallMinGas_1Call {
231    fn apply(&self, state: &mut Cheatcodes) -> Result {
232        let Self { callee, msgValue, minGas, data, count } = self;
233        expect_call(
234            state,
235            callee,
236            data,
237            Some(msgValue),
238            None,
239            Some(*minGas),
240            *count,
241            ExpectedCallType::Count,
242        )
243    }
244}
245
246impl Cheatcode for expectEmit_0Call {
247    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
248        let Self { checkTopic1, checkTopic2, checkTopic3, checkData } = *self;
249        expect_emit(
250            ccx.state,
251            ccx.ecx.journaled_state.depth(),
252            [true, checkTopic1, checkTopic2, checkTopic3, checkData],
253            None,
254            false,
255            1,
256        )
257    }
258}
259
260impl Cheatcode for expectEmit_1Call {
261    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
262        let Self { checkTopic1, checkTopic2, checkTopic3, checkData, emitter } = *self;
263        expect_emit(
264            ccx.state,
265            ccx.ecx.journaled_state.depth(),
266            [true, checkTopic1, checkTopic2, checkTopic3, checkData],
267            Some(emitter),
268            false,
269            1,
270        )
271    }
272}
273
274impl Cheatcode for expectEmit_2Call {
275    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
276        let Self {} = self;
277        expect_emit(ccx.state, ccx.ecx.journaled_state.depth(), [true; 5], None, false, 1)
278    }
279}
280
281impl Cheatcode for expectEmit_3Call {
282    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
283        let Self { emitter } = *self;
284        expect_emit(ccx.state, ccx.ecx.journaled_state.depth(), [true; 5], Some(emitter), false, 1)
285    }
286}
287
288impl Cheatcode for expectEmit_4Call {
289    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
290        let Self { checkTopic1, checkTopic2, checkTopic3, checkData, count } = *self;
291        expect_emit(
292            ccx.state,
293            ccx.ecx.journaled_state.depth(),
294            [true, checkTopic1, checkTopic2, checkTopic3, checkData],
295            None,
296            false,
297            count,
298        )
299    }
300}
301
302impl Cheatcode for expectEmit_5Call {
303    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
304        let Self { checkTopic1, checkTopic2, checkTopic3, checkData, emitter, count } = *self;
305        expect_emit(
306            ccx.state,
307            ccx.ecx.journaled_state.depth(),
308            [true, checkTopic1, checkTopic2, checkTopic3, checkData],
309            Some(emitter),
310            false,
311            count,
312        )
313    }
314}
315
316impl Cheatcode for expectEmit_6Call {
317    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
318        let Self { count } = *self;
319        expect_emit(ccx.state, ccx.ecx.journaled_state.depth(), [true; 5], None, false, count)
320    }
321}
322
323impl Cheatcode for expectEmit_7Call {
324    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
325        let Self { emitter, count } = *self;
326        expect_emit(
327            ccx.state,
328            ccx.ecx.journaled_state.depth(),
329            [true; 5],
330            Some(emitter),
331            false,
332            count,
333        )
334    }
335}
336
337impl Cheatcode for expectEmitAnonymous_0Call {
338    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
339        let Self { checkTopic0, checkTopic1, checkTopic2, checkTopic3, checkData } = *self;
340        expect_emit(
341            ccx.state,
342            ccx.ecx.journaled_state.depth(),
343            [checkTopic0, checkTopic1, checkTopic2, checkTopic3, checkData],
344            None,
345            true,
346            1,
347        )
348    }
349}
350
351impl Cheatcode for expectEmitAnonymous_1Call {
352    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
353        let Self { checkTopic0, checkTopic1, checkTopic2, checkTopic3, checkData, emitter } = *self;
354        expect_emit(
355            ccx.state,
356            ccx.ecx.journaled_state.depth(),
357            [checkTopic0, checkTopic1, checkTopic2, checkTopic3, checkData],
358            Some(emitter),
359            true,
360            1,
361        )
362    }
363}
364
365impl Cheatcode for expectEmitAnonymous_2Call {
366    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
367        let Self {} = self;
368        expect_emit(ccx.state, ccx.ecx.journaled_state.depth(), [true; 5], None, true, 1)
369    }
370}
371
372impl Cheatcode for expectEmitAnonymous_3Call {
373    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
374        let Self { emitter } = *self;
375        expect_emit(ccx.state, ccx.ecx.journaled_state.depth(), [true; 5], Some(emitter), true, 1)
376    }
377}
378
379impl Cheatcode for expectCreateCall {
380    fn apply(&self, state: &mut Cheatcodes) -> Result {
381        let Self { bytecode, deployer } = self;
382        expect_create(state, bytecode.clone(), *deployer, CreateScheme::Create)
383    }
384}
385
386impl Cheatcode for expectCreate2Call {
387    fn apply(&self, state: &mut Cheatcodes) -> Result {
388        let Self { bytecode, deployer } = self;
389        expect_create(state, bytecode.clone(), *deployer, CreateScheme::Create2)
390    }
391}
392
393impl Cheatcode for expectRevert_0Call {
394    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
395        let Self {} = self;
396        expect_revert(ccx.state, None, ccx.ecx.journaled_state.depth(), false, false, None, 1)
397    }
398}
399
400impl Cheatcode for expectRevert_1Call {
401    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
402        let Self { revertData } = self;
403        expect_revert(
404            ccx.state,
405            Some(revertData.as_ref()),
406            ccx.ecx.journaled_state.depth(),
407            false,
408            false,
409            None,
410            1,
411        )
412    }
413}
414
415impl Cheatcode for expectRevert_2Call {
416    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
417        let Self { revertData } = self;
418        expect_revert(
419            ccx.state,
420            Some(revertData),
421            ccx.ecx.journaled_state.depth(),
422            false,
423            false,
424            None,
425            1,
426        )
427    }
428}
429
430impl Cheatcode for expectRevert_3Call {
431    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
432        let Self { reverter } = self;
433        expect_revert(
434            ccx.state,
435            None,
436            ccx.ecx.journaled_state.depth(),
437            false,
438            false,
439            Some(*reverter),
440            1,
441        )
442    }
443}
444
445impl Cheatcode for expectRevert_4Call {
446    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
447        let Self { revertData, reverter } = self;
448        expect_revert(
449            ccx.state,
450            Some(revertData.as_ref()),
451            ccx.ecx.journaled_state.depth(),
452            false,
453            false,
454            Some(*reverter),
455            1,
456        )
457    }
458}
459
460impl Cheatcode for expectRevert_5Call {
461    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
462        let Self { revertData, reverter } = self;
463        expect_revert(
464            ccx.state,
465            Some(revertData),
466            ccx.ecx.journaled_state.depth(),
467            false,
468            false,
469            Some(*reverter),
470            1,
471        )
472    }
473}
474
475impl Cheatcode for expectRevert_6Call {
476    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
477        let Self { count } = self;
478        expect_revert(ccx.state, None, ccx.ecx.journaled_state.depth(), false, false, None, *count)
479    }
480}
481
482impl Cheatcode for expectRevert_7Call {
483    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
484        let Self { revertData, count } = self;
485        expect_revert(
486            ccx.state,
487            Some(revertData.as_ref()),
488            ccx.ecx.journaled_state.depth(),
489            false,
490            false,
491            None,
492            *count,
493        )
494    }
495}
496
497impl Cheatcode for expectRevert_8Call {
498    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
499        let Self { revertData, count } = self;
500        expect_revert(
501            ccx.state,
502            Some(revertData),
503            ccx.ecx.journaled_state.depth(),
504            false,
505            false,
506            None,
507            *count,
508        )
509    }
510}
511
512impl Cheatcode for expectRevert_9Call {
513    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
514        let Self { reverter, count } = self;
515        expect_revert(
516            ccx.state,
517            None,
518            ccx.ecx.journaled_state.depth(),
519            false,
520            false,
521            Some(*reverter),
522            *count,
523        )
524    }
525}
526
527impl Cheatcode for expectRevert_10Call {
528    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
529        let Self { revertData, reverter, count } = self;
530        expect_revert(
531            ccx.state,
532            Some(revertData.as_ref()),
533            ccx.ecx.journaled_state.depth(),
534            false,
535            false,
536            Some(*reverter),
537            *count,
538        )
539    }
540}
541
542impl Cheatcode for expectRevert_11Call {
543    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
544        let Self { revertData, reverter, count } = self;
545        expect_revert(
546            ccx.state,
547            Some(revertData),
548            ccx.ecx.journaled_state.depth(),
549            false,
550            false,
551            Some(*reverter),
552            *count,
553        )
554    }
555}
556
557impl Cheatcode for expectPartialRevert_0Call {
558    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
559        let Self { revertData } = self;
560        expect_revert(
561            ccx.state,
562            Some(revertData.as_ref()),
563            ccx.ecx.journaled_state.depth(),
564            false,
565            true,
566            None,
567            1,
568        )
569    }
570}
571
572impl Cheatcode for expectPartialRevert_1Call {
573    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
574        let Self { revertData, reverter } = self;
575        expect_revert(
576            ccx.state,
577            Some(revertData.as_ref()),
578            ccx.ecx.journaled_state.depth(),
579            false,
580            true,
581            Some(*reverter),
582            1,
583        )
584    }
585}
586
587impl Cheatcode for _expectCheatcodeRevert_0Call {
588    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
589        expect_revert(ccx.state, None, ccx.ecx.journaled_state.depth(), true, false, None, 1)
590    }
591}
592
593impl Cheatcode for _expectCheatcodeRevert_1Call {
594    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
595        let Self { revertData } = self;
596        expect_revert(
597            ccx.state,
598            Some(revertData.as_ref()),
599            ccx.ecx.journaled_state.depth(),
600            true,
601            false,
602            None,
603            1,
604        )
605    }
606}
607
608impl Cheatcode for _expectCheatcodeRevert_2Call {
609    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
610        let Self { revertData } = self;
611        expect_revert(
612            ccx.state,
613            Some(revertData),
614            ccx.ecx.journaled_state.depth(),
615            true,
616            false,
617            None,
618            1,
619        )
620    }
621}
622
623impl Cheatcode for expectSafeMemoryCall {
624    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
625        let Self { min, max } = *self;
626        expect_safe_memory(ccx.state, min, max, ccx.ecx.journaled_state.depth())
627    }
628}
629
630impl Cheatcode for stopExpectSafeMemoryCall {
631    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
632        let Self {} = self;
633        ccx.state.allowed_mem_writes.remove(&ccx.ecx.journaled_state.depth());
634        Ok(Default::default())
635    }
636}
637
638impl Cheatcode for expectSafeMemoryCallCall {
639    fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
640        let Self { min, max } = *self;
641        expect_safe_memory(ccx.state, min, max, ccx.ecx.journaled_state.depth() + 1)
642    }
643}
644
645impl RevertParameters for ExpectedRevert {
646    fn reverter(&self) -> Option<Address> {
647        self.reverter
648    }
649
650    fn reason(&self) -> Option<&[u8]> {
651        self.reason.as_deref()
652    }
653
654    fn partial_match(&self) -> bool {
655        self.partial_match
656    }
657}
658
659/// Handles expected calls specified by the `expectCall` cheatcodes.
660///
661/// It can handle calls in two ways:
662/// - If the cheatcode was used with a `count` argument, it will expect the call to be made exactly
663///   `count` times. e.g. `vm.expectCall(address(0xc4f3), abi.encodeWithSelector(0xd34db33f), 4)`
664///   will expect the call to address(0xc4f3) with selector `0xd34db33f` to be made exactly 4 times.
665///   If the amount of calls is less or more than 4, the test will fail. Note that the `count`
666///   argument cannot be overwritten with another `vm.expectCall`. If this is attempted,
667///   `expectCall` will revert.
668/// - If the cheatcode was used without a `count` argument, it will expect the call to be made at
669///   least the amount of times the cheatcode was called. This means that `vm.expectCall` without a
670///   count argument can be called many times, but cannot be called with a `count` argument after it
671///   was called without one. If the latter happens, `expectCall` will revert. e.g
672///   `vm.expectCall(address(0xc4f3), abi.encodeWithSelector(0xd34db33f))` will expect the call to
673///   address(0xc4f3) and selector `0xd34db33f` to be made at least once. If the amount of calls is
674///   0, the test will fail. If the call is made more than once, the test will pass.
675#[expect(clippy::too_many_arguments)] // It is what it is
676fn expect_call(
677    state: &mut Cheatcodes,
678    target: &Address,
679    calldata: &Bytes,
680    value: Option<&U256>,
681    mut gas: Option<u64>,
682    mut min_gas: Option<u64>,
683    count: u64,
684    call_type: ExpectedCallType,
685) -> Result {
686    let expecteds = state.expected_calls.entry(*target).or_default();
687
688    if let Some(val) = value {
689        if *val > U256::ZERO {
690            // If the value of the transaction is non-zero, the EVM adds a call stipend of 2300 gas
691            // to ensure that the basic fallback function can be called.
692            let positive_value_cost_stipend = 2300;
693            if let Some(gas) = &mut gas {
694                *gas += positive_value_cost_stipend;
695            }
696            if let Some(min_gas) = &mut min_gas {
697                *min_gas += positive_value_cost_stipend;
698            }
699        }
700    }
701
702    match call_type {
703        ExpectedCallType::Count => {
704            // Get the expected calls for this target.
705            // In this case, as we're using counted expectCalls, we should not be able to set them
706            // more than once.
707            ensure!(
708                !expecteds.contains_key(calldata),
709                "counted expected calls can only bet set once"
710            );
711            expecteds.insert(
712                calldata.clone(),
713                (ExpectedCallData { value: value.copied(), gas, min_gas, count, call_type }, 0),
714            );
715        }
716        ExpectedCallType::NonCount => {
717            // Check if the expected calldata exists.
718            // If it does, increment the count by one as we expect to see it one more time.
719            match expecteds.entry(calldata.clone()) {
720                Entry::Occupied(mut entry) => {
721                    let (expected, _) = entry.get_mut();
722                    // Ensure we're not overwriting a counted expectCall.
723                    ensure!(
724                        expected.call_type == ExpectedCallType::NonCount,
725                        "cannot overwrite a counted expectCall with a non-counted expectCall"
726                    );
727                    expected.count += 1;
728                }
729                // If it does not exist, then create it.
730                Entry::Vacant(entry) => {
731                    entry.insert((
732                        ExpectedCallData { value: value.copied(), gas, min_gas, count, call_type },
733                        0,
734                    ));
735                }
736            }
737        }
738    }
739
740    Ok(Default::default())
741}
742
743fn expect_emit(
744    state: &mut Cheatcodes,
745    depth: u64,
746    checks: [bool; 5],
747    address: Option<Address>,
748    anonymous: bool,
749    count: u64,
750) -> Result {
751    let expected_emit =
752        ExpectedEmit { depth, checks, address, found: false, log: None, anonymous, count };
753    if let Some(found_emit_pos) = state.expected_emits.iter().position(|(emit, _)| emit.found) {
754        // The order of emits already found (back of queue) should not be modified, hence push any
755        // new emit before first found emit.
756        state.expected_emits.insert(found_emit_pos, (expected_emit, Default::default()));
757    } else {
758        // If no expected emits then push new one at the back of queue.
759        state.expected_emits.push_back((expected_emit, Default::default()));
760    }
761
762    Ok(Default::default())
763}
764
765pub(crate) fn handle_expect_emit(
766    state: &mut Cheatcodes,
767    log: &alloy_primitives::Log,
768    interpreter: &mut Interpreter,
769) {
770    // Fill or check the expected emits.
771    // We expect for emit checks to be filled as they're declared (from oldest to newest),
772    // so we fill them and push them to the back of the queue.
773    // If the user has properly filled all the emits, they'll end up in their original order.
774    // If not, the queue will not be in the order the events will be intended to be filled,
775    // and we'll be able to later detect this and bail.
776
777    // First, we can return early if all events have been matched.
778    // This allows a contract to arbitrarily emit more events than expected (additive behavior),
779    // as long as all the previous events were matched in the order they were expected to be.
780    if state.expected_emits.iter().all(|(expected, _)| expected.found) {
781        return
782    }
783
784    let should_fill_logs = state.expected_emits.iter().any(|(expected, _)| expected.log.is_none());
785    let index_to_fill_or_check = if should_fill_logs {
786        // If there's anything to fill, we start with the last event to match in the queue
787        // (without taking into account events already matched).
788        state
789            .expected_emits
790            .iter()
791            .position(|(emit, _)| emit.found)
792            .unwrap_or(state.expected_emits.len())
793            .saturating_sub(1)
794    } else {
795        // Otherwise, if all expected logs are filled, we start to check any unmatched event
796        // in the declared order, so we start from the front (like a queue).
797        0
798    };
799
800    let (mut event_to_fill_or_check, mut count_map) = state
801        .expected_emits
802        .remove(index_to_fill_or_check)
803        .expect("we should have an emit to fill or check");
804
805    let Some(expected) = &event_to_fill_or_check.log else {
806        // Unless the caller is trying to match an anonymous event, the first topic must be
807        // filled.
808        if event_to_fill_or_check.anonymous || !log.topics().is_empty() {
809            event_to_fill_or_check.log = Some(log.data.clone());
810            // If we only filled the expected log then we put it back at the same position.
811            state
812                .expected_emits
813                .insert(index_to_fill_or_check, (event_to_fill_or_check, count_map));
814        } else {
815            interpreter.instruction_result = InstructionResult::Revert;
816            interpreter.next_action = InterpreterAction::Return {
817                result: InterpreterResult {
818                    output: Error::encode("use vm.expectEmitAnonymous to match anonymous events"),
819                    gas: interpreter.gas,
820                    result: InstructionResult::Revert,
821                },
822            };
823        }
824        return
825    };
826
827    // Increment/set `count` for `log.address` and `log.data`
828    match count_map.entry(log.address) {
829        Entry::Occupied(mut entry) => {
830            // Checks and inserts the log into the map.
831            // If the log doesn't pass the checks, it is ignored and `count` is not incremented.
832            let log_count_map = entry.get_mut();
833            log_count_map.insert(&log.data);
834        }
835        Entry::Vacant(entry) => {
836            let mut log_count_map = LogCountMap::new(&event_to_fill_or_check);
837
838            if log_count_map.satisfies_checks(&log.data) {
839                log_count_map.insert(&log.data);
840
841                // Entry is only inserted if it satisfies the checks.
842                entry.insert(log_count_map);
843            }
844        }
845    }
846
847    event_to_fill_or_check.found = || -> bool {
848        if !checks_topics_and_data(event_to_fill_or_check.checks, expected, log) {
849            return false
850        }
851
852        // Maybe match source address.
853        if event_to_fill_or_check.address.is_some_and(|addr| addr != log.address) {
854            return false;
855        }
856
857        let expected_count = event_to_fill_or_check.count;
858
859        match event_to_fill_or_check.address {
860            Some(emitter) => count_map
861                .get(&emitter)
862                .is_some_and(|log_map| log_map.count(&log.data) >= expected_count),
863            None => count_map
864                .values()
865                .find(|log_map| log_map.satisfies_checks(&log.data))
866                .is_some_and(|map| map.count(&log.data) >= expected_count),
867        }
868    }();
869
870    // If we found the event, we can push it to the back of the queue
871    // and begin expecting the next event.
872    if event_to_fill_or_check.found {
873        state.expected_emits.push_back((event_to_fill_or_check, count_map));
874    } else {
875        // We did not match this event, so we need to keep waiting for the right one to
876        // appear.
877        state.expected_emits.push_front((event_to_fill_or_check, count_map));
878    }
879}
880
881/// Handles expected emits specified by the `expectEmit` cheatcodes.
882///
883/// The second element of the tuple counts the number of times the log has been emitted by a
884/// particular address
885pub type ExpectedEmitTracker = VecDeque<(ExpectedEmit, AddressHashMap<LogCountMap>)>;
886
887#[derive(Clone, Debug, Default)]
888pub struct LogCountMap {
889    checks: [bool; 5],
890    expected_log: RawLog,
891    map: HashMap<RawLog, u64>,
892}
893
894impl LogCountMap {
895    /// Instantiates `LogCountMap`.
896    fn new(expected_emit: &ExpectedEmit) -> Self {
897        Self {
898            checks: expected_emit.checks,
899            expected_log: expected_emit.log.clone().expect("log should be filled here"),
900            map: Default::default(),
901        }
902    }
903
904    /// Inserts a log into the map and increments the count.
905    ///
906    /// The log must pass all checks against the expected log for the count to increment.
907    ///
908    /// Returns true if the log was inserted and count was incremented.
909    fn insert(&mut self, log: &RawLog) -> bool {
910        // If its already in the map, increment the count without checking.
911        if self.map.contains_key(log) {
912            self.map.entry(log.clone()).and_modify(|c| *c += 1);
913
914            return true
915        }
916
917        if !self.satisfies_checks(log) {
918            return false
919        }
920
921        self.map.entry(log.clone()).and_modify(|c| *c += 1).or_insert(1);
922
923        true
924    }
925
926    /// Checks the incoming raw log against the expected logs topics and data.
927    fn satisfies_checks(&self, log: &RawLog) -> bool {
928        checks_topics_and_data(self.checks, &self.expected_log, log)
929    }
930
931    pub fn count(&self, log: &RawLog) -> u64 {
932        if !self.satisfies_checks(log) {
933            return 0
934        }
935
936        self.count_unchecked()
937    }
938
939    pub fn count_unchecked(&self) -> u64 {
940        self.map.values().sum()
941    }
942}
943
944fn expect_create(
945    state: &mut Cheatcodes,
946    bytecode: Bytes,
947    deployer: Address,
948    create_scheme: CreateScheme,
949) -> Result {
950    let expected_create = ExpectedCreate { bytecode, deployer, create_scheme };
951    state.expected_creates.push(expected_create);
952
953    Ok(Default::default())
954}
955
956fn expect_revert(
957    state: &mut Cheatcodes,
958    reason: Option<&[u8]>,
959    depth: u64,
960    cheatcode: bool,
961    partial_match: bool,
962    reverter: Option<Address>,
963    count: u64,
964) -> Result {
965    ensure!(
966        state.expected_revert.is_none(),
967        "you must call another function prior to expecting a second revert"
968    );
969    state.expected_revert = Some(ExpectedRevert {
970        reason: reason.map(<[_]>::to_vec),
971        depth,
972        kind: if cheatcode {
973            ExpectedRevertKind::Cheatcode { pending_processing: true }
974        } else {
975            ExpectedRevertKind::Default
976        },
977        partial_match,
978        reverter,
979        reverted_by: None,
980        max_depth: depth,
981        count,
982        actual_count: 0,
983    });
984    Ok(Default::default())
985}
986
987fn checks_topics_and_data(checks: [bool; 5], expected: &RawLog, log: &RawLog) -> bool {
988    if log.topics().len() != expected.topics().len() {
989        return false
990    }
991
992    // Check topics.
993    if !log
994        .topics()
995        .iter()
996        .enumerate()
997        .filter(|(i, _)| checks[*i])
998        .all(|(i, topic)| topic == &expected.topics()[i])
999    {
1000        return false
1001    }
1002
1003    // Check data
1004    if checks[4] && expected.data.as_ref() != log.data.as_ref() {
1005        return false
1006    }
1007
1008    true
1009}
1010
1011fn expect_safe_memory(state: &mut Cheatcodes, start: u64, end: u64, depth: u64) -> Result {
1012    ensure!(start < end, "memory range start ({start}) is greater than end ({end})");
1013    #[expect(clippy::single_range_in_vec_init)] // Wanted behaviour
1014    let offsets = state.allowed_mem_writes.entry(depth).or_insert_with(|| vec![0..0x60]);
1015    offsets.push(start..end);
1016    Ok(Default::default())
1017}