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

使用Viem与Hardhat测试时,无法向revertWithCustomError传入合约

解决Hardhat+Viem测试自定义错误时revertWithCustomError不兼容问题

你碰到的问题源于revertWithCustomError是为Ethers合约实例设计的断言方法,它要求合约对象包含interface属性,但Viem生成的合约实例用abi属性替代了interface,导致类型不匹配报错。以下是两种可行的解决方案:

方案一:使用Viem原生方式验证自定义错误

Viem提供了getContractError工具函数,可直接解析交易失败的错误信息,无需依赖Ethers的合约结构:

  1. 导入Viem的错误解析工具:
import { getContractError } from '@nomicfoundation/hardhat-viem/utils'
  1. 修改测试代码,捕获错误并断言:
it('Should block the heir', async () => {
  const { deployedContract, other } = await loadFixture(deployFixture);

  try {
    await deployedContract.write.withdraw([BigInt(0)], {
      account: other.account,
    });
    expect.fail('交易未按预期回滚');
  } catch (error) {
    const contractError = getContractError(error, deployedContract.abi);
    expect(contractError?.name).to.equal('Unauthorized');
  }
});

方案二:混用Ethers合约实例做断言

如果更习惯revertWithCustomError的语法,可以同时获取Ethers风格的合约实例,用它满足断言的参数要求:

  1. 在部署Fixture中添加Ethers合约实例:
async function deployFixture() {
  const [owner, other] = await hre.viem.getWalletClients();
  const deployedContract = await hre.viem.deployContract("Inheritance", [], {
    value: BigInt('50'),
  });
  const ethersContract = await hre.ethers.getContractAt("Inheritance", deployedContract.address);

  return {
    owner, other, deployedContract, ethersContract,
  };
};
  1. 测试时用Ethers合约作为revertWithCustomError的第一个参数:
it('Should block the heir', async () => {
  const { deployedContract, other, ethersContract } = await loadFixture(deployFixture);

  await expect(
    deployedContract.write.withdraw([BigInt(0)], {
      account: other.account,
    })
  ).to.be.revertedWithCustomError(ethersContract, "Unauthorized");
});

核心原因说明

revertWithCustomError是Hardhat Ethers插件扩展的Chai断言,它依赖Ethers合约的interface属性解码自定义错误。而Viem的合约实例采用了不同设计,用abi属性存储合约ABI,没有interface字段,因此直接传入Viem合约会触发类型错误。

内容的提问来源于stack exchange,提问作者Francisco Canela

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 09:10:11