1

I am using Hardhat and chai for my testing and attempting to trigger an error that gets reverted to make sure my contract is acting properly. Note: I'm running on a forked hardhat chain of mainnet.

I define the error like so: error FundMe__WithdrawProceedsGreaterThanBalance(uint256 amount, uint256 balance); and revert it with

function withdrawFunds(uint256 amount) public {
        if (amount > s_funders[msg.sender].amount) {
            revert FundMe__WithdrawFundsGreaterThanBalance(
                amount,
                s_funders[msg.sender].amount
            );
        }

Then in my test I purposefully trigger it:

await expect(fundMe.withdrawFundsFromPool(higherFundAmount)
    ).to.be.revertedWith(
         "FundMe__WithdrawFundsGreaterThanBalance"
    )

Here is where it goes wrong, instead of passing that test, it fails with an error:

AssertionError: Expected transaction to be reverted with FundMe__WithdrawFundsGreaterThanBalance, but other exception was thrown: ProviderError: Error: Transaction reverted without a reason string

It's so strange because if I change the solidity code to revert a string like `revert ("Test failure") and change the test code to expect that string to be reverted, it works. I'm thinking this issue might have to do with some sort of versioning issue, with hardhat, chai, and waffle but I haven't been able to figure it out. I believe these are the versions that matter so I'll paste them here:

"@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers",
    "@nomiclabs/hardhat-etherscan": "^3.1.0",
    "@nomiclabs/hardhat-waffle": "^2.0.3",
    "chai": "^4.3.6",

Not really sure what to do. I've tried other solutions I've seen people like adding hardhat-chai-matchers but nothing works

4 Answers 4

1

It looks like revertedWith checks for the string you pass as argument anywhere in the revert message. From my humble experience, this matcher works best when a revert happens due to a require statement. I could think of 2 options to solve this:

  • use require (condition, "The condition is not met." in the contract code and then testing it in the test file like so:

await expect (contract.foo().to.be.revertedWith('the string that is the second argument to the require statement in. your solidity code')

  • or simply assert that the tx would be reverted ( without pointing to the specific reason for that) by going for:

await expect(token.transfer(walletTo.address, 1007)).to.be.reverted

Hope I helped you buddy.

1
  • .to.be.reverted works but I was hoping to be specific about the reverted error without using a string revert because that is apparently less gas efficient. I know it's possible because I've done this exact same thing in Patrick Collins' solidity tutorial but for some reason in works in that project and not this one
    – l1nkm4rine
    Commented Oct 27, 2022 at 19:46
1

I have the same issue, and search a lot until I gave up using "revertedWith", but go with "rejectedWith"

1

I'm making the assumption here, but let me know if this helps.

I'm assuming that FundMe__WithdrawFundsGreaterThanBalance is a custom error, right?

So when you are validating, you could use the revertedWithCustomError() method. So your test example should look like this:

await expect(fundMe.withdrawFundsFromPool(higherFundAmount)
    ).to.be.revertedWithCustomError(
         contract,
         "FundMe__WithdrawFundsGreaterThanBalance"
    );
0

most likely you called wrong method or wrong contract address because in most cases empty revert string will be returned if the contract receives non-existent function selector. Also, you aren't showing the full code of the function but if , for example, you have a division and the divisor is 0 , you will get an empty revert string as result but the actual require() statement won't be triggered at all. You can try to use hardhat-tracer package and run your test script with --fulltrace option, it may give some hints on what is going on, if for example, the revert occurs early in the trace log, it means you called wrong function on the contract (or used wrong address)

also try using expect(await contract.yourMethod(...)) instead of await expect(contract.yourMethod(...))) , I have found that the latter doesn't catch reverts and passes the test silently.

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.