Error

Error

Setup

Target contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

contract Error {
    error NotAuthorized();

    function throwError() external {
        require(false, "not authorized");
    }

    function throwCustomError() external {
        revert NotAuthorized();
    }
}

Test file:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;

import "forge-std/Test.sol";
import {Error} from "../src/Error.sol";

contract ErrorTest is Test {
    Error public err;

    function setUp() public {
        err = new Error();
    }

    function testFail() public {
        err.throwError();
    }

    function testRevert() public {
        vm.expectRevert();
        err.throwError();
    }

    function testRequireMessage() public {
        vm.expectRevert(bytes("not authorized"));
        err.throwError();
    }

    function testCustomError() public {
        vm.expectRevert(Error.NotAuthorized.selector);
        err.throwCustomError();
    }

    // Add label to assertions
    function testErrorLabel() public {
        assertEq(uint256(1), uint256(1), "test 1");
        assertEq(uint256(1), uint256(1), "test 2");
        assertEq(uint256(1), uint256(1), "test 3");
        assertEq(uint256(1), uint256(2), "test 4");
        assertEq(uint256(1), uint256(1), "test 5");
    }
}

vm.expectRevert()

If we want a test case to simply revert, use testFail prefix in the function name:

    function testFail() public {
        err.throwError();
    }

Another way of doing the same thing is to use test prefix in the function name and vm.expectRevert() before that operation:

    function testRevert() public {
        vm.expectRevert();
        err.throwError();
    }

Test require error message

If we want to test for a require() statement's error message, such as the following:

    function throwError() external {
        require(false, "not authorized");
    }

use vm.expectRevert(bytes(error_message)):

    function testRequireMessage() public {
        vm.expectRevert(bytes("not authorized"));
        err.throwError();
    }

Custom error

If we want to test for custom error instead, such as the following:

    function throwCustomError() external {
        revert NotAuthorized();
    }

use vm.expectRevert(Error.custom_error_name.selector):

    function testCustomError() public {
        vm.expectRevert(Error.NotAuthorized.selector);
        err.throwCustomError();
    }

Label assertions

If we have a lot of assertions in a test case, Foundry won't tell us which ones succeed and which ones fail. For example:

    function testErrorLabel() public {
        assertEq(uint256(1), uint256(1));
        assertEq(uint256(1), uint256(1));
        assertEq(uint256(1), uint256(1));
        assertEq(uint256(1), uint256(2));
        assertEq(uint256(1), uint256(1));
    }

The 4th assertion clearly would fail but Foundry won't tell us the failed one is the 4th assertion. In order to distinguish assertions, we can label them with different names:

    // Add label to assertions
    function testErrorLabel() public {
        assertEq(uint256(1), uint256(1), "test 1");
        assertEq(uint256(1), uint256(1), "test 2");
        assertEq(uint256(1), uint256(1), "test 3");
        assertEq(uint256(1), uint256(2), "test 4");
        assertEq(uint256(1), uint256(1), "test 5");
    }

Last updated