Rari Capital, a lending protocol, was hacked on April 30th between 9:00 and 9:35 a.m. (UTC) and lost approximately $80 million as the hacker drained seven of Rari’s fused pools.
The Rari Capital hack was a surprise because the protocol had recently patched its functions by adding a re-entrancy guard in all CToken about two months ago. Despite the added patch, an unknown hacker exploited the Rari’s re-entrancy vulnerability, according to a tweet by BlockSec, a team focused on the security of the blockchain ecosystem.
Rari Capital acknowledged the hack of their various fused pools via Twitter, stating that borrowing has been paused globally, assured that no further funds are at risk, and announced a 10 million-dollar bounty to the hacker if the stolen funds are returned.
The protocol’s vulnerability stems from its old Compound codebase, which has been known to have a broken check-effect-interaction pattern in the borrow function of re-entrancy, which can only be exploited if there’s an asset with a transfer hook, such as ERC-777. However, many forks, including Compound, are not exploited because the re-entrancy puzzle is incomplete as long as they check if a token has a transfer hook before adding it to the market.
Another issue is that Rari uses an old codebase is that it uses.call.value () instead of.transfer () to send out ETH, which is a re-entrance pattern because if the receiver is a contract, it can make a call to another/same contract via receive (). Therefore, it is possible to borrow all available funds by combining them.
After borrowing an asset, the transfer hook is triggered, but the debt balance is not immediately updated. As a result, it is possible to borrow again.
The patch, which was added to all CToken two months ago to prevent users from entering any other functions even if re-enterancy is available, did not protect functions in the comptroller, particularly the exit market. The hacker took advantage of this major vulnerability.
Calling the Comptroller.exitMarket() removes a deposited asset as collateral for the loan, allowing it to be withdrawn at any time. The function determines whether or not the current health factor allows an asset to be disabled. However, the check can be bypassed.
Here’s how the attack went down:
The hacker first flashloaned 150,000,000 USDC and 50,000 WETH before depositing 150,000,000 USDC as collateral into the fUSDC-127 contract, a vulnerable fork of the compound protocol.
With deposited collateral, the attacker borrowed 1,977 ETH using the borrow() function, which transferred ETH to the hacker’s contract before updating the attacker’s actual borrow records. Because the hacker’s record was not immediately updated, the hacker made a re-entrant call to the vulnerable exitmarket() function in the fallback function, allowing the attacker to withdraw all of his collateral, 150M USDC.
The steps were repeated up to five times on different tokens before the attacker repaid the flash loan, sent the remainder to his address and routed some of the funds to Tornado Cash.