Although the JUSD contract disallow liquidation from the same address, the user can bypass it with another wallet in control. The key to prevent users from doing self liquidation is to make it not profitable for traders.
Vulnerability Detail
The isValidLiquidator() check can be circumvented by using another wallet.
The trader will have incentive to use another wallet to do a self liquidation as long as the liquidationPriceOff is not less than the insurance fee.
Assuming, 3% liquidationPriceOff and 2% insurance. For a loan of 100,000 JUSD, when liquidated, the difference in liquidationPriceOff and insurance fee is 3% - 2% = 1%, 100,000 * 1% = $1,000.
Even the liquidationPriceOff is the same value as insurance fee, there is still a little profit for self liquidation, since in JUSDBank.sol#_calculateLiquidateAmount(), amount.decimalMul(priceOff) is calculated first, and used as the base amount for insuranceFee calculation. With the above example, assuming the insurance fee is increased to 3%, 100,000 JUSD, after priceOff discount, reduced amount is 97% 100,000 = 97,000. A discount of 3,000.
insuranceFee is 97,000 3% = 2,910.
The self liquidation will profit for 3,000 - 2,910 = 90, due to the discounted base amount for insurance fee.
The trader will have motivation to do self liquidation with another wallet in control. Effectively skip some portion of fund ought to pay to the protocol.
In JUSDOperation.sol#initReserve(), add checks for _liquidationPriceOff and _insuranceFeeRate, to make sure the insurance fee is larger than the discount, so that self liquidation is not profitable.
141345
medium
Incentive to self liquidate JUSD
Summary
Although the JUSD contract disallow liquidation from the same address, the user can bypass it with another wallet in control. The key to prevent users from doing self liquidation is to make it not profitable for traders.
Vulnerability Detail
The
isValidLiquidator()
check can be circumvented by using another wallet.The trader will have incentive to use another wallet to do a self liquidation as long as the
liquidationPriceOff
is not less than the insurance fee.Assuming, 3%
liquidationPriceOff
and 2% insurance. For a loan of 100,000 JUSD, when liquidated, the difference inliquidationPriceOff
and insurance fee is 3% - 2% = 1%, 100,000 * 1% = $1,000.Even the
liquidationPriceOff
is the same value as insurance fee, there is still a little profit for self liquidation, since inJUSDBank.sol#_calculateLiquidateAmount()
,amount.decimalMul(priceOff)
is calculated first, and used as the base amount forinsuranceFee
calculation. With the above example, assuming the insurance fee is increased to 3%, 100,000 JUSD, after priceOff discount, reduced amount is 97% 100,000 = 97,000. A discount of 3,000.insuranceFee
is 97,000 3% = 2,910. The self liquidation will profit for 3,000 - 2,910 = 90, due to the discounted base amount for insurance fee.Impact
The trader will have motivation to do self liquidation with another wallet in control. Effectively skip some portion of fund ought to pay to the protocol.
Code Snippet
https://github.com/sherlock-audit/2023-04-jojo/blob/main/JUSDV1/src/Impl/JUSDBank.sol#L397-L434
Tool used
Manual Review
Recommendation
In
JUSDOperation.sol#initReserve()
, add checks for_liquidationPriceOff
and_insuranceFeeRate
, to make sure the insurance fee is larger than the discount, so that self liquidation is not profitable.Duplicate of #321