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

LibUsdOracle incorrectly assumes that USDC/USD and USDT/USD Chainlink price feeds have 1 hour heartbeat

Summary

If oracleImpl.encodeType == bytes1(0x02) then it means that it firstly fetches price from Token/Stablecoin on Uniswap, and then fetches Stablecoin/USD from Chainlink where Stablecoin is USDC or USDT. Problem is that it invalidates answer most of the time because of incorrect timeout.

Vulnerability Details

Here it fetches stablecoin price:

function getTokenPriceFromExternal(
address token,
uint256 lookback
) internal view returns (uint256 tokenPrice) {
...
} else if (oracleImpl.encodeType == bytes1(0x02)) {
// assumes a dollar stablecoin is passed in
// if the encodeType is type 2, use a uniswap oracle implementation.
address chainlinkToken = IUniswapV3PoolImmutables(oracleImpl.target).token0();
chainlinkToken = chainlinkToken == token
? IUniswapV3PoolImmutables(oracleImpl.target).token1()
: token;
tokenPrice = LibUniswapOracle.getTwap(
lookback == 0 ? LibUniswapOracle.FIFTEEN_MINUTES : uint32(lookback),
oracleImpl.target,
chainlinkToken,
token,
uint128(10) ** uint128(IERC20Decimals(token).decimals())
);
// USDC/USD
// call chainlink oracle from the OracleImplmentation contract
Implementation memory chainlinkOracleImpl = s.sys.oracleImplementation[chainlinkToken];
address chainlinkOraclePriceAddress = chainlinkOracleImpl.target;
if (chainlinkOraclePriceAddress == address(0)) {
// use the chainlink registry
chainlinkOraclePriceAddress = ChainlinkPriceFeedRegistry(chainlinkRegistry).getFeed(
chainlinkToken,
0x0000000000000000000000000000000000000348
); // 0x0348 is the address for USD
}
uint256 chainlinkTokenPrice = LibChainlinkOracle.getTokenPrice(
chainlinkOraclePriceAddress,
@> LibChainlinkOracle.FOUR_HOUR_TIMEOUT,
lookback
);
return tokenPrice.mul(chainlinkTokenPrice).div(1e6);
}
...

However USDC and USDT price feeds have 1 day heartbeat:

  1. https://data.chain.link/feeds/ethereum/mainnet/usdc-usd

  2. https://data.chain.link/feeds/ethereum/mainnet/usdt-usd

Impact

Most of the time price of Stablecoin will be unavailable, i.e. 20 hours a day. It will return 0 price most of the time.

Tools Used

Manual Review

Recommendations

Use 4 day timeout:

uint256 chainlinkTokenPrice = LibChainlinkOracle.getTokenPrice(
chainlinkOraclePriceAddress,
- LibChainlinkOracle.FOUR_HOUR_TIMEOUT,
+ LibChainlinkOracle.FOUR_DAY_TIMEOUT,
lookback
);
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Using 4 hour heartbeat for USDC/USD chainlink price feed which has a 24 h heartbeat

Appeal created

golanger85 Auditor
about 1 year ago
T1MOH Submitter
about 1 year ago
inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Using 4 hour heartbeat for USDC/USD chainlink price feed which has a 24 h heartbeat

Support

FAQs

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