Lucene search

K
code423n4Code4renaCODE423N4:2022-10-INVERSE-FINDINGS-ISSUES-550
HistoryOct 30, 2022 - 12:00 a.m.

Consideration of tokens with decimals higher than 18

2022-10-3000:00:00
Code4rena
github.com
2

Lines of code
<https://github.com/code-423n4/2022-10-inverse/blob/3e81f0f5908ea99b36e6ab72f13488bbfe622183/src/Oracle.sol#L112-L144&gt;

Vulnerability details

Impact

Oracle contract has 2 functions - viewPrice & getPrice - to get the price through the Chainlink price feed in DOLA. Both functions check the decimals of the feedDecimals answer by calling feed.decimals() and calculate the price by 36 - feedDecimals - tokenDecimals;. DOLA has 18 decimals, hence it can be seen that the feedDecimals is considered not to be higher than 18. If any tokens with decimals higher than 18 are decided to be added to the system and accepted as collateral tokens, both viewPrice & getPrice functions will revert.

Proof of Concept

For viewPrice;

    function viewPrice(address token, uint collateralFactorBps) external view returns (uint) {
        if(fixedPrices[token] &gt; 0) return fixedPrices[token];
        if(feeds[token].feed != IChainlinkFeed(address(0))) {
            // get price from feed
            uint price = feeds[token].feed.latestAnswer();
            require(price &gt; 0, "Invalid feed price");
            // normalize price
            uint8 feedDecimals = feeds[token].feed.decimals();
            uint8 tokenDecimals = feeds[token].tokenDecimals;
            uint8 decimals = 36 - feedDecimals - tokenDecimals; // @audit-info - The function would revert when feedDecimals GT 18
            uint normalizedPrice = price * (10 ** decimals);
            uint day = block.timestamp / 1 days;
            // get today's low
            uint todaysLow = dailyLows[token][day];
            // get yesterday's low
            uint yesterdaysLow = dailyLows[token][day - 1];
            // calculate new borrowing power based on collateral factor
            uint newBorrowingPower = normalizedPrice * collateralFactorBps / 10000;
            uint twoDayLow = todaysLow &gt; yesterdaysLow && yesterdaysLow &gt; 0 ? yesterdaysLow : todaysLow;
            if(twoDayLow &gt; 0 && newBorrowingPower &gt; twoDayLow) {
                uint dampenedPrice = twoDayLow * 10000 / collateralFactorBps;
                return dampenedPrice &lt; normalizedPrice ? dampenedPrice: normalizedPrice;
            }
            return normalizedPrice;


        }
        revert("Price not found");
    }

Permalink-1

For getPrice;

    function getPrice(address token, uint collateralFactorBps) external returns (uint) {
        if(fixedPrices[token] &gt; 0) return fixedPrices[token];
        if(feeds[token].feed != IChainlinkFeed(address(0))) {
            // get price from feed
            uint price = feeds[token].feed.latestAnswer();
            require(price &gt; 0, "Invalid feed price");
            // normalize price
            uint8 feedDecimals = feeds[token].feed.decimals();
            uint8 tokenDecimals = feeds[token].tokenDecimals;
            uint8 decimals = 36 - feedDecimals - tokenDecimals; // @audit-info - The function would revert when feedDecimals GT 18
            uint normalizedPrice = price * (10 ** decimals);
            // potentially store price as today's low
            uint day = block.timestamp / 1 days;
            uint todaysLow = dailyLows[token][day];
            if(todaysLow == 0 || normalizedPrice &lt; todaysLow) {
                dailyLows[token][day] = normalizedPrice;
                todaysLow = normalizedPrice;
                emit RecordDailyLow(token, normalizedPrice);
            }
            // get yesterday's low
            uint yesterdaysLow = dailyLows[token][day - 1];
            // calculate new borrowing power based on collateral factor
            uint newBorrowingPower = normalizedPrice * collateralFactorBps / 10000;
            uint twoDayLow = todaysLow &gt; yesterdaysLow && yesterdaysLow &gt; 0 ? yesterdaysLow : todaysLow;
            if(twoDayLow &gt; 0 && newBorrowingPower &gt; twoDayLow) {
                uint dampenedPrice = twoDayLow * 10000 / collateralFactorBps;
                return dampenedPrice &lt; normalizedPrice ? dampenedPrice: normalizedPrice;
            }
            return normalizedPrice;


        }
        revert("Price not found");
    }

Permalink-2

Tools Used

Manual Review

Recommended Mitigation Steps

The team can consider this point if any tokens having more than 18 decimals is decided to be added.


The text was updated successfully, but these errors were encountered:

All reactions