$4 500 000 USD
DESCRIPTION OF EVENTS
xToken is "a decentralized passive investing protocol," "a project which automates staking and liquidity strategies and wraps them into ERC-20 tokens." "xToken offers eight tokens, such as xSNXa and xBNTa, that offer exposure to returns from DeFi projects. They come in the form of Ethereum-based tokens that are wrapped around certain DeFi tokens, such as SNX and BNT. They give you some of the same benefits as the underlying token, such as staking rewards, but without having to leave the Ethereum ecosystem."
"On 29 August at 04:43 UTC, a vulnerability in our xSNX contract was exploited. We estimate the loss to holders at $4.5 million."
"That the attacker was able to call the callFunction function was the source of the vulnerability. This function should only have been callable from dydx’s SoloMargin flashloan contract that we had integrated to improve fund performance on rebalances. An erroneous require statement allowed the function to be publicly callable." "We mistakenly used require(sender==address(this) when we should have used require(msg.sender==soloMarginAddress)."
"Flash loan of 25,000 ETH from dydx. Borrow of ~1m SNX from a combination of Aave V1 and V2. Swap of 6.8k ETH to 519k SNX on Bancor. (Attacker now holds ~1.5m SNX.) Swap of 1.5m SNX on Kyber for ~6.5m USDC, lowering SNX price considerably. Swap of ~6.5m USDC for ~6.5m sUSD on Curve. Transfer of ~2m sUSD to xSNXAdmin contract (this is the contract that holds the assets managed by xSNX), with the intention of repaying the contract’s sUSD debt in order to unlock SNX. Call of the callFunction function on xSNXAdmin contract, burning outstanding sUSD debt and swapping ~614k SNX for ~811k sUSD debt at artificially depressed price." "Swap of ~811k sUSD for ~811k USDC, which remains in the contract." "The attacker then reverses all actions, swapping back to ETH and repaying loans. The source of the value extraction was that the attacker used xSNX assets to pressure SNX price and create profitable external arbitrage opportunities."
"Through the comments, we can know that [callFunction] is used to flash loan and then to return the debt. This function will first convert the loaned USDC into sUSD, the amount is the loanAmount (1) passed in by the attacker. Burn sUSD liabilities. Convert the SNX in the contract to sUSD, the swap amount is the snxAmount passed in by the attacker (about 614,240). Swap through Kyber/Uniswap/SUSHI/Curve, where slippage has been generated in the fourth step above. The 614,240 SNX should theoretically be exchanged for 6,756,640 sUSD. But the slippage was not checked, only 808,433 sUSD was swapped. After that, sUSD is converted into 811,078 USDC to return the debt. The loanAmount passed in before is 1. So the final check usdcBalance> loanAmount + 2 is 811,078> 1 + 2 is established and bypassed the check."
"We are incredibly disappointed in ourselves and deeply sorry to our community." "At this time, we believe it best to sunset our xSNX product offering. The current xSNX implementation is by far our most complicated product, with complex dependencies and significant surface area for vulnerabilities. More info later in the post about how users will be able to unwind their positions."
"We will no longer be staking SNX from the xSNX contract. We’re pushing a contract upgrade early this week that will allow us to swap all of the assets in the contract into ETH to allow for maximum value at redemption. There is currently a large quantity of USDC in the contract that is not counting towards NAV so we encourage you to wait to redeem until we’ve made this update. We will post in the #announcements channel in our Discord once this is complete."
"Once we’ve swapped the USDC for ETH, xSNX‘s sole holding will be ETH. You may redeem your xSNX for ETH at any time. However, we would note that starting in October, SNX from Synthetix staking rewards will begin to vest on our contract. As this SNX vests, we will swap it for more ETH. We do not have early access to SNX staking rewards so, put simply, the longer you wait to redeem, the more ETH you will receive."
"We are working this week to write accurate snapshot scripts to properly calculate investor losses. If you redeemed post-exploit, you will still receive compensation. We will need a few days to work out the details of this script and ensure accuracy."
"To compensate xSNX holders for losses from the August exploit, we’ve deployed an rXTK contract and funded it with XTK. As a reminder, we are a small project with a very limited treasury, so we’re forced to be creative with compensation plans. We are a dedicated team still very much focused on our goal of building a decentralized asset management stack, and we want to give our community an opportunity to recoup full value."
"We’ve funded the rXTK contract with ~4.04m XTK — a value derived by applying the same ratio of USD losses to XTK as we used for the previous exploit. We know that to some members of our community this resolution may leave something to be desired. Rest assured that we’ll be continuing to build, working to drive as much value as possible to the xToken ecosystem." "We understand that this is not an optimal resolution for all. We’re working to do the best we can with the resources at our disposal."
xToken stored user funds in a particularly complex smart contract hot wallet. Through missing checks, an attacker was able to drain the wallet. xToken plans to compensate users, and retire the contract, which was already breached once in May.
blocksec-incidents/2021.md at main · openblocksec/blocksec-incidents · GitHub (Aug 11)
Xsnx Post Mortem (Sep 19)
Rekt - X-Token - REKT X2 (Sep 19)
xToken Market (May 17)
Slowmist Brief Analysis Of The Xtokenattack Event (Oct 20)
Ethereum Transaction Hash (Txhash) Details | Etherscan (Oct 20)
Xsnx Compensation Mechanics (Oct 20)