Wie können mehrere interne Transaktions-Out-of-Gas-Nebenwirkungen vermieden/erkannt werden?

Nach einem Problem, das ich in Github geöffnet habe, stört mich das. Die in dem Problem beschriebene Operation, die während des folgenden Tutorials von Avsa zum Erstellen eines DAO stattfand, generierte zwei interne Transaktionen, wie hier ersichtlich: txKurz gesagt, die internen Transaktionen sind:

  • Ändern Sie den Status des angeforderten Vorgangs im DAO auf "abgeschlossen".
  • Führen Sie die Operation tatsächlich durch, indem Sie eine Transaktion an einen anderen Vertrag senden

Die erste interne Transaktion wurde erfolgreich abgeschlossen - das bedeutet, dass die Operation im DAO auf den Status "abgeschlossen" aktualisiert wurde. Der zweite schlägt fehl, höchstwahrscheinlich, weil ihm das Benzin ausgegangen ist (mehrere Versuche führten zu den gleichen Ergebnissen, während das Hinzufügen von 100.000 Gas dazu führte, dass es mehrmals funktionierte).

Ich denke, die Implikationen, wenn so etwas in einem echten DAO passiert, sind klar. Ich bin (fälschlicherweise) davon ausgegangen, dass der gesamte Vorgang (einschließlich der ersten Transaktion) zurückgesetzt wird, wenn der zweiten Transaktion das Benzin ausgeht.

Wie im Kommentar von eth vorgeschlagen, werde ich eine spezifische Frage zu dieser Situation stellen - wie kann ich sie im Vertrag erkennen? Hilft es, die Reihenfolge der Operationen zu ändern?

Vielen Dank für Ihre erste Frage, und sie hat das Zeug zu einer ziemlich guten Frage. Fragen und Antworten sollten für sich alleine stehen können, ohne auf Links klicken zu müssen (weil Links tot sind). Insofern empfehle ich eine Überarbeitung. Ihre Frage hat auch einige Teile und es kann besser sein, sie aufzuteilen. Q1 zum Ändern der Reihenfolge ist für Ihr Beispiel ziemlich spezifisch, aber die anderen könnten separat gefragt werden.

Antworten (1)

Der gesamte Vorgang wurde nicht zurückgesetzt, da vom Transaktionsursprung der Gesamttransaktion genügend Gas bereitgestellt wurde. Wenn nicht genügend Gas bereitgestellt wurde, würden Sie das erwartete Verhalten beobachten, bei dem beide internen Transaktionen rückgängig gemacht würden.

Die zweite interne Transaktion wurde rückgängig gemacht, weil sie kein Benzin mehr hatte. Um dies zu erkennen, könnte die aufgerufene Funktion einen trueRückgabewert enthalten (verwenden Sie bei Bedarf ein Tupel). Der Anrufer kann diesen trueWert explizit überprüfen, da ein Gasmangel den Standardwert zurückgeben würde, der 0 ( false) ist.

Hier ist ein Beispiel dafür, was passiert ist. Die erste (interne) Transaktion erfordert 200 Gas und die zweite Transaktion erfordert 700 Gas. Insgesamt Transaktion wurde mit 1000 Gas bereitgestellt. Das Gas, das für die zweite Transaktion zur Verfügung gestellt wurde, war weniger als 700. Das gesamte Gas wurde nicht vollständig für die zweite interne Transaktion bereitgestellt. Erläuterung siehe unterer HINWEIS.

Hier sind einige Dinge, die helfen können:

  • Das Ändern der Reihenfolge der Vorgänge, wie Sie vorschlagen, kann hilfreich sein, da die Transaktion, bei der das Gas ausgegangen ist, jetzt die erste ist und zunächst das gesamte verfügbare Gas hat (anstatt eine Rückerstattung des Gases zu verlangen).
  • Halten Sie die Operationen in der gleichen Reihenfolge, aber für die erste Transaktion begrenzen Sie das Gas, das mit dem Funktionsaufruf über die .gas(amount)Syntax gesendet wird. Dies könnte dann bei der zweiten Transaktion mehr Gas ermöglichen. (Im obigen Beispiel könnte die erste interne Transaktion explizit auf 220 Gas begrenzt werden, sodass das erstattete Gas nur 20 beträgt.)

Die einfachste Lösung besteht darin, dass der Transaktionsursprung mehr Gas in der Transaktion bereitstellt . Es gibt kaum Nachteile, da das gesamte ungenutzte Gas zurückerstattet wird und mit viel Gas, das möglicherweise für interne Transaktionen verfügbar ist, können Grenzfälle vermieden werden.

HINWEIS , warum nicht "alles" Gas für einen Anruf bereitgestellt wird (interne Transaktion):

Chriseth (Autor von Solidity) sagte :

Dies ist einer der skurrilen Orte der EVM. Du kannst nicht einfach sagen "mein ganzes Benzin mitschicken", du musst immer eine eindeutige Nummer angeben. Wir haben zwar den GAS-Opcode, der uns die noch verfügbare Gasmenge angibt, aber das Problem ist, dass das Ausführen des Anrufs selbst auch etwas Gas kostet, also müssen wir die Gasmenge, die die Anrufkosten kosten, von dem von GAS bereitgestellten Wert abziehen und Wir müssen auch die Menge an Benzin abziehen, die es kostet, die Subtraktion durchzuführen ...

BEARBEITEN: Um mögliche Fehlinterpretationen zu klären: 1) Verträge zahlen niemals Gas - sie können das Gas für einen anderen Vertragsaufruf reservieren / delegieren / begrenzen. 2) Zurückgekehrte Transaktionen sind immer noch in Blöcken und Pay-Gas enthalten.