First Flight #21: KittyFi

First Flight #21
Beginner FriendlyDeFiFoundry
100 EXP
View results
Submission Details
Severity: medium
Valid

KittyVault NOT checking For Stale Prices

Summary

the KittyVault.sol smart contract doesn’t check whether that price data sent by chainlink pricefeeds is stale.

Vulnerability Details

If Chainlink pricefeed returns pricing data that is stale,KittyVault::getTotalMeowllateralInAave and KittyVault::getUserVaultMeowllateralInEuros will execute with prices that don’t reflect the current pricing of the asset, and this result in a potential loss of funds for the user and/or the protocol.

Impact

  • Loss of funds for the protocol if a wrong high price is used to check for the assets pricing as this may lead to not liquidating users that may be liquidatable

  • Loss of funds for protocol users is wrong low price is used in KittyVault::getUserVaultMeowllateralInEuros

Tools Used

  • manual review

  • chainlink documentation

Recommendations

check the updatedAt parameter returned from latestRoundData() and compare it to a staleness threshold(heartbeat) specified in the chainlink docs.
e.g for BTC/USD, the heartbeat is 3600s i.e.1 hour, hence do the check like this...

function getUserVaultMeowllateralInEuros(address _user) external view returns (uint256) {
- (, int256 collateralToUsdPrice, , , ) = i_priceFeed.latestRoundData();
+ (, int256 collateralToUsdPrice, ,uint256 updatedAt , ) = i_priceFeed.latestRoundData();
+ if (updatedAt < block.timestamp - 3600) {
+ revert("stale price feed");
+ }
(, int256 euroPriceFeedAns, , ,) = i_euroPriceFeed.latestRoundData();
uint256 collateralAns = getUserMeowllateral(_user).mulDiv(uint256(collateralToUsdPrice) * EXTRA_DECIMALS, PRECISION);
return collateralAns.mulDiv(uint256(euroPriceFeedAns) * EXTRA_DECIMALS, PRECISION);
}
function getTotalMeowllateralInAave() public view returns (uint256) {
(uint256 totalCollateralBase, , , , , ) = i_aavePool.getUserAccountData(address(this));
- (, int256 collateralToUsdPrice, , , ) = i_priceFeed.latestRoundData();
+ (, int256 collateralToUsdPrice, ,uint256 updatedAt , ) = i_priceFeed.latestRoundData();
+ if (updatedAt < block.timestamp - 3600) {
+ revert("stale price feed");
+ }
return totalCollateralBase.mulDiv(PRECISION, uint256(collateralToUsdPrice) * EXTRA_DECIMALS);
}
Updates

Lead Judging Commences

shikhar229169 Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Stale Price from Chainlink Datafeed

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.