Im vergangenen Jahr (30.03.2026 - 05.04.2026) hat BlockSec neun Angriffsereignisse erkannt und analysiert, mit geschätzten Gesamtschäden von ca. 287 Mio. $. Die folgende Tabelle fasst diese Vorfälle zusammen. Detaillierte Analysen für jeden Fall sind in den folgenden Unterabschnitten aufgeführt.
| Datum | Vorfall | Typ | Geschätzter Schaden |
|---|---|---|---|
| 30.03.2026 | Unbekannter Protokollvorfall | Fehlerhafte Geschäftslogik | ~10.000 $ |
| 30.03.2026 | WDGG Token Vorfall | Zugriffskontrolle | ~40.000 $ |
| 31.03.2026 | i6Token Vorfall | Fehlerhafte Geschäftslogik | ~273.800 $ |
| 01.04.2026 | Drift Protocol Vorfall | Phishing-Angriff | ~285,3 Mio. $ |
| 01.04.2026 | LML Staking Protocol Vorfall | Fehlerhafte Geschäftslogik | ~950.000 $ |
| 01.04.2026 | Tactile Vorfall | Preismanipulation | ~12.000 $ |
| 02.04.2026 | SAS Token Vorfall | Fehlerhafte Geschäftslogik | ~12.000 $ |
| 03.04.2026 | Unbekannter EIP-7702 Vorfall | Zugriffskontrolle | ~17.200 $ |
| 03.04.2026 | Silo Finance Vorfall | Fehlkonfiguration | ~359.000 $ |
1. Unbekannter Protokollvorfall
Kurze Zusammenfassung
Am 30. März 2026 verlor ein unbekanntes Protokoll auf der BNB Chain aufgrund fehlerhafter Geschäftslogik rund 10.000 $. Das Protokoll wies einen Teil der Einlagen von Benutzern zu, um seinen Plattform-Token PSTART zu kaufen und Liquidität hinzuzufügen, was bedeutet, dass die Benutzer effektiv LP-Positionen hielten, die Preisschwankungen auf dem Markt unterlagen. Beim Abheben rechnete das Protokoll jedoch nicht den tatsächlichen einlösbaren Wert der LP zu diesem Zeitpunkt ab. Stattdessen versprach es weiterhin einen festen Betrag an Stablecoins basierend auf der historischen Einlage und vordefinierten Regeln. Infolgedessen konnte der Angreifer nach der Kapitalbindung durch erzwungene Investitionen Gelder zu einem voreingestellten festen Wert abheben, wodurch Verluste, die eigentlich von der LP-Position hätten getragen werden müssen, auf das Protokoll verlagert wurden und letztendlich ein kostenloses Gewinn erzielt wurde.
Hintergrund
Das Protokoll funktioniert wie folgt: Nach einer Einlage von BUSD durch einen Benutzer verwendet das Protokoll automatisch einen Teil der Gelder, um PSTART zu kaufen, und kombiniert diesen dann mit dem verbleibenden BUSD, um Liquidität in den Pool einzubringen. Die resultierenden LP-Anteile werden dann vom Vault verwahrt, während das Protokoll in seinem internen Hauptbuch eine Anweisung für den Benutzer aufzeichnet, die eine feste tägliche Rendite verspricht.
Anschließend kann der Benutzer Belohnungen zu einem festen Zinssatz beanspruchen und beim Ausstieg rechnet der Vault das Kapital und die Rendite gemäß vordefinierten Regeln ab, anstatt streng nach dem aktuellen Nettoinventarwert der zugrunde liegenden LP-Position abzurechnen.
Schwachstellenanalyse
Diese Schwachstelle ergibt sich aus einem unangemessenen Protokolldesign (0x587984...73a43c): Die Abrechnungslogik ist vom tatsächlichen Wert der zugrunde liegenden Vermögenswerte entkoppelt.
Nachdem ein Benutzer BUSD eingezahlt hat, verwendet das Protokoll einen Teil davon, um PSTART zu kaufen und Liquidität hinzuzufügen. Das bedeutet, die tatsächliche zugrunde liegende Position des Benutzers ist eine LP-Exposition, deren Wert mit den Marktpreisen schwankt. Wenn der Benutzer jedoch aussteigt, rechnet das Protokoll nicht basierend auf dem tatsächlichen einlösbaren Wert der LP zu diesem Zeitpunkt ab. Stattdessen verspricht es weiterhin, eine feste Menge an Stablecoins gemäß dem historischen Einlagebetrag und vordefinierten Abrechnungsregeln zu zahlen.
Der Angreifer nutzte diesen Fehler aus, indem er einen Flash-Loan verwendete, um eine große Menge an Kapital zu erhalten, und dann wiederholt deposit() ausführte. Auf diese Weise zwang der Angreifer das Protokoll, kontinuierlich PSTART zu kaufen und die Vermögenszusammensetzung des Pools zu ändern, wodurch der PSTART-Preis künstlich in die Höhe getrieben und eine Arbitragemöglichkeit geschaffen wurde.
Der Angreifer führte dann withdraw() aus und löste Gelder zum voreingestellten festen Wert ein, wodurch die Verluste, die von der zugrunde liegenden LP-Position hätten getragen werden müssen, effektiv auf das Protokoll selbst übertragen wurden, was letztendlich zu einem kostenlosen Gewinn führte.
Angriffsanalyse
Die folgende Analyse basiert auf der Transaktion 0xf3b8...55e7.
-
Schritt 1: Der Angreifer erhielt durch einen Flash-Loan etwa 2.000.000e18
BUSDund tauschte diese im Pool gegen 19.013.120e18PSTART. -
Schritt 2: Der Angreifer rief wiederholt die
deposit()-Funktion des Vertrags auf, um Gelder zu staken. Bei jeder Einzahlung berechnete das Protokoll, wie vielBUSDzum Kauf von Token verwendet werden sollte, damit das endgültige Token-zu-BUSD-Verhältnis für die Hinzufügung von Liquidität besser mit dem aktuellen Verhältnis des Pools übereinstimmt. Durch wiederholte Einzahlungen injizierte der Angreifer kontinuierlichBUSDin den Pool, während die Menge anPSTARTnahezu unverändert blieb. Infolgedessen stieg der Wert vonPSTARTweiter an. In dieser Phase wurde die durch die Einzahlungen des Angreifers erhalteneLPtatsächlich mit Verlust erworben. -
Schritt 3: Der Angreifer verkaufte dann den in Schritt 1 gekauften
PSTARTzurück in den Pool. Da Schritt 2 dieBUSD-Reserven des Pools erhöht hatte, brachte dieser Tausch etwa 2.010.655e18BUSDein, was einem Gewinn von etwa 10.655BUSDin einem einzigen Angriffszyklus entspricht. -
Schritt 4: Schließlich führte der Angreifer
withdraw()für alle in Schritt 2 eröffneten Staking-Positionen aus. Zu diesem Zeitpunkt war der Marktwert der Vermögenswerte, die diesen Positionen entsprachen, bereits weit unter ihrem ursprünglichen Einlagebetrag. Nach normaler wirtschaftlicher Logik wäre eine vollständige Rückerstattung nicht möglich gewesen. Das Protokoll berechnete jedoch den einlösbarenBUSD-Betrag basierend auf dem historischen Einlagebetrag, was es dem Angreifer ermöglichte, alle zuvor erzwungenen Investitionskosten vollständig zurückzuerhalten, ohne Verluste zu tragen.

