5/8/2021: Rari Capital Ethereum Pool — Post-Mortem
Details on the Rari Capital Ethereum Pool hack on May 8, 2021
This morning, an attacker stole approximately 2600 ETH, around $10m USD at the time of writing. These funds were extracted from Rari Capital’s Ethereum Pool before the attacker was stopped when the contracts were paused. This loss equates to 60% of all users’ funds in the Rari Capital Ethereum Pool.
As core contributors to the protocol, we take such an attack extremely seriously. Below, we describe in detail exactly what happened and the primary steps we will be taking to proactively prevent attacks from happening in the future. In the next couple days, you can expect another blog post describing the potential paths towards making everyone whole again.
The Rari Capital Ethereum Pool deposits ETH into Alpha Finance’s ibETH token as one of our yield-generating strategies. This strategy tracks the value of its ibETH as `ibETH.totalETH() / ibETH.totalSupply()`.
According to Alpha Finance, `ibETH.totalETH()` is vulnerable to manipulation inside the `ibETH.work` function, and a user of `ibETH.work` can call any contract it wants to inside `ibETH.work`, including the Rari Capital Ethereum Pool deposit and withdrawal functions.
The attacker repeatedly executed the following steps inside of `ibETH.work` (simplified explanation):
1. Flashloan ETH from dYdX.
2. Deposit that ETH into the Rari Capital Ethereum Pool.
3. Manipulate the value of `ibETH.totalETH()` by pushing it artificially high.
4. Withdraw more ETH from the Rari Capital Ethereum Pool than the attacker deposited because the Rari Capital Ethereum Pool’s balances are artifically inflated (because `ibETH.totalETH()` is artificially inflated).
5. At the end of `ibETH.work`, the value of `ibETH.totalETH()` returns to its true value, leading the Rari Capital Ethereum Pool’s balances to values lower than they were before the attack as a result of the attacker withdrawing more than they deposited while their balance was artificially inflated.
Unfortunately, the Rari Capital contributors were not aware that `ibETH.totalETH()` could be manipulated for the duration of these external calls from `ibETH.work`, nor were we aware of the flexibility of `ibETH.work` to call any contract.
Rari’s integration of Alpha was audited by Quantstamp, but, unfortunately, they were not aware of these conditions either.
To avoid issues like this in the future, we will be implementing the following additional security measures:
1. Enlist the protocols we integrate to review our integrations of them for security. This is by far the most important security measure, as the protocols themselves know the code they wrote better than anyone else.
2. Check invariants that shouldn’t need to be checked but, in the event of an unexpected malfunction or attack, offer failsafes (i.e., additional protection against damage).
— For example, to prevent issues like this where the pool is arbitraged because subpool balances are manipulated, we could check to make sure that the value per share of a lossless pool like the Rari Capital Ethereum Pool has not dropped below its last known value. For pools where impermanent loss is possible, we can set a loss threshold at which the pool pauses itself to avoid further damage.
3. Prevent deposits and withdrawals in the same block (or timelock by up to one hour) to mitigate the speed of potential attacks by preventing flashloan-based attacks.
4. Internally review the protocols we integrate to look for attack vectors.
5. Of course, we hope to enlist more top auditing firms other than Quantstamp and Omniscia. We already have another audit planned with OpenZeppelin.
We are extremely grateful to everybody that has helped us throughout the course of the investigation.