Skip to content
This repository has been archived by the owner on Dec 17, 2023. It is now read-only.

bitsurfer - Liquidations will be frozen, when the oracle go offline or a token's price dropping to zero #433

Closed
sherlock-admin opened this issue Jun 11, 2023 · 14 comments
Labels
Escalation Resolved This issue's escalations have been approved/rejected Non-Reward This issue will not receive a payout Sponsor Disputed The sponsor disputed this issue's validity Won't Fix The sponsor confirmed this issue will not be fixed

Comments

@sherlock-admin
Copy link
Contributor

bitsurfer

medium

Liquidations will be frozen, when the oracle go offline or a token's price dropping to zero

Summary

Liquidations will be frozen, when the oracle go offline or a token's price dropping to zero

Vulnerability Detail

In certain exceptional scenarios, such as when oracles go offline/paused or token prices plummet to zero, liquidations will be temporarily suspended.

When liquidator want to liquidate() an account because of bad debt, it will check the _isLiquidatable() and loop over through the userEnteredMarkets to check if debtValue > liquidationCollateralValue for an account. To calculate this oracle is called to get the asset price.

If this call to oracle is corrupted due to offline/paused, the liquidate() call function will reverted. More over if the price is returning 0 it will be reverted because require(assetPrice > 0, "invalid price");

Impact

During critical periods, there is a risk that liquidations may not be feasible when they are most needed by the protocol. This can lead to a situation where the value of users' assets declines below their outstanding debts, effectively disabling any motivation for liquidation. Consequently, this can potentially push the protocol into insolvency, posing significant challenges and potential financial instability.

Code Snippet

https://github.com/sherlock-audit/2023-05-ironbank/blob/main/ib-v2/src/protocol/pool/IronBank.sol#L1065-L1092

File: IronBank.sol
499:         require(_isLiquidatable(borrower), "borrower not liquidatable");

File: IronBank.sol
1065:     function _isLiquidatable(address user) internal view returns (bool) {
...
1069:         address[] memory userEnteredMarkets = allEnteredMarkets[user];
1070:         for (uint256 i = 0; i < userEnteredMarkets.length; i++) {
...
1079:             uint256 assetPrice = PriceOracleInterface(priceOracle).getPrice(userEnteredMarkets[i]);
1080:             require(assetPrice > 0, "invalid price");
...
1090:         }
1091:         return debtValue > liquidationCollateralValue;
1092:     }

