Lucene search

K
code423n4Code4renaCODE423N4:2021-11-MALT-FINDINGS-ISSUES-342
HistoryDec 01, 2021 - 12:00 a.m.

RewardReinvestor.provideReinvest and splitReinvest are vulnerable to sandwich attacks as market price isn't checked

2021-12-0100:00:00
Code4rena
github.com
5

Handle

hyh

Vulnerability details

Impact

Liquidity provision can happen at a manipulated price which leads to immediate loss for liquidity provider (i.e. IL happens right after liquidity provision in this case).

This yields direct loss for an LP account owner, for example (schematically):
0. Suppose tokens A and B has equal value, i.e. market is 1:1 token A:B

  1. Attacker swaps A for B to manipulate it to be 1.5:1, say sides are 150 A and 100 B tokens
  2. LP enters with 150/9 A, 100/9 B, owning 10% of the pool as a result
  3. Attacker swaps back (with profit before fees as after LP entered more funds is needed to move the pool), the pool is back to be around 1:1
  4. If LP leaves now, this will yield (100+x)/10 A, (100+x)/10 B payout, which will be cumulatively less number of equally valued A and B tokens than was deposited in (2)
  5. Attacker has profited at the expense of IL loss induced on LP

Proof of Concept

addLiquidity is called by RewardReinvestorโ€™s provideReinvest and splitReinvest functions:
<https://github.com/code-423n4/2021-11-malt/blob/main/src/contracts/RewardReinvestor.sol#L62&gt;
<https://github.com/code-423n4/2021-11-malt/blob/main/src/contracts/RewardReinvestor.sol#L78&gt;

RewardReinvestor, provideReinvest -> _bondAccount -> dexHandler.addLiquidity

addLiquidity doesnโ€™t check for implied market price at which liquidity provision happens:
<https://github.com/code-423n4/2021-11-malt/blob/main/src/contracts/DexHandlers/UniswapHandler.sol#L206&gt;

Recommended Mitigation Steps

The issue here is the absence of external source check for price verification, which can be front run not only in direct market operation, but in liquidity provision case as well.

When addLiquidity is called by provideReinvest and splitReinvest functions, in both variants the liquidity calculation is exact and the problem is that the whole reinvest transaction can be sandwiched.

This way any slippage tolerance level within addLiquidity will not help, as the manipulation will happen before the amounts needed are calculated.

That is, an attacker will move the pool, then either getOptimalLiquidity (in provideReinvest) or direct reward token selling (in splitReinvest) will be carried out at a manipulated price and liquidity provision within the same transaction with 0 slippage will still happen at manipulated price.

The solution here is to check Oracle average price estimation versus price level the liquidity provision happens at and revert if the two are too far apart. The simplest way in the current implementation is to use MaltDataLab for reward token average price and require effective price during the liquidity provision to be within some predefined threshold from the recorded average price.


The text was updated successfully, but these errors were encountered:

All reactions