Closed code423n4 closed 2 years ago
WatchPug
https://github.com/code-423n4/2022-01-yield/blob/e946f40239b33812e54fafc700eb2298df1a2579/contracts/Cvx3CrvOracle.sol#L110-L127
function _peek( bytes6 base, bytes6 quote, uint256 baseAmount ) private view returns (uint256 quoteAmount, uint256 updateTime) { require( (base == ethId && quote == cvx3CrvId) || (base == cvx3CrvId && quote == ethId), "Invalid quote or base" ); (, int256 daiPrice, , , ) = DAI.latestRoundData(); (, int256 usdcPrice, , , ) = USDC.latestRoundData(); (, int256 usdtPrice, , , ) = USDT.latestRoundData(); require( daiPrice > 0 && usdcPrice > 0 && usdtPrice > 0, "Chainlink pricefeed reporting 0" );
On Cvx3CrvOracle.sol, we are using Chainlink's latestRoundData API, but there is no check if the return value indicates stale data. This could lead to stale prices according to the Chainlink documentation:
Cvx3CrvOracle.sol
latestRoundData
See also: https://github.com/yieldprotocol/vault-v2/blob/master/contracts/oracles/chainlink/ChainlinkMultiOracle.sol#L88-L90
Consider adding missing checks for stale data.
For example:
(uint80 daiRoundID, int256 daiPrice, , uint256 daiTimestamp, uint80 daiAnsweredInRound) = DAI.latestRoundData(); require(daiPrice > 0, "DAI: Chainlink price <= 0"); require(daiAnsweredInRound >= daiRoundID, "DAI: Stale price"); require(daiTimestamp != 0, "DAI: Round not complete"); (uint80 usdcRoundID, int256 usdcPrice, , uint256 usdcTimestamp, uint80 usdcAnsweredInRound) = USDC.latestRoundData(); require(usdcPrice > 0, "USDC: Chainlink price <= 0"); require(usdcAnsweredInRound >= usdcRoundID, "USDC: Stale price"); require(usdcTimestamp != 0, "USDC: Round not complete"); (uint80 usdtRoundID, int256 usdtPrice, , uint256 usdtTimestamp, uint80 usdtAnsweredInRound) = USDT.latestRoundData(); require(usdtPrice > 0, "USDT: Chainlink price <= 0"); require(usdtAnsweredInRound >= usdtRoundID, "USDT: Stale price"); require(usdtTimestamp != 0, "USDT:Round not complete");
Handle
WatchPug
Vulnerability details
https://github.com/code-423n4/2022-01-yield/blob/e946f40239b33812e54fafc700eb2298df1a2579/contracts/Cvx3CrvOracle.sol#L110-L127
On
Cvx3CrvOracle.sol
, we are using Chainlink'slatestRoundData
API, but there is no check if the return value indicates stale data. This could lead to stale prices according to the Chainlink documentation:See also: https://github.com/yieldprotocol/vault-v2/blob/master/contracts/oracles/chainlink/ChainlinkMultiOracle.sol#L88-L90
Recommendation
Consider adding missing checks for stale data.
For example: