sherlock-audit / 2023-05-USSD-judging

9 stars 7 forks source link

whiteh4t9527 - rebalance() could be manipulated by flash loan #959

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

whiteh4t9527

high

rebalance() could be manipulated by flash loan

Summary

The rebalance() function is based on getSupplyProportion() which uses the token0 and token1 balances of uniPool. However, the balances could be easily manipulated by flash loan.

Vulnerability Detail

The uniPool.flash() function allows users to loan an arbitrary amount of token0/token1 out, which is a built-in feature of UniswapV3Pool. If the bad actor invokes rebalance() inside the flash loan callback, the USSDamount and DAIamount could be manipulated. Therefore, the rebalance()ed result would not be the expected result. Bad actors can actually buy/sell any amount of USSD.

Impact

Since the buying/selling operations of the USSDRebalancer could be manipulated, bad actors could make profit from arbitrage.

Code Snippet

    function getSupplyProportion() public view returns (uint256, uint256) {
      uint256 vol1 = IERC20Upgradeable(uniPool.token0()).balanceOf(address(uniPool));
      uint256 vol2 = IERC20Upgradeable(uniPool.token1()).balanceOf(address(uniPool));
      if (uniPool.token0() == USSD) {
        return (vol1, vol2);
      }
      return (vol2, vol1);
    }

    function rebalance() override public {
      uint256 ownval = getOwnValuation();
      (uint256 USSDamount, uint256 DAIamount) = getSupplyProportion();
      if (ownval < 1e6 - threshold) {
        // peg-down recovery
        BuyUSSDSellCollateral((USSDamount - DAIamount / 1e12)/2);
      } else if (ownval > 1e6 + threshold) {
        // mint and buy collateral
        // never sell too much USSD for DAI so it 'overshoots' (becomes more in quantity than DAI on the pool)
        // otherwise could be arbitraged through mint/redeem
        // the execution difference due to fee should be taken into accounting too
        // take 1% safety margin (estimated as 2 x 0.5% fee)
        IUSSD(USSD).mintRebalancer(((DAIamount / 1e12 - USSDamount)/2) * 99 / 100); // mint ourselves amount till balance recover
        SellUSSDBuyCollateral();
      }
    }

Tool used

Manual Review

Recommendation

Don't use the balances which could be easily manipulated.