sherlock-audit / 2022-11-float-capital-judging

2 stars 1 forks source link

neila - Caused DoS by division 0 as a denominator #35

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

neila

medium

Caused DoS by division 0 as a denominator

Summary

Caused DoS by division 0 as a denominator Found by: @Tomosuke0930

Vulnerability Detail

In the _getValueChangeAndFunding(), the value of pools[PoolType.FLOAT][0].value is used as a denominator.

In solidity, if you divide with 0 as the denominator, the transaction returns revert.

This value is a value to show the liquidity of the float pool and this value is updated after _getValueChangeAndFunding is called.

Therefore, when the pools[PoolType.FLOAT][0].value is 0, the updateSystemStateUsingValidatedOracleRoundIds() can return revert and this function can’t execute because there is no way to update the pools[PoolType.FLOAT][0].value

Impact

Protocol teams need to deploy the new MarketCore.sol again to solve this issue.

Code Snippet

function _getValueChangeAndFunding(
    uint256 effectiveValueLong,
    uint256 effectiveValueShort,
    int256 previousPrice,
    int256 currentPrice
  ) internal view returns (int256 floatPoolLeverage, ValueChangeAndFunding memory params) {

    uint256 floatPoolLiquidity = pools[PoolType.FLOAT][0].value;
        /* ~~~ */
    floatPoolLeverage = (int256(effectiveValueShort) - int256(effectiveValueLong)).div(int256(floatPoolLiquidity));
function _rebalancePoolsAndExecuteBatchedActions(
    uint32 epochIndex,
    uint128[2] memory totalEffectiveLiquidityPoolType,
    int256 floatPoolLeverage,
    ValueChangeAndFunding memory params
  ) internal returns(/* ... */) {
  /* ~~~ */
  pools[PoolType(poolType)][poolTier].value = uint256(poolValue);
  /* ~~~ */
}
function updateSystemStateUsingValidatedOracleRoundIds(uint80[] memory oracleRoundIdsToExecute) external checkMarketNotDeprecated {
      /* ~~~ */
    for (uint256 i = 0; i < numberOfEpochsToExecute; ) {
      /* ~~~ */
      (int256 floatPoolLeverage, ValueChangeAndFunding memory rebalanceParams) = _getValueChangeAndFunding(
        totalEffectiveLiquidityPoolType[LONG_TYPE],
        totalEffectiveLiquidityPoolType[SHORT_TYPE],
        // this is the previous execution price, not the previous oracle update price
        previousPrice,
        epochPrices[I]
      );

      /* ~~~ */
      (totalEffectiveLiquidityPoolType, poolStates) = _rebalancePoolsAndExecuteBatchedActions(
        latestExecutedEpochIndex + uint32(++i),
        totalEffectiveLiquidityPoolType,
        floatPoolLeverage,
        rebalanceParams
      );

      /* ~~~ */
  }

Tool used

Manual Review

Recommendation

Set the initial value of pools[PoolType.FLOAT][0].value to a non-zero value like UniswapV2#mint

uint public constant MINIMUM_LIQUIDITY = 10**3;

function mint(address to) external lock returns (uint liquidity) {
         /* ~~~ */
    if (_totalSupply == 0) {
          liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
         _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
      }
         /* ~~~ */
}

Duplicate of #8