DeFiHardhatFoundry
250,000 USDC
View results
Submission Details
Severity: high
Valid

LibUsdOracle returns incorrect price from Chainlink

Summary

Protocol widely assumes that price from oracle adapters has 1e6 precission. However it will return incorrect price when configured oracle for token is Chainlink price Price feed because it for some reason divides 1e24 by correct price.

Vulnerability Details

For some reason it returns 1e24 / chainlinkPrice instead of chainlinkPrice:

function getTokenPriceFromExternal(
address token,
uint256 lookback
) internal view returns (uint256 tokenPrice) {
....
if (oracleImpl.encodeType == bytes1(0x01)) {
// if the address in the oracle implementation is 0, use the chainlink registry to lookup address
address chainlinkOraclePriceAddress = oracleImpl.target;
if (chainlinkOraclePriceAddress == address(0)) {
// use the chainlink registry
chainlinkOraclePriceAddress = ChainlinkPriceFeedRegistry(chainlinkRegistry).getFeed(
token,
0x0000000000000000000000000000000000000348
); // 0x0348 is the address for USD
}
return
@> uint256(1e24).div(
LibChainlinkOracle.getTokenPrice(
chainlinkOraclePriceAddress,
LibChainlinkOracle.FOUR_HOUR_TIMEOUT,
lookback
)
);

However it's widely assumed that function returns how much USD 1 token worths:

/**
@> * @notice returns the price of a given token in USD (token:Usd Price)
@> * @dev if ETH returns 1000 USD, this function returns 1000
@> * (ignoring decimal precision)
*/
function getTokenPrice(address token, uint256 lookback) internal view returns (uint256) {
// oracles that are implmented within beanstalk should be placed here.
if (token == C.WETH) {
uint256 ethUsdPrice = LibEthUsdOracle.getEthUsdPrice(lookback);
if (ethUsdPrice == 0) return 0;
return ethUsdPrice;
}
if (token == C.WSTETH) {
uint256 wstethUsdPrice = LibWstethUsdOracle.getWstethUsdPrice(0);
if (wstethUsdPrice == 0) return 0;
return wstethUsdPrice;
}
// tokens that use the default chainlink oracle implementation,
// or a custom oracle implementation are called here.
@> return getTokenPriceFromExternal(token, lookback);
}

Impact

Incorrect price is returned.

Tools Used

Manual Review

Recommendations

Just return price:

return
- uint256(1e24).div(
LibChainlinkOracle.getTokenPrice(
chainlinkOraclePriceAddress,
LibChainlinkOracle.FOUR_HOUR_TIMEOUT,
lookback
)
- );
Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Appeal created

T1MOH Submitter
11 months ago
inallhonesty Lead Judge
11 months ago
giovannidisiena Auditor
11 months ago
inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Validated
Assigned finding tags:

`getUsdPrice` returns mixed decimals

Support

FAQs

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