Skip to content

Latest commit

 

History

History
110 lines (87 loc) · 3.82 KB

014.md

File metadata and controls

110 lines (87 loc) · 3.82 KB

Low Tangerine Cod

Medium

Users can buy options for cheap

Summary

_ethVolatility in depositTokens is not being validated and can be set by user input

Root Cause

Whenever option price is being calculated, ethVolatility is being used in formula which can be set to any value by user from input params

    function calculateOptionPrice(
        uint128 _ethPrice,
        uint256 _ethVolatility,
        uint256 _amount,
        StrikePrice _strikePrice
    ) public view returns (uint256) {
-->        uint256 a = _ethVolatility;
   ...
        uint256 b = (cdsVault * 1e2 * OPTION_PRICE_PRECISION) / E;
-->        uint256 baseOptionPrice = ((sqrt(10 * a * ethPrice)) * PRECISION) / OPTION_PRICE_PRECISION + ((3 * PRECISION * OPTION_PRICE_PRECISION) / b); // 1e18 is used to handle division precision

        uint256 optionPrice;
        // Calculate option fees based on strike price chose by user
        if (_strikePrice == StrikePrice.FIVE) {
            // constant has extra 1e3 and volatility have 1e8
            optionPrice = baseOptionPrice + (400 * OPTION_PRICE_PRECISION * baseOptionPrice) / (3 * a);
        } else if (_strikePrice == StrikePrice.TEN) {
            optionPrice = baseOptionPrice + (100 * OPTION_PRICE_PRECISION * baseOptionPrice) / (3 * a);
        } else if (_strikePrice == StrikePrice.FIFTEEN) {
            optionPrice = baseOptionPrice + (50 * OPTION_PRICE_PRECISION * baseOptionPrice) / (3 * a);
        } else if (_strikePrice == StrikePrice.TWENTY) {
            optionPrice = baseOptionPrice + (10 * OPTION_PRICE_PRECISION * baseOptionPrice) / (3 * a);
        } else if (_strikePrice == StrikePrice.TWENTY_FIVE) {
            optionPrice = baseOptionPrice + (5 * OPTION_PRICE_PRECISION * baseOptionPrice) / (3 * a);
        } else {
            revert("Incorrect Strike Price");
        }
        return ((optionPrice * _amount) / PRECISION) / USDA_PRECISION;
    }

Core_logic/Options.sol#L106

   function deposit(
        IBorrowing.BorrowLibDeposit_Params memory libParams,
        IBorrowing.BorrowDepositParams memory params,
        IBorrowing.Interfaces memory interfaces,
        mapping(IBorrowing.AssetName => address assetAddress) storage assetAddress
    ) public returns (uint256) {
...
        // Call calculateOptionPrice in options contract to get options fees
        uint256 optionFees = interfaces.options.calculateOptionPrice(
            libParams.ethPrice,
-->            params.volatility,
            params.depositingAmount,
            params.strikePercent
        );

lib/BorrowLib.sol#L676

    function depositTokens(
        BorrowDepositParams memory depositParam
    ) external payable nonReentrant whenNotPaused(IMultiSign.Functions(0)) {
..
        totalNormalizedAmount = BorrowLib.deposit(
            BorrowLibDeposit_Params(
                LTV,
                APR,
                lastCumulativeRate,
                totalNormalizedAmount,
                exchangeRate,
                ethPrice,
                lastEthprice
            ),
-->            depositParam,
            Interfaces(treasury, globalVariables, usda, abond, cds, options),
            assetAddress
        );

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

Calculate volatility from the formula above, so option price will be lowest and pass with input params

Impact

Users can buy options for less than they suppose it, thus protocol will receive less funds than suppose.

PoC

No response

Mitigation

Somehow validate it, make it local param, which updated by admin or bots.