Description:
On the KittyVault.sol
in both the getUserVaultMeowllateralInEuros()
and getTotalMeowllateralInAave()
we are using the latestRoundData()
, but there is no check if the return value indicates stale data.
function getUserVaultMeowllateralInEuros(address _user) external view returns (uint256) {
@> (, int256 collateralToUsdPrice, , , ) = i_priceFeed.latestRoundData();
@> (, 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();
return totalCollateralBase.mulDiv(PRECISION, uint256(collateralToUsdPrice) * EXTRA_DECIMALS);
}
Impact:
This could lead to stale prices which means that prices would be executed that don't reflect the current pricing resulting in a potential loss of funds for the user and/or the protocol
Tools Used:
Manual Review.
Recommended Mitigation:
The updatedAt
parameter should be returned from latestRoundData()
and compare it to a staleness threshold.
function getUserVaultMeowllateralInEuros(address _user) external view returns (uint256) {
- (, int256 collateralToUsdPrice, , , ) = i_priceFeed.latestRoundData();
+ (, int256 collateralToUsdPrice, , uint256 updatedAt,) = i_priceFeed.latestRoundData();
- (, int256 euroPriceFeedAns, , ,) = i_euroPriceFeed.latestRoundData();
+ (, int256 euroPriceFeedAns, , uint256 updatedAt,) = i_euroPriceFeed.latestRoundData();
+ if (updatedAt < block.timestamp - 60 * 60 ) {
+ revert("stale price feed");
+ }
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 - 60 * 60 ) {
+ revert("stale price feed");
+ }
return totalCollateralBase.mulDiv(PRECISION, uint256(collateralToUsdPrice) * EXTRA_DECIMALS);
}