Trüffeltest, Protokolle enthalten kein ausgegebenes Ereignis

Ich rufe eine Vertragsfunktion auf, die ein Ereignis in einer Transaktion ausgibt. Diese Transaktion sollte das Ereignis enthalten und ist normalerweise sichtbar über:

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

Diese enthält normalerweise eine Liste der ausgegebenen Ereignisnamen in der Transaktion. In meinem Aufruf geben die Tests jedoch Folgendes aus:

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

mit Testblock, der fehlschlägt:

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

Die erste Zeile führt den Funktionsaufruf aus, der das Ereignis ausgibt Stored. Die zweite Zeile ruft die Instanz nach Ereignisname aus den Protokollen ab. Die dritte Zeile protokolliert einfach die enthaltenen Ereignisse. Die vierte Zeile bestätigt, dass das Ereignis in den Protokollen vorhanden ist.

Wie in der Testausgabe gezeigt, waren die Protokolle leer [], aber das Ereignis wurde ausgegeben.

Warum wird angezeigt, dass das Ereignis ausgegeben wurde, aber auch nicht in den Protokollen der Transaktion vorhanden ist, die es ausgegeben hat?

Antworten (2)

Es stellt sich heraus, dass Transaktionsempfangsprotokolle nur Ereignisse enthalten, die im Zusammenhang mit der aufgerufenen Direktvertragsfunktion ausgegeben werden. Wenn die aufgerufene Funktion einen weiteren Aufruf an einen separaten externen Vertrag durchführt, der ein Ereignis ausgibt, werden diese nicht eingeschlossen, selbst wenn sie ausgegeben werden.

Um diese emittierten Ereignisse von anderen Verträgen zu nutzen:

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

wo someFunctionist eine Funktion, die eine Funktion eines anderen Vertrages aufruft, der sich von unterscheidet instance.

Dadurch werden die Protokolle aus dem Empfangsobjekt abgerufen. Die Protokolle sollten Themen enthalten, von denen das erste eine gehashte Ereignissignatur ist. Daher können wir das verwenden, was wir von unserer Ereignissignatur erwarten, sie hashen und auf Existenz in den Protokollen testen. Dies funktioniert, weil alle Ereignisse in den Empfangsprotokollen enthalten sind, aber nicht in den von Truffle/Ganache bereitgestellten Transaktionsprotokollen zurückgegeben werden.

Dieser Beitrag hat geholfen.

In späteren Versionen von Truffle (getestet mit v5.1.0) werden dieselben Protokolle und Themen unter einer anderen Transaktionsempfangseigenschaft gefunden 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");
Gute Antwort. Nur fürs Protokoll, Sie müssen nicht installieren js-sha3, stattdessen können Sie verwenden web3.utils.keccak256.
Update : Es scheint, dass dieser Code mit Truffle ^5.0.30 nicht mehr funktioniert. Es gibt keine Themen.
@PaulRazvanBerg Das Objekt hat sich leicht geändert, aber sie sind immer noch zugänglich (zum Glück!). Ich habe die Antwort aktualisiert, um dies zu berücksichtigen.

Sie könnten web3 verwenden und die Methode Contract mit der Truffle-Instanz abi und der Vertragsadresse aufrufen. Verwenden Sie dann die Ereignismethoden. Sie müssen web3 nicht deklarieren, da Trüffel dies bereitstellen.

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)  

Folgen Sie der web3.js- Dokumentation für weitere Ereignismethoden