Skip to content

Testing emits

Ref - https://book.getfoundry.sh/forge/cheatcodes

The ERC-20 contract emits events whenever a transfer/approval happens.

Ref - https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol#L181

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol#L249

Emits

In Solidity, emits refers to the action of emitting an event. Events are a fundamental feature of the Ethereum smart contract system, allowing contracts to log important data that can be observed externally.

// Declaring an event
event Transfer(address indexed from, address indexed to, uint256 value);
// Emitting an event
emit Transfer(msg.sender, recipient, 100);

This is how they’re stored on the blockchain

Event Log:
- Topics:
- from: 0x1234567890abcdef (address of the sender)
- to: 0xfedcba0987654321 (address of the recipient)
- Data:
- value: 1000 (value transferred in the transaction)
Indexed Parameters in Events

Screenshot 2024-12-10 at 9.39.01 PM.png

https://etherscan.io/tx/0x046c2609f21f3308d8f7f902a51ac14f86b9e6b9f54ab1b4f269575d09bc93e5#eventlog

Indexed parameters

In Solidity, events allow you to mark some of the parameters as indexed. Indexed parameters make the event log searchable, as they allow external listeners (like DApps or off-chain services) to filter events by those parameters more efficiently.

The EVM allows you to index up to 3 parameters per event.

Testing emits

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
import { MyToken } from "../src/Token.sol";
contract CounterTest is Test {
MyToken public token;
event Transfer(address indexed from, address indexed to, uint256 amount);
function setUp() public {
token = new MyToken();
}
function test_ExpectEmit() public {
token.mint(address(this), 100);
// Check that topic 1, topic 2, and data are the same as the following emitted event.
// Checking topic 3 here doesn't matter, because `Transfer` only has 2 indexed topics.
vm.expectEmit(true, true, false, true);
// The event we expect
emit Transfer(address(this), 0x075c299cf3b9FCF7C9fD5272cd2ed21A4688bEeD, 100);
// The event we get
token.transfer(0x075c299cf3b9FCF7C9fD5272cd2ed21A4688bEeD, 100);
}
function test_ExpectEmitApprove() public {
token.mint(address(this), 100);
vm.expectEmit(true, true, false, true);
emit Approval(address(this), 0x075c299cf3b9FCF7C9fD5272cd2ed21A4688bEeD, 100);
token.approve(0x075c299cf3b9FCF7C9fD5272cd2ed21A4688bEeD, 100);
vm.prank(0x075c299cf3b9FCF7C9fD5272cd2ed21A4688bEeD);
token.transferFrom(address(this), 0x075c299cf3b9FCF7C9fD5272cd2ed21A4688bEeD, 100);
}
}