首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Hardhat中测试发出的事件

在Hardhat中测试发出的事件
EN

Ethereum用户
提问于 2021-09-15 23:40:39
回答 3查看 11.2K关注 0票数 12

我有一份从ERC721PresetMinterPauserAutoId继承下来的牢固合同

我想编写一个测试,以验证在调用公共Transfer函数之后契约是否已经发出了一个mint(to)事件。到目前为止,我的测试结果如下:

代码语言:javascript
复制
const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("MyContract -- Contract Tests", function () {
    let admin, addr1, addr2;
    let myContract;
    let minterRole = ethers.utils.id("MINTER_ROLE");

    beforeEach(async () => {
        ([admin, addr1, addr2] = await ethers.getSigners());
        const MyContract = await ethers.getContractFactory('MyContract');
        myContract = await MyContract.deploy();
    });   

    // Test passes
    it("Should not allow account without MINTER_ROLE to mint", async function() {
        await expect(myContract.connect(addr1).mint(addr1.address))
                .to.be.revertedWith('ERC721PresetMinterPauserAutoId: must have minter role to mint');

    });

    it("Should allow account with MINTER_ROLE to mint", async function() {
        await myContract.connect(admin).grantRole(minterRole, addr1.address);
        expect(await myContract.hasRole(minterRole, addr1.address)).to.equal(true);

        await expect(myContract.connect(addr1).mint(addr1.address))
            .to.emit(myContract, 'Transfer')
            .withArgs(address(0), addr1.address, 1); // <-- this part is broken
    });
});

显然,address(0)undefined。我查看了底层_mint函数的源代码,它如下所示:

代码语言:javascript
复制
function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);
}

所以我有几个问题。

  • 如何在测试中捕获为发出的事件捕获的参数,以便调试输出?
  • 对事件发出的参数进行测试的正确方法是什么?我很难为1编写令牌计数器,但这是因为我还没有找到一个API来告诉我造币的总数。此外,我也不完全确定如何测试address(0)
EN

回答 3

Ethereum用户

发布于 2021-09-16 14:22:45

这个例子展示了如何处理一般情况下的事件,并包含了一个测试,说明了一些场景。

tl;dr是这样的一个合同:

代码语言:javascript
复制
contract EventEmitter {
  event MyEventWithData(uint, string);

  function emitMyEventWithData(uint x, string calldata s) public {
    emit MyEventWithData(x, s);
  }
}

您可以在这样的测试中检查它(请注意,这依赖于硬帽华夫饼):

代码语言:javascript
复制
  it("Should emit MyEventWithData", async function () {
    const EventEmitter = await ethers.getContractFactory("EventEmitter");
    const eventEmitter = await EventEmitter.deploy();
    await eventEmitter.deployed();

    await expect(eventEmitter.emitMyEventWithData(42, "foo"))
      .to.emit(eventEmitter, "MyEventWithData")
      .withArgs(42, "foo");
  });
票数 19
EN

Ethereum用户

发布于 2022-08-17 02:56:52

您可以传递一个函数作为参数来捕获事件参数。

代码语言:javascript
复制
let capturedValue
const captureValue = (value) => {
    capturedValue = value
    return true
}
await expect(eventEmitter.emitBothEvents(arg1, arg2))
            .to.emit(myContract, 'Transfer')
            .withArgs(captureValue, otherArg1, otherArg2)
console.log("CapturedValue:", capturedValue)
票数 0
EN

Ethereum用户

发布于 2023-02-26 04:52:55

零地址由Ethers.js常数ethers.constants.AddressZero表示。正如您提到的,使用address(0)不起作用,因为它实际上并不代表代码中的任何内容。在稳固性中,address(0)表示类型为address的零值;在Java中,它表示调用函数address(0)并将其传递为零,这在您的情况下没有任何意义。在您的示例中,需要将address(0)替换为ethers.constants.AddressZero (它是一个由20个字节(40个字节)组成的零字符串),或者是一个实际的零字符串(如0x0000000000000000000000000000000000000000 )。

您提供的_mint(address to, uint256 tokenId)函数与您正在调用的函数不同。_mint函数有两个参数,在测试中调用的mint函数只需要一个参数。如果不知道您的mint函数是什么,以及您正在测试的Transfer事件预期会返回什么tokenId,就不可能为您提供确切的解决方案。

但是,在您的代码中,您试图断言Transfer事件发出的参数是zero addressto address1 (我假设是令牌id )。让我们假设我们知道由该事件发出的tokenId应该等于1;那么您可以执行以下操作:

代码语言:javascript
复制
...

const expectedTokenId = 1;
const zeroAddress = ethers.constants.AddressZero;

await expect(myContract.connect(addr1).mint(addr1.address))
            .to.emit(myContract, 'Transfer')
            .withArgs(zeroAddress, addr1.address, expectedTokenId);

... 

.withArgs()接受预期的事件参数,并将这些参数与实际事件返回的参数进行比较,以断言它们等于通过测试。

票数 0
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/110004

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档