Summary
getWstethEthPrice()
returns wstethEthPrice
as 0 when the price difference between chainlinkPrice
and uniswapPrice
is greater than MAX_DIFFERENCE
.
Vulnerability Details
In getWstethEthPrice()
, it returns wstethEthPrice = 0
when LibOracleHelpers.getPercentDifference(chainlinkPrice, uniswapPrice) >= MAX_DIFFERENCE
.
function getWstethEthPrice(uint256 lookback) internal view returns (uint256 wstethEthPrice) {
uint256 chainlinkPrice = lookback == 0 ?
LibChainlinkOracle.getPrice(WSTETH_ETH_CHAINLINK_PRICE_AGGREGATOR, LibChainlinkOracle.FOUR_DAY_TIMEOUT) :
LibChainlinkOracle.getTwap(WSTETH_ETH_CHAINLINK_PRICE_AGGREGATOR, LibChainlinkOracle.FOUR_DAY_TIMEOUT, lookback);
if (chainlinkPrice == 0) return 0;
uint256 stethPerWsteth = IWsteth(C.WSTETH).stEthPerToken();
chainlinkPrice = chainlinkPrice.mul(stethPerWsteth).div(CHAINLINK_DENOMINATOR);
if (lookback > type(uint32).max) return 0;
uint256 uniswapPrice = LibUniswapOracle.getTwap(
lookback == 0 ? LibUniswapOracle.FIFTEEN_MINUTES :
uint32(lookback),
WSTETH_ETH_UNIV3_01_POOL, C.WSTETH, C.WETH, ONE
);
if (uniswapPrice == 0) return 0;
if (LibOracleHelpers.getPercentDifference(chainlinkPrice, uniswapPrice) < MAX_DIFFERENCE) {
wstethEthPrice = chainlinkPrice.add(uniswapPrice).div(AVERAGE_DENOMINATOR);
if (wstethEthPrice > stethPerWsteth) wstethEthPrice = stethPerWsteth;
wstethEthPrice = wstethEthPrice.div(PRECISION_DENOMINATOR);
}
}
But according to the comment, it should return min(stethPerWsteth, chainlinkPrice)
if the difference between chainlinkPrice
and uniswapPrice
is greater than MAX_DIFFERENCE
.
Impact
getWstethEthPrice()
returns 0 wrongly for some cases. It will impact further logic seriously as this function is used to calculate token/usd prices.
Tools Used
Manual Review
Recommendations
getWstethEthPrice()
should be modified like this.
if (LibOracleHelpers.getPercentDifference(chainlinkPrice, uniswapPrice) < MAX_DIFFERENCE) {
wstethEthPrice = chainlinkPrice.add(uniswapPrice).div(AVERAGE_DENOMINATOR);
if (wstethEthPrice > stethPerWsteth) wstethEthPrice = stethPerWsteth;
wstethEthPrice = wstethEthPrice.div(PRECISION_DENOMINATOR);
}
+ else {
+ wstethEthPrice = chainlinkPrice;
+ if (wstethEthPrice > stethPerWsteth) wstethEthPrice = stethPerWsteth;
+ wstethEthPrice = wstethEthPrice.div(PRECISION_DENOMINATOR);
+ }