Schlussfolgerung
Die Hauptursache dieses Vorfalls liegt darin, dass das Protokoll Benutzereinlagen in LP-Positionen investierte, die Marktschwankungen unterworfen waren, und dennoch eine Abrechnung in fester BUSD-Menge basierend auf historischen Einlagebeträgen und vordefinierten Regeln versprach. Dies führte zu einer Diskrepanz zwischen den Verbindlichkeiten des Protokolls und dem tatsächlichen Wert seiner zugrunde liegenden Vermögenswerte.
Der Angreifer nutzte diesen Fehler aus, indem er wiederholt deposit() verwendete, um die Vermögensstruktur des Pools zu verändern und den Preis von PSTART in die Höhe zu treiben, dann durch eine externe Position eine Arbitrage abschloss und schließlich withdraw() verwendete, um die zuvor verlustbringenden Positionen zum Buchwert einzulösen. Auf diese Weise wurden Verluste, die von den Positionen selbst hätten getragen werden müssen, auf das Protokoll verlagert, was letztendlich einen risikofreien Gewinn ermöglichte.
2. WDGG Token Vorfall
Kurze Zusammenfassung
Am 30. März 2026 wurde der WDGG-Token auf der BNB Chain ausgenutzt, was zu Verlusten von rund 40.000 $ führte. Die Hauptursache war das Fehlen einer Zugriffskontrolle in der Funktion burnFrom(). Insbesondere erlaubte die Funktion burnFrom(), dass beliebige Benutzer WDGG-Token von jeder beliebigen Adresse verbrennen konnten. Der Angreifer nutzte dies aus, indem er WDGG-Token aus dem PancakeSwap-Pool verbrannte, dann die Funktion sync() aufrief, um die WDGG-Reserven des Pools zu reduzieren, und anschließend einen umgekehrten Swap durchführte, um Profit zu erzielen.
Hintergrund
Dieser Vorfall betrifft einen einzelnen Token, WDGG, der ein dividendenverteilender Token ist, der bei jeder Übertragung eine Gebühr erhebt.
Schwachstellenanalyse
Der WDGG-Token-Vertrag (0x512de7...6b90c5) gab burnFrom() ohne jegliche Aufrufer-Autorisierung frei. Infolgedessen konnte jede Adresse WDGG-Token von jedem Halter verbrennen, einschließlich des PancakeSwap-Pools selbst. Gepaart mit dem öffentlich aufrufbaren sync() von PancakeSwap, das die aufgezeichneten Reserven mit den tatsächlichen Guthaben abgleicht, ermöglichte dieser Fehler, dass die WDGG-Reserve des Pools willkürlich reduziert und die Konstante des Produktinvariante gebrochen wurde, ohne dass ein legitimer Handel stattfand, wodurch der Pool Preisungleichgewichten ausgesetzt wurde.

Ein sekundärer Fehler in setWdgAddress() erlaubte es jedem Aufrufer, eine beliebige Adresse als gebührenbefreit zu markieren, was den durch diese Angriffsfläche extrahierbaren Gewinn weiter maximierte.

Angriffsanalyse
Die folgende Analyse basiert auf der Transaktion 0x2da5...0bd1.
- Schritt 1: Der Angreifer rief zuerst
setWdgAddress()auf, um seine eigene Adresse als gebührenbefreit zu setzen, was es nachfolgenden Übertragungen ermöglichte, die Gebühr des Tokens zu umgehen.

-
Schritt 2: Der Angreifer tauschte dann eine kleine Menge
BNBgegenWDGG-Token über den PancakeSwap-Pool. -
Schritt 3: Nach Erhalt von
WDGGrief der AngreiferburnFrom()auf, umWDGG-Token direkt aus der PancakeSwap-Paaradresse zu verbrennen. -
Schritt 4: Der Angreifer rief anschließend
sync()auf, was das Paar zwang, seine Reserven anzupassen, um den manipulierten Token-Salden zu entsprechen. Infolgedessen wurde dieWDGG-Reserve im Pool auf nur 1 Wei reduziert.

- Schritt 5: Da die Poolreserven stark verzerrt waren, führte der Angreifer einen umgekehrten Swap durch und entnahm Profit aus dem Preisungleichgewicht.

Schlussfolgerung
Dieser Vorfall wurde letztendlich durch das Fehlen einer Zugriffskontrolle in der Funktion burnFrom() des WDGG-Token-Vertrags verursacht. Infolgedessen konnte ein Angreifer Token direkt aus dem PancakeSwap-Pool verbrennen, die Reserven des Pools über sync() manipulieren und das daraus resultierende Preisungleichgewicht gewinnbringend ausnutzen.
3. i6Token Vorfall
Kurze Zusammenfassung
Am 31. März 2026 verlor der i6-Token auf der BNB Chain rund 273.800 $, da invest() den Spotpreis des Pools verschob, während withdraw() Salden über einen nachlaufenden TWAP abwickelte, und die beiden in derselben Transaktion kombiniert werden konnten. Der Angreifer blähte den Spotpreis über invest() auf, löste überschüssiges i6 zum veralteten TWAP über withdraw() ein und verkaufte das i6 zurück in den aufgeblähten Pool, um Profit zu erzielen.
Hintergrund
Das Protokoll funktioniert wie folgt: Wenn ein Benutzer invest() aufruft, werden USDT eingezahlt und teilweise zum Kauf von i6 auf PancakeSwap verwendet. Das erworbene i6 wird zusammen mit den verbleibenden USDT als Liquidität in den USDT/i6-Pool eingebracht, und die resultierenden LP-Token werden verbrannt. Das Protokoll zeichnet Benutzer- und Empfehlungsbilanzen in USDT auf.
Wenn withdraw() aufgerufen wird, berechnet das Protokoll den aufgelaufenen Wert des Benutzers in USDT und wandelt ihn unter Verwendung eines vom Protokoll gepflegten TWAP-Preises (twapPrice) in i6 um.
Schwachstellenanalyse
Die Hauptursache im Protokollvertrag (0x1cb36b...2a18a) ist, dass invest() den Spotpreis des USDT/i6-Pools als Nebenwirkung des Kaufs von i6 und der Hinzufügung von Liquidität verändert, während withdraw() aufgelaufene, in USDT denominierte Salden unter Verwendung eines vom Protokoll gepflegten TWAP (twapPrice) in i6 abwickelt, der erst nach Ablauf eines Zeitfensters aktualisiert wird. Nichts im Vertrag verhindert, dass diese beiden Funktionen in derselben Transaktion ausgeführt werden.
Da ein invest()-Aufruf den Spotpreis innerhalb derselben Transaktion aufblähen kann, in der eine nachfolgende withdraw() einen noch nicht aktualisierten TWAP liest, sehen die beiden effektiv zwei unterschiedliche Preise für denselben Poolzustand. Ein durch withdraw() abgewickelter, in USDT denominierter Saldo wird dann zum veralteten, viel niedrigeren Preis in i6 ausgezahlt, obwohl jeder i6 jetzt im Pool selbst für weit mehr USDT realisierbar ist. Diese Lücke verwandelt jeden aufgelaufenen USDT-Saldo im Protokoll in eine ausnutzbare Spanne zwischen interner Abrechnung und dem Live-Pool.
Angriffsanalyse
Die folgende Analyse basiert auf der Transaktion 0xc1b9...2f16.
-
Schritt 1: Der Angreifer beschaffte sich zunächst 270.000
WBNBüber einen Flash-Loan, hinterlegte diese dann als Sicherheit bei Venus und lieh sich eine große MengeUSDT. Der Angreifer setzte auch den Angriffskontrakt A unter der Adresse0xda49und den Hilfskontrakt B unter der Adresse0x096aein. -
Schritt 2: Der Angriffskontrakt führte die erste
invest()-Operation aus. Während dieses Prozesses verwendete das Protokoll zunächst 531.489e18USDT, um 234.188e18i6zu kaufen, und fügte dann 354.326e18USDTzusammen mit 72.607e18i6in den Pool ein. Infolgedessen stieg der Pool-Spotpreis schnell von etwa 1,05159USDT/i6auf etwa 4,89287USDT/i6, während der vom Protokoll erfassteTWAPbei nur 1,05159 blieb.