File: PriceOracle.sol
66:     function getPriceFromChainlink(address base, address quote) internal view returns (uint256) {
67:         (, int256 price,,,) = registry.latestRoundData(base, quote);
68:         require(price > 0, "invalid price");

Tool used

Manual Review

Recommendation

Implement a protective measure to mitigate this potential risk. For example, enclose any oracle get price function within a try-catch block, and incorporate fallback logic within the catch block to handle scenarios where access to the Chainlink oracle data feed is denied. Or use second oracle for backup situation.

@ibsunhub
Copy link

It doesn't make any sense to liquidate an asset whose price is 0. It won't add value to debt nor collateral. It just can't have a zero-price asset on a lending protocol.

We thought about creating a backing oracle to be ready to replace ChainLink if ChainLink's price feed goes wrong. However, it also creates a trust issue since we control the price of the backing oracle and we could switch to it at will. For now, we stick with ChainLink. If the price from ChainLink is inaccurate (including being 0), we pause the borrow / repay / liquidate on this token.

@ibsunhub ibsunhub added the Sponsor Disputed The sponsor disputed this issue's validity label Jun 20, 2023
@0xffff11
Copy link
Collaborator

I do believe this is an actual issue. Oracle failure should not pause liquidations, Another fix I can recommend (having a fallback oracle is the best), it is that for every fetch, the last price is stored on a variable. If the oracle fails, the last price on the variable will be the one used instead.

@ibsunhub
Copy link

There are different failure for ChainLink price feed. If the price is not updated, retrieving the stale price from ChainLink is basically the same with the solution that stores a variable. Another concern is that we believe this fix (store the previous price on a variable) will not solve the root cause and will increase a significant amount of gas consumption for user operations (additional read / write storage during every price retrieval).

I think the best solution here is still a backing oracle. However, that's another topic to create a sub-system to deal with the trust issue and the availability issue.

@0xffff11
Copy link
Collaborator

Yes, I agree with your point, backing oracle should be the way to go. I think tellor oracles are very common as the fallback oracle. Might be worth checking those out. Therefore, I believe that you confirm that the issue is valid, right? @ibsunhub

@ib-tycho
Copy link

We maintain our position that this issue is not valid. It should be noted that prominent lending protocols like Compound v3 Comet, AAVE, and Euler do not implement fallback oracles or address Chainlink's potential downtime. While having fallback oracles can be beneficial, we consider them to be optional rather than essential for protocol functionality.

@0xffff11
Copy link
Collaborator

Issue will be kept as a medium at the moment because there is a chance of the price going to 0 and the scenario would be given.

@IAm0x52
Copy link
Collaborator

IAm0x52 commented Jun 27, 2023

Escalate for 10 USDC

This should be low. I agree with the sponsor's comments. Chainlink will never show the price of the oracle as zero unless the price is truly zero. If the token really is worth 0 then there is no point in liquidating it anyways so that scenario is invalid. Second it is not a vulnerability that they don't have a backup oracle, that is simply a design choice and as mentioned many blue-chip protocols don't use backup oracles.

@sherlock-admin
Copy link
Contributor Author

Escalate for 10 USDC

This should be low. I agree with the sponsor's comments. Chainlink will never show the price of the oracle as zero unless the price is truly zero. If the token really is worth 0 then there is no point in liquidating it anyways so that scenario is invalid. Second it is not a vulnerability that they don't have a backup oracle, that is simply a design choice and as mentioned many blue-chip protocols don't use backup oracles.

You've created a valid escalation for 10 USDC!

To remove the escalation from consideration: Delete your comment.

You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.

@0xffff11
Copy link
Collaborator

0xffff11 commented Jul 5, 2023

I agree with the escalation from the watson. Chainlink does not return 0 anymore if the price is not 0. And the fallback oracle, while it could be an improvement it is a design decision that most of big protocols don't even use. Low

@0x3agle
Copy link

0x3agle commented Jul 9, 2023

I agree with the escalation from the watson. Chainlink does not return 0 anymore if the price is not 0. And the fallback oracle, while it could be an improvement it is a design decision that most of big protocols don't even use. Low

I agree that this scenario is not possible, but in my report (#121), I have shown that if the Chainlink oracle is taken down by a multi-sig admin, then the contract does not have any way to handle that scenario and will always revert, causing a denial-of-service (DoS). Therefore, I believe that at least this case must be considered as valid. The suggested mitigation is to add a try-catch block.

Additionally, could you please explain why my issue was considered a duplicate of this one? Both issues involve different scenarios, but they require the same mitigation. One scenario may not be valid, but it is important to consider all the scenarios related to this part of the code.

@0xbitsurfer
Copy link

I wish IllIllI had submit this issue again in this contest, thus no one can argue

even the negative value issue does exist, and confirmed from previous contest

according to @hrishibhat : sherlock-audit/2023-02-gmx-judging#156 (comment)

Although unlikely, a zero price should not break the liquidations.
Considering this a valid medium


Another reason why submitter name should be blurred, @Evert0x @jacksanford1

@IAm0x52
Copy link
Collaborator

IAm0x52 commented Jul 11, 2023

I don't know the context of the issues you've linked to but the asset referenced there are real world assets. Crypto assets can never go negative in price because they cannot have carrying costs. Ironbank lists crypto asset not RWA so low still seems appropriate to me. If GMX does not intend to list RWA then the issue you've linked should also have been invalid/low.

@hrishibhat
Copy link

hrishibhat commented Jul 17, 2023

Result:
Low
Has duplicates
Agree with the comments on the escalation. If the price of the asset is zero then there is no point liquidating it.

Also, Iron bank works differently from gmx.
Some context on the gmx issue tagged:
The gmx issue is related to futures: oil futures did go negative, and a future is not a RWA. if something hits zero, the other side of the position should be able to exit the position at maximum possible value - they shouldn't be prevented from doing so due to a bug. Also there could be fee associated with it.

@sherlock-admin2
Copy link

sherlock-admin2 commented Jul 17, 2023

Escalations have been resolved successfully!

Escalation status:

@sherlock-admin sherlock-admin added Non-Reward This issue will not receive a payout and removed Reward A payout will be made for this issue labels Jul 17, 2023
@hrishibhat hrishibhat removed the Medium A valid Medium severity issue label Jul 17, 2023
@sherlock-admin sherlock-admin removed the Escalated This issue contains a pending escalation label Jul 17, 2023
@sherlock-admin2 sherlock-admin2 added the Escalation Resolved This issue's escalations have been approved/rejected label Jul 17, 2023
@sherlock-admin sherlock-admin removed the Has Duplicates A valid issue with 1+ other issues describing the same vulnerability label Jul 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Escalation Resolved This issue's escalations have been approved/rejected Non-Reward This issue will not receive a payout Sponsor Disputed The sponsor disputed this issue's validity Won't Fix The sponsor confirmed this issue will not be fixed
Projects
None yet
Development

No branches or pull requests

9 participants