Zurückgeben eines Fehlercodes mit Revert

Gemäß der neuesten Version des Yellow Paper und der Solidity-Assembly-Spezifikation kann Revert Opcode einen Fehlercode zurückgeben.

http://solidity.readthedocs.io/en/develop/assembly.html

revert(p, s) - Ausführung beenden, Zustandsänderungen rückgängig machen, Daten zurückgeben mem[p..(p+s))

Die Revert-Funktion in reiner Solidität hat jedoch 0 Argumente. Ich denke, es unterstützt noch keinen Rückgabecode.

[F] : Wie kann ich die Wiederherstellung von der Solidity-Assembly verwenden, um einen Fehlercode an die aufrufende web3-JavaScript-Anwendung zu übergeben? Falls dies nicht möglich ist, begründen Sie bitte warum.

Update : siehe auch Solidity: Wie können wir eine Fehlermeldung in "require" schreiben?

Können wir davon ausgehen, dass diese Einschränkung auch für das requireNachrichtenfeld gilt?
Ja. Require ist auf den Revert-Opcode angewiesen.

Antworten (1)

Wie in den Kommentaren besprochen, gibt es keine einfache Möglichkeit, den Rückgabegrund in der Dapp zu erhalten. Diese Funktion wird jedoch möglicherweise in Zukunft unterstützt.

Hier ist die anfängliche EIP und ihre Diskussion:

https://github.com/ethereum/EIPs/blob/master/EIPS/eip-658.md https://github.com/ethereum/EIPs/pull/658


Vorherige Antwort

Soweit ich weiß, ist es einem Client wie web3 nicht möglich, die Revert-Ausgabe zu lesen, ebenso wie es nicht möglich ist, die Ausgabe im Falle eines normalen Transaktionsabschlusses zu lesen. Revert verwendet Ausgabedaten owie im Yellow Paper definiert, die für Nachrichtenaufrufe verwendet werden können, aber für Transaktionen ignoriert werden.

Nachrichtenaufrufe haben auch eine zusätzliche Komponente – die Ausgabedaten, die durch das Byte-Array o gekennzeichnet sind. Dies wird bei der Ausführung von Transaktionen ignoriert, jedoch können aufgrund der Ausführung von VM-Code Nachrichtenaufrufe initiiert werden, und in diesem Fall werden diese Informationen verwendet.

Die Wirkung des REVERT-Opcodes ist durch die Formel 140 gegeben, die sich auf den Ausgang bezieht o.

Remix zeigt jedoch die Ausgabe bei Verwendung von JavaScript VM, da es Transaktionen synchron ausführt:

pragma solidity^0.4.11;

contract C {
    function testRevert() pure public returns (uint result) {
        uint memOffset;
        assembly {
             memOffset := msize() // Get the highest available block of memory
             mstore(add(memOffset, 0x00), 6) // Set value
             mstore(0x40, add(memOffset, 0x20)) // Update the msize offset to be our memory reference plus the amount of bytes we're using
             revert(memOffset, 0x20) // revert returning 1 byte
        }
    }
}

Decodierte Ausgabe:

{
    "0": "uint256: result 6"
}

Bei der Ausführung auf Testnets oder Mainnet gibt es keine Ausgabe.

Es sollte möglich sein, die Revert-Ausgabe zu lesen, wenn Low-Level-Assembly verwendet callwird delegatecall( callcodeich werde diese Antwort aktualisieren, wenn ich ein funktionierendes Codebeispiel habe).

Ich gehe davon aus, dass in Solidity eine try-catch-ähnliche Funktion hinzugefügt wird, wenn call, delegatecall, callcodeund Verträge über ihre Schnittstelle aufgerufen werden (wird die Antwort aktualisieren, wenn ich Referenzen habe).

Hm. Es gibt also eigentlich keine Möglichkeit, einen Fehlercode zurückzugeben. Der richtige Ort dafür wäre der Transaktionsbeleg, oder? Ich habe gelesen, dass es eine statusEigenschaft in der tx-Quittung gibt, aber es kann nur 0oder sein 1. Wissen Sie, ob es Pläne gibt (z. B. ERC/EIPs), die Retourendaten auf der Quittung zu speichern? Das Auslösen eines Fehlerereignisses würde dem Zurücksetzen der gesamten Transaktion widersprechen. Für das Fehlerereignis müsste ich die Erstellung des Ereignisses festschreiben, aber alles andere rückgängig machen. Was wäre ein Muster dafür?
@ivicaa Sie haben Recht mit dem Fehlerereignis, ich habe es aus meiner Antwort gelöscht. Die Verwendung des Statusfelds in der Quittung ist eine gute Idee, denke ich. Alles, was ich gefunden habe, ist diese EIP github.com/ethereum/EIPs/blob/master/EIPS/eip-658.md , die der ursprüngliche Vorschlag für den Status 0|1 ist.
Das Hässliche am Statusfeld (0|1) ist, dass wiederum nichts Genaueres als Fehlercode an die DAPP-UI zurückgegeben werden kann. Es ist besser als die sentGas == usedGasvorherige Überprüfung, aber effektiv können Sie in der Benutzeroberfläche nur sagen, "Es ging durch" oder "Etwas ist schief gelaufen". Aber was genau schief gelaufen ist, geht in der Zusammenfassung verloren. Ich denke, man könnte die Ablaufverfolgung der Transaktion durchgehen, um den Speicherort zu finden, aber es klingt für diesen Anwendungsfall nach einer Problemumgehung.
@ivicaa Interessanterweise trug das EIP ursprünglich den Titel „Einbetten von Transaktionsrückgabedaten in Quittungen“ und wurde später in „Einbetten des Transaktionsstatuscodes in Quittungen“ geändert . github.com/ethereum/EIPs/pull/658/files/… . Nicht sicher, was der Grund dafür ist.
In der Diskussion ( github.com/ethereum/EIPs/pull/658 ) sagen sie: „Nach Rücksprache mit anderen habe ich es wegen Bedenken hinsichtlich DoS- und Spam-Möglichkeiten fallen gelassen; Rückdaten werden nicht berechnet (außer für Speicher Erweiterung), aber wenn es Teil des Konsens ist, müsste es auf unbestimmte Zeit mit Quittungen gespeichert werden. Es ist immer noch eine Möglichkeit, dies zu späteren Gabeln hinzuzufügen, aber ich wollte nichts überstürzen, das nicht vollständig durchdacht war. -- IMHO nicht so optimal diese Entscheidung. Wenn es Angst vor DDoS gibt, hätten sie einfach die Rückgabe eines Bytes zulassen können. Das wäre besser als 0/1. :-/
@ivicaa fand dort auch: „Eine Kopie dieses EIP mit unterschiedlichen Anforderungen wäre im Grunde das absolute Minimum. Um das DoS-Problem zu lösen, müsste es wahrscheinlich auch eine Art Gaskosten für Rücksendedaten angeben, die in Quittungen enden. Jetzt wäre ein guter Zeitpunkt, darüber nachzudenken, da wir bis zum nächsten Fork noch viel Zeit haben." Ich vermute, dass es eine weitere EIP für Verbesserungen geben wird.
Ich habe gute Beiträge von Ihnen zum Thema Speichertrie gelesen, ich würde es sehr schätzen, wenn Sie ein Auge darauf werfen könnten: ethereum.stackexchange.com/questions/41464/…
@ivicaa hat meine Antwort gepostet :)