15

I have a custom error described as such:

error AlreadyListed(address nftAddress, uint256 tokenId);

And in my tests, I'd like to check to see that it's thrown:

expect(await nftMarketplace.listItem(basicNft.address, TOKEN_ID, PRICE)).to.be.revertedWith(`AlreadyListed`)

However, this of course fails with:

 Error: VM Exception while processing transaction: reverted with custom error 'AlreadyListed("0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", 0)

Do I need to string interpolate with quotes and such, or is there a better way? This looks ugly:

expect(await nftMarketplace.listItem(basicNft.address, TOKEN_ID, PRICE)).to.be.revertedWith(`AlreadyListed("${basicNft.address}", ${TOKEN_ID})`)
Patrick Collins
  • 11,186
  • 5
  • 44
  • 97

3 Answers3

22

Update to selected answer

Custom error

hardhat will check for the name of the error, not the contents of the message

MyContract.sol

error SomeCustomError(string message);

contract MyContract { function someFunction() public {

    if (!false) {
        revert SomeCustomError("Some error message");
    }
}

}

MyContract.ts

await expect(contract.call()).to.be.revertedWithCustomError(
  contract,
  "SomeCustomError"
);

got from hardhat docs https://hardhat.org/hardhat-chai-matchers/docs/overview

Basic Revert

MyContract.sol

contract MyContract {
function someFunction() public payable {
    require(msg.value > 1 ether, "Please send enough ETH");
}

}

MyContract.ts

await expect(contract.someFunction()).to.be.revertedWith("Some error message");
8koi
  • 331
  • 2
  • 5
13

Try moving the await before the expect. e.g.

await expect(nftMarketplace.listItem(basicNft.address, TOKEN_ID, PRICE)).to.be.revertedWith(`AlreadyListed`)

That's what my tests use for custom errors

Hope this helps

Patrick Collins
  • 11,186
  • 5
  • 44
  • 97
helpful hint
  • 146
  • 1
  • 2
  • this worked. any idea why it didn't worked when written "await" inside bracket? – Deepak Bhavsar May 25 '22 at 11:50
  • 2
    Anything inside the parenthesis will be fully executed before being passed into expect(). Thus, if awaiting the call will fail, expect() will never even be called to check.

    Instead, we just pass in the Promise<> to expect() and await for expect() to decide what to do -- which it is fully capable of catching and comparing Promise<> errors when used with .to.be.revertedWith()

    – helpful hint May 26 '22 at 13:36
0

Current hardhat documentation:

await expect(contract.call()).to.be.reverted;

or revert and test the error message:

await expect(contract.call()).to.be.revertedWith("Some revert message");

Example:

const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Storage Contract Test", function () { let owner;

beforeEach(async function() {
    [owner] = await ethers.getSigners();

    const SimpleStorage = await ethers
        .getContractFactory(&quot;SimpleStorage&quot;);

    simpleStorage = await SimpleStorage.deploy();
});


it("should not set a new contract owner to the zero address", async () => { //Arrange const zeroAddr = "0x0000000000000000000000000000000000000000"; //Act const currentAddr = await simpleStorage.getOwner(); //Assert expect(currentAddr).to.equal(owner.address); console.log(currentAddr); await expect(simpleStorage.changeOwner(zeroAddr)) .to.be.reverted; await expect(simpleStorage.changeOwner(zeroAddr)) .to.be.revertedWith("new owner cannot be zero address 0x0") }); });

djd
  • 19
  • 3