2

I'm toying with the recently introduced custom errors. Here's a mini replica of my set up:

interface MyInterface {
    error MyCustomError();
}

I'm writing my tests in Solidity and I'd like to use the expectRevert cheatcode (part of HEVM) to test that my implementation contract reverts with MyCustomError. Here's what I came up with so far:

vm.expectRevert(abi.encodeWithSignature("MyCustomError()"));

This works since the expectRevert cheatcode is implemented in three different ways:

  • expectRevert()
  • expectRevert(bytes calldata)
  • expectRevert(bytes4)

But using abi.encodeWithSignature feels like going in a roundabout way. I tried to reference the custom error directly:

vm.expectRevert(MyInterface.MyCustomError);

But this doesn't compile, so it follows that MyCustomError is neither bytes nor bytes4 when referenced like this. That's fine. But then, what type is it, and could I cast it to either bytes or bytes4?

2
  • Have you tried MyInterface.MyCustomError.selector ? it should return a bytes4 to identify your error in a relatively readable way.
    – hroussille
    Commented Apr 4, 2022 at 13:44
  • Thanks @hroussille, I forgot about the .selector member. I posted an answer below. Commented Apr 4, 2022 at 13:54

2 Answers 2

3

I eventually figured out half of the answer on my own by trying to force cast the type to bytes4. It seems like MyInterface.MyCustomError is of type function() pure:

Explicit type conversion not allowed from "function () pure" to "bytes4".

Note that I compile my code with Solidity v0.8.13+commit.abaa5c0e.

The other half was elucidated by @hroussille's tip to use the .selector member to access the bytes4 signature of the MyCustomError custom error. The following works:

vm.expectRevert(MyInterface.MyCustomError.selector);

Side note: I ended making a suggestion in the Solidity forum to add a bespoke type for custom errors, i.e. something like error which would be an alias for bytes24 (just like function).

Update: it looks like this is actually a bug in Solidity. Casting MyInterface.MyCustomError to bytes4 should work. I opened an issue for this.

0

Actually MyInterface.MyCustomError.selector will return bytes4 but expectRevert expects bytes, so the above would throw an error. But that can be easily fixed using

vm.expectRevert(abi.encodePacked(MyInterface.MyCustomError.selector));
4
  • What version of forge are you using, Diganta? Commented May 30, 2022 at 10:59
  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented May 30, 2022 at 11:29
  • Its "forge 0.1.0". Am I outdated lol Commented May 31, 2022 at 11:40
  • 1
    @DigantaKalita yup. Visit the README for instructions on how to upgrade to the latest version. Commented May 31, 2022 at 14:02

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.