Open code423n4 opened 1 year ago
08xmt marked the issue as disagree with severity
08xmt marked the issue as sponsor acknowledged
In the unlikely event of a chainlink msig block, the protocol can still recover through the use of governance actions to insert a new feed. I'd consider this a Low Severity, as protocol is only DOS'ed for a short period, and can't be repeatedly DOS'ed.
2 — Med: Assets not at direct risk, but the function of the protocol or its availability could be impacted, or leak value with a hypothetical attack path with stated assumptions, but external requirements.
I don't think a M requires some amount of time for the DOS to be valid, so I think without a mitigation or fallback in place, this is a valid issue and should qualify as M
0xean marked the issue as satisfactory
@0xean That's fair.
0xean marked the issue as selected for report
Lines of code
https://github.com/code-423n4/2022-10-inverse/blob/main/src/Oracle.sol#L78-L105 https://github.com/code-423n4/2022-10-inverse/blob/main/src/Oracle.sol#L112-L144 https://github.com/code-423n4/2022-10-inverse/blob/main/src/Market.sol#L344-L347 https://github.com/code-423n4/2022-10-inverse/blob/main/src/Market.sol#L323-L327 https://github.com/code-423n4/2022-10-inverse/blob/main/src/Market.sol#L353-L363
Vulnerability details
Impact
Based on the current implementation, when the protocol wants to use Chainlink oracle data feed for getting a collateral token's price, the fixed price for the token should not be set. When the fixed price is not set for the token, calling the
Oracle
contract'sviewPrice
orgetPrice
function will executeuint price = feeds[token].feed.latestAnswer()
. As https://blog.openzeppelin.com/secure-smart-contract-guidelines-the-dangers-of-price-oracles/ mentions, it is possible that Chainlink’s "multisigs can immediately block access to price feeds at will". When this occurs, executingfeeds[token].feed.latestAnswer()
will revert so calling theviewPrice
andgetPrice
functions also revert, which cause denial of service when calling functions likegetCollateralValueInternal
andgetWithdrawalLimitInternal
. ThegetCollateralValueInternal
andgetWithdrawalLimitInternal
functions are the key elements to the core functionalities, such as borrowing, withdrawing, force-replenishing, and liquidating; with these functionalities facing DOS, the protocol's usability becomes very limited.https://github.com/code-423n4/2022-10-inverse/blob/main/src/Oracle.sol#L78-L105
https://github.com/code-423n4/2022-10-inverse/blob/main/src/Oracle.sol#L112-L144
https://github.com/code-423n4/2022-10-inverse/blob/main/src/Market.sol#L344-L347
https://github.com/code-423n4/2022-10-inverse/blob/main/src/Market.sol#L323-L327
https://github.com/code-423n4/2022-10-inverse/blob/main/src/Market.sol#L353-L363
Proof of Concept
The following steps can occur for the described scenario.
depositAndBorrow
function to deposit some of the collateral token and borrows some DOLA against the collateral.feeds[token].feed.latestAnswer()
will revert.borrow
function, which eventually executesfeeds[token].feed.latestAnswer()
, reverts.withdraw
function, which eventually executesfeeds[token].feed.latestAnswer()
, reverts.forceReplenish
andliquidate
functions would all revert as well.Tools Used
VSCode
Recommended Mitigation Steps
The
Oracle
contract'sviewPrice
andgetPrice
functions can be updated to refactorfeeds[token].feed.latestAnswer()
intotry feeds[token].feed.latestAnswer() returns (int256 price) { ... } catch Error(string memory) { ... }
. The logic for getting the collateral token's price from the Chainlink oracle data feed should be placed in thetry
block while some fallback logic when the access to the Chainlink oracle data feed is denied should be placed in thecatch
block. If getting the fixed price for the collateral token is considered as a fallback logic, then setting the fixed price for the token should become mandatory, which is different from the current implementation. Otherwise, fallback logic for getting the token's price from a fallback oracle is needed.