Mein Ziel ist es, eine einfache Funktion auszuführen, aber der Benutzer sollte sich bewusst sein, wenn der Anruf fehlschlägt. Ein Beispiel für eine einfache Funktion ist hier zu sehen .
Anstelle von return false
möchte ich verwenden throw
. Wäre ihre Wirkung auf den Fluss der Funktion dieselbe? Und welcher verbraucht weniger Sprit?
Welches könnte insgesamt motivierter sein, es zu verwenden?
Diese Diskussion ist hauptsächlich im Zusammenhang mit einem Vertrag von Bedeutung, der einen anderen Vertrag aufruft. Wenn der Callee-Vertrag wirft, gibt es catch
in aktuellen EVM-Versionen keine im Caller-Vertrag. Daher ist es unmöglich, einen Throw-Fehler bei Bedarf zu beheben. Dies wird jedoch in den üblichen Anwendungsfällen selten benötigt.
Die Verwendung von throw macht es einfacher zu sehen, ob die Transaktion einen Fehler in einem Blockchain-Explorer hatte.
Siehe auch Diskussion über kommende Funktionen, die sich mit diesen https://github.com/ethereum/EIPs/issues/140 befassen
Ich dachte nur, ich würde mich einschalten, falls diese Fragen und Antworten für andere nützlich sind. Stellen Sie sich der Kürze halber vor, ich hätte meiner Meinung nach allem vorangestellt .
Es ist eine sehr allgemeine Frage. Ich würde die Situationen in zwei Fälle einteilen:
Im ersten Fall return false
vielleicht der richtige Weg. Zum Beispiel: "Ist es Montag?" - Nein. Nichts ist besonders falsch und "Nein" ist eine gültige und erwartete Antwort. Implizit sollte der Anrufer auf die Möglichkeit vorbereitet sein, dass ein „Nein“ zurückkommt, und entsprechend damit umgehen.
Eine große Anzahl von Fällen fällt in die zweite Kategorie; Irgendwas stimmt nicht. In diesen Fällen ist es throw;
meiner Meinung nach fast immer vorzuziehen .
Bedenken Sie, dass wir einen Vertrag bereitstellen können und der Anrufer in Zukunft möglicherweise ein anderer Vertrag ist. Wenn wir return false
tatsächlich den Anrufer mit der Verantwortung belasten, mit unerwarteten Ergebnissen zu kämpfen. Das führt zu Komplexität und Komplexität ist etwas, was wir in Smart Contracts nicht wollen. Auf der anderen Seite throw
tun wir allen zukünftigen Anrufern einen Dienst, wenn wir das erste Anzeichen von Schwierigkeiten bemerken; Wenn unsere Funktion "nicht passiert" ist, ist nichts passiert.
Das ist genau das Gegenteil von der Philosophie in anderen Umgebungen, in denen man fast besessen davon ist, Fehler zu erkennen und Probleme zu erklären. Ich denke, es verdient eine Erwähnung für diejenigen, die anfangen und sich möglicherweise über den üblichen Ansatz wundern.
In einem Smart Contract neige ich dazu, früh zu scheitern, hart zu scheitern und nichts zu erklären. Also throw
bei (fast) jeder Gelegenheit.
Allgemeine Heuristik:
Es mag ein wenig brutal erscheinen. Ein Smart Contract sollte sich meiner Meinung nach auf die Wahrung der Integrität von Anwendungen (und Daten) konzentrieren und dies auf möglichst einfache Weise tun, da wir es mit einer Plattform zu tun haben, auf der ein Fehler oder Versehen nicht triviale Folgen haben und schwierig sein könnte oder unmöglich zu beheben.
Wir streben nach „offensichtlich richtig“. Die Minimierung der Komplexität impliziert, dass die Erklärung der Gründe ein separates Anliegen ist (das die Kunden herausfinden müssen). Throw
ist normalerweise die sicherste und einfachste Reaktion auf Ausnahmen, die die Integrität des Systems bedrohen.
Ich hoffe es hilft.
Im Allgemeinen JA , es ist besser, throw
anstelle von zu verwenden return false
.
Ein objektiver Grund ist, dass throw
es sicherer ist, weil es alle Zustandsänderungen rückgängig macht: Es ist sicher, dass sich nichts ändert, wenn der Anruf fehlschlägt. Es kann möglich sein, alle Änderungen manuell zu verfolgen und rückgängig zu machen, aber es ist möglich, etwas zu übersehen, wenn Sie es "manuell" tun.
Ein subjektiver Grund ist, dass Korrektheit, Sicherheit und Sicherheit die wichtigsten Prioritäten für dezentrale, vertrauenswürdige Anwendungen sind (wie @Rob beschreibt) und throw
objektiv sicherer sind.
Throw vs. Return beschreibt:
throw
throw
und den Benutzer warnenreturn
throw
.Eine weitere Überlegung ist die Fehlerberichterstattung. Mit throw
gibt es derzeit keine Möglichkeit, mehr Informationen über den Fehler zu erhalten, während Ereignisse und Fehlercodes verwendet werden könnten return
, um einen genaueren Grund für den Fehler zu vermitteln.
Eine weitere Sache, die Sie bei der Verwendung von web3.js beachten sollten, ist, dass throw
web3.js derzeit ein Problem mit false
values hat, wenn ein Solidity auftritt .
revert
wird wahrscheinlich diejenige sein, die verwendet werden sollte, da sie alle Vorteile von throw
und hat return
:
Die
REVERT
Anweisung bietet eine Möglichkeit, die Ausführung zu stoppen und Zustandsänderungen rückgängig zu machen, ohne das gesamte bereitgestellte Gas zu verbrauchen, und mit der Möglichkeit, einen Grund zurückzugeben.
Paul S
Mikko Ohtamaa
Paul S