Component
Forge
Have you ensured that all of these are up to date?
What version of Foundry are you on?
forge 0.2.0 (4fcd7e0 2022-05-26T00:08:37.693306Z)
What command(s) is the bug in?
forge test
Operating System
No response
Describe the bug
My understanding is that the expected behavior of expectEmit is "look for event in the next call" but it seems to actually be "look for expected event before the end of the test". And the docs are contradictory here—one part says it must be the "next event" (which seems to imply it needs to be the first event in the next call), another part says "before the end of the current function". Similarly issue for expectCall behavior.
To ensure tests are clear, I think expectEmit and expectCall should only look in the next call. Otherwise this can result in bugs where your event was emitted eventually in a later portion of your test, but not emitted at the time you expected it, and the test still passes.
Reproduce with this test:
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.13;
import "forge-std/Test.sol";
contract CallMe {
function calling() public {}
}
contract MyContract {
CallMe callMe;
constructor(CallMe _callMe) {
callMe = _callMe;
}
event MyEvent();
event OtherEvent();
function noEventOrCall() public {}
function myEventAndCall() public {
emit OtherEvent(); // Shows event order does not matter if only checking for MyEvent.
emit MyEvent();
callMe.calling();
}
}
contract ExpectTest is Test {
event MyEvent();
CallMe callMe;
MyContract myContract;
function setUp() public {
callMe = new CallMe();
myContract = new MyContract(callMe);
}
// -------- expectEmit Tests --------
function test_MyEvent() public {
// Passes like expected.
vm.expectEmit(true, true, true, true);
emit MyEvent();
myContract.myEventAndCall();
}
function test_NoEventOrCall() public {
// Fails like expected.
vm.expectEmit(true, true, true, true);
emit MyEvent();
myContract.noEventOrCall();
}
function test_EventuallyMyEvent() public {
// Passes, but should fail, because expectEmit should only check the next call.
vm.expectEmit(true, true, true, true);
emit MyEvent();
myContract.noEventOrCall();
myContract.myEventAndCall();
}
// -------- expectCall Tests --------
function test_Call() public {
// Passes like expected.
vm.expectCall(address(callMe), abi.encodeWithSelector(CallMe.calling.selector));
myContract.myEventAndCall();
}
function test_NoCall() public {
// Fails like expected.
vm.expectCall(address(callMe), abi.encodeWithSelector(CallMe.calling.selector));
myContract.noEventOrCall();
}
function test_EventuallyCall() public {
// Passes, but should fail, because expectCall should only check the next call.
vm.expectCall(address(callMe), abi.encodeWithSelector(CallMe.calling.selector));
emit MyEvent();
myContract.noEventOrCall();
myContract.myEventAndCall();
}
}
Component
Forge
Have you ensured that all of these are up to date?
What version of Foundry are you on?
forge 0.2.0 (4fcd7e0 2022-05-26T00:08:37.693306Z)
What command(s) is the bug in?
forge test
Operating System
No response
Describe the bug
My understanding is that the expected behavior of
expectEmitis "look for event in the next call" but it seems to actually be "look for expected event before the end of the test". And the docs are contradictory here—one part says it must be the "next event" (which seems to imply it needs to be the first event in the next call), another part says "before the end of the current function". Similarly issue forexpectCallbehavior.To ensure tests are clear, I think
expectEmitandexpectCallshould only look in the next call. Otherwise this can result in bugs where your event was emitted eventually in a later portion of your test, but not emitted at the time you expected it, and the test still passes.Reproduce with this test: