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

Hardhat函数权限验证测试问题:非白名单用户测试报错

Hardhat测试合约权限控制的正确写法

我正在验证一个智能合约函数,确保仅白名单成员或合约所有者可访问该函数。但运行Hardhat测试文件时出现回滚错误,错误信息如下:

Validations
         should revert error for non whitelisted memeber:
     Error: VM Exception while processing transaction: reverted with reason string 'Only owner or whiteListed members allowed'
    at KeyboardNFT.isWhiteListedorOwner (contracts/nft_erc721.sol:1102)

对应的测试代码如下:

describe("Validations", function () {
    it("should revert error for non whitelisted memeber", async function () {
      const {hardhatToken, owner, addr1, addr2} = await loadFixture(deployTokenFixture);
      expect(await hardhatToken.connect(addr1).awardItem(addr1.address,"first nft")).to.throw("Only owner or whiteListed members allowed");
    });
  });

请问如何正确在Hardhat测试中验证该函数的权限控制逻辑?


问题根源

你当前的测试写法存在两个核心问题:

  1. 直接用await执行交易调用,当合约触发revert时会直接抛出异常,导致测试提前终止,根本走不到to.throw的断言环节。
  2. Chai原生的to.throw只适用于同步函数的异常捕获,而合约交易是异步操作,需要用Hardhat集成的Chai断言库提供的异步revert专用方法。

修正后的测试代码

改用await expect(交易调用).to.be.revertedWith(错误信息)的方式,就能正确捕获并验证合约的revert逻辑:

describe("Validations", function () {
    it("should revert error for non whitelisted member", async function () {
      const { hardhatToken, addr1 } = await loadFixture(deployTokenFixture);
      // 把交易调用传入expect,用revertedWith匹配reason字符串
      await expect(
        hardhatToken.connect(addr1).awardItem(addr1.address, "first nft")
      ).to.be.revertedWith("Only owner or whiteListed members allowed");
    });
});

关键注意事项

  • 不要在交易调用前加await,而是将整个交易调用作为参数传给expect,再给expect本身加await(因为断言逻辑是异步的)。
  • .revertedWith()会精确匹配合约revert时抛出的reason字符串,确保权限控制逻辑符合预期。

补充完整测试场景

为了全面验证权限控制,还可以补充测试合法调用的场景:

describe("Validations", function () {
    it("should revert error for non whitelisted member", async function () {
      const { hardhatToken, addr1 } = await loadFixture(deployTokenFixture);
      await expect(
        hardhatToken.connect(addr1).awardItem(addr1.address, "first nft")
      ).to.be.revertedWith("Only owner or whiteListed members allowed");
    });

    it("should allow owner to call the function", async function () {
      const { hardhatToken, owner } = await loadFixture(deployTokenFixture);
      // 验证所有者调用不会revert
      await expect(
        hardhatToken.connect(owner).awardItem(owner.address, "owner nft")
      ).not.to.be.reverted;
      // 额外验证NFT是否成功 mint(根据合约逻辑调整)
      const tokenId = 1;
      expect(await hardhatToken.ownerOf(tokenId)).to.equal(owner.address);
    });

    it("should allow whitelisted member to call the function", async function () {
      const { hardhatToken, addr1, owner } = await loadFixture(deployTokenFixture);
      // 先将addr1加入白名单(假设合约有addWhitelist方法)
      await hardhatToken.connect(owner).addWhitelist(addr1.address);
      // 验证白名单用户调用成功
      await expect(
        hardhatToken.connect(addr1).awardItem(addr1.address, "whitelist nft")
      ).not.to.be.reverted;
    });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 09:45:45