Skip to content
This repository has been archived by the owner on Nov 26, 2023. It is now read-only.

VAD37 - Exploitation of getSupplyProportion(): Using Uniswap Flashloan to force USSDRebalancer.sol Pool/Collateral Swap and Subsequent Fund Thefts #733

Closed
sherlock-admin opened this issue May 24, 2023 · 0 comments
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label High A valid High severity issue Reward A payout will be made for this issue

Comments

@sherlock-admin
Copy link
Contributor

sherlock-admin commented May 24, 2023

VAD37

high

Exploitation of getSupplyProportion(): Using Uniswap Flashloan to force USSDRebalancer.sol Pool/Collateral Swap and Subsequent Fund Thefts

Summary

The getSupplyProportion() function, using the balanceOf() function, is designed to maintain the balance of the USSD/DAI pool in order to stabilize the USSD value at $1.

However, this balance can be manipulated, particularly through UniswapPool flashloan, which facilitates the alteration of the balanceOf() value of both USSD and DAI in the pool. This then tricks the USSDRebalancer.rebalance() function into swapping half the total pool value.

Even without the mintRebalancer() exploit, this creates two potential profitable attack routes:

  1. Minting New USSD: This involves generating new USSD tokens for pool rebalancing. As USSD prices remain stable, USSDRebalancer sells large quantities of DAI to acquire USSD, disrupting the pegged price and allowing exploiters to purchase USSD at a reduced price. They can then call for pool rebalancing again to sell USSD in exchange for DAI.
  2. Selling Collateral: Large-scale collateral swapping makes profitable arbitrage possible due to the absence of slippage check in the USSD.sol swap function.

Vulnerability Detail

The Uniswap flash() function hands out pool tokens to users without modifying the pool token price or updating any data. Despite having a lock modifier, this does not inhibit swap() from executing. Code

The getSupplyProportion() function can be easily manipulated by an exploiter taking a flashloan and withdrawing all of one token type (USSD/DAI) from the Uniswap pool. This ensures that the USSDamount or DAIamount drops to a third of its original value, tricking the rebalancer into believing the difference between USSD and DAI is two-thirds of the initial pool value and causing it to swap a third of the pool token value for rebalancing.

This manipulation sets the rebalancer into a buy or sell mode involving a third of the pool token, following the formula |USSDamount - DAIamount| / 2.

File: src\USSDRebalancer.sol
094:       (uint256 USSDamount, uint256 DAIamount) = getSupplyProportion(); //@audit USSDamount or DAIamount can be 0
095:       if (ownval < 1e6 - threshold) {//999977 for DAI/USDC
096:         // peg-down recovery
097:         BuyUSSDSellCollateral((USSDamount - DAIamount / 1e12)/2);
098:       } else if (ownval > 1e6 + threshold) {
099:         // mint and buy collateral
100:         // never sell too much USSD for DAI so it 'overshoots' (becomes more in quantity than DAI on the pool)
101:         // otherwise could be arbitraged through mint/redeem
102:         // the execution difference due to fee should be taken into accounting too
103:         // take 1% safety margin (estimated as 2 x 0.5% fee)
104:         IUSSD(USSD).mintRebalancer(((DAIamount / 1e12 - USSDamount)/2) * 99 / 100); // mint ourselves amount till balance recover
105:         SellUSSDBuyCollateral();
106:       }

There are two possible exploits:

  1. Direct Buying of Cheap USSD or DAI: As the USSD/DAI pool has a UniswapV3 seed pool position set from tick -880000 -> 880000 in the test file, the USSD/DAI price can range from 0.00000001 to infinity. When a third of the pool swaps, exploiters can buy back tokens cheaply due to a 20% price drop or rise along the Uniswap price curve, and then call rebalance() again to sell the token back to the pool at the $1 price.

  2. Collateral Selling Arbitrage: Due to the absence of slippage check in the USSD.sol swap function, and the selling of all collateral by USSDRebalancer.sol to cover the difference between USSD and DAI. A discrepancy arises between the fixed Chainlink oracle price and the Uniswap liquidity price. Rebalancer will sell collateral at chainlink price hope that uniswap have the same price. Exploiters can then make a profit by swapping sufficient ETH/BTC tokens before rebalancing to force a loss for USSDRebalancer.sol when swapping collateral, and then selling back the ETH/BTC.

Impact

using token.balanceOf() allow exploiter to manipulate the price of USSD and DAI on uniswap pool.
Allowing exploiter to steal pool fund through arbitrage/fronrun

Code Snippet

https://github.com/sherlock-audit/2023-05-USSD/blob/main/ussd-contracts/contracts/USSDRebalancer.sol#L84-L85
https://github.com/Uniswap/v3-core/blob/6562c52e8f75f0c10f9deaf44861847585fc8129/contracts/UniswapV3Pool.sol#L822-L867

Tool used

Manual Review

Recommendation

Even if token.balanceOf() is avoided, it is still possible to steal funds from the pool through other Uniswap mechanisms, such as the tick Position.

The only way to prevent on-chain theft from Uniswap is to ensure that no user can mint tokens out of thin air or have direct access to the swap function. We recommend turning the rebalance() function into an admin/guardian function.

Duplicate of #808

@github-actions github-actions bot closed this as completed Jun 5, 2023
@github-actions github-actions bot added High A valid High severity issue Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label labels Jun 5, 2023
@sherlock-admin sherlock-admin added the Reward A payout will be made for this issue label Jun 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label High A valid High severity issue Reward A payout will be made for this issue
Projects
None yet
Development

No branches or pull requests

1 participant