code-423n4 / 2023-12-initcapital-findings

3 stars 3 forks source link

Lack of way to handle not fully repaid bad debt after liquidation after the lending pool share or WLP are fully seized #9

Open c4-bot-10 opened 9 months ago

c4-bot-10 commented 9 months ago

Lines of code

https://github.com/code-423n4/2023-12-initcapital/blob/a53e401529451b208095b3af11862984d0b32177/contracts/core/PosManager.sol#L235

Vulnerability details

Impact

Lack of way to handle not fully repaid bad debt after liquidation after the lending pool share or WLP are fully seized

Proof of Concept

When user has bad debt, user's borrow credit > collateral credit

liqudiator can steps in liquidate and seize user's share or seize user WLP and repay the debt

while the liquidate function aims to let liqudiator take the min share available for bad debt repayment

// take min of what's available (for bad debt repayment)
shares = shares.min(IPosManager(POS_MANAGER).getCollAmt(_posId, _poolOut)); // take min of what's available
_require(shares >= _minShares, Errors.SLIPPAGE_CONTROL);

after the user's pool share is transferred out, or after user's WLP is seized, the rest of unpaid debt becomes bad debt permanently

for example,

user's borrow 1000 USDT and has debt 1000 USDT, his share only worth 500 USD as collateral price drops

because the code let liquidator takes min of what's available for both lending pool share and take min of what's available (for bad debt repayment) for WLP amount

the liqudiator can repay 800 USD and seize share of 500 USD

but there are 200 USD remaining debt,

when other liquidator (even this liquidator belongs to protocol) writes to repay and erase the rest 200 USD bad debt, he cannot because removeCollateralTo validates share > 0, if share is 0, revert

_require(_shares > 0, Errors.ZERO_VALUE);

if the underlying collateral is WLP, the second liquidation aims to write off bad debt does not work as well because if all WLP is transfered out, calling _harvest and unwrap again is likely to revert

_harvest(_posId, _wLp, _tokenId);
IBaseWrapLp(_wLp).unwrap(_tokenId, _amt, _receiver);

the bad permenantly inflate the totalAssets() in lending pool and inflate the total debt to not let other user borrow from protocol because of the borrow cap checks

also, the lender suffer the loss because if the bad debt is not repaid, the lender that deposit cash into the lending pool is lost

Tools Used

Manual Review

Recommended Mitigation Steps

add a way o handle not fully repaid bad debt after liquidation after the lending pool share or WLP is fully seized

add a function donate to the lending pool to let user supply asset or add a function to socialize the bad debt as loss explicilty

Assessed type

Token-Transfer

c4-judge commented 8 months ago

hansfriese marked the issue as primary issue

c4-sponsor commented 8 months ago

fez-init (sponsor) confirmed

c4-judge commented 8 months ago

hansfriese marked the issue as satisfactory

c4-judge commented 8 months ago

hansfriese marked the issue as selected for report