The premiums used to determine the liquidation condition have the liquidation reward already discounted, potentially causing a lien to be considered underwater while technically it is not.
Positions in Particle LAMM can be liquidated if the owed tokens exceed the available premiums in the lien. Liquidators are incentivized with a reward to keep the protocol sane. This can be found in the implementation of liquidatePosition():
348: // calculate liquidation reward
349: liquidateCache.liquidationRewardFrom =
350: ((closeCache.tokenFromPremium) * LIQUIDATION_REWARD_FACTOR) /
351: uint128(Base.BASIS_POINT);
352: liquidateCache.liquidationRewardTo =
353: ((closeCache.tokenToPremium) * LIQUIDATION_REWARD_FACTOR) /
354: uint128(Base.BASIS_POINT);
355: closeCache.tokenFromPremium -= liquidateCache.liquidationRewardFrom;
356: closeCache.tokenToPremium -= liquidateCache.liquidationRewardTo;
357:
358: // check for liquidation condition
359: ///@dev the liquidation condition is that
360: /// (EITHER premium is not enough) OR (cutOffTime > startTime AND currentTime > startTime + LOAN_TERM)
361: if (
362: !((closeCache.tokenFromPremium < liquidateCache.tokenFromOwed ||
363: closeCache.tokenToPremium < liquidateCache.tokenToOwed) ||
364: (lien.startTime < lps.getRenewalCutoffTime(lien.tokenId) &&
365: lien.startTime + LOAN_TERM < block.timestamp))
366: ) {
367: revert Errors.LiquidationNotMet();
368: }
The liquidation rewards are calculated as a portion of the premiums, and discounted from these to keep them reserved from any further calculation that may involve tokenFromPremium or tokenToPremium. However, these are discounted before checking the liquidation condition.
The values used to check the conditions at lines 362 and 363 already incorporate the discounted rewards. This implies that the borrower might still maintain a healthy position if it werenβt for the subtracted amounts. The lien could be liquidated even if itβs not technically underwater.
Subtract the liquidation rewards from premiums after checking the liquidation condition.
- // calculate liquidation reward
- liquidateCache.liquidationRewardFrom =
- ((closeCache.tokenFromPremium) * LIQUIDATION_REWARD_FACTOR) /
- uint128(Base.BASIS_POINT);
- liquidateCache.liquidationRewardTo =
- ((closeCache.tokenToPremium) * LIQUIDATION_REWARD_FACTOR) /
- uint128(Base.BASIS_POINT);
- closeCache.tokenFromPremium -= liquidateCache.liquidationRewardFrom;
- closeCache.tokenToPremium -= liquidateCache.liquidationRewardTo;
// check for liquidation condition
///@dev the liquidation condition is that
/// (EITHER premium is not enough) OR (cutOffTime > startTime AND currentTime > startTime + LOAN_TERM)
if (
!((closeCache.tokenFromPremium < liquidateCache.tokenFromOwed ||
closeCache.tokenToPremium < liquidateCache.tokenToOwed) ||
(lien.startTime < lps.getRenewalCutoffTime(lien.tokenId) &&
lien.startTime + LOAN_TERM < block.timestamp))
) {
revert Errors.LiquidationNotMet();
}
+ // calculate liquidation reward
+ liquidateCache.liquidationRewardFrom =
+ ((closeCache.tokenFromPremium) * LIQUIDATION_REWARD_FACTOR) /
+ uint128(Base.BASIS_POINT);
+ liquidateCache.liquidationRewardTo =
+ ((closeCache.tokenToPremium) * LIQUIDATION_REWARD_FACTOR) /
+ uint128(Base.BASIS_POINT);
+ closeCache.tokenFromPremium -= liquidateCache.liquidationRewardFrom;
+ closeCache.tokenToPremium -= liquidateCache.liquidationRewardTo;
Other
The text was updated successfully, but these errors were encountered:
All reactions