Summary
Inside library LibEvaluate, In the function evalPrice(). beanUsdPrice
is being calculated wrongly
beanUsdPrice = 1e30 / ((usd/tkn)*(bean/tkn))
Vulnerability Details
function evalPrice(int256 deltaB, address well) internal view returns (uint256 caseId) {
AppStorage storage s = LibAppStorage.diamondStorage();
if (deltaB > 0) {
uint256 beanTknPrice = LibWell.getBeanTokenPriceFromTwaReserves(well);
if (beanTknPrice > 1) {
> uint256 beanUsdPrice = uint256(1e30).div(
> LibWell.getUsdTokenPriceForWell(well)
> .mul(beanTknPrice)
);
if (beanUsdPrice > s.sys.seedGaugeSettings.excessivePriceThreshold) {
return caseId = 6;
}
}
caseId = 3;
}
}
Here LibWell.getUsdTokenPriceForWell(well)
returns value in terms of usd/tkn price.
function getUsdTokenPriceForWell(address well) internal view returns (uint tokenUsd) {
> tokenUsd = LibAppStorage.diamondStorage().sys.usdTokenPrice[well];
}
and LibWell.getBeanTokenPriceFromTwaReserves(well)
return value in terms of bean/tkn price.
function getBeanTokenPriceFromTwaReserves(address well) internal view returns (uint256 price) {
AppStorage storage s = LibAppStorage.diamondStorage();
if (s.sys.twaReserves[well].reserve0 == 0 || s.sys.twaReserves[well].reserve1 == 0) {
price = 0;
} else {
if (getBeanIndexFromWell(well) == 0) {
> price = uint256(s.sys.twaReserves[well].reserve0).mul(1e18).div(
s.sys.twaReserves[well].reserve1
);
} else {
price = uint256(s.sys.twaReserves[well].reserve1).mul(1e18).div(
s.sys.twaReserves[well].reserve0
);
}
}
}
Combining above beanUsdPrice
will be wrongly calculated in the form of 1e30 / ((usd/tkn)*(bean/tkn)) .
Impact
Wrong calculation of caseId which could result error in the evaluation of beanstalk causing wrong updation of temperature, BeanToMaxLPRatio, incorrect handling of rain and issuing wrong soil.
Tools Used
Manual review
Recommendations
- uint256 beanUsdPrice = uint256(1e30).div(
- LibWell.getUsdTokenPriceForWell(well).mul(beanTknPrice)
- );
+ uint256 beanUsdPrice = beanTknPrice.mul(1e18)
+ .div(LibWell.getUsdTokenPriceForWell(well)
+ );