-
Schritt 3: Der Angreifer übertrug dann 124.014.184e18
USDTan den Hilfskontrakt B, der wiederuminvest()mitreferrer = Aaufrief. Dieser Schritt zwang das Protokoll erneut, einen massivenUSDT -> i6-Kauf und eineaddLiquidity()-Operation durchzuführen, was die Poolreserven in einen neuen Zustand trieb, der einem Spotpreis von etwa 15.528USDT/i6entsprach. Da jedoch kein neues Zeitfenster verstrichen war, aktualisierte das Protokoll denTWAPnicht entsprechend. -
Schritt 4: Nach Abschluss der zweiten
invest()-Operation erhielt der Angriffskontrakt A als Empfehlungsgeber sofort Anspruch auf eine Empfehlungsprämie inUSDT. Der Angreifer rief dannwithdraw()auf. Das Protokoll verwendete den veraltetenTWAP, um die auszuzahlende Menge ani6zu berechnen und übertrug die Token aus seinem eigenen Guthaben, was zu einer Gesamtauszahlung von 5.896.508e18i6führte. -
Schritt 5: Nach Erhalt des
i6rief der Angreifer sofortswapExactTokensForTokensSupportingFeeOnTransferTokens()auf, um alle 5.896.508e18i6zurück in den Pool zu verkaufen und dafür 125.177.224e18USDTzu erhalten. Da diesei6-Token mit dem veraltetenTWAPvon etwa 1,05159USDT/i6abgerechnet worden waren, während sie gegen einen Pool-Spotpreis verkauft wurden, der vom Angreifer auf etwa 15.528USDT/i6hochgetrieben worden war, konnte der Angreifer die enorme Spanne zwischen den beiden Preisen direkt realisieren. -
Schritt 6: Nach Rückzahlung des Flash-Loans behielt der Angreifer 273.802e18
USDT, was der tatsächliche Gewinn aus dem Angriff war.
Schlussfolgerung
Die Hauptursache liegt darin, dass eine Spotpreis-beeinflussende Funktion (invest()) und eine TWAP-abgerechnete Funktion (withdraw()) innerhalb einer einzigen Transaktion kombiniert werden konnten, wodurch die beiden unterschiedliche Preise für denselben Poolzustand sehen konnten.
Um diese Art von Fehler zu vermeiden, sollten Protokolle, die AMM-Interaktionen mit verzögerter Preisgestaltung kombinieren, es vermeiden, Salden zu einem TWAP in derselben Transaktion abzurechnen, in der eine Begleitfunktion den Spotpreis des zugrunde liegenden Pools verschiebt, und stattdessen Auszahlungen an den realisierbaren Live-Wert des Pools anstatt an einen veralteten oder abgeleiteten Preis anbinden.
4. Drift Protocol Vorfall
Kurze Zusammenfassung
Am 1. April 2026 (UTC) wurde das Drift Protocol auf Solana für rund 285,3 Mio. $ kompromittiert. Die Hauptursache war kein Smart-Contract-Bug, sondern ein Zusammenbruch des Multisig-Autorisierungsverfahrens, verschärft durch einen 2-von-5-Sicherheitsrat ohne Timelock und den Durable-Nonce-Mechanismus von Solana, der es erlaubte, vorab gesammelte Multisig-Genehmigungen bis zur Ausführung durch den Angreifer gültig zu bleiben. Nach wochenlanger Vorbereitung veranlasste der Angreifer zwei von fünf Unterzeichnern, bösartige Governance-Transaktionen, die an Durable-Nonce-Konten gebunden waren, vorab zu signieren, reichte sie später ein, um die Admin-Kontrolle zu übernehmen, führte dann ein gefälschtes Sicherheiten-Asset (CVT) ein, blähte dessen Oracle-Preis auf, lockerte die Auszahlungslimits und zog echte Vermögenswerte über den Drift Vault (JCNCMF...XJfrw) ab.
Hintergrund
Drift Protocol ist ein DeFi-Protokoll auf Solana, das Margin-Trading, Lending, Spotmärkte und Derivate unterstützt. Seine Vorgänge mit hohen Berechtigungen, einschließlich Admin-Änderungen, Markterstellung, Oracle-Konfiguration, Risikoparameter-Updates und Auszahlungslimit-Anpassungen, werden eher durch das Squads Multisig-Framework als durch einen einzelnen privaten Schlüssel gesteuert. Zum Zeitpunkt des Angriffs operierte der Sicherheitsrat von Drift unter einer 2-von-5-Schwellenkonfiguration ohne Timelock, was bedeutet, dass zwei von fünf Unterzeichnern administrative Aktionen mit sofortiger Wirkung autorisieren konnten. Die Sicherheit dieses Systems hängt nicht nur von der Verwahrung der Schlüssel der Unterzeichner ab, sondern auch von der Integrität der gesamten Genehmigungspipeline: Welche Transaktion wurde erstellt, welche Transaktionen glaubten die Unterzeichner zu genehmigen, und stimmten die endgültigen ausgeführten Anweisungen mit diesem Überprüfungskontext überein.
Separates dazu ersetzen die Durable-Nonce-Konten von Solana den kurzlebigen Blockhash durch eine persistente Nonce, die in einem dedizierten Konto gespeichert ist. Dies ermöglicht, dass eine signierte Transaktion bis zur Advancierung der Nonce unbegrenzt gültig bleibt. Dieser Mechanismus ist für legitime Anwendungsfälle wie Offline-Signierung und verzögerte Einreichung konzipiert, führt aber zu einem kritischen Angriffsprimitiv, indem er den Zeitpunkt der Signierung von dem Zeitpunkt der Ausführung auf der Kette trennt. Sobald ein Unterzeichner eine Durable-Nonce-Transaktion genehmigt, kann die Genehmigung nicht widerrufen werden, es sei denn, der Nonce-Autorisiert hat das Nonce-Konto manuell weitergeschaltet.
Schwachstellenanalyse
Die Hauptursache ist kein Smart-Contract-Bug, sondern drei strukturelle Schwächen in der Governance-Konfiguration von Drift, die zusammen eine Social-Engineering-Möglichkeit in einen Abfluss von 285,3 Mio. $ verwandelten. Erstens entfernten die Durable Nonces das implizite Signatur-Ablauf-Sicherheitsnetz. Bei normalen Blockhash-basierten Transaktionen wird die Genehmigung eines getäuschten Unterzeichners entweder umgehend ausgeführt oder läuft innerhalb eines engen Fensters harmlos ab, was den Spielraum für koordinierte Ausbeutung begrenzt. Durable Nonces lösen diese Einschränkung auf: Sobald zwei Unterzeichner des Sicherheitsrats dazu gebracht wurden, bösartige Governance-Transaktionen durch irreführende Signierungsanfragen zu genehmigen, blieben ihre Signaturen unbegrenzt ausnutzbar, was dem Angreifer die vollständige Kontrolle über den Ausführungszeitpunkt gab.
Zweitens bedeutete der Null-Timelock bei administrativen Aktionen, dass, sobald die vorab signierten Transaktionen eingereicht waren, die Admin-Übertragung sofort wirksam wurde, ohne dass ein Zeitfenster für Erkennung oder Intervention verblieb. Drittens war der Umfang der Admin-Rolle breit genug, um neue Sicherheitenmärkte zu schaffen, Oracle-Quellen zu wechseln und Auszahlungslimits zu lockern, alles innerhalb eines einzigen privilegierten Pfades. Eine erfolgreiche Governance-Übernahme reichte daher aus, um jedes beliebige Asset in eine echte Geldbeschaffung umzuwandeln, ohne weitere Genehmigungsbarrieren.
Angriffsanalyse
Der Angriff entfaltete sich in drei separaten Phasen: Pre-Attack Staging, in der der Angreifer eine mehrwöchige Operation durchführte, um ein gefälschtes Sicherheiten-Asset herzustellen und durch irreführende Signierungsanfragen Governance-Zugang zu erhalten; Governance Takeover, in der zwei vorab signierte Durable-Nonce-Transaktionen in schneller Folge eingereicht wurden, um die administrative Kontrolle zu übernehmen; und Fund Extraction, in der der Angreifer Protokollparameter manipulierte und echte Vermögenswerte über die Kreditvergabe-Pfade des Protokolls abzweigte. Das Diagramm unten veranschaulicht den Ausführungsfluss über diese drei Phasen hinweg.
-
Phase 1 (Pre-Attack Staging): Ab dem 11. März zog der Angreifer 10
ETHaus Tornado Cash ab und setzte den CarbonVote Token (CVT) ein, prägte 750 Millionen Einheiten, bot dann Liquidität auf Raydium an und nutzte Wash-Trading, um eine künstliche Preisgeschichte nahe 1 $ aufzubauen. Parallel dazu wurden bis zum 23. März vier Durable-Nonce-Konten erstellt, zwei davon mit Drift Security Council-Mitgliedern verknüpft und zwei vom Angreifer kontrolliert, was darauf hindeutet, dass mindestens zwei von fünf Unterzeichnern bereits Transaktionen im Zusammenhang mit Durable-Nonce-Konten signiert hatten. Am 27. März führte Drift aufgrund eines Mitgliederwechsels eine geplante Migration des Sicherheitsrats durch, die die zuvor gesammelten Signaturen ungültig machte; bis zum 30. März hatte der Angreifer jedoch die erforderliche Schwelle unter der neuen Konfiguration wieder erreicht, was eine aktive Überwachung der On-Chain-Governance-Änderungen und eine Echtzeit-Anpassung zeigte. -
Phase 2 (Governance Takeover): Am 1. April um ca. 16:05 UTC, etwa eine Minute nachdem Drift eine legitime Testauszahlung aus dem Versicherungsfonds durchgeführt hatte, reichte der Angreifer zwei vorab signierte Durable-Nonce-Transaktionen vier Slots voneinander entfernt ein. Die erste Transaktion (2HvMSg...2C4H) erstellte und genehmigte den bösartigen Admin-Übertragungsantrag. Die zweite Transaktion (4BKBmA...RsN1) genehmigte und führte sie aus, beginnend mit
AdvanceNonceAccount, um die gespeicherte Nonce zu aktivieren, überproposalApproveundvaultTransactionExecutebis hin zur Aufrufung vonUpdateAdmin, um die administrative Kontrolle auf eine vom Angreifer kontrollierte Adresse zu übertragen. -
Phase 3 (Fund Extraction): Mit voller Admin-Befugnis erstellte der Angreifer einen Sicherheitenmarkt für
CVT, wechselte zu einem vom Angreifer kontrollierten Oracle, um dessen Buchpreis aufzublähen, und hob die Auszahlungslimits für wichtige Asset-Märkte an oder entfernte sie. Der Angreifer zahlte dann eine große Menge überbewertetesCVTin das Protokoll ein und führte 31 schnelle Auszahlungen über etwa 12 Minuten durch, wobei erUSDC,JLP,SOL,cbBTC,USDT,wETH,dSOL,WBTC,JTOundFARTCOINfür einen Gesamtverlust von rund 285,3 Mio. $ abzweigte, berechnet auf Basis des vom Angreifer genutzten Kontos (HkGz4K...pZES).

