🎓 A1Learner
🔍
0 of 48 lessons completed

Solidity Testing Reverts Events

A revert test is a test that proves a call fails when it should fail. An event test is a test that proves a contract announced an event with the right details.

A revert test proves a zero deposit fails

The vault rejects a deposit of zero. The test catches the failure and requires the flag to be set.

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

contract SmallVault {
    uint256 public balance;

    function deposit(uint256 amount) public {
        require(amount > 0, "zero deposit");
        balance += amount;
    }
}

An event test reads the log of a deposit

The test records logs, deposits, and then reads the log back. The first topic is the event signature, the second topic is the sender, and the data holds the amount.

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

contract LoggedVault {
    event Deposited(address indexed sender, uint256 amount);

    uint256 public balance;

    function deposit(uint256 amount) public {
        require(amount > 0, "zero deposit");
        balance += amount;
        emit Deposited(msg.sender, amount);
    }
}

A reverted call leaves the balance unchanged

The vault already holds ten. A zero deposit reverts, and the balance is still ten afterwards.

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

contract SmallVault {
    uint256 public balance;

    function deposit(uint256 amount) public {
        require(amount > 0, "zero deposit");
        balance += amount;
    }
}

Example

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

contract EventVault {
    event Deposited(address indexed sender, uint256 amount);
    event Withdrawn(address indexed sender, uint256 amount);

    uint256 public balance;

    function deposit(uint256 amount) public {
        require(amount > 0, "zero deposit");
        balance += amount;
        emit Deposited(msg.sender, amount);
    }

    function withdraw(uint256 amount) public {
        require(amount <= balance, "insufficient balance");
        balance -= amount;
        emit Withdrawn(msg.sender, amount);
    }
}

Key points

  • Revert test: a revert test proves a call fails, usually with a try and catch block that sets a flag.
  • Catch flag: a catch flag is a boolean that records whether the call reverted.
  • State after a revert: a reverted call changes nothing, so the state stays exactly as it was.
  • Event log: an event test reads the logs recorded during a call and checks their contents.
  • Indexed detail: an indexed event detail appears as a topic in the log, and the other details appear as data.
  • Use a revert test for every rule that must reject bad input, and an event test for every announcement a reader must trust.

In this example, a deposit emits an event with the sender and amount, a withdrawal larger than the balance reverts and leaves the balance unchanged, and a valid withdrawal emits its own event with the withdrawn amount.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Remix IDE

Exercise

How does a revert test prove a call failed?