Würde "throw" diesen rekursiven Angriff verhindern?

Ich schreibe einen Basisvertrag, um Ethereum gleichmäßig auf zwei Adressen aufzuteilen.

In meiner withdraw()Funktion habe ich den folgenden Code:

function withdraw() {
    uint256 amount = this.balance / 2;
    addressOne.transfer(amount);
    addressTwo.transfer(amount);
}

Das Problem ist, dass nachfolgende Übertragungen wie diese rekursive Angriffe ermöglichen. Der Besitzer von addressOnekönnte die Funktion aufrufen und den Stapel überlaufen lassen, bevor die andere Hälfte des Kontostands an gesendet wird addressTwo.

Wiederholt ausgeführt, addressOnekönnte der Inhaber von Kontrakten der Reihe nach ablaufen (einen ausgeglichenen Saldo vorausgesetzt, also kein Rest):

Geben Sie hier die Bildbeschreibung ein

Mein Lösungsvorschlag ist dann folgender:

if(!addressOne.send(amount)) throw;
if(!addressTwo.send(amount)) throw;

Aber würde ein solches Werfen denselben Angriff verhindern?

Warum schreibst du nicht einen Test und findest es heraus? Ich habe gehört, dass trufflees ein ziemlich gutes Tool ist, um Verträge zu schreiben und zu testen.

Antworten (1)

Es gibt ein paar Probleme mit diesem Vertrag.

  1. Unabhängig davon, ob throwdie Transaktionen zurückgesetzt werden, würde dies einen Wiedereintrittsangriff nicht verhindern. Wenn addressOnees sich um folgenden Vertrag handelt:

    contract AddressOne {
       function() payable {
         OriginalContract.withdraw();
    
         // some case to stop recursion to prevent exhausting gas
       }
    }
    

    addressOnekann den Vertrag ablaufen lassen, wenn withdrawangerufen wird. Sie können dies verhindern, indem Sie eines von zwei Dingen tun: Verwenden Sie einen Auszahlungsfluss, bei dem jede Adresse ihren eigenen Anteil an den Geldern nach Belieben abhebt, oder indem Sie einen Mutex über den globalen Vertragsstatus setzen. Wenn Sie Ersteres tun möchten, sehen Sie sich meinen Splitter-Vertrag für ein Beispiel an.

  2. withdrawJeder kann die Funktion aufrufen . Ich denke nicht, dass dies beabsichtigt ist.

Bitte korrigieren Sie mich, wenn ich falsch liege.

Gültiger Punkt für #1, aber für #2 Es spielt keine Rolle, ob jemand anderes callt und zurückzieht. Sie würden nur Benzin verschwenden, aber ich würde immer noch meinen Äther bekommen
Es muss eine Möglichkeit geben, nachfolgende Sendeaufrufe in einer Funktion durchzuführen und sicherzustellen, dass beide ausgeführt werden, ich habe nur noch nicht daran gedacht