4

In forge tests I've been redeclaring events within the test file so that I can use vm.assertEmit. Is there a way to import events from the contract I am testing instead?

e.g.

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

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

contract RegistryDeployerTest is Test {

  // re-declare event for assertions
  event Deployed();
  // ^^^^^^^^^^
  // I don't want to have to do this
  // ^^^^^^^^^^

  function testDeployer() public {
    vm.expectEmit(true, true, true, true);
    emit Deployed();
    new RegistryDeployer();
  }
}
1
  • Ditto for errors
    – Milk
    Commented Mar 29, 2023 at 18:32

1 Answer 1

1

You can create an interface where the event is defined, and import it both in your source contract and your tests contract:

interface MyEvents {
  event Deployed();
}

contract RegistryDeployer is MyEvents {
  // ...
}

In your tests you wouldn't need to re-declare it:

contract RegistryDeployerTest is Test, MyEvents {

  function testDeployer() public {
    vm.expectEmit(true, true, true, true);
    emit Deployed();
    new RegistryDeployer();
  }
}

I think your example is cleaner. AFAIK there is no direct access to the event with RegistryDeployer.Deployer, so I would do what you showed in your example.

2
  • I like this but for something like IERC1155 it means declaring each of the functions in the test class too which isn't really any better.
    – Milk
    Commented May 2, 2023 at 0:40
  • Accepting this answer. I've been using this pattern for about a year now and it's become my go to for new implementations. Here's a write up I did on it. michael.standen.link/2023/06/30/solidity-interface-pattern.html
    – Milk
    Commented May 22 at 21:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.