codehawks-2023-07-dsc-l02

[L-02] Zero address check for tokens

보고서

Summary

생성자에서 주소 파라미터를 받아 저장할 때, 이 주소가 유효한 지(address(0)가 아닌지) 확인하지 않는다. 실수로 잘못 배포했다면 다시 배포해야 할 것이다.

Keyword

lack of input validation

Vulnerability

생성자에서 토큰과 가격 피드의 주소가 유효한지 확인하지 않는다. 따라서 위와 같이 담보 토큰의 주소를 address(0)로 설정해도 배포에 실패하지 않는다.

또한 코드 상에는 가격 피드의 주소가 address(0)일 때 revert 하는 isAllowedToken modifier는 존재하지만, 토큰의 주소가 address(0)인지 확인하는 modifier는 존재하지 않는다.

    modifier isAllowedToken(address token) {
        if (s_priceFeeds[token] == address(0)) {
            revert DSCEngine__NotAllowedToken();
        }
        _;
    }

Impact

배포가 잘못되면 배포를 새로 해야한다.

Mitigation

생성자에서 address(0)인지 확인한다.

constructor(address[] memory tokenAddresses, address[] memory priceFeedAddresses, address dscAddress) {
    // USD Price Feeds
    if (tokenAddresses.length != priceFeedAddresses.length) {
        revert DSCEngine__TokenAddressesAndPriceFeedAddressesMustBeSameLength();
    }
    // For example ETH / USD, BTC / USD, MKR / USD, etc
    for (uint256 i = 0; i < tokenAddresses.length; i++) {
+       if (tokenAddresses[i] == address(0) || priceFeedAddresses[i] == address(0)) {
+           revert DSCEngine__TokenAddressZero();
+       }
        s_priceFeeds[tokenAddresses[i]] = priceFeedAddresses[i];
        s_collateralTokens.push(tokenAddresses[i]);
    }
    i_dsc = DecentralizedStableCoin(dscAddress);
}

값을 사용할 때도 확인한다.

function getTokenAmountFromUsd(address token, uint256 usdAmountInWei) public view returns (uint256) {
    // price of ETH (token)
    // $/ETH ETH ??
    // $2000 / ETH. $1000 = 0.5 ETH
+   if (token == address(0)) {
+       revert DSCEngine__NotAllowedToken();
+   }
    AggregatorV3Interface priceFeed = AggregatorV3Interface(s_priceFeeds[token]);
    (, int256 price,,,) = priceFeed.staleCheckLatestRoundData();
 
    // ($10e3 * 1e18) / ($2000e8 * 1e10)
    return (usdAmountInWei * PRECISION) / (uint256(price) * ADDITIONAL_FEED_PRECISION);
}
 
function getUsdValue(address token, uint256 amount) public view returns (uint256) {
+   if (token == address(0)) {
+       revert DSCEngine__NotAllowedToken();
+   }
 
    AggregatorV3Interface priceFeed = AggregatorV3Interface(s_priceFeeds[token]);
    (, int256 price,,,) = priceFeed.staleCheckLatestRoundData();
    // 1 ETH = $1000
    // The returned value from CL will be 1000 * 1e8
    return ((uint256(price) * ADDITIONAL_FEED_PRECISION) * amount) / PRECISION;
}

tags: bughunting, codehawks, smart contract, solidity, lack-of-input-validation-vul, severity low