Wie viel Berechnung kann in einer Fallback-Funktion durchgeführt werden?

Durch einfaches Senden von Ether an einen Vertrag wird der Code des Vertrags ausgeführt . In Solidity wird dieser Code der so genannten Fallback-Funktion zugeordnet.

Wie viel Arbeit kann in einer Fallback-Funktion erledigt werden?

Antworten (1)

Die Fallback-Funktion kann so viel berechnen, wie viel Gas sie bekommt.

Es gibt 2 Fälle (im Grunde recipient.sendund recipient.call{value:...}("")) und Fall 2 hat Auswirkungen auf die Sicherheit und ist ein Schlüsselelement dafür, wie theDAO am 17. Juni 2016 angegriffen und ausgenutzt wurde.

Fall 1: 2300 Gas

recipientDie Fallback-Funktion eines Vertrags erhält nur dann einen 2300 -Gas-Zuschuss, wenn sie mit recipient.transferoderrecipient.send aufgerufen wurde . Dies ist dasselbe wie bei einem externen Konto, das recipientmit bezahlt web3.eth.sendTransaction({to:recipient, gas:21000, ...}).

Der letzte Teil eines Ethereum-Blogbeitrags erklärt:

Wenn Sie möchten, dass Ihr Vertrag Ether empfängt, müssen Sie seine Fallback-Funktion billig machen. Es kann nur 2300 Gas verwenden, was weder Speicherschreibvorgänge noch Funktionsaufrufe zulässt, die Ether mitsenden. Grundsätzlich sollten Sie innerhalb der Fallback-Funktion nur ein Ereignis protokollieren, damit externe Prozesse darauf reagieren können.

Beispiele für einen externen Prozess sind web3.js-Filter und -Überwachungen.

Hinweis: Seit Dez 2019 recipient.transferund recipient.sendwerden nicht mehr empfohlen: Ist transfer() nach dem Istanbul-Update noch sicher?

Fall 2: So viel Gas wie es geht, achten Sie auf die Sicherheit

recipient.call{value:...}("")(und die Verwendung verwandter Funktionen wie .callcode, .delegatecall) wird der Fallback-Funktion praktisch[1] so viel Gas geben, wie der Anrufer übrig hat.

Um die gleichen Effekte (2300 Gas Stipendium) und Sicherheit wie in Fall 1 zu erhalten, müssen Anrufer das Gas explizit auf null begrenzen, wenn sie das recipientby aufrufen:recipient.call{gas: 0, value: ...}("")

(Die DAO begrenzte das Gas nicht und erlitt am 17. Juni 2016 einen Wiedereintrittsangriff . )


Fußnoten

[1] Erklärung, warum eine Fallback-Funktion fast alles, aber nicht alles Gas bekommt. 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 ...

Ist recipient.call.gas(2300).value(...)gleichbedeutend mit recipient.call.gas(0).value(...)?
@K._ Nein, ersterer schickt 2300 mehr Gas.
Wichtige Aktualisierung : Ab Mai 2021 gilt die Verwendung von sendund transfernicht mehr als sicher . Verwenden Sie call{value: amount}("")stattdessen.
@PaulRazvanBerg Danke, fügte den Hinweis zu Case1 hinzu und aktualisierte auch die Solidity-Syntax.