Users who have been flagged for liquidation and attempt to partially repay their debt can inadvertently lock their NFTs in the Lending contract forever. Apparently, if a user fully repays eventually before liquidation is finalized, their debt balance reaches zero, preventing StabilityPool.liquidateBorrower()
from executing due to the if (userDebt == 0) revert InvalidAmount();
check. Since liquidation is never finalized, the Stability Pool cannot reclaim their NFTs, effectively locking them permanently in LendingPool.sol with no way to recover them.
Users Can Reduce Their Debt to Zero Before Liquidation Finalization
liquidateBorrower()
checks if userDebt == 0
and reverts if true.
If a user flagged for liquidation partially repays multiple times, they can reduce their debt to exactly zero before liquidation is finalized before/after the grace period has expired. The reasons can be several as I have reported separately, e.g. not calling closeLiquidation()
in time after making a full repayment, being grieved for a large partial payment mistankenly made during liquidation and might as well pay the debt down to DoS the permissioned finalizeLiquidation()
, etc. Consequently, the NFTs remain stuck forever in LendingPool.sol.
Lending Pool Contract Has No Mechanism to Release NFTs Manually
Once the liquidation process is triggered, users or the Stability Pool cannot withdraw their NFTs until the process is separately complete.
If liquidation never closes/finalizes, the NFTs remain trapped inside the Lending Pool contract indefinitely.
Neither the user nor the liquidator can retrieve them, leading to a deadlock scenario.
NFTs are permanently locked in the Lending Pool contract with no way to retrieve them.
Liquidation cannot be completed, breaking protocol functionality.
Users who try to repay their debt before liquidation finalization can suffer an irreversible loss of assets.
Liquidators miss out on arbitrage opportunity since they cannot claim seized collateral.
The only possible fix would require a governance intervention resorting to a smart contract upgrade via proxy, making this an unacceptable UX failure.
Manual
**Allow liquidateBorrower()
to Execute Even If userDebt == 0
and lending.isUnderLiquidation[userAddress] = true
Instead of reverting, proceed with finalizing liquidation and releasing the NFTs if the debt is already cleared.
Return the NFTs to the user.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.