且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在使用ethers js运行硬帽测试时,约定事件侦听器不会触发。

更新时间:2023-12-04 12:30:34

完整答案在此:https://github.com/nomiclabs/hardhat/issues/1692#issuecomment-905674692

但总而言之,这不起作用的原因是,在默认情况下,ethers.js使用轮询来获取事件,轮询间隔为4秒。如果您在测试结束时添加以下内容:
await new Promise(res => setTimeout(() => res(null), 5000));

应激发该事件。

然而!您还可以调整给定合同的轮询间隔,如下所示:

// at the time of this writing, ethers' default polling interval is
// 4000 ms. here we turn it down in order to speed up this test.
// see also
// https://github.com/ethers-io/ethers.js/issues/615#issuecomment-848991047
const provider = greeter.provider as EthersProviderWrapper;
provider.pollingInterval = 100;

如下所示:https://github.com/nomiclabs/hardhat/blob/master/packages/hardhat-ethers/test/index.ts#L642

然而!(再说一次)如果您想从事件中获得结果,以下方法不需要更改轮询或任何其他基于时间和时间的解决方案,根据我的经验,这可能会导致不可靠的测试:

it('testcase', async() => {
  const tx = await contract.transfer(...args); // 100ms
  const rc = await tx.wait(); // 0ms, as tx is already confirmed
  const event = rc.events.find(event => event.event === 'Transfer');
  const [from, to, value] = event.args;
  console.log(from, to, value);
})

这是我的TypeScripty化版本(根据我自己的合同,事件和参数略有不同):

const contractTx: ContractTransaction = await tokenA.mint(owner.address, 500)
const contractReceipt: ContractReceipt = await contractTx.wait()
const event = contractReceipt.events?.find(event => event.event === 'TokensMinted')
const amountMintedFromEvent: BigNumber = event?.args!['amount']

这是与上面的代码一起使用的实体中的事件声明:

event TokensMinted(uint amount);