code-423n4 / 2022-01-yield-findings

1 stars 0 forks source link

Cvx3CrvOracle can report stale prices #132

Closed code423n4 closed 2 years ago

code423n4 commented 2 years ago

Handle

hyh

Vulnerability details

Impact

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.

Proof of Concept

_peek ignore price state Oracle data:

https://github.com/code-423n4/2022-01-yield/blob/main/contracts/Cvx3CrvOracle.sol#L120-127

Recommended Mitigation Steps

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");
iamsahu commented 2 years ago

Duplicate of #136

GalloDaSballo commented 2 years ago

Duplicate of #136