DeFiHardhat
35,000 USDC
View results
Submission Details
Severity: low
Invalid

Mainnet oracles are incompatible with wstETH causing `getWstethEthPrice` fail regularly

Summary

Mainnet oracles are incompatible with wstETH causing comparison in getWstethEthPrice fail. Chainlink does not have wstETH oracles and using Uniswap LP pairs would be very dangerous given their low liquidity.

Vulnerability Details

ChainlinkAdapterOracle only supports single asset price data. This makes it completely incompatible with wstETH because chainlink doesn't have a wstETH oracle on mainnet, you can use it from Lido. And then this price is compared to the wstETH price got from Uniswap oracles which are highly dangerous given their low liquidity.

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

The comparison between chainlinkPrice and uniswapPrice can mostly fail as wstETH LP of Uniswap have low liquidity and can easily be manipulated. If an attacker targets this, price can easily be manipulated and even DOS is also possible with this.

Also there is no other oracle or alternative used other than comparing with Uniswap price. And there is no else condition in the function too.

Tools Used

Manual Review

Recommendations

Create a special bypass specifically for wstETH utilizing the stETH oracle and it's current exchange rate.

Updates

Lead Judging Commences

giovannidisiena Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

Informational/Invalid

0xbeastboy Submitter
about 1 year ago
giovannidisiena Lead Judge
about 1 year ago
giovannidisiena Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

Informational/Invalid

Support

FAQs

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