Foundry does have vm.recordLogs()
to record events and vm.getRecordedLogs()
to get all the emitted events data which I think is best for this kind of test case (refer docs here).
Example : Here I have shown a foundry test which accepts fuzz inputs and emits it in MyEvent
event. The test also shows how to assert for values that fall within a particular range. You can ignore assertions for values that are not a concern, which is also shown in the test.
// SPDX-License-Identifier: CAL
pragma solidity =0.8.19;
import {Test, console2} from "forge-std/Test.sol";
import {Vm} from "forge-std/Vm.sol";
contract TiggerEvent {
// Example Event
event MyEvent(uint256 indexed value1, address indexed addr, uint256 value2);
// Function to tigger `MyEvent`
function tiggerEvent(uint256 value1, address addr, uint256 value2) public {
emit MyEvent(value1, addr, value2);
}
}
contract ExpectEmit is TiggerEvent, Test {
// Foundry test to get fuzz inputs.
function testEventEmit(uint256 value1, address addr, uint256 value2) public {
//Bound a value within a range to be emitted in event.
value1 = bound(value1, 100, 1e36);
//Start recording Logs
vm.recordLogs();
// Emit `MyEvent`
tiggerEvent(value1, addr, value2);
//Get recorded events
Vm.Log[] memory entries = vm.getRecordedLogs();
//Assert number of emitted events.
console2.log(entries.length);
//Decoded emitted values and addresses from topics and data.
bytes memory topicsData = bytes.concat(entries[0].topics[1], entries[0].topics[2]);
(uint256 emittedValue1, address emittedAddr) = abi.decode(topicsData, (uint256, address));
uint256 emittedValue2 = abi.decode(entries[0].data, (uint256));
// Assert values and addresses
// Check a value for exact match
assertEq(emittedAddr, addr);
//Check a vaule for range
assertGe(emittedValue1, 100);
assertLe(emittedValue1, 1e36);
//Ignore a value
//assertEq(emittedValue2,value2);
}
}
- The only thing to note is that if your contract function emits multiple events you will have to get the index from the logs array. You can filter through the
entries
array by looping over it and checking for topics[0].Eg :
//Get recorded events
Vm.Log[] memory entries = vm.getRecordedLogs();
for(uint256 i = 0 ; i < entries.length ;i++){
if(entries[i].topics[0] == keccak256("MyEvent(uint256,address,uint256)")){
// Event found decode data
}
}