Schlussfolgerung
Die Hauptursache dieses Vorfalls ist keine Smart-Contract-Schwachstelle oder Kompromittierung von Schlüsseln, sondern ein Zusammenbruch des Multisig-Autorisierungsverfahrens in Kombination mit einer Durable-Nonce-basierten verzögerten Ausführung und einem administrativen Pfad ohne Timelock. Vorab gesammelte Genehmigungen, die normalerweise innerhalb von Minuten abgelaufen wären, blieben auf unbegrenzte Zeit ausnutzbar, und sobald sie eingereicht wurden, hinterließen die Admin-Übernahme und die anschließende Geldbeschaffung kein Zeitfenster für Interventionen.
Die Minderung dieser Risikoklasse erfordert die Sicherung der gesamten Autorisierungspipeline anstelle nur der Schlüsselverwahrung der Unterzeichner, die Durchsetzung von Timelocks für Vorgänge mit hohen Berechtigungen und die Behandlung von verzögerten Ausführungsmechanismen wie Durable Nonces als eigenständige Bedrohungsoberfläche, die höhere Signaturschwellen, zeitgebundene oder widerrufbare Genehmigungen und Einschränkungen für unbegrenzt gültige signierte Transaktionen erfordert.
5. LML Staking Protocol Vorfall
Kurze Zusammenfassung
Am 1. April 2026 wurde das LML-Staking-Protokoll auf der BNB-Kette für rund 950.000 $ ausgenutzt. Die Hauptursache war eine Inkonsistenz in der Belohnungsberechnungslogik: Die Belohnungskonvertierung las einen gespeicherten LML/USDT-Preis, der hinter einer Aktualisierungssperre von 3600 Sekunden gesperrt war, während das ausgezahlte LML zum Live-AMM-Preis einlösbar war, ohne Abweichungsprüfung zwischen den beiden. Der Angreifer nutzte Flash-Loans, um den Pool-Spotpreis aufzublähen, und EIP-7702-Code-Delegation, um Belohnungen für 11 vorab gestakte EOAs in einer einzigen Transaktion zu stapeln, eine überhöhte Menge an LML zum veralteten gespeicherten Preis zu erhalten und diese dann über den nun stark verzerrten Pool zu verkaufen, um Profit zu erzielen.
Hintergrund
LML ist ein Staking-Protokoll auf der BNB-Kette, bei dem Benutzer BNB über den APower-Vertrag staken, um LML-Token als Belohnungen zu erhalten. Belohnungen werden in USDT-Begriffen berechnet und dann basierend auf einem vom Protokoll gespeicherten LML/USDT-Preis in LML-Beträge umgewandelt, bevor sie verteilt werden. Der gespeicherte Preis wird durch updatePrice() aktualisiert, das den AMM-Spotpreis liest, aber eine 3600-Sekunden-Sperre zwischen den Updates erzwingt. Belohnungsansprüche werden über APower's receive() basierend auf msg.sender ausgelöst, sodass nur die ursprüngliche Staking-Adresse ihre eigenen Belohnungen beanspruchen kann.
Schwachstellenanalyse
Der Kernfehler im Staking-Vertrag (0xbe9713...adce19) besteht darin, dass die Belohnungsakkumulation und die Belohnungseinlösung an zwei unterschiedliche Preise desselben Pools gebunden sind, ohne dass eine Konsistenzprüfung zwischen ihnen erfolgt. Die Belohnungsformel reward += (10^18 * base_reward) / stored_price berechnet die LML-Auszahlung aus _prices[], einem vom Protokoll gespeicherten LML/USDT-Preis, der nur durch updatePrice() nach einer 3600-Sekunden-Sperre aktualisiert wird, obwohl das ausgezahlte LML sofort zum Live-AMM-Spotpreis einlösbar ist. Jede externe Aktivität, die den Spotpreis innerhalb dieses Sperrfensters verschiebt, öffnet eine Lücke zwischen einer eingefrorenen Akkumulationspreis und einem Live-Verkaufspreis, und nichts im Vertrag lehnt einen Anspruch ab, wenn diese Lücke unangemessen wird.



