Ich habe einen Vertrag, der einen anderen Vertrag aufruft, der einen anderen aufruft. Wenn irgendwo im zweiten Kontrakt ein Wurf (oder kein Gasfehler) auftritt, wird die gesamte Transaktion rückgängig gemacht oder ist es nur das Zeug im zweiten und dritten Kontrakt, das dies tut, während die Ausführung vom ersten Kontrakt erfolgt noch steht?
In Solidity standardmäßig ja.
Auf der EVM-Ebene kehrt ein Wurf (schlechter Sprung, kein Gas oder jede andere Ausnahme) nur den Anruf zurück, in dem er sich befindet. Solidity setzt die Ausnahme hilfreicherweise im Stack fort, bis alles rückgängig gemacht ist.
Es ist möglich, dies mit Code auf niedrigerer Ebene (insbesondere address.call()) zu verhindern. Hier ist ein Beispiel dafür, wie dies als improvisiertes Try-Catch-Konstrukt verwendet wird.
Um die Antwort von @Matthew zu ergänzen, hängt es davon ab, wie der Aufruf in Solidity erfolgt.
Wenn C
aufgerufen D.foo()
wird und foo
ein ausgeführt throw
wird, wird die gesamte Transaktion rückgängig gemacht.
Wenn C
ein "Rohaufruf auf niedrigerer Ebene" wie D.call(bytes4(sha3('foo()')))
und foo
ein ausgeführt throw
wird, werden nur foo
und seine Unteraufrufe zurückgesetzt. Dies liegt daran, dass ein Rohaufruf keine Ausnahmen weitergibt: Ein Rohaufruf wie D.call
gibt nur einen booleschen Wert zurück, der angibt, ob der Aufruf erfolgreich war oder auf eine Ausnahme gestoßen ist.
In Solidity throw
verursacht a eine Ausnahme, indem es Bytecode generiert, der zu einem ungültigen Sprungziel führt . (Für die anderen Fälle siehe Alle Fälle, in denen Solidity zu einem ungültigen Sprungziel kompiliert wird .)
Aus der Solidity-Perspektive führt eine Ausnahme, die nicht geschluckt oder nicht erfasst/nicht behandelt wird, dazu, dass die gesamte Transaktion rückgängig gemacht wird.
Es gibt derzeit keine Möglichkeit, eine Ausnahme in Solidity abzufangen, daher führt eine Ausnahme, wie z. B. throw
, dazu, dass die gesamte Transaktion rückgängig gemacht wird.
Raw-Aufrufe "schlucken" jedoch Ausnahmen: Raw-Aufrufe verbreiten keine Ausnahmen, und deshalb werden nur die Unteraufrufe zurückgesetzt.
Es ist die gesamte Transaktion, die rückgängig gemacht wird.
Außerdem geht das gesamte mit der Transaktion verbundene Gas (einschließlich des verbleibenden) an den Miner.
ZMitton
Matthäus Schmidt
ZMitton