Wurf vs. Return

Wir versuchen herauszufinden, ob returnoder throwin Solidity verwendet werden soll, wenn eine Bedingung fehlschlägt, und wir gehen nicht von einer Böswilligkeit des Benutzers aus. Hier sind die Vor- und Nachteile, die wir bisher herausgefunden haben:

Warum verwendenthrow

  • Alle Nebeneffekte des Codes werden rückgängig gemacht
  • Einige Brieftaschen können im Voraus vorhersagen throwund den Benutzer warnen

Warum verwendenreturn

  • Der ahnungslose Benutzer verbraucht weniger Gas (wieder unter der Annahme, dass es sich nicht um einen böswilligen Anruf handelt).
  • Anders als bei throw.

Gibt es weitere Überlegungen (oder Best Practices), die wir beachten sollten?

Antworten (2)

Alle Überlegungen in der Frage sind hilfreich.

throwist sicherer, da es sicherstellt, dass keine Nebenwirkungen verbleiben, aber eine weitere Überlegung ist die Fehlerberichterstattung. Mit throwgibt 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 throwweb3.js derzeit ein Problem mit falsevalues ​​hat, wenn ein Solidity auftritt .

BEARBEITEN: Da throwdas gesamte Gas verbraucht wird, behalten Sie die EIP 140 REVERT-Anweisung im Auge :

Die REVERTAnweisung 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.

Seien Sie vorsichtig, da throw den gesendeten Ether nicht zurückgibt, sondern nur Änderungen an Daten rückgängig macht.
@PabloYabo Richtig, wenn Sie meinten, dass throwdas gesamte Gas verbraucht wird, und ich habe die Klarstellung hinzugefügt. Andernfalls wird eine Ätherübertragung entweder mit a throwoder rückgängig gemacht revert.
Was ich meine ist, dass, wenn Sie die send-Funktion aufrufen, um Ether an ein anderes Konto zu senden, der gesendete Ether nicht mit einem Throw zurückgesetzt wird.
@PabloYabo A rollt throwden gesendeten Ether zurück: ethereum.stackexchange.com/questions/2428/…
Der Wurf gibt den gesendeten Ether zurück, aber er rollt den innerhalb des ausgeführten Codes gesendeten Ether nicht zurück. Es gibt den msg.value zurück, aber nur das. Wenn Sie Ether in Ihrem Code gesendet haben, wird dieser nicht zurückgesetzt.
Hallo @PabloYabo. Kannst du bitte eine neue Frage zu dem öffnen, was du beobachtest? Eine Transaktion, die wirft, verbraucht das gesamte Gas und alle Statusänderungen und Ether-Transfers werden rückgängig gemacht.

Vielleicht möchten Sie auch überlegen, warum Sie throw / return nicht verwenden sollten:

Warum nicht Throw verwenden

  • Alles Gas ist verbraucht, alles zurückgekehrt
  • Dem Anrufer kann nicht mitgeteilt werden, warum der Anruf fehlgeschlagen ist
  • Fehler können nicht abgefangen werden, also können sie nicht elegant gehandhabt werden

Warum nicht die Rückgabe verwenden

  • Aufrufern ist möglicherweise nicht klar, dass die Funktion nicht erfolgreich ausgeführt werden kann. Dies kann zu katastrophalen Folgen führen: contract.doSomeImportantCall()kann zurückgeben false, aber der Aufrufer hat stattdessen einen Wurf erwartet, sodass schlimme Dinge passieren können, wenn er den Rückgabewert nicht überprüft.
  • Sie werden feststellen, dass Sie überall mehrere Werte zurückgeben: zB returns (bool _successful, uint _result)vsreturns (uint _result)
  • Die Handhabung mehrerer Rückgabewerte ist umständlich und schwieriger zu testen.

Es gibt wirklich keinen Konsens darüber, wie man Dinge richtig macht. Tatsächlich gibt es derzeit beispielsweise eine Debatte über Wurf vs. Rückschlag für transferdie aktualisierte ERC20-Spezifikation.