我有一份从ERC721PresetMinterPauserAutoId继承下来的牢固合同
我想编写一个测试,以验证在调用公共Transfer函数之后契约是否已经发出了一个mint(to)事件。到目前为止,我的测试结果如下:
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函数的源代码,它如下所示:
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)。发布于 2021-09-16 14:22:45
这个例子展示了如何处理一般情况下的事件,并包含了一个测试,说明了一些场景。
tl;dr是这样的一个合同:
contract EventEmitter {
event MyEventWithData(uint, string);
function emitMyEventWithData(uint x, string calldata s) public {
emit MyEventWithData(x, s);
}
}您可以在这样的测试中检查它(请注意,这依赖于硬帽华夫饼):
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");
});发布于 2022-08-17 02:56:52
您可以传递一个函数作为参数来捕获事件参数。
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)发布于 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 address、to address和1 (我假设是令牌id )。让我们假设我们知道由该事件发出的tokenId应该等于1;那么您可以执行以下操作:
...
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()接受预期的事件参数,并将这些参数与实际事件返回的参数进行比较,以断言它们等于通过测试。
https://ethereum.stackexchange.com/questions/110004
复制相似问题