malicious borrowers can follow reclaimLiquidity() then execute addPremium() to invalidate renewalCutoffTime
mediumLines of code
Vulnerability details
Vulnerability details
LP can set renewalCutoffTime=block.timestamp by executing reclaimLiquidity(), to force close position
solidityfunction liquidatePosition( DataStruct.ClosePositionParams calldata params, address borrower ) external override nonReentrant { ... if ( !((closeCache.tokenFromPremium < liquidateCache.tokenFromOwed || closeCache.tokenToPremium < liquidateCache.tokenToOwed) || @> (lien.startTime < lps.getRenewalCutoffTime(lien.tokenId) && lien.startTime + LOAN_TERM < block.timestamp)) ) { revert Errors.LiquidationNotMet(); }
The restrictions are:
- Loan expires
- lien.startTime < lps.getRenewalCutoffTime(lien.tokenId)
Since addPremium() will modify lien.startTime = block.timestamp
we need to restrict , if lps.getRenewalCutoffTime(lien.tokenId) > lien.startTime, addPremium() cannot be executed.
Otherwise, addPremium() can indefinitely postpone liquidatePosition() to forcibly close position.
solidityfunction addPremium(uint96 lienId, uint128 premium0, uint128 premium1) external override nonReentrant { .. @> if (lps.getRenewalCutoffTime(lien.tokenId) > lien.startTime) revert Errors.RenewalDisabled();
The problem is that this judgment condition is >, so if lps.getRenewalCutoffTime(lien.tokenId) == lien.startTime, it can be executed.
This leads to, the borrower can monitor the mempool, if LP executes reclaimLiquidity(), front-run or follow closely to execute addPremium(0). It can be executed successfully, resulting in lien.startTime == lps[tokenId].renewalCutoffTime == block.timestamp.
In this case, liquidatePosition() will fail , because the current condition for liquidatePosition() is lien.startTime < lps.getRenewalCutoffTime(lien.tokenId), liquidatePosition() will revert Errors.LiquidationNotMet();.
So by executing reclaimLiquidity() and addPremium() in the same block, it can maliciously continuously prevent LP from retrieving Liquidity.
Impact
Malicious borrowers can follow reclaimLiquidity() then execute addPremium() to invalidate renewalCutoffTime, thereby maliciously preventing the position from being forcibly closed, and LP cannot retrieve Liquidity.
Recommended Mitigation
Use >= lien.startTime to replace > lien.startTime.
In this way, the borrower has at most one chance and cannot postpone indefinitely.
difffunction addPremium(uint96 lienId, uint128 premium0, uint128 premium1) external override nonReentrant { .. - if (lps.getRenewalCutoffTime(lien.tokenId) > lien.startTime) revert Errors.RenewalDisabled(); + if (lps.getRenewalCutoffTime(lien.tokenId) >= lien.startTime) revert Errors.RenewalDisabled();
Assessed type
Other
