sherlock-audit / 2023-12-dodo-gsp-judging

6 stars 5 forks source link

Bandit - `adjustPrice` Can by Sandwiched For Profit #79

Closed sherlock-admin2 closed 6 months ago

sherlock-admin2 commented 6 months ago

Bandit

medium

adjustPrice Can by Sandwiched For Profit

Summary

adjustPrice can be sandwiched buy manipulating the price, letting the adjustment go through and then selling into extra liquidity.

Vulnerability Detail

When an action that the underlying liquidity, it can be sandwiched in a way that profits off the underlying liquidity providers. The most well known example is a liquidity deposit:

  1. push price up
  2. liquidity deposit
  3. sell into liquidity deposit

The oracle price change can also be conceptualised as a liquidity change event.It is a "change in the curve which determines liquidity concentration", which essentially increases liquidity in certain prices and decreases liquidity between certain prices. So the same liquidity sandwiching attack can occur on the underlying pool.

For example, if the price change increases the liquidity around the current price point, this has the same effect as "depositing liquidity" in the above attack.

Let's say the scenario is that the price of a stablecoin pair is around an exchange rate of 1 which and _I_ is also 1 but one stablecoin depegs such that exchange rate is 1.2 and then the maintainer wants to adjustPrice to match the new exchange rate.

Since the liquidity is not concentrated around 1.2 before adjustPrice, it a relatively small token buy can manipulate the price significantly. Before the liquidity is shifted, then the user can make a market buy, then let the price adjustment go through and then market sell through the extra liquidity which is concentrated around the price.

Step by step:

  1. buy BASE Token (on average the attacker overpays)
  2. adjustPrice is called which increases the liquidity between the new price and old price. Note that when I is updated to be closer to the reserve price, it concentrates the liquidity around the new price. This is essentially analagous to depositing liquidity around the reserve price and removing it from other areas of the price curve. This can be visualized using Dodex simulator: https://simulator.dodoex.io/
  3. sell BASE token (on average the liquidity providers overpay). The sell is through the extra liquidity caused by the change in I and therefore the price impact is lower than the buy action. If the price impact is lower than the "average selling price" is higher than the "average buying price" resulting in a profit

Impact

adjustPrice can be sandwiched by attacker to profit off liquidity providers.

Code Snippet

https://github.com/sherlock-audit/2023-12-dodo-gsp/blob/main/dodo-gassaving-pool/contracts/GasSavingPool/impl/GSPVault.sol#L169-L174

Tool used

Manual Review

Recommendation

Normal slippage limits would not work for oracle price changes like they would for liquidity deposits, as there is no minAmount to check for. Instead, there are two possible solutions:

  1. If adjustedPrice was called in the same block, calls to sellBaseToken and sellQuoteToken revert. This prevents an attacker from performing the sandwich in a single block and thus if they wish to do the attack, it opens them up to be arbitraged. It is infeasible due to the likelihood they simply lose $ to arbitrage. This causes very little inconvenience to users as price adjustments are rare and swaps are only stopped for a single block.
  2. If the price significantly deviates from the TWAP, the adjustPrice call reverts. This is similar to slippage parameters in that significant deviations cause reversion. The downside of this solution is that it could mean that adjustedPrice doesn't always succeed and cannot be called after extreme price movements.

Duplicate of #40