Nur zu Bildungszwecken; keine Anlageberatung. Eine Reentrancy-Lücke kann schnell zu unumkehrbaren Verlusten von Vertragsvermögen führen, und keine einzelne Schutzmaßnahme oder Prüfung beweist die Sicherheit eines Vertrags.
Direkte Antwort
Ein Reentrancy-Angriff kann entstehen, wenn ein Vertrag externen Code aufruft und dieser zurückruft, bevor die ursprüngliche Ausführung beendet und ihre Invarianten wiederhergestellt sind. Bleiben alte Salden, Anteile, Rechte oder Preise sichtbar, kann der Callback mit dem inkonsistenten Zustand eine Aktion wiederholen oder eine andere beeinflussen.
Der Callback muss weder dieselbe Funktion aufrufen noch native Währung übertragen. Token-Hooks, NFT-Empfänger-Callbacks, Vault- oder Strategieaufrufe und Flashloan-Callbacks können Kontrolle an nicht vertrauenswürdigen Code übergeben. Reentrancy kann Funktionen, Verträge und Module überschreiten; Read-only-Reentrancy kann ein anderes Protokoll einen vorübergehenden Wert verwenden lassen.
Funktionsweise
Ein typischer Angriff läuft so ab:
- Der Angreifer ruft eine zustandsändernde Funktion auf und besteht deren erste Prüfungen.
- Der anfällige Vertrag ruft vor Abschluss seiner Buchführung eine Adresse, einen Token oder ein Protokoll auf.
- Vom Angreifer kontrollierter Code tritt in den ursprünglichen oder einen verbundenen Vertrag ein, solange der alte Zustand sichtbar ist.
- Der verschachtelte Aufruf wiederholt einen Effekt oder ändert gemeinsamen Zustand; die Ausführung kehrt mit gebrochener Invariante zurück.
Die externe Kontrollübergabe kann als Low-Level-Aufruf sichtbar oder hinter Token-Transfer, Empfänger-Hook, sicherem Minting, Strategieadapter oder beliebiger Aufrufschnittstelle verborgen sein. Ein Revert rollt normalerweise den betroffenen Aufrufbaum zurück, doch ein Angreifer kann eine erfolgreiche verschachtelte Folge bilden, die nach Wertentnahme oder beschädigter Buchführung normal zurückkehrt.
Schutzmaßnahmen sollten geschichtet sein:
- Checks-Effects-Interactions anwenden: zuerst prüfen, dann alle relevanten internen Effekte festschreiben und zuletzt extern interagieren.
- Alle Einstiegspunkte mit derselben geschützten Invariante absichern, nicht nur die Funktion mit dem offensichtlichen Aufruf.
- Wo passend Abrufzahlungen bevorzugen und Aufrufe an nicht vertrauenswürdige Token, Empfänger, Hooks, Proxys und Integrationen minimieren.
- Vertragsübergreifende Invarianten definieren und bösartige Callbacks, funktionsübergreifende Pfade, verschachtelte Multicalls und Read-only-Verbraucher testen.
- Implementierungsprüfung mit Überwachung, Pause und Incident Response verbinden, soweit das Design dies unterstützt.
Beispiel
Betrachten Sie einen Vault, der Wert sendet und den Nutzersaldo erst nach dem Aufruf löscht:
function withdraw() external {
uint256 amount = balances[msg.sender];
require(amount > 0, "empty balance");
(bool ok, ) = msg.sender.call{value: amount}("");
require(ok, "transfer failed");
balances[msg.sender] = 0;
}Der Empfänger erhält Kontrolle, während balances[msg.sender] noch den alten Betrag enthält. Seine Empfangsfunktion kann withdraw() erneut aufrufen, dieselbe Prüfung bestehen und eine weitere Übertragung verlangen. Eine Saldoänderung vor dem Aufruf schließt dieses Fenster; ein Schutz kann verschachtelten Eintritt ablehnen. Beides beweist nicht die Sicherheit des Gesamtsystems, da ein anderer Einstiegspunkt oder verbundener Vertrag dieselbe unvollständige Invariante offenlegen kann.
Risiken
- Ein Schutz deckt eine Funktion ab, während eine andere denselben Zustand offenlegt.
- Die lokale Aufrufreihenfolge stimmt, aber eine vertragsübergreifende Invariante bleibt während des Callbacks inkonsistent.
- Token, Empfänger, Flashloan-Callback oder Strategieadapter führen unerwartet externen Code aus.
- Eine View-Funktion veröffentlicht einen vorübergehenden Preis oder Wechselkurs, den ein anderes Protokoll in derselben Transaktion nutzt.
- Upgrade, Modul oder Änderung des Speicherlayouts umgehen oder beschädigen die ursprüngliche Sperre.
- Tests prüfen rekursive Entnahme, lassen aber funktions-, vertragsübergreifende und Read-only-Pfade aus.
Für Nutzer belegen ein Audit-Siegel oder Reentrancy-Schutz nur eine Kontrollmaßnahme; sie sind keine Garantie. Upgrades, Integrationen und privilegierte Notfallaktionen können die Angriffsfläche ändern. Begrenzen Sie Genehmigungen und Exposition, prüfen Sie die bereitgestellte Implementierung und nehmen Sie nicht an, dass Verluste rückgängig werden.
Häufige Missverständnisse
- Reentrancy bedeutet nur, dieselbe Entnahmefunktion zu wiederholen. Sie kann eine andere Funktion oder einen anderen Vertrag betreten oder einem Leser inkonsistente Daten zeigen.
- Nur Transfers nativer Währung lösen Callbacks aus. Token-Standards, Empfänger-Hooks und Protokollintegrationen können ebenfalls externen Code ausführen.
- Ein Schutz oder Checks-Effects-Interactions macht den Vertrag sicher. Umfang, alle gemeinsamen Einstiegspunkte und vertragsübergreifenden Invarianten müssen weiter geprüft werden.
- Ein erfolgreiches Audit schließt Reentrancy aus. Audits sind begrenzte Prüfungen; spätere Änderungen und ungeprüfte Integrationen können neue Pfade schaffen.
Verwandte Themen
Quellen
- Sicherheitsüberlegungen - Solidity Documentation (abgerufen: 2026-08-21)
- Smart-Contract-Sicherheit - ethereum.org (abgerufen: 2026-08-21)
- ReentrancyGuard - OpenZeppelin Documentation (abgerufen: 2026-08-21)
- SC08:2026 Reentrancy-Angriffe - OWASP Smart Contract Security (abgerufen: 2026-08-21)