The calculation of the caller reward uses an incorrect value. If the exchangeRate remains the same but a lot of interest accrues, then there will be no liquidation reward. Without a liquidation reward borrowing positions will not get liquidated and incur bad debt for the protocol.
Proof of Concept
The function Market._getCallerReward is called in BigBang._liquidateUser like this:
The issue is that userBorrowPart does not describe the actual borrowed value/debt, but just his share of the total debt. The part does not increase over time through accruals (opposed to the elastic value which the part describes).
A simple example:
user provides 1 ETH collateral at a current price of 2000$
with a collateralization rate of 75% the user can borrow up to 1500$
he borrows 1499$. assuming no interest has accrued yet, his userBorrowPart will also be 1499 (ignoring 1e18 factor for simplicity).
now interest accrues and users actual debt will increase. He is insolvent at 1500, but in the code above if (borrowed < startTVLInAsset) return 0 will always be true, because borrowed will always be 1499 (startTVLInAsset is point of insolvency, here 1500).
Tools Used
Manual review
Recommended Mitigation Steps
Use the elastic value (users debt consisting of borrowed amount + interest)
Lines of code
https://github.com/Tapioca-DAO/tapioca-bar-audit/blob/2286f80f928f41c8bc189d0657d74ba83286c668/contracts/markets/bigBang/BigBang.sol#L577
Vulnerability details
Impact
The calculation of the caller reward uses an incorrect value. If the exchangeRate remains the same but a lot of interest accrues, then there will be no liquidation reward. Without a liquidation reward borrowing positions will not get liquidated and incur bad debt for the protocol.
Proof of Concept
The function
Market._getCallerReward
is called inBigBang._liquidateUser
like this:The issue is that
userBorrowPart
does not describe the actual borrowed value/debt, but just his share of the total debt. The part does not increase over time through accruals (opposed to the elastic value which the part describes).A simple example:
userBorrowPart
will also be 1499 (ignoring 1e18 factor for simplicity).if (borrowed < startTVLInAsset) return 0
will always be true, becauseborrowed
will always be 1499 (startTVLInAsset
is point of insolvency, here 1500).Tools Used
Manual review
Recommended Mitigation Steps
Use the elastic value (users debt consisting of borrowed amount + interest)
Assessed type
Other