Return to site
Return to site

Bug Deep Dive #16

All taker collateral and collected fees can be stolen by re-entering via RFTLib.settle to manipulate uniswap spot price - $4432

· Bug Deep Dive
Section image

When any user adds maker liquidity (via newMaker or adjustMaker), the amounts of token0 and token1 required from the user are calculated in the data.xBalance and data.yBalance, however the actual amounts spent to mint the required liquidity are never checked, the contract simply sends whatever amounts of both tokens are given by the uniswap pool in the mint callback. When the funds are settled for the maker liquidity change, the following functions are called:

Section image

This allows the user to manipulate the uniswap pool spot price to a different value via the RFTLib callback. PoolWalker.settle will then proceed to mint the required liquidity, but will use amounts of token0 and token1 different from the ones calculated and received from the user. Moreover, the total value of these tokens will always be higher than the value of tokens received from the user. When user manipulates the price back to initial value, he will have profit from this manipulation, stealing token0 and/or token1 from the contract.

As the contract uses Diamond proxy, this contract holds all token balances at the same address which is used to mint uniswap liquidity. In particular, the following funds are under risk:

  • All Takers collateral
  • All fees collected from the uniswap pool

Alpha: note how this is only possible because there is a central entity holding all the funds (diamond), always make sure to thing the attack through. Always make sure to check if changing pool spot price can lead to more funds for the attacker.

Weaponizing it

Note: a0 is used for amount of token0, a1 for amount of token1
1. Current price = 100;
2. Takers have a total collateral of 100 a0 and 10000 a1 (these are contract balances);
3. There is liquidity of 1 in the range [100;10000];
4. Attacker adds 111 maker liquidity in the range [100;10000], paying 10 a0;
5. In the RFTLib.settle attacker manipulates the price to 10000:
5.1. Attacker pays a1: -90;
5.2. Attacker receives a0: +0.09;
6. Attacker returns from the RFTLib callback, 111 liquidity is minted to Amplify, taking 10000 a1 from it;
7. Attacker manipulates the price back to 100:
6.1. Attacker pays a0: -10;
6.2. Attacker receives a1: +10000;
8. Attacker waits for jit penalty time to pass and withdraws his 111 maker liquidity, receiving 10 a0;

Contract balances:
• before: 100 a0 + 10000 a1 = $20000
• after: 110 a0 + 0 a1 = $11000

Attacker balances:
• a0: -10 + 0.09 - 10 + 10 = -9.91 [- $991]
• a1: -90 + 10000 = +9910 [+ $9910]
• uniswap manipulation fees (0.3%): (90 + 10000) * 0.003 = -30
Total : 9910 - 991 - 30 = +$8889

Conclusion

This finding would earn you $4432, and is quite elaborate, always make sure that it is safe to fetch the current reserves / spot price of an integrated Uniswap pool.

Full Report
Codebase

Subscribe
Previous
Bug Deep Dive #15
Next
 Return to site
Cookie Use
We use cookies to improve browsing experience, security, and data collection. By accepting, you agree to the use of cookies for advertising and analytics. You can change your cookie settings at any time. Learn More
Accept all
Settings
Decline All
Cookie Settings
Necessary Cookies
These cookies enable core functionality such as security, network management, and accessibility. These cookies can’t be switched off.
Analytics Cookies
These cookies help us better understand how visitors interact with our website and help us discover errors.
Preferences Cookies
These cookies allow the website to remember choices you've made to provide enhanced functionality and personalization.
Save