Post-Mortem: Euler Liquidation Vulnerability
A review of the ~$197,000,000 Euler Finance vulnerability on 03/13/2023 as well as our response at Swivel.
At 08:51 UTC on March 13th, Euler Finance suffered from the exploit of a severe vulnerability, leaving their protocol insolvent with a shortfall of roughly $197.3m.
This shortfall includes roughly $1m of USDC that had been deposited through Swivel’s Euler USDC fixed-rate integration.
The Vulnerability
Unlike other lending market shortfalls of this scale, this vulnerability was the result of mechanisms unique to Euler – fee donations and liquidation bonuses.
donateToReserves
The core vulnerability relates to a relatively superfluous method added in eIP 14 — `donateToReserves`:
This method allows a user to, as is implied, donate some of their eTokens in order to clear dust or otherwise pay a voluntary fee to the Euler reserves.
For additional context, as a general heuristic Euler allows users to take on an unsustainable position within a transaction so long as it is resolved atomically (similar to a flash loan).
In this case, an attacker was able to create significant eToken and dToken positions (supply / debt positions) without triggering any protocol fail-safes -- which in and of itself does not represent a security issue.
However… the `donateToReserves` method has no checks on a user’s debt, allowing a user to “donate” their significant eToken balance and leave a large amount of “debt” to the protocol.
Liquidation Bonuses
At this point, a user may have a large debt position that is not necessarily “real.”
Again, in a vacuum this may not present an issue given at this point no funds have been withdrawn by the attacker.
However, this “fake” debt may still be liquidated, and herein lies the issue — Euler pays significant bonuses to liquidators depending on the health of a position.
And because the position is so extremely underwater, the bonus for liquidation is significant — significant enough that an attacker has the ability to create a second account and profitably perform the liquidation on themselves.
(Note: The mechanism more directly relates to the “discount” on liquidation but can be effectively seen as a bonus.)
The Hack — A Story of Two “Attackers”
The Setup (08:50:23)
At 08:50:23 UTC on March 13th, an attacker deploys the first exploit contract — Etherscan
At nearly the same moment (one block later), 08:50:35, a second “attacker” deploys the same exploit contract — Etherscan
As a clone, both core attacking contracts do the exact same thing – deploy two modular components:
Initializer Contract — A contract that utilizes the described method to initialize a liquidatable position.
Liquidator Contract — A contract with the sole job of liquidating the initializer and returning the accrued funds.
The Front-Run (08:50:59)
Immediately after the second attacker deployed a duplicate contract, an attack (on Euler’s DAI markets) from the first attacker hit the mempool.
The second attacker then revealed themselves to be a generalized frontrunner rather than a specialized attack, managing to out-bid the first attacker, executing the transaction that triggered initial concerns — Etherscan
The result was the first larger hack attempt was thwarted (Etherscan) while a relatively advanced generalized frontrunner then found themselves with ~$21m in funds.
The Execution (08:56:35 - 09:08:59)
Unfortunately, just minutes later, the primary attacker continued to execute the attack, targeting WETH markets at 8:56, WBTC markets at 9:03, wstETH markets at 9:04, USDC markets at 9:05, and stETH markets at 9:09.
The final result was that Euler’s markets were insolvent to the tune of roughly ~$198 million — One attacker with ~$21m, one attacker with ~$177m.
The Mistake (11:38:11)
At first, many suspected (myself included) that the larger attacker was a unique participant — a whitehat saving remaining funds.
This assumption was unfortunately revealed to be incorrect. By decompiling the attack contract bytecode, I found that the contract contained whitelisted access to the primary attacker.
While this clarified to us that the two attackers were in fact different participants, the frontrunner unfortunately had not done similar analysis on hardcoded addresses in the attacker’s contract.
As the frontrunner describes above, the whitelisting restricted certain methods to the attacker’s wallets, and more importantly, the duplicated contract retained the hardcoded address for the withdrawal of funds.
This meant that while the frontrunner had successfully stolen (perhaps as a whitehat) ~$21m in DAI+WETH, these funds were immediately sent to the initial malicious attacker when the frontrunner attempted a withdrawal. (Etherscan)
The Bank Run (~09:00 - ~12:00)
With the largest markets completely insolvent, the majority of Euler’s lenders were left with collateral that could not be withdrawn.
In a natural attempt to avoid a complete loss, these lenders then did the only thing they could — borrowed as much unimpacted collateral as possible (e.g., cbETH, COMP, etc.).
For many, up to 50% of funds were able to be saved through these alternate means, For others, their otherwise unimpacted deposits were now taking on the contagion of the initial attack.
The final result was the insolvency of nearly all Euler markets, regardless of Euler’s isolated architecture.
Minimal Recovery
Direct Recovery Attempts
As of today (03/15/2023) no funds have been returned by the attacker(s).
The Euler team has insofar taken three routes to recovery:
Established collaboration with law enforcement and security specialists (TRM Labs) to trace fund origin
Attempted communication with the attacker — Etherscan
We understand that you are responsible for this morning's attack on the Euler platform. We are writing to see whether you would be open to speaking with us about any potential next steps.
Placed a significant bounty placed for information — Etherscan
Following up on our message from yesterday. If 90% of the funds are not returned within 24 hours, tomorrow we will launch a $1M reward for information that leads to your arrest and the return of all funds.
Little has been gained so far from these efforts.
Indirect Recovery
While the attacked funds may have a low chance of direct recovery, alternate methods may lead to at least partial fund recovery.
To begin, Euler had reserved roughly $5m of coverage through Sherlock following their audits last year.
This coverage was capped by the available Sherlock reserves, leading to a $4.5M payout.
Further, the Euler team has extolled the size of their treasury on multiple occasions.
When only accounting for their on-chain assets, Euler has roughly $31m in reserves (closer to $40m including off-chain assets), leaving Euler as one of the most well-capitalized teams in DeFi.
While a team’s runway is not an insurance policy, lenders are currently hoping for a partial repayment of the losses through this treasury.
In an optimistic scenario, the $4.5m in Sherlock coverage alongside ~$15m from the Euler treasury will result in an ~10% repayment of losses.
Next Steps
Impact on Swivel & our Lenders
At Swivel we took a heavy hit. Our new Swivel v3 USDC market had been growing consistently, however a ~$1m loss impacts this progress significantly.
We are not in a financial position to recapitalize our protocol’s losses directly, and are instead reliant on the recovery process of the Euler Foundation / Protocol. That said, we will likewise attempt to recover funds in any way possible.
For those impacted further remuneration may come through alternate means — for more information stay tuned for announcements and governance initiatives.
Euler & USDC Markets
While our Euler USDC markets are currently insolvent alongside all of Euler’s deposits, we HAVE NOT paused our markets for the time being.
Should any small opportunity arise to remove your funds, feel free to capture said opportunity.
That said, within the next week we will be sunsetting our Euler USDC market in order to launch an additional market through one of:
Yearn
Morpho
Compound
Aave
If you have any suggestions please indicate so through our governance forum or discord before we initiate our next vote.
Founder’s Note
At nearly $200m, the Euler hack is the largest and most impactful in DeFi history.
No previously exposed codebases had been through the same rigor as the Euler’s. The wider code (and concepts) had been through 6 audits (1 relevant), had a $1m bug bounty, and at this point had been live for nearly 2 years, previously eclipsing the current TVL.
The Rari hack (that we narrowly missed at Swivel) resulted in the death of multiple projects, but this time the Euler hack touches nearly every new DeFi protocol with upwards of 20 projects impacted.
That said, the widespread impact and shock of this hack will morph the attitudes of lenders and the opinions of developers going forward and we have only begun to see the effects of this shift.
While a tough lesson to learn, there are three immediate implementations that could have mitigated the current situation:
Rate Limiting — Prevents excess vulnerability
Diversification / Isolation — Ensures partial solvency
Limited Upgradability — Reduces attack surface
It will take some time to see the full fallout across the wider ecosystem, but at Swivel we will continue as always to build the most innovative and important products in the fixed-rate space (and DeFi more widely).
— Julian Traversa
About Swivel Finance
Swivel is the protocol for fixed-rate lending and tokenized cash-flows.
Currently live on Ethereum, Swivel provides lenders the most efficient way to lock in a fixed rate as well as trade rates, and liquidity providers the most familiar and effective way to manage their inventory.
Website | Substack | Discord | Twitter | Github | Gitcoin | Careers