You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
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
sherlock-admin opened this issue
May 24, 2023
· 0 comments
Labels
DuplicateA valid issue that is a duplicate of an issue with `Has Duplicates` labelHighA valid High severity issueRewardA payout will be made for this issue
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:
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.
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.sol094: (uint256USSDamount,uint256DAIamount)=getSupplyProportion();//@audit USSDamount or DAIamount can be 0095: if(ownval<1e6-threshold){//999977 for DAI/USDC096: // peg-down recovery097: BuyUSSDSellCollateral((USSDamount-DAIamount/1e12)/2);098: }elseif(ownval>1e6+threshold){099: // mint and buy collateral100: // 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/redeem102: // the execution difference due to fee should be taken into accounting too103: // 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 recover105: SellUSSDBuyCollateral();106: }
There are two possible exploits:
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.
Collateral Selling Arbitrage: Due to the absence of slippage check in the USSD.solswap 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
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.
Sign up for freeto subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
DuplicateA valid issue that is a duplicate of an issue with `Has Duplicates` labelHighA valid High severity issueRewardA payout will be made for this issue
VAD37
high
Exploitation of
getSupplyProportion()
: Using Uniswap Flashloan to forceUSSDRebalancer.sol
Pool/Collateral Swap and Subsequent Fund TheftsSummary
The
getSupplyProportion()
function, using thebalanceOf()
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 theUSSDRebalancer.rebalance()
function into swapping half the total pool value.Even without the
mintRebalancer()
exploit, this creates two potential profitable attack routes: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.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 alock
modifier, this does not inhibitswap()
from executing. CodeThe
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 theUSSDamount
orDAIamount
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
.There are two possible exploits:
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 callrebalance()
again to sell the token back to the pool at the $1 price.Collateral Selling Arbitrage: Due to the absence of slippage check in the
USSD.sol
swap function, and the selling of all collateral byUSSDRebalancer.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 forUSSDRebalancer.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
The text was updated successfully, but these errors were encountered: