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

Missing else condition in `getWstethEthPrice` function

Summary

The LibWstethEthOracle:getWstethEthPrice function computes the current price of wstETH (Wrapped stETH) relative to ETH (Ethereum) by utilizing multiple data sources, including the Chainlink Oracle and Uniswap V3. It calculates the price in three ways: by multiplying the wstETH:stETH redemption rate with the stETH:ETH price obtained from Chainlink, by fetching the price directly from the wstETH:ETH Uniswap Pool, and by considering the stETH redemption rate alone. The function then computes a final price by taking the minimum of the last method and either the average or the Chainlink-based price if their difference falls within a predefined threshold.

In the getWstethEthPrice function, there is no else condition at the end of the if statement block. This means that if the condition within the if statement (LibOracleHelpers.getPercentDifference(chainlinkPrice, uniswapPrice) < MAX_DIFFERENCE) evaluates to false, the function will exit without returning a value.

Vulnerability Details

See the following code:

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) {
wstethEthPrice = chainlinkPrice.add(uniswapPrice).div(AVERAGE_DENOMINATOR);
if (wstethEthPrice > stethPerWsteth) wstethEthPrice = stethPerWsteth;
wstethEthPrice = wstethEthPrice.div(PRECISION_DENOMINATOR);
}
}

Impact

Without an else condition, the function may terminate abruptly without providing any meaningful output if the condition in the if statement is not met. This can lead to unpredictable behavior, making it difficult to determine why the function failed to produce a result. Incomplete or unexpected function execution paths can introduce bugs into the codebase, making it harder to maintain and debug the application. Developers may have difficulty understanding the intended behavior of the function without clear error handling or fallback mechanisms.

Tools Used

Manual Review

Recommendations

To address this issue, we need to ensure that the function always returns a value, even if the condition within the if statement evaluates to false. By adding an else condition, we ensure that the function always returns a value, even if the condition in the if statement is not met. This enhances the reliability and predictability of the codebase, making it easier to understand and maintain.

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.