Truffle Testing – Logs Not Showing Emitted Events in JavaScript

eventsjavascriptlogstestingtruffle

I am calling a contract function which emits an event in a transaction. This transaction should include the event and is typically visible via:

const receipt = await contractInstance.someFunction()
let logs = receipt.logs

This normally contains a list of the emitted event names in the transaction. However in my call the tests output:

[]
    1) Test someFunction()

    Events emitted during test:
    ---------------------------

    Stored()

    ---------------------------

  1 failing

  1) Contract: Test.js
       Test someFunction():
     AssertionError: Stored event not emitted: expected false to be truthy
      at Context.it (test/test.js:145:12)
      at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:188:7)

with testing block that fails:

const receipt = await instance.someFunction();
let event = validationReceipt.logs.some(l => { return l.event == "Stored" });
console.log(validationReceipt.logs);
assert.ok(event, "Stored event not emitted");

First line performs the function call which emits the event Stored. Second line retrieves the instance by event name from the logs. Third line simply logs the contained events. Fourth line asserts that the event exists in the logs.

As shown in the test output, the logs were empty [], but the event was emitted.

Why is the event being shown to have been emitted but also not present in the logs of the transaction that emitted it?

Best Answer

Turns out transaction receipt logs only include events emitted in the context of the direct contract function being called. If the called function makes another call to a separate external contract that emits an event, those won't be included even if there are emitted.

To make use of those emitted events from other contracts:

const sha3 = require('js-sha3').keccak_256
...

const tx = await instance.someFunction(();
let event = tx.receipt.logs.some(l => { return l.topics[0] == '0x' + sha3("Stored()") });
assert.ok(event, "Stored event not emitted");

where someFunction is a function that calls a function of another contract different to instance.

This grabs the logs from the receipt object. The logs should contain topics, the first of which is a hashed event signature. Thus we can use what we expect our event signature to be, hash it and test for existence in the logs. This works because all events are included in receipt logs but are not returned in the transaction logs provided by truffle/ganache.

This post helped.

On later versions of Truffle (have tested with v5.1.0), the same logs and topics are found under a different transaction receipt property rawLogs:

const tx = await instance.someFunction(();
let event = tx.receipt.rawLogs.some(l => { return l.topics[0] == '0x' + sha3("Stored()") });
assert.ok(event, "Stored event not emitted");
Related Topic