Here is a very small repo to show the issue: https://github.com/adamdry/ethers-event-issue

But I'll explain it here too. This is my contract:

//SPDX-License-Identifier: UNLICENSED;
pragma solidity 0.8.4;

contract ContractA {

    event TokensMinted(uint amount);

    function mint(uint amount) public {
        emit TokensMinted(amount);


And this is my test code:

import * as chai from 'chai'
import { BigNumber, ContractTransaction } from 'ethers'
import { ethers } from 'hardhat'
import { ContractA, ContractAFactory } from '../typechain'

const expect = chai.expect

describe("Example test", function () {
    it("should fire the event", async function () {
        const [owner] = await ethers.getSigners();

        const contractAFactory = (await ethers.getContractFactory(
        )) as ContractAFactory

        const contractA: ContractA = await contractAFactory.deploy()

        contractA.on('TokensMinted', (amount: BigNumber) => {

        const contractTx: ContractTransaction = await contractA.mint(123)
        const contractReceipt: ContractReceipt = await contractTx.wait()

        for (const event of contractReceipt.events!) {

I was expecting the ########### to get printed to the console however it doesn't so the listener function isn't being executed for some reason.

If I dig into the ContractReceipt the correct event data is there:

  "transactionIndex": 0,
  "blockNumber": 2,
  "transactionHash": "0x55d118548c8200e5e6c19759d9aab56cb2e6a274186a92643de776d617d51e1a",
  "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
  "topics": [
  "data": "0x000000000000000000000000000000000000000000000000000000000000007b",
  "logIndex": 0,
  "blockHash": "0x808e6949118509b5a9e482e84cf47921a2fcffbcd943ebbd8ce4f6671469ee01",
  "args": [
      "type": "BigNumber",
      "hex": "0x7b"
  "event": "TokensMinted",
  "eventSignature": "TokensMinted(uint256)"

1 Answer 1


The problem here is, default polling interval in an ethers provider is 4 seconds. By the time it polls, your it('', async function () {}) has finished execution, and garbage collector might even clear the local variables contract immediately after it finishes.

A simple solution could be to add a wait of 4 seconds or higher, v


  for (const event of contractReceipt.events!) {

  // waits for 5 sec
  await new Promise(res => setTimeout(res, 5000));

You can also reduce the polling interval, however, the minimum value is 1 msec.

contractA.provider.pollingInterval = 1;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.