xToken Loses $4.5 Million in Second Flash Loan Attack on Its xSNX Contract
xToken was exploited for a second time on August 30, 2021, with attackers draining roughly $4.5 million from its xSNX contract using a flash loan — the same contract and the same general attack technique that had cost the protocol $24 million just three months earlier. Rekt's earlier coverage of that first incident had described xToken as "a quality protocol"; this repeat episode raises questions about why the same vulnerability class was allowed to resurface.
Attack transaction: 0x924e6a6288587b497f73ddcf6ae3c184f15ab35dfcb85f3074b55266974029ef

Details below draw on xToken's official post-mortem.
01The Attack Sequence
- The attacker took out a flash loan of 25,000 ETH from dYdX.
- Using that capital, they borrowed roughly 1 million SNX across a combination of Aave V1 and V2.
- They swapped 6.8 thousand ETH for 519,000 SNX on Bancor, bringing their total SNX holdings to roughly 1.5 million.
- That 1.5 million SNX was then swapped on Kyber for approximately 6.5 million USDC, an action that pushed the SNX price down considerably.
- The ~6.5 million USDC was swapped again, this time for roughly 6.5 million sUSD on Curve.
- About 2 million sUSD was transferred to the xSNXAdmin contract — the contract holding assets managed by xSNX — with the goal of repaying the contract's sUSD debt and unlocking its SNX holdings.
- The attacker then called the
callFunctionfunction on the xSNXAdmin contract, which burned the outstanding sUSD debt and swapped roughly 614,000 SNX for about 811,000 sUSD of debt at the artificially depressed price created in step 4. - The resulting ~811,000 sUSD was swapped for an equivalent amount of USDC, which stayed in the attacker's contract.
- Finally, the attacker unwound the sequence, converting back to ETH and repaying the flash loan and borrowed positions.
The underlying profit came from using xSNX's own assets to push down the SNX price and then exploit the resulting arbitrage opportunity externally.
02The Root Cause
The vulnerability was that callFunction could be called by anyone, when it was intended to be restricted to dYdX's SoloMargin flash-loan contract — an integration originally added to improve fund performance during rebalances. An incorrect require statement was to blame: the contract checked require(sender==address(this)) where it should have used require(msg.sender==soloMarginAddress).
03Aftermath

xToken said it would again compensate affected users and confirmed it had decided to phase out its xSNX product entirely. Its post-mortem stated:
xSNX is by far our most complex product and we want to be maximally confident in the products we're offering investors. We are highly confident in our other products and contracts, but can no longer say the same about the current implementation of our xSNX contract.
The team's response — compensating users again and retiring the affected product — suggests a degree of accountability, even as a second appearance on the Rekt leaderboard in three months represents lasting reputational damage. Whether publicly acknowledging that the xSNX design was too complex helps or further hurts that reputation remains an open question. Having now suffered two exploits of the same contract in short succession, xToken may be better served by a clean break from the product than by further iteration on it.
Get new scam files the moment we publish them — usually 2–3 emails a week.