Тест Truffle, журналы не включают сгенерированное событие

Я вызываю функцию контракта, которая генерирует событие в транзакции. Эта транзакция должна включать событие и обычно отображается через:

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

Обычно он содержит список имен эмитированных событий в транзакции. Однако в моем вызове тесты выводят:

[]
    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)

с тестовым блоком, который не работает:

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");

Первая строка выполняет вызов функции, которая генерирует событие Stored. Вторая строка извлекает экземпляр по имени события из журналов. Третья строка просто регистрирует содержащиеся в ней события. Четвертая строка утверждает, что событие существует в журналах.

Как видно из тестового вывода, журналы были пусты [], но событие было сгенерировано.

Почему показано, что событие было сгенерировано, но также отсутствует в журналах транзакции, которая его сгенерировала?

Ответы (2)

Оказывается, журналы квитанций транзакций включают только события, испускаемые в контексте вызываемой функции прямого контракта. Если вызываемая функция делает еще один вызов отдельного внешнего контракта, который создает событие, они не будут включены, даже если они были созданы.

Чтобы использовать эти эмитированные события из других контрактов:

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");

где someFunctionфункция, которая вызывает функцию другого контракта, отличную от instance.

Это захватывает журналы из объекта получения. В логах должны быть темы, первая из которых — хешированная сигнатура события. Таким образом, мы можем использовать то, что мы ожидаем от нашей сигнатуры события, хэшировать ее и проверять на наличие в журналах. Это работает, потому что все события включаются в журналы квитанций, но не возвращаются в журналы транзакций, предоставляемые truffle/ganache.

Этот пост помог.

В более поздних версиях Truffle (проверено с v5.1.0) те же журналы и темы находятся в другом свойстве получения транзакции 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");
Отличный ответ. Для справки, вам не нужно устанавливать js-sha3, вместо этого вы можете использовать web3.utils.keccak256.
Обновление : похоже, этот код больше не работает с трюфелем ^ 5.0.30. Нет тем.
@PaulRazvanBerg Объект немного изменился, но он по-прежнему доступен (к счастью!). Я обновил ответ, чтобы учесть это.

Вы можете использовать web3 и вызвать метод Contract с abi экземпляра трюфеля и адресом контракта. Затем используйте методы событий. Не нужно объявлять web3, так как трюфель предоставит это.

const receipt = await contractInstance.someFunction()

const contract = new web3.eth.Contract(contractInstance.abi, contractInstance.address)

//Now get evens depending on what you need
contract.getPastEvents("allEvents", {fromBlock: 0, toBlock: "latest"})
.then(console.log)  

Следуйте документации web3.js, чтобы узнать больше о методах обработки событий .