DeFiHardhat
35,000 USDC
View results
Submission Details
Severity: medium
Valid

`LibWstethEthOracle.getWstethEthPrice()` is missing a case during the price calculation.

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);
// Check if the chainlink price is broken or frozen.
if (chainlinkPrice == 0) return 0;
uint256 stethPerWsteth = IWsteth(C.WSTETH).stEthPerToken();
chainlinkPrice = chainlinkPrice.mul(stethPerWsteth).div(CHAINLINK_DENOMINATOR);
// Uniswap V3 only supports a uint32 lookback.
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
);
// Check if the uniswapPrice oracle fails.
if (uniswapPrice == 0) return 0;
if (LibOracleHelpers.getPercentDifference(chainlinkPrice, uniswapPrice) < MAX_DIFFERENCE) { //@audit missing other case
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);
+ }
Updates

Lead Judging Commences

giovannidisiena Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

wstETH:ETH price max difference

Support

FAQs

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