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 addressOne
könnte die Funktion aufrufen und den Stapel überlaufen lassen, bevor die andere Hälfte des Kontostands an gesendet wird addressTwo
.
Wiederholt ausgeführt, addressOne
könnte der Inhaber von Kontrakten der Reihe nach ablaufen (einen ausgeglichenen Saldo vorausgesetzt, also kein Rest):
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?
Es gibt ein paar Probleme mit diesem Vertrag.
Unabhängig davon, ob throw
die Transaktionen zurückgesetzt werden, würde dies einen Wiedereintrittsangriff nicht verhindern. Wenn addressOne
es sich um folgenden Vertrag handelt:
contract AddressOne {
function() payable {
OriginalContract.withdraw();
// some case to stop recursion to prevent exhausting gas
}
}
addressOne
kann den Vertrag ablaufen lassen, wenn withdraw
angerufen 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.
withdraw
Jeder kann die Funktion aufrufen . Ich denke nicht, dass dies beabsichtigt ist.
Bitte korrigieren Sie mich, wenn ich falsch liege.
0xcaff
truffle
es ein ziemlich gutes Tool ist, um Verträge zu schreiben und zu testen.0xcaff