From 420d8146b69189450ae60196817bc9dded9dba92 Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Thu, 11 May 2023 18:20:11 -0400 Subject: [PATCH] chore: be able to match in between events rather than strictly full-sequences --- .../executor/inspector/cheatcodes/expect.rs | 12 +++++- testdata/cheats/ExpectEmit.t.sol | 42 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/evm/src/executor/inspector/cheatcodes/expect.rs b/evm/src/executor/inspector/cheatcodes/expect.rs index e8cf12c46cd7..d97d44c1ee65 100644 --- a/evm/src/executor/inspector/cheatcodes/expect.rs +++ b/evm/src/executor/inspector/cheatcodes/expect.rs @@ -180,13 +180,23 @@ pub fn handle_expect_emit(state: &mut Cheatcodes, log: RawLog, address: &Address event_to_fill_or_check.found &= expected.data == log.data; } } + + // If we found the event, we can push it to the back of the queue + // and begin expecting the next event. + if event_to_fill_or_check.found { + state.expected_emits.push_back(event_to_fill_or_check); + } else { + // We did not match this event, so we need to keep waiting for the right one to appear. + state.expected_emits.push_front(event_to_fill_or_check); + } + } // Fill the event. None => { event_to_fill_or_check.log = Some(log); + state.expected_emits.push_back(event_to_fill_or_check); } } - state.expected_emits.push_back(event_to_fill_or_check); } #[derive(Clone, Debug, Default)] diff --git a/testdata/cheats/ExpectEmit.t.sol b/testdata/cheats/ExpectEmit.t.sol index b801c6fa2dfa..be3c58254b21 100644 --- a/testdata/cheats/ExpectEmit.t.sol +++ b/testdata/cheats/ExpectEmit.t.sol @@ -17,6 +17,8 @@ contract Emitter { /// Ref: issue #760 event SomethingElse(uint256 data); + event SomethingNonIndexed(uint256 data); + function emitEvent(uint256 topic1, uint256 topic2, uint256 topic3, uint256 data) public { emit Something(topic1, topic2, topic3, data); } @@ -36,6 +38,13 @@ contract Emitter { emitNested(Emitter(address(this)), 1, 2, 3, 4); } + function emitOutOfExactOrder() public { + emit SomethingNonIndexed(1); + emit Something(1, 2, 3, 4); + emit Something(1, 2, 3, 4); + emit Something(1, 2, 3, 4); + } + function emitNested(Emitter inner, uint256 topic1, uint256 topic2, uint256 topic3, uint256 data) public { inner.emitEvent(topic1, topic2, topic3, data); } @@ -74,6 +83,8 @@ contract ExpectEmitTest is DSTest { event SomethingElse(uint256 indexed topic1); + event SomethingNonIndexed(uint256 data); + function setUp() public { emitter = new Emitter(); } @@ -217,6 +228,37 @@ contract ExpectEmitTest is DSTest { ); } + function testExpectEmitCanMatchWithoutExactOrder() public { + cheats.expectEmit(true, true, true, true); + emit Something(1, 2, 3, 4); + cheats.expectEmit(true, true, true, true); + emit Something(1, 2, 3, 4); + + emitter.emitOutOfExactOrder(); + } + + function testFailExpectEmitCanMatchWithoutExactOrder() public { + cheats.expectEmit(true, true, true, true); + emit Something(1, 2, 3, 4); + // This should fail, as this event is never emitted + // in between the other two Something events. + cheats.expectEmit(true, true, true, true); + emit SomethingElse(1); + cheats.expectEmit(true, true, true, true); + emit Something(1, 2, 3, 4); + + emitter.emitOutOfExactOrder(); + } + + function testExpectEmitCanMatchWithoutExactOrder2() public { + cheats.expectEmit(true, true, true, true); + emit SomethingNonIndexed(1); + cheats.expectEmit(true, true, true, true); + emit Something(1, 2, 3, 4); + + emitter.emitOutOfExactOrder(); + } + function testExpectEmitAddress() public { cheats.expectEmit(address(emitter)); emit Something(1, 2, 3, 4);