Platform: Code4rena
Start Date: 28/01/2022
Pot Size: $30,000 USDC
Total HM: 4
Participants: 22
Period: 3 days
Judge: GalloDaSballo
Total Solo HM: 2
Id: 80
League: ETH
Rank: 18/22
Findings: 1
Award: $69.12
๐ Selected for report: 0
๐ Solo Findings: 0
hyh
Whenever Chainlink's latestRoundData
for any reason returns some not recent, but positive price, it will be used as current price by Cvx3CrvOracle's peek
and get
despite there will be no confirmation for it.
This way an attacker can monitor Chainlink oracle state and act on a stale price observation, knowing that stale 3CRV/ETH figure will be used in the system.
This kind of mispricing induced attacks tend to yield a partial loss of contract funds.
_peek ignore price state Oracle data:
https://github.com/code-423n4/2022-01-yield/blob/main/contracts/Cvx3CrvOracle.sol#L120-127
The fix is to check both replyโs round number to be recent and it's timestamp to be updated:
Now:
(, int256 daiPrice, , , ) = DAI.latestRoundData(); (, int256 usdcPrice, , , ) = USDC.latestRoundData(); (, int256 usdtPrice, , , ) = USDT.latestRoundData(); require(daiPrice > 0 && usdcPrice > 0 && usdtPrice > 0, "Chainlink pricefeed reporting 0" );
To be:
(uint roundID1, int256 daiPrice, , uint updatedAt1, uint answeredInRound1) = DAI.latestRoundData(); (uint roundID2, int256 usdcPrice, , uint updatedAt2, uint answeredInRound2) = USDC.latestRoundData(); (uint roundID3, int256 usdtPrice, , uint updatedAt3, uint answeredInRound3) = USDT.latestRoundData(); require(daiPrice > 0 && usdcPrice > 0 && usdtPrice > 0, "Chainlink pricefeed reporting 0"); require(updatedAt1 != 0 && answeredInRound1 >= roundID1 && updatedAt2 != 0 && answeredInRound2 >= roundID2 && updatedAt3 != 0 && answeredInRound3 >= roundID3, "Chainlink pricefeed stale");
#0 - iamsahu
2022-02-01T19:34:42Z
Duplicate of #136
#1 - GalloDaSballo
2022-02-18T00:58:01Z
Duplicate of #136