Liquidating chaining can be achieved by liquidating token collateral with the highest collateralFactor
#202
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
downgraded by judge
Judge downgraded the risk level of this issue
high quality report
This report is of especially high quality
M-09
primary issue
Highest quality submission among a set of duplicates
satisfactory
satisfies C4 submission criteria; eligible for awards
selected for report
This submission will be included/highlighted in the audit report
Lines of code
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseLending.sol#L1250
Vulnerability details
Impact
The liquidation mechanism is intended as follows:
This feature is programmed here
However, since the liquidator can select which collateral he will receive, he can intentionally liquidate the highest
collateralFactor
tokens in order to make the overall position'scollateralFactor
to go down and being able to keep liquidating the other tokens. Since the intended maximum amount to liquidate when the position has no bad debt is 50%, if a user can intentionally create a sequence of liquidation that leads to a greater percentage it can be considered a high impact vulnerability.Written proof of concept
Imagine the following situation:
The protocol supports these 4 tokens, A, B, C and D with these
collateralFactors
The initial prices for these tokens are as follows:
Alice deposits these 3 amounts of token A, B and C as collateral
Alice can borrow up to 20 * 0.95 = 19 worth of ETH, for the sake of simplicity, since token D is valued 1 ETH, she can borrow up to 19 of token D. However, she decides to borrow 18.9 to have a tiny healthy zone.
Unfortunately for Alice, the price of token C drops to 0.25. And the situation continues as follows:
In this stage, Alice can be liquidated up to 50% because her borrowed amount (18.9 ETH) is greater than her weighted value (17.5 ETH). Just 50% is liquidable because the 89% of her weighted value is greater than her borrowed amount.
Let's now demonstrate that if the liquidator receives the token with the highest
collateralFactor
, the position will still be liquidable and he can chain this function call in order to liquidate a huge amount of collateral.collateralFactor
.The new borrowed value from Alice would be 18.9 - 9.09 = 9.81
We can clearly see that the borrowed value is still greater than Alice's weighted value. Hence, she can be liquidated again!
See Coded Proof of Concept to see the full chain liquidation
collateralFactor
:The liquidator is forced to receive token C (lowest
collateralFactor
). He decides to repay 4.54 worth of token D that when added with the fee (10%) will be 5. The whole value of collateral token C.The new borrowed value would be 18.9 - 4.54 = 14.36
This new borrowed value is smaller than the weighted value. Thus, Alice is no longer liquidable and her position is healthy.
See Coded Proof of Concept.
Coded Proof of Concept
For the sake of testing, I adjusted the collateral factors manually when deploying the protocol locally:
And also created a function inside the
MockChainlink
to set the prices of the tokens:With all that said, let's see the PoC for the 2 previously explained situations:
Result:
With 3 liquidation calls, the liquidator could repay 81% of Alice's position when in fact, the maximum percentage that the protocol allows when there is no bas debt is 50%.
collateralFactor
and then her position becomes healthyResult:
With just a single liquidation call, the liquidator could only repay 25% of Alice's position and at that point, her position becomes healthy and she is no longer liquidable.
Tools Used
Manual review
Recommended Mitigation Steps
This issue can be easily solved by forcing all liquidations to be done with the lowest
collateralFactor
tokens first. As shown in the written and coded PoC, if the user would have been forced to receive the collateral token with the lowestcollateralFactor
, the health of the position would go to non-liquidable and the liquidator would not be able to continue liquidating the position.Also, a really good safety check would be to ensure that after the liquidation is executed, the health of the position must be good in order to prevent this chain liquidation.
Assessed type
Error
The text was updated successfully, but these errors were encountered: