We Rescued $4M from Rari Capital. But Was It Worth It?

Hacxyk
8 min readApr 28, 2022

--

On April 6th, we discovered a verified Fuse pool in Rari Capital used a weak price oracle prone to manipulation. Usually, exploiting a price manipulation vulnerability requires a certain amount of capital from the attacker. However, we found that the affected pool’s token had extremely thin liquidity that almost anyone could have pulled off the attack with less than 1 ETH (~$3k). If it was exploited, the pool would suffer a $4M loss.

We reported this critical issue to Rari via ImmuneFi. While they triaged and fixed the issue within hours, they downgraded the severity to medium with an unpleasant bounty amount.

We will describe the issue, our interactions with the teams, and why users should interact with Rari’s Fuse with caution.

Rari’s Fuse

Rari’s Fuse is a decentralized lending protocol on Ethereum. It’s different from other lending protocols in the sense that anyone can create a pool with any tokens of the pool’s creator’s choice. The pools are divided into verified and unverified, where verified pools are examined by Rari to ensure they are safe for lending/borrowing.

Lending protocols use something called price oracle to reflect assets’ price, which is then used to determine how much borrowers can borrow, and at what price they will be liquidated. Rari’s Fuse uses 3 types of oracles depending on pools. Chainlink, Uniswap V2 Oracle, and Uniswap V3 Oracle. Chainlink is an off-chain oracle which is difficult to manipulate, while Uniswap V2/V3 Oracle are on-chain which is easier to manipulate.

Uniswap V3 Oracle Manipulation

Unlike Uniswap V2, V3 has a native oracle implementation. After the first trade in a block, the token’s price and the transaction timestamp will be recorded in the LP contract. It exposes an interface UniswapV3Pool.observe(secondsAgos) which calculates and returns the time-weighted average price within the last secondsAgos using geometric means.

Although Uniswap V2’s oracle requires writing custom contracts, it is many times safer than V3 because the price is determined by the well-known x*y=k curve. The further you want the future price to deviate from the current price, the higher the price impact is, and the more capital intensive a manipulation is.

No matter how much one trades, there’s always some liquidity left. (red line denotes price after trade)

Uniswap V3 uses concentrated liquidity. If a V2 and V3 pool have the same liquidity, but the V3 pool has all of it concentrated in a narrow price range, then by buying up the available tokens, the price will be pushed to “infinity” (1.0001^887271 due to technical limit).

By buying all liquidity concentrated in a price range, there will be no liquidity left. (price = ∞) (red line denotes price after trade)

The behavior can be best summarized by a tweet from @bantg
https://twitter.com/bantg/status/1455151835828867079.

Dog Park Has No Dogs

Pool 45 (Dog Park) is a verified Fuse pool that had $4M borrowable funds. Besides mainstream tokens, DOG and NFD can be used as collateral. The pool uses Uniswap V3 Oracle for DOG and NFD.

For NFD, a majority of the liquidity is in SushiSwap.

However, we found that the Uniswap V3 LP that the oracle relies on had less than $1k liquidity.
https://etherscan.io/address/0xAe91b3BC45379290d9E8fF8a633F34aD3101086B

In addition, the TWAP window of the oracle is merely 10 minutes (600 seconds). That is, only trades within the last 10 minutes matter.
https://etherscan.io/address/0xCa1394570e25A123e3E297449a21075188d16e1a#readContract

This makes a perfect oracle manipulation attack target.

We tested that by buying ~0.8 ETH worth of NFD, it’s enough to push the price to an absurd number. In fact, the oracle reported a 10,000x price increase of NFD in less than 1 minute. The following table shows the exponential price increase by block number, where block n is before the buyout, and price n+1 onwards are after the buyout. (Assuming 1 block takes 13 seconds to mine)

# Oracle reporting for NFD (unit=eth)
Block n : 0.000000043177249
Block n+1: 0.000000426281204
Block n+2: 0.000004208597541
Block n+3: 0.000041546570730
Block n+4: 0.000410181808579

An exploitation would look like this.

  1. An attacker buys ~0.8 ETH worth (~$2400) of NFD from NFD/ETH Uniswap V3 LP. The attacker should get 7.4M NFD (~$660)
  2. The attacker deposits the acquired NFD into Fuse pool 45
  3. The attacker waits for 1 minute
  4. The attacker collateral is now worth $660 * 10000 = $6.6M. With a collateral ratio of 60%, the attacker can borrow $6.6M * 60% = $3.96M worth of funds without ever repaying

The attacker can also prepare more capital to reduce the waiting time.

Responsible Disclosure

Once we identified the issue, we quickly wrote up a PoC in Hardhat and submitted it to Tribe DAO (which Rari Capital merged with). The report was triaged in 3 minutes, and escalated in 10 minutes. The issue was then fixed in a day. Overall, we were impressed by how fast the process was.

However, things took a turn after a day following the resolution of the issue. The report was downgraded to Medium severity with the following explanations.

Hey! Thanks for the report. We were able to go in and disable borrowing soon after receiving this report.

We’ve decided to classify this as a medium-severity bug due to a couple of reasons:

* the banner on the website warning of the uni-v3 oracle for the asset in question

* repeated communications for pool operators about uni-v3 liquidity range

We’ll be updating our bounty text shortly to make to make it clear that this particular type of bug — low uni-v3 oracle with manipulation potential — is not in scope. However, because it was unclear, we’re happy to pay this out as a medium bug (with a 2x payout).

10,000 Fei coming to you shortly.

FEI is a stable coin which is pegged to $1 USD, so the total bounty amount is $10k ($5k without the 2x bonus).

We disagreed with the decision and request a mediation to ImmuneFi. After 1 week, ImmuneFi responded saying they agreed with Tribe DAO’s assessment. We tried to make another comment, but has since been ghosted for 2 weeks.

Criticality

It’s without a doubt that almost anyone could have performed the attack. In fact, similar attacks have happened many times in Rari Capital which we will cover in a later section. $4M was definitely at risk and could have been drained and hence it’s a critical issue.

Scope

Here’s the original rules of the program
http://webcache.googleusercontent.com/search?q=cache:eIQGQw9qD2gJ:https://immunefi.com/bounty/raricapital/&hl=en&gl=nz&strip=1&vwsrc=0

We believe it’s clear evidence that they were specifically interested in this type of issue.

Bounty Amount

We provided a PoC even though it’s not required, as we wished to assist the team with faster triaging and resolution. The bounty amount did not respect our effort. The team seemed to suggest that the 2x bonus was some sort of compensation, while in fact they announced on Twitter there’s a 2x bonus for all reports. We are not a special case.

Users Own Diligence

The team went further into saying it’s not Rari’s fault because there’s a banner that warns users. There are a few issues with this banner.

  1. For an average user, it’s impossible to understand what the warning truly means. It doesn’t provide a link or further explanation, nor we could find it on their documentations.
  2. Even for experienced DeFi users, they would need to have the ability to read smart contracts and understand how oracles work. Uniswap analytics cannot display the affected V3’s LP info due to thin liquidity
  3. If you visit a pool by URL (https://app.rari.capital/fuse/pool/45), the banner sometimes disappears
  4. The pool is verified. Rari has reviewed the pool

We understand that for some pools, it is indeed users’ responsibility to do their own diligence. For example, Pool 136 (Ichi) had massive liquidation events because of over leverages. Likewise, we would have agreed the issue to be medium severity if a significant amount of capital was required for the attack. But in this case, anyone with little capital could have done it.

Over $1B was stolen in Q1 this year alone. It’s time for the community to work together and respect each other. We hope bug bounty programs can do their part to encourage more whitehats to come to Web3 Bug Bounty instead of discouraging them. As @AshiqAmien put it,

People love paying grey/blackhats fat bounties once their money is held hostage.

Rari’s Fuse is not for Average Joes

Rari has been exploit in multiple occasions. Here’s a list of Rari exploits we’ve gathered.

Omitting some that we think can barely be categorized as exploits.

The oracle manipulation bugs mentioned above, if reported to Rari via responsible disclosure, would have had the same fate. Unless you are a security folk yourself, you are not going “do the diligence”. With over 50 verified Fuse pools, we recommend non-technical users to re-evaluate their accepted level of risks should they continue to use Rari.

Timeline

April 6th — Issue reported to Tribe DAO via ImmuneFi
April 6th — Issue triaged and escalated within 10 minutes
April 7th — Issue resolved by disabling borrowing in the affected pool
April 8th — Issue downgraded to medium with a $10K bounty
April 8th — Mediation requested to ImmuneFi
April 16th — ImmuneFi responded the assessment being appropriate
April 18th — Further comment by us
April 27th — Bounty paid with no response

--

--