Ein zweiter struktureller Fehler liegt darin, wie die Belohnungsquelle aufgefüllt wird. Wenn das LML-Guthaben des PROOF-Vertrags nicht ausreicht, um einen Anspruch zu bezahlen, füllt swapBack() es auf, indem es super._transfer(swapPair, PROOF, deficit) aufruft, gefolgt von sync(). Dabei wird LML direkt aus den Reserven des LP-Paares entnommen und der gespeicherte Zustand des Paares neu ausgerichtet, anstatt einen normalen Swap zu durchlaufen. Da dieser Pfad die Preisfindung des Paares umgeht, reduziert jeder Anspruch, der ihn auslöst, die LML-Reserven des Paares und verschiebt den Spotpreis weiter, ohne dass ein gegenläufiger Token-Zufluss stattfindet. Wiederholte Ansprüche vergrößern mechanisch die Lücke zwischen dem eingefrorenen gespeicherten Preis und dem Live-Verkaufspreis.


Angriffsanalyse
Die folgende Analyse basiert auf den Transaktionen 0x805d...5b47, 0x70f7...3572.
-
Schritt 1: Der Angreifer aggregierte eine große Menge
USDTundWBNBdurch Flash-Loans von Moolah, lieh sich von Venus und Moolah Pool (unter Verwendung vonWBNBals Sicherheit) und Flash-Loans von PancakeSwap V4, mehreren V3-Pools und V2-Pools. Dieses Kapital wurde benötigt, um den Preis desLML/USDT-Paares zu manipulieren. -
Schritt 2: Der Angreifer rief
swapAndTrans()imLML-Token-Vertrag auf, der die im Vertrag angesammeltenLML-Gebühren inUSDTtauschte. Dies entzog demLML-Vertrag sein eigenesLML-Guthaben, was bedeutete, dass er nicht mehr als lokaler Token-Lieferant dienen konnte. Jede nachfolgende normale Belohnungsverteilung müssteLMLaus dem LP-Paar überswapBack()beziehen.

- Schritt 3: Der Angreifer tauschte
USDTgegenLMLüber PancakeRouterswapExactTokensForTokensSupportingFeeOnTransferTokens, wobei die Zieladresse auf die Nulladresse gesetzt wurde. Die gekauftenLML-Token wurden verbrannt, anstatt vom Angreifer empfangen zu werden. Der alleinige Zweck war es,LMLaus dem Paar zu entziehen und denLML-Preis am AMM aufzublähen; der Angreifer benötigte die Token selbst nicht, nur die Preisverzerrung.

- Schritt 4: Der Angreifer hatte zuvor mit 11 EOA-Adressen in das Staking-Protokoll eingezahlt. Da
APower'sreceive()_claimReward(msg.sender)basierend aufmsg.senderauslöst, können Belohnungen nur von der einzahlenden Adresse selbst beansprucht werden. Um Belohnungen für alle 11 EOAs innerhalb einer einzigen Transaktion zu beanspruchen, nutzte der Angreifer EIP-7702, um Code auf diesen EOAs zu setzen, wodurch sie als Verträge vom Hauptvertrag des Angreifers aufgerufen werden konnten. Jeder EOA führte einetransfer(rst, fte)-Funktion aus, die eine kleine MengeBNBan APower sendete, wasreceive()und_claimReward(EOA)auslöste. Innerhalb jedes Anspruchs:updatePrice()wurde übersprungen (3600s-Sperre nicht erfüllt, daher bliebstored_pricebeim historischen niedrigen Wert),updateUser()berechnete die Belohnung unter Verwendung des veralteten niedrigen Preises,sendMining()übertrugLMLvon PROOF an APower und löste dannswapBack()aus, das PROOF auffüllte, indem esLMLaus dem LP-Paar zog undsync()aufrief, wodurch die Reserven des Paares weiter reduziert wurden. Schließlich verteilteclaimReward()LMLan die EOA, und jede EOA übertrug ihre erhalteneLMLzurück an den Angriffskontrakt.


-
Schritt 5: Der Angreifer tauschte die angesammelte
LMLüber den nun stark ausgedünnten Pool zum extrem aufgeblähten Preis zurück inUSDT. -
Schritt 6: Rückzahlung aller Flash-Loans, Kredite und Gebühren. Überweisung des verbleibenden Gewinns.
Schlussfolgerung
Die Hauptursache ist eine Diskrepanz zwischen Belohnungsakkumulation und Einlösung im Staking-Vertrag: Auszahlungen werden aus einem gespeicherten LML/USDT-Preis berechnet, der hinter einer 3600-Sekunden-Sperre gesperrt ist, aber in LML abgerechnet wird, dessen realer Wert dem Live-AMM-Preis folgt, ohne Abweichungsprüfung zwischen den beiden. Der swapBack()-Nachfüllpfad verschärft diesen Fehler, indem er LML bei jedem Anspruch direkt aus dem LP-Paar entzieht und die Lücke zwischen dem eingefrorenen gespeicherten Preis und dem Live-Verkaufspreis mechanisch vergrößert, je mehr Ansprüche verarbeitet werden.
Staking-Protokolle, die Belohnungen aus AMM-abgeleiteten Preisen berechnen, sollten bei der Einlösung eine Abweichungsprüfung zwischen dem gespeicherten Preis und dem aktuellen Spotpreis erzwingen und rückgängig machen, wenn die Lücke einen sicheren Schwellenwert überschreitet. Sie sollten auch Nachfüllmechanismen vermeiden, die LP-Reserven außerhalb normaler Swap-Pfade verändern, da solche Mechanismen die Preisfindung umgehen, die andernfalls den Schaden durch veraltete Preisgestaltung begrenzen würde.
6. Tactile Vorfall
Kurze Zusammenfassung
Am 1. April 2026 erlitt Tactile, ein gestaffeltes Einlagenprotokoll auf Polygon, einen Verlust von rund 12.000 $. Die Hauptursache war eine Inkonsistenz in seiner Einzahlungs- und Auszahlungsabrechnungslogik: Sowohl der Ein- als auch der Ausstieg wurden zum aktuellen Spotpreis von CES abgerechnet, und der interne Anteil trug keine Aufzeichnung über den Wert des Vermögenswerts, zu dem er ursprünglich geprägt wurde. Der Angreifer nutzte dies aus, indem er den Spotpreis vor der Einzahlung aufblähte, um übermäßige Anteile zu erhalten, dann den Preis vor der Auszahlung senkte, um mehr CES pro Anteil einzulösen, und den Zyklus über Hilfskontrakte wiederholte, um Profit zu erzielen.
Hintergrund
Tactile ist ein gestaffeltes Einlagenprotokoll auf Polygon, bei dem Benutzer CES gemäß einer ausgewählten Stufe in einen Zahlungsvertrag einzahlen. Der erforderliche Einzahlungsbetrag wird aus dem aktuellen Spotpreis von CES und der Stufenkonfiguration berechnet, und der Benutzer erhält einen internen Buchhaltungsanteil, der seine Position darstellt. Bei der Auszahlung wird der aufgezeichnete Anteil anstelle der ursprünglichen Einzahlung in CES umgerechnet, sodass die Guthaben der Benutzer effektiv als preisabhängige Buchungseinheiten verfolgt werden und nicht als feste Vermögensbeträge.
Schwachstellenanalyse
Der Kernfehler im Zahlungsvertrag (0x9153e1...09b654) besteht darin, dass Ein- und Auszahlungen zu zwei verschiedenen Zeitpunkten gegen dasselbe Spotpreis-Oracle abgerechnet werden, ohne dass eine unveränderliche Verankerung sie verbindet. Zum Zeitpunkt der Einzahlung liest der Vertrag getActualPrice() und rechnet die eingezahlten CES basierend auf dem aktuellen Preis in einen internen Anteil um; zum Zeitpunkt der Auszahlung wird derselbe Anteil unter Verwendung des Spotpreises zum Zeitpunkt der Einlösung wieder in CES umgerechnet.
Da der Anteil selbst keine Aufzeichnung über den Preis oder den Betrag des Vermögenswerts enthält, zu dem er geprägt wurde, führt jede Verschiebung des Spotpreises zwischen diesen beiden Zeitpunkten direkt zu einer Diskrepanz zwischen eingezahltem CES und ausgezahltem CES, wodurch die Buchhaltung des Protokolls vollständig dem Preispfad und nicht dem Wert des zugrunde liegenden Vermögenswerts ausgesetzt ist.

Angriffsanalyse
Die folgende Analyse basiert auf der Transaktion 0xc321...da74.
- Schritt 1: Der Angreifer lieh sich zunächst 55.365e18
CESaus einem Uniswap V3-Flash-Pool und verteilte die Gelder auf 5 Hilfskontrakte. Jeder Helfer erhielt zunächst 6.426e18CESund rief danndeposit(12)auf. Während dieses Prozesses fragte jeder Helfer zuerstgetPriceForLevel(12)ab und bereitete dann die für diese Einzahlung erforderliche Menge anCESbasierend auf dem aktuellen Preis vor.


- Schritt 2: Nachdem alle 5 Helfer die erste Runde von
depositabgeschlossen hatten, verkaufte der Angreifer 300.000CESamDEX, was den vombankverwendeten Preis von1.067585auf0.688542senkte. Die 5 Helfer führten dann nacheinanderwithdrawaus und lösten die zuvor zum hohen Preis erstellten Anteile gegenCESzum nun niedrigeren Preis ein. Jeder Helfer erhielt 9.427e18CES.

-
Schritt 3: Nach Abschluss der ersten Runde von
withdrawtauschte der Angreifer den erworbenen Gegenpartei-Vermögenswert zurück inCESund trieb damit den Preis wieder nach oben. Der Angreifer wiederholte dann die Schritte 2-3. -
Schritt 4: Schließlich, nach mehreren Angriffszyklen und nach Rückzahlung des Flash-Loans zuzüglich der Flash-Gebühr von 166.097975017841805126
CES, verblieben dem Angreifer 567.736e18CESals Gewinn.
Schlussfolgerung
Die Hauptursache dieses Vorfalls liegt darin, dass Tactile sowohl die Einzahlung als auch die Auszahlung gegen einen manipulierbaren Spotpreis abwickelte, ohne den Buchhaltungsanteil an den Betrag oder Preis des Vermögenswerts zum Zeitpunkt der Einzahlung zu binden. Dadurch war die interne Buchhaltung vollständig Preisschwankungen zwischen Ein- und Ausstieg ausgesetzt.
Protokolle, die Anteile gegen volatile Vermögenswerte ausgeben, sollten jeden Anteil an den konkreten Betrag oder Preis des Vermögenswerts zum Zeitpunkt der Prägung binden, damit die Einlösung den ursprünglichen wirtschaftlichen Wert reproduziert, anstatt ihn gegen ein Live-Oracle neu zu bewerten. Wenn Abrechnungsfunktionen auf einen aktuellen Preis verweisen müssen, sollten sie zeitgewichtete oder anderweitig manipulationsresistente Quellen verwenden und vermeiden, denselben Spotpreis zu lesen, der durch Trades verschoben werden kann, die in derselben Transaktion wie der Abrechnungsaufruf ausgeführt werden.
7. SAS Token Vorfall
Kurze Zusammenfassung
Am 2. April 2026 wurde der SAS-Token auf der BNB-Kette für rund 12.000 $ ausgenutzt. Die Hauptursache war ein Fehler in der benutzerdefinierten Übertragungslogik des Tokens: Das Senden von SAS an den LP-Pool erhöhte nur einen globalen sellBurn-Zähler, und jede nachfolgende normale Übertragung konnte dann SAS direkt aus dem Pool verbrennen und sync() aufrufen, um seine Reserven neu zu schreiben, alles ohne den AMM's Swap-Logik zu durchlaufen. Der Angreifer nutzte dies aus, indem er sellBurn durch Verkäufe ansammelte, eine nicht verwandte normale Übertragung auslöste, um SAS aus dem Pool zu verbrennen und seine Reserve auf 1 Wei zu reduzieren, und dann den verbleibenden SAS für Profit umkehrte.
Hintergrund
SAS ist ein deflationärer Token auf der BNB-Kette mit benutzerdefinierter Übertragungslogik, die auf einem PancakeSwap V2-Pool aufbaut. Seine transfer()-Funktion unterscheidet zwischen zwei Pfaden: einem Verkaufspfad, der ausgelöst wird, wenn das Ziel einer Übertragung der LP-Pool ist und der einen globalen sellBurn-Akkumulator um den übertragenen Betrag erhöht; und einem normalen Übertragungspfad, der, wenn sellBurn nicht null ist, SAS direkt aus dem LP-Pool verbrennt und dann sync() aufruft, um seine Reserven an den neuen On-Chain-Saldo anzupassen. Die beiden Pfade sollen zusammen als deflationärer Mechanismus fungieren, der die SAS-Reserve des Pools als Reaktion auf kumulativen Verkaufsdruck reduziert.
Schwachstellenanalyse
Der Kernfehler im SAS-Token-Vertrag (0xbfa266...3d91c6) liegt darin, wie der deflationäre Mechanismus in transfer() integriert ist. Wenn SAS an den LP-Pool gesendet wird, erhöht der Vertrag einen globalen sellBurn-Akkumulator um den übertragenen Betrag. Dann, bei jeder späteren normalen Übertragung, wenn sellBurn nicht null ist, ruft der Vertrag _burnFromPair() auf, um SAS direkt aus dem LP-Pool zu verbrennen, und folgt ihm mit sync(), das die Poolreserven neu schreibt, um sie an den On-Chain-Saldo anzupassen.
Das Problem ist, dass dieser Burn-and-Sync-Pfad die Poolreserven neu schreibt, ohne die AMM-Swap-Logik zu durchlaufen. Sobald sellBurn durch Übertragungen in den Pool erhöht wurde, reicht eine nicht verwandte normale Übertragung aus, um den Burn und Sync auszulösen, wodurch die SAS-Reserve des Pools gegen null gedrängt und eine große Preisverzerrung erzeugt wird, die dann durch einen normalen Swap geerntet werden kann.



Angriffsanalyse
Die folgende Analyse basiert auf der Transaktion 0x878e...adc5.
-
Schritt 1: Der Angreifer lieh sich
WBNBüber einen Flash-Loan. -
Schritt 2: Der Angreifer tauschte
WBNBgegenSAS.
-
Schritt 3: Der Angreifer setzte einen Vertrag ein und führte die Angrifflogik im
constructor()aus. Dies wurde verwendet, um dieis_contract()-Prüfung des Protokolls zu umgehen, da der Token-Vertrag verlangte, dasstransfer()von einer Whitelist-Adresse oder einer EOA stammt.


- Schritt 4: Der Angreifer übertrug
SASin den Pool, was den Verkaufspfad auslöste undsellBurnakkumulierte.

- Schritt 5: Der Angreifer setzte einen zweiten Vertrag ein und löste, wiederum innerhalb seines
constructor(), eine normale Übertragung aus. DasellBurnbereits ungleich null war (aus Schritt 4), löste diese Übertragung die Funktion_burnFromPair()aus, dieSASdirekt aus dem LP-Pool verbrannte und dann die Funktionsync()aufrief, wodurch dieSAS-Reserve auf 1 Wei reduziert wurde.

- Schritt 6: Der Angreifer führte einen Umkehr-Swap durch und verkaufte den verbleibenden
SASfür Profit.
Schlussfolgerung
Die Hauptursache dieses Vorfalls ist ein Fehler in der benutzerdefinierten Übertragungslogik des SAS-Tokens: Eine normale Übertragung konnte SAS direkt aus dem LP-Pool verbrennen und seine Reserven an den reduzierten Saldo anpassen, wodurch die kumulierte Verkaufstätigkeit in eine willkürliche Reduzierung der SAS-Reserve des Pools und von dort in eine große Preisverzerrung umgewandelt wurde, die dann durch einen normalen Swap geerntet werden konnte.
Token sollten nicht in einen externen AMM-Pool eingreifen und dessen Reserven außerhalb normaler Swap-Pfade verändern. Wenn ein deflationäres Design tatsächlich das Verbrennen aus einem Pool erfordert, müssen das Verbrennen und das dazugehörige sync() an einen eng kontrollierten internen Auslöser gebunden werden, wie z. B. einen vertrauenswürdigen Keeper oder einen ratenlimitierten Zeitplan, anstatt sich auf willkürliche Benutzertransfers zu stützen.
8. Unbekannter EIP-7702 Vorfall
Kurze Zusammenfassung
Am 3. April 2026 wurde ein Benutzerkonto auf der BNB-Kette, das die delegierte Code-Ausführung über EIP-7702 aktiviert hatte, für rund 17.200 $ geleert. Der delegierte Code legte eine pancakeV3SwapCallback()-Funktion ohne ordnungsgemäße Zugriffskontrolle offen. Der Angreifer rief diesen Callback direkt mit präparierten Calldata auf, wodurch das Konto des Opfers gezwungen wurde, seine Token an eine vom Angreifer kontrollierte Adresse zu übertragen.
Hintergrund
Das EOA des Opfers verwendete eine EIP-7702 Typ-4-Transaktion, um delegierten Code einzurichten, damit das Konto Swap-bezogene Logik ausführen konnte. Die delegierte Implementierung enthielt jedoch eine öffentliche pancakeV3SwapCallback()-Funktion, die nur während eines legitimen PancakeSwap V3-Pool-Callbacks aufgerufen werden sollte.
Schwachstellenanalyse
Die Hauptursache ist das Fehlen einer Zugriffskontrolle in der pancakeV3SwapCallback()-Funktion des delegierten Vertrags (0x02C809...aEDbAE).
Bei einem korrekten UniswapV3/PancakeV3-Callback-Design muss der Callback überprüfen, ob msg.sender der erwartete kanonische Pool ist (abgeleitet vom Factory-, Tokenpaar- und Gebühren-Trio oder verifiziert gegen eine vertrauenswürdige Poolliste). In diesem Fall fehlte diese Validierung, sodass jeder externe Aufrufer den Callback direkt aufrufen konnte.
Da der Callback Token-Übertragungen von dem Konto ausführt, das ihn hostet, bedeutet die fehlende msg.sender-Prüfung, dass jeder externe Aufruf mit positiven amount0Delta/amount1Delta in den Zahlungspfad innerhalb des Callbacks gelangt und Token aus dem Konto des Opfers verschiebt, ohne dass ein tatsächlicher Swap stattfindet.
Angriffsanalyse
Die folgende Analyse basiert auf der Transaktion 0x5b2c...4261.
- Schritt 1: Der Angreifer rief
pancakeV3SwapCallback()direkt mit präparierten Parametern auf, was die Callback-Übertragungslogik auslöste, um die Token des Opfers an vom Angreifer kontrollierte Adressen zu übertragen.


Schlussfolgerung
Dieser Vorfall wurde durch die Bereitstellung von Swap-Callback-Logik auf einem EIP-7702-Konto ohne strenge Callback-Authentifizierung verursacht. Da pancakeV3SwapCallback() keine Zugriffskontrolle hatte, konnte der Callback von jedem externen Aufrufer aufgerufen und verwendet werden, um Token aus dem Konto des Opfers zu verschieben, ohne dass jemals ein legitimer Swap stattfand.
Für jeden Vertrag oder delegierten EIP-7702-Code, der V3-ähnliche Callbacks implementiert, müssen Entwickler überprüfen, ob msg.sender der kanonische PancakeV3-Pool ist (abgeleitet vom vertrauenswürdigen Factory-, Tokenpaar- und Gebührentyp), bevor der Callback in eine Übertragungslogik eintritt.
9. Silo Finance Vorfall
Kurze Zusammenfassung
Am 3. April 2026 wurde das Silo Finance soUSDC-Vault auf Arbitrum für rund 359.000 $ ausgenutzt. Die Hauptursache war das Zusammentreffen von drei Mängeln: ein unveränderliches wstUSR-Oracle, das den Token immer noch mit ~1,133 bewertete, nachdem sein Marktpreis auf ~0,12 gefallen war, ein Kapazitätsmechanismus für die Angebotsgrenze bei soUSDC, der nur die eigenen Einlagen des Vaults, aber nicht externe, einschränkte, und ein totalAssets()-Rechnungsfehler, der extern gutgeschriebene bUSDC-Anteile zählte, ohne entsprechende soUSDC-Anteile zu prägen. Durch die direkte Einzahlung von USDC in den Null-Cap-wstUSR-Markt mit receiver=soUSDC blähte der Angreifer den Anteilspreis des Vaults auf, lieh sich dieselben USDC gegen überbewertete wstUSR-Sicherheiten zurück und löste zuvor erworbene soUSDC-Anteile zur aufgeblähten Bewertung ein, wobei der Fehlbetrag aus anderen gesunden Märkten in der Auszahlungswarteschlange gezogen wurde.
Hintergrund
Silo Finance ist ein risikoisolierter Kreditprotokoll auf Arbitrum. Jeder Silo-Markt ist ein zweiseitiges Kreditpaar (z. B. wstUSR/USDC): Kreditnehmer zahlen Sicherheiten (wstUSR) ein und leihen den Kreditbetrag (USDC), während Kreditgeber USDC einzahlen und Zinsen verdienen. Wenn ein Kreditgeber USDC in einen bestimmten Markt einzahlt, erhält er den Einlagenanteils-Token dieses Marktes. Wenn ein Kreditnehmer Sicherheiten einzahlt, erhält er einen Sicherheitenanteils-Token (z. B. bwstUSR-149).
soUSDC ist ein SiloVault, der auf mehreren Silo-Märkten aufsetzt, um USDC-Kredite zu aggregieren. Benutzer zahlen USDC in soUSDC ein und erhalten soUSDC-Anteile. Das Vault leitet dann das eingezahlte USDC basierend auf Angebotsgrenzen, die vom Allokator festgelegt wurden, an genehmigte Silo-Märkte weiter, und das Vault selbst hält die bUSDC-Anteile jedes Marktes, in den es eingezahlt hat. Wenn ein Benutzer soUSDC-Anteile einlöst, berechnet das Vault, wie viel USDC die Anteile wert sind, indem es totalAssets() verwendet, das jeden Markt in der Auszahlungswarteschlange durchläuft und den bUSDC-Anteilsaldo des Vaults in jedem davon summiert. Das Vault zieht dann USDC aus seinen zugrunde liegenden Märkten ab, um den Einlöser zu bezahlen.
wstUSR (Wrapped Staked USR) ist ein Staking-Derivat des USR-Stablecoins, der von Resolv ausgegeben wird. Nachdem Resolv ausgenutzt wurde, verlor USR seine Bindung, stUSR verlor ebenfalls seine Bindung, und der Marktpreis von wstUSR kollabierte auf ~0,12. Die Chainlink-Feed für wstUSR verfolgte jedoch nur die wstUSR/stUSR-Austauschrate (~1,133), und das Protokoll nahm implizit an, dass 1 stUSR = 1 USD ist. Daher bewertete das Oracle wstUSR weiterhin mit ~1,133, eine Lücke von ~10x gegenüber der Realität des Marktes.
Schwachstellenanalyse
Die Oracle-Adresse des wstUSR/USDC-Marktes ist in SiloConfig fest codiert und unveränderlich und kann nicht ersetzt werden. Der Oracle-Vertrag (0x836a1a...04425e) selbst ist ein ChainlinkV3Oracle, dessen zugrunde liegender Chainlink-Feed (Beschreibung: "wstUSR / stUSR Exchange Rate") nur das wstUSR zu stUSR-Wrapper-Verhältnis (~1,133) verfolgt und nicht den Sekundärmarktpreis. Das Protokoll nimmt implizit an, dass 1 stUSR = 1 USD ist, und bewertet wstUSR daher mit ~1,133. Nachdem USR seine Bindung verloren hatte, verlor auch stUSR seine Bindung, und wstUSR fiel im offenen Markt auf ~0,12, aber das Oracle meldete weiterhin ~1,133, eine ~10-fache Überbewertung.


Das Protokoll war sich des Risikos teilweise bewusst: Die Angebotsgrenze von soUSDC für den wstUSR-Markt war auf 0 gesetzt, was bedeutet, dass das Vault niemals freiwillig USDC dorthin leiten würde. Diese Grenze regelt jedoch nur die eigenen ausgehenden deposit()-Aufrufe des Vaults. Da wstUSR_Market.deposit() einen beliebigen receiver-Parameter akzeptiert, kann jeder USDC direkt in den wstUSR-Markt einzahlen und die resultierenden bUSDC-Anteile an die Adresse von soUSDC gutschreiben und so die Angebotsgrenze vollständig umgehen.
Dies schafft den Kern des Exploit-Pfads. Wenn bUSDC-Anteile über eine solche externe Einzahlung in soUSDCs Guthaben gelangen, zählt totalAssets() sie: Es durchläuft jeden Markt in der Auszahlungswarteschlange und liest das tatsächliche Anteilguthaben des Vaults, ohne zu prüfen, ob die Position freiwillig eingegangen wurde. Mittlerweile werden keine neuen soUSDC-Anteile für diese extern gutgeschriebenen Positionen geprägt, da die eigene Prägelogik des Vaults nie ausgelöst wurde – totalAssets steigt, totalShares bleibt gleich, und der soUSDC-Anteilspreis bläht sich auf. Gleichzeitig schafft dies USDC-Liquidität im zuvor leeren wstUSR-Markt, die für den nächsten Schritt benötigt wird.




Angriffsanalyse
Die folgende Analyse basiert auf der Transaktion 0xf77a...f3e1.
Der Angreifer kaufte zunächst wstUSR auf dem Sekundärmarkt für etwa 0,12 pro Token.
-
Schritt 1: Flash-Loan von ca. 4.236.352
USDCvon Morpho. Die Fehlbewertung durch das Oracle allein reicht nicht aus – derwstUSR-Markt hatte keineUSDC-Liquidität (cap=0,soUSDCzahlte dort nie ein), sodass es nichts gibt, was gegen die überbewerteten Sicherheiten geliehen werden kann. Der Flash-Loan stellt das für die anschließenden Einzahlungs- und Spenden-Schritte benötigte Kapital bereit. -
Schritt 2: Einzahlung von
wstUSRin denwstUSR-Markt als Sicherheit und Erhalt vonbwstUSR-149. Dies ist die Vorbereitung für die Ausleihe in Schritt 5 – das Oracle bewertet 13.797wstUSRmit ~15.633 (zu je 1,133), obwohl der Angreifer nur ~1.656 bezahlt hat.

- Schritt 3: Einzahlung von ca. 4.222.007
USDCin dassoUSDC-Vault, wobeisoUSDC-Anteile empfangen werden (~91,5 % des Gesamtangebots). Das Vault leitet dieseUSDCan bestehende gesunde Märkte weiter (nicht denwstUSR-Markt, da cap=0). DiesesoUSDC-Anteile sind das Instrument zur Gewinnentnahme in Schritt 6 – je mehr Anteile der Angreifer hält, desto mehr profitiert er, wenn der Anteilspreis aufgebläht wird.

- Schritt 4: Einzahlung von ca. 14.344
USDCdirekt in denwstUSR-Markt überwstUSR_Market.deposit(receiver=soUSDC)und Prägung vonbUSDC-149ansoUSDC. Die resultierendenbUSDC-Anteile werden an die Adresse vonsoUSDCgutgeschrieben, nicht an die des Angreifers. Dies ist die Kernmanipulation:soUSDCstotalAssets()umfasst nun diesebUSDC-Anteile zum Nennwert (~14.344USDC), aber es werden keine neuensoUSDC-Anteile geprägt, da die eigene Einzahlungslogik des Vaults nie ausgelöst wurde –totalAssetssteigt,totalSharesbleibt gleich und dersoUSDC-Anteilspreis bläht sich auf. Gleichzeitig schafft diesUSDC-Liquidität im zuvor leerenwstUSR-Markt, die für den nächsten Schritt benötigt wird.


- Schritt 5: Ausleihen von ca. 14.344
USDCaus demwstUSR-Markt unter Verwendung der in Schritt 2 hinterlegten Sicherheiten. Das Oracle bewertet die Sicherheiten mit ~15.633, sodass bei 92 % maxLTV der Angreifer ~14.344 leihen kann. Dies deckt die in Schritt 4 gespendetenUSDCab – die Ausleihe und die Spende sind Bargeld-neutral. Aber derwstUSR-Markt ist nun vollständig ausgedünnt: AlleUSDCwurden ausgeliehen, wodurch nur eine ausstehende Darlehensposition gegen nahezu wertlosewstUSR-Sicherheiten übrig bleibt.soUSDChält weiterhin diebUSDC-Anteile zum Nennwert intotalAssets().



- Schritt 6: Einlösung aller in Schritt 3 erworbenen
soUSDC-Anteile. Der Anteilspreis ist nun aufgrund der Spende in Schritt 4 aufgebläht, sodass der Angreifer ~4.235.143USDCerhält, ~13.136 mehr als die in Schritt 3 eingezahlten 4.222.007. Das Vault versucht, aus demwstUSR-Markt abzuheben, findet aber keine Liquidität (in Schritt 5 ausgeliehen), sodass es den Fehlbetrag aus anderen gesunden Märkten in der Auszahlungswarteschlange zieht. Hier materialisiert sich der Verlust: EchteUSDCaus den Märkten anderersoUSDC-Einzahler werden übertragen, um die aufgeblähte Einlösung abzudecken.
Schlussfolgerung
Dieser Vorfall wurde durch das Zusammentreffen eines Oracles, das eine Staking-Austauschrate und nicht den Marktpreis eines abgestürzten Assets verfolgte, eines Vault-Buchhaltungssystems, das extern gutgeschriebene Positionen in totalAssets() zählte, ohne entsprechende Anteile zu prägen, und eines Angebotsdeckelungsmechanismus, der nur die eigenen Einzahlungen des Vaults, aber nicht externe einschränkte, verursacht. Die Oracle-Adresse, die in SiloConfig unveränderlich war, verhinderte eine Notfallkorrektur, nachdem das Problem offensichtlich wurde.
Vault-Protokolle, die über Kreditmärkte aggregieren, sollten sicherstellen, dass totalAssets() nur Positionen zählt, die das Vault durch eigene Einzahlungsoperationen eingegangen ist, nicht extern gutgeschriebene Anteilssalden. Oracle-Adressen sollten nicht dauerhaft unveränderlich sein; Notfall-Governance-Mechanismen sollten für die Aktualisierung von Preis-Feeds vorhanden sein, wenn zugrunde liegende Assets ihre Bindung verlieren.



