Op 25 januari 2026 verloor SwapNet — een DEX aggregator — meer dan $13 miljoen op Ethereum, Arbitrum, Base en BSC. Aperture Finance werd diezelfde dag getroffen via dezelfde kwetsbaarheid. Beide protocollen deelden een zwakte: hun smart contracts accepteerden arbitrary low-level calls zonder te controleren waar die calls daadwerkelijk naartoe gingen.
De aanval was in principe eenvoudig. Gebruikers hadden token approvals verleend aan deze contracten voor normale swap-operaties. De contracten hoorden die calls te routeren naar legitieme pools en routers. Maar omdat de inputvalidatie zwak was, kon de aanvaller een tokenadres als call target substitueren — waardoor het contract transferFrom() uitvoerde op de goedgekeurde tokens van de gebruiker en ze rechtstreeks naar de wallet van de aanvaller drainede.
Er werden geen private keys gestolen. Geen complexe exploit chain. Gewoon een gecraftede function call die het contract had moeten weigeren, maar dat niet deed.
Het closed-source probleem
Zowel SwapNet als Aperture Finance draaiden op closed-source contracten. Dat verandert je aanpak van forensische analyse compleet.
Zonder broncode werk je met gedecompileerde bytecode — duizenden regels geneste branching logic waar de intentie achter elke functie ambigu is. Je kunt reconstrueren wat er is gebeurd aan de hand van execution traces, maar je kunt niet eenvoudig vaststellen wat het contract hoorde te doen. Dat onderscheid tussen bedoeld gedrag en daadwerkelijk gedrag is precies wat juridische teams nodig hebben, en het is het moeilijkst vast te stellen wanneer de code niet leesbaar is.
Ik heb aan zaken als deze gewerkt waar de eerste vraag van juridisch is: "Was dit een bug of een feature?" Bij closed-source contracten ben je in feite het antwoord aan het reverse-engineeren vanuit bytecode en transactie-traces. Het is haalbaar, maar het vereist een andere skillset dan Solidity lezen.
Hoe de exploit werkte
De kwetsbare functie accepteerde door de gebruiker aangeleverde parameters die een low-level call aanstuurden. Normaal zouden die parameters naar een router of liquidity pool wijzen. De aanvaller verving ze door token contract-adressen — USDC, USDT, wat de gebruiker ook had goedgekeurd.
Het contract voerde vervolgens USDC.transferFrom(slachtoffer, aanvaller, bedrag) uit. Elke gebruiker die unlimited approvals had verleend was blootgesteld.
Dit patroon herhaalde zich op vier chains. Dezelfde fout, verschillende deployments. De aanvaller hoefde geen vier verschillende bugs te vinden — een architecturele zwakte was voldoende.
Wat dit praktisch betekent
Als je contracten beoordeelt die token approvals vasthouden en door gebruikers aangestuurde call targets accepteren, is dit het risico: elke functie die gebruikersinput doorgeeft aan een low-level call zonder strikte whitelisting is een potentiele drain vector.
De SwapNet-zaak legde ook een risico aan gebruikerszijde bloot dat de meeste mensen over het hoofd zien. Gebruikers die de "one-time approval"-instelling uitschakelden — en kozen voor unlimited approvals — hadden hun volledige goedgekeurde saldo op het spel, niet alleen het bedrag voor een enkele trade. Dat permissiemodel vergrootte de blast radius dramatisch.
Voor iedereen die post-incident analyse doet op closed-source contracten: begin met execution traces, reconstrueer de call flow vanuit bytecode-decompilatie, en documenteer waar je interpretatie berust op inference in plaats van leesbare code. Die transparantie is wat de analyse overeind houdt.