How to test for events that are dispatched in a nested operation?

I have a function in a contract that dispatches an event. But it also executes functions on other contracts that dispatch an event each. The first event is part of the transaction, the latter events not.

Example code:

function assignTeamVesting(address teamVesting) public onlyOwner {
    require(teamVesting != address(0), "xxxTokenSale: no Zero address allowed as team vesting address");

    _teamVesting = teamVesting;
    emit TeamVestingAssigned(_teamVesting);

    // update time locks/token vesting contracts as well
    if(_timeLocks.length > 0) {
        for(uint256 i = 0; i < _timeLocks.length; i++) {
            TokenVesting vesting = _timeLocks[i];
            vesting.updateBeneficiary(teamVesting);
        }
    }
}

The TokenVesting contracts function updateBeneficiary is:

function updateBeneficiary(address beneficiary) public onlyOwnerOrUpdater {
    address oldBeneficiary = _beneficiary;
    _beneficiary = beneficiary;
    emit BeneficiaryUpdate(_beneficiary, oldBeneficiary);
}

truffle test --show-events shows that all events was dispatched as expected:

TeamVestingAssigned(teamVesting: 0x90dAE34cb6e655868e1ee6D358591548D605d7D8 (address))
BeneficiaryUpdate(beneficiary: 0x90dAE34cb6e655868e1ee6D358591548D605d7D8 (address), oldBeneficiary: 0xFcCe0b0346cde1e6c609757345Fc34d5D9a60102 (address))
BeneficiaryUpdate(beneficiary: 0x90dAE34cb6e655868e1ee6D358591548D605d7D8 (address), oldBeneficiary: 0xFcCe0b0346cde1e6c609757345Fc34d5D9a60102 (address))

But in a test, when I execute the following line:

      const tx = await this.tokenSale.assignTeamVesting(another, {from: owner});

only the first event can be found in tx.logs:

[ { logIndex: 0,
    transactionIndex: 0,
    transactionHash:
     '0x2323194579b38689dd14cb1c81f4e69683cb3f6005f60b6c17bced36ea06c291',
    blockHash:
     '0x37506a8e1f0500422efa530ef187dd182c46995f160fce3c0f8e25109d87d7d1',
    blockNumber: 4696,
    address: '0x5BEd044dc960763E7C058B11dbc18e37C45CAe05',
    type: 'mined',
    id: 'log_65c362d2',
    event: 'TeamVestingAssigned',
    args:
     Result {
       '0': '0x90dAE34cb6e655868e1ee6D358591548D605d7D8',
       __length__: 1,
       teamVesting: '0x90dAE34cb6e655868e1ee6D358591548D605d7D8' } } ]

Is there any way to test for the other events as well?

(Maybe I should also ask on truffle-repo)

1 Like

Use openzeppelin-test-helpers expectEvent.inTransaction to test for events from other contracts

https://github.com/OpenZeppelin/openzeppelin-test-helpers#async-intransaction-txhash-emitter-eventname-eventargs--

async inTransaction (txHash, emitter, eventName, eventArgs = {})

Same as inLogs , but for events emitted in an arbitrary transaction (of hash txHash ), by an arbitrary contract ( emitter ), even if it was indirectly called (i.e. if it was called by another smart contract and not an externally owned account).


I put together the following sample code to illustrate

B.test.js

const { expectEvent } = require('openzeppelin-test-helpers');

const A = artifacts.require('A');
const B = artifacts.require('B');

contract('B', function () {
  beforeEach(async function () {
    this.a = await A.new();
    this.b = await B.new(this.a.address);
  });

  it('does stuff', async function () {
    const receipt = await this.b.doBStuff();

    // Log-checking will not only look at the event name, but also the values, which can be addresses, strings, numbers, etc.
    await expectEvent.inLogs(receipt.logs, 'DidBStuff', { message: "B" });
    await expectEvent.inTransaction(receipt.tx, A, 'DidAStuff', { message: "A" });
  });
});

A.sol

pragma solidity ^0.5.0;

contract A {

    function doAStuff() public {
        emit DidAStuff("A");
    }

    event DidAStuff(string message);
}

B.sol

pragma solidity ^0.5.0;

import "./A.sol";

contract B {

    A _a;

    constructor(A a) public {
        _a = a;
    }

    function doBStuff() public {
        _a.doAStuff();
        emit DidBStuff("B");
    }

    event DidBStuff(string message);
}
1 Like

Hi @itinance if my reply answered your question, could you mark it as the solution please, thank you. :pray: Otherwise let me know if you need more information.