In LendingPool
a user is able to borrow reserveTokens
and is minted equal debtTokens
, After depositing their NFT as collateral.
The protocol has a base LiquidationThreshold
-> 80%
This means that the user can borrow / have debt up to 80% of the value of their collateral. If the value of their collateral falls or any situation which the user ends up with more debt than 80% of the value of their collateral, they can be liquidated to save the protocol from having bad debt.
BUT there is a wrong check for the value that a user can borrow in the LendingPool::borrow
function, which allows the user to receive MORE than their borrowing power and even more than the value of thier collateral.
The liquidationThreshold
percentage should be applied to the collateral that a user has to accurately check if they have less debt than their borrowing power. The function however, applies the liquidationThreshold
to the users debt
balance, which, since it is a percentage (80%) -> lowers the value of the actual debt they have.
Lets follow this scenario:
User has borrowed 0, they are making their first borrow. User deposits their NFT worth a value of 100
.
User calls borrow
with 120
as the amount to borrow.
userTotalDebt
is calculated and 120
is added, so it will equal 120
The if
statement checks incorrectly:
collateralValue
= 100.
userTotalDebt
* * 80% -> 120 * * 80% -> Which equals 96
if 100 < 96 , then revert.
But 100 IS NOT less than 96. So the function continues.
The function continues, the user is minted 120 debtTokens
and sent 120 reserveTokens
The user ends up with still 100 collateral value and 120 debtTokens and reserveTokens. The protocol immediately has 20 bad debt that it incurs as an imemdiate loss.
Verification of the wrong liquidationThreshold
check can be seen here, when the liquidationThreshold
is correctly applied to the collateralValue
of the user -> to see if their debt amount is above the threshold:
NOT only is the user receiving / borrowing more than their liquidation threshold amount of 80
, they are also receiving more than their entire collateral value.
The user can GO COMPLETELY INSOLVENT. The protocol will have to take on that bad debt as a loss.
The example above uses small values for simplicity, but the NFT's represent real-estate which can be very large values. The user can have very large collateral, and exploit this will very large values.
For example, instead of 100 collateral and 120 borrow amount -> use 100,000 and 120,000. The protocol now has a 20,000 loss. And this can keep scaling. The protocol gets bad debt and immediate loss, can be very substancial loss.
manual review
The liquidationThreshold
should be applied to the collateralValue
of the user. And then compare that value to the amount of debt they have, which will accurately ensure they can borrow that amount.
In the above example, If correctly applying liquidationThreshold
:
The if
statement will operate as such:
collateralValue *liquidtyThreshold -> 100 * * 80% -> collateralValue
= 80
userTotalDebt = 120
80 < 120 , then revert.
80 Is definitely less than 120, which reverts and does not allow the user to borrow that amount.
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.