Airdrop, expectEvent and Array

I am implementing an airdrop function as follows:

--- SNIP ---
event Airdrop(address[] recipients, uint256[] values);
--- SNIP ---

function airdrop(address[] memory recipients, uint256[] memory values)
        public
    {
        for (uint256 i = 0; i < recipients.length; i++) {
            transfer(recipients[i], values[i]);
        }

        emit Airdrop(recipients, values);
    }
--- SNIP ---

And trying to test this function as follows:

contract("Miscellanous", async (accounts) => {
  const [sender] = accounts;

  it("should airdrop x% of minted tokens", async () => {
    const senderBalance = await this.token.balanceOf(sender);
    const recipients = accounts.slice(1, 6);
    const totalAmount = BigNumber(2.5)
      .dividedBy(100)
      .multipliedBy(senderBalance.toString())
      .toFixed();

    const amounts = Array(recipients.length).fill(
      new BN(totalAmount).div(new BN(recipients.length))
    );

    const receipt = await this.token.airdrop(recipients, amounts, {
      from: sender,
    });

    await expectEvent(receipt, "Airdrop", {
      recipients: recipients,
      values: amounts,
    });

    recipients.forEach(async (i, recipient) => {
      await expectEvent(receipt, "Transfer", {
        from: sender,
        to: recipient,
        value: amounts[i],
      });

      const recipientBalance = await this.token.balanceOf(recipient[i]);

      expect(recipientBalance).to.be.bignumber.equal(amounts[i]);
    });

    const senderBalanceAfterTx = await this.token.balanceOf(sender);

    expect(senderBalanceAfterTx).to.be.bignumber.equal(
      senderBalance.sub(new BN(totalAmount))
    );
  });
});

I am not sure how expectEvent deals with Arrays but I am getting the following stacktrace:

  2) Contract: Miscellanous
       should airdrop x% of minted tokens:

      expected event argument 'values' to have value 5000000000000000000000000000000,5000000000000000000000000000000,5000000000000000000000000000000,5000000000000000000000000000000,5000000000000000000000000000000 but got 5000000000000000000000000000000,5000000000000000000000000000000,5000000000000000000000000000000,5000000000000000000000000000000,5000000000000000000000000000000
      + expected - actual

             0
             36267216
             16848388
             16543612
      +      0
           ]
         }
         {
           "length": 4
--
             0
             36267216
             16848388
             16543612
      +      0
           ]
         }
         {
           "length": 4
--
             0
             36267216
             16848388
             16543612
      +      0
           ]
         }
         {
           "length": 4
--
             0
             36267216
             16848388
             16543612
      +      0
           ]
         }
         {
           "length": 4
--
             0
             36267216
             16848388
             16543612
      +      0
           ]
         }
       ]

      at contains (node_modules\@openzeppelin\test-helpers\src\expectEvent.js:158:34)
      at C:\Users\ateyar\Documents\GitHub\erc20-deflationary\node_modules\@openzeppelin\test-helpers\src\expectEvent.js:57:9
      at Array.find (<anonymous>)
      at inLogs (node_modules\@openzeppelin\test-helpers\src\expectEvent.js:54:24)
      at expectEvent (node_modules\@openzeppelin\test-helpers\src\expectEvent.js:29:12)
      at Context.<anonymous> (test\ERC20Deflationary.test.js:433:11)
      at processTicksAndRejections (internal/process/task_queues.js:93:5)

What am I missing there? :thinking:

Can you provide a (ideally minimal) reproduction repository so we can look at this in more detail?

1 Like

Hi @frangio the above code is the relevant bits, might have to do with the way array are handled by expectEvent or the fact that it is an array of Big Numbers (BN).

Any update on this ticket?

I haven’t had the time to look into it. If you can provide a repository that I can clone and run npm test to reproduce the error that would help move this along faster.

It is a private repo, I can share it with you if you send me your username.

GitHub username is frangio.

Invited! look at the burn-only branch, and whilst at it just tested my token which implements a tax (burn tax) and is therefore deflationary, on my tests, it works fine however when deploying onto PCS/Uniswap a normal (aka unprivileged user who has to pay tax) can buy but not sell to PCS/Uniswap.

If you could kindly let me know what is causing this bug that would be super appreciated since it might also be the root cause of why my liquidity tax (liquidity-only branch) does not work. :pray:

Took a quick look. expectEvent does not support arrays of bignumbers.

As a workaround, remove values from the expectEvent call and manually compare the values array.

const e = expectEvent(receipt, 'Airdrop', { recipients: ... });
// here verify the value of e.args.values

Hmm… That’s what I thought, @frangio any idea why on Uniswap the burn-only token can only be bought but not sell? Has it got to do with the _approve not working within the _transfer?

I’m not familiar with this part of Uniswap. Take a look at Common Errors in the Uniswap docs.

I found out what the bug is it got to do with the _approve function posted more details on Simple Burnable Token Incompatible with (Uni|Pancake)Swap

1 Like