You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hardhat中revertedWith匹配自定义错误Raffle__UpkeepNotNeeded失败求助

问题:测试Solidity自定义错误时断言失败

我正在为Lottery合约编写测试,测试触发自定义错误的场景,但遇到了断言失败的问题。

Solidity合约代码

function performUpkeep(
    bytes calldata /* performData*/
) external override {
    (bool upkeepNeeded, ) = checkUpkeep("");
    if (!upkeepNeeded) {
        revert Raffle__UpkeepNotNeeded(
            address(this).balance,
            s_players.length,
            uint256(s_raffleState)
        );
    }
    s_raffleState = RaffleState.CALCULATING;
    uint256 requestId = i_vrfCoordinator.requestRandomWords(
        i_gasLane, //
        i_subscriptionId,
        REQUEST_CONFIRMATIONS,
        i_callbackGasLimit,
        NUM_WORDS
    );
    emit RequestedRaffleWinner(requestId);
}

测试脚本代码

describe("performUpkeep", function () {
    it("can only run if checkupkeep is true", async () => {
        await raffle.enterRaffle({ value: raffleEntranceFee })
        await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
        await network.provider.request({ method: "evm_mine", params: [] })
        const tx = await raffle.performUpkeep("0x")
        assert(tx)
    })
    it("reverts if checkup is false", async () => {
        await expect(raffle.performUpkeep("0x")).to.be.revertedWith(
            `Raffle__UpkeepNotNeeded(0,0,0)`
        )
    })
})

遇到的错误

AssertionError: Expected transaction to be reverted with Raffle__UpkeepNotNeeded(0,0,0), but other exception was thrown: Error: VM Exception while processing transaction: reverted with custom error 'Raffle__UpkeepNotNeeded(0, 0, 0)'

解决方案

原因分析

Waffle的revertedWith匹配的是字符串形式的错误消息,合约抛出的自定义错误参数之间有空格((0, 0, 0)),但测试代码里写的是(0,0,0),格式不匹配导致断言失败。

解决方法1:精确匹配错误字符串

修改测试代码中的错误消息,保留参数间的空格:

it("reverts if checkup is false", async () => {
    await expect(raffle.performUpkeep("0x")).to.be.revertedWith(
        `Raffle__UpkeepNotNeeded(0, 0, 0)`
    )
})

解决方法2:使用自定义错误专用匹配器(推荐)

使用Waffle提供的revertedWithCustomError匹配器,直接匹配错误类型和参数,无需依赖字符串格式:

it("reverts if checkup is false", async () => {
    await expect(raffle.performUpkeep("0x"))
        .to.be.revertedWithCustomError(raffle, "Raffle__UpkeepNotNeeded")
        .withArgs(0, 0, 0);
})

这种方式更健壮,后续参数格式变化也不会影响测试结果,只需保证参数值和类型正确即可。

内容的提问来源于stack exchange,提问作者Vasanth Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 03:40:34