The _repay
function, and the finalizeLiquidation
function both minus the DebtToken
burned from the reserve asset
scaled balance. This causes wrong accounting in which even though the borrower burns the entire DebtToken
minted for them when they initially borrow the reserve asset
, the user.scaledDebtBalance
will never be 0
. This will trap the borrower's NFT in the protocol.
In the _repay
function, the borrower repays (with interest) the reserve asset
loan that they had taken. It has the following lines of code:
As shown above, the user.scaledDebtBalance
minuses the amountBurned
from it.
In this function, the amountBurned
is the number of DebtToken
owned by the borrower that is burned according to the amount of loan they want to pay back.
The user.scaledDebtBalance
is the amount of reserve asset + Interest
that the user needs to pay back to fully pay the loan.
So, as you can see, the DebtToken
burned is minused from the reserve asset + Interest
which is wrong.
To drive this point home, lets look at the borrow
function where the scaledDebtBalance
is updated initially:
As shown above, the amount
is the amount of reserve asset
the borrower wants to borrow from the platform, and the scaledAmount
is the amount / usageIndex
which includes the current interest.
Hence, we can see that the amount of reserve asset + interest
is added to the scaledDebtBalance
in the borrow
function, but the amount of DebtTokens
burned is minused from the scaledDebtBalance
in the _repay
function.
The same bug is also present in the finalizeLiquidation
function as shown below:
Since the number of DebtTokens
is actually the 1:1
representation of the number of reserve asset
borrowed initially without the interest, this error will ensure that the user.scaledDebtBalance
will never reach 0
even if the borrower burns all of the DebtTokens
they received. If it never reaches 0
, the borrower will never be able to withdraw their NFT they transferred as collateral.
To showcase this, imagine a situation where a borrower has burned all of their DebtTokens, but the scaledDebtBalance
still has some value in it. When they call the withdrawNFT
function, it will trigger the following code snippet:
In our hypothetical situation, the userDebt
will be the interest amount left after removing all the DebtToken
burned. Let's say that the borrower only has 1 NFT as collateral. So the comparison shown above will be as follows:
The function will always revert due to the amount leftover in the scaledDebtBalance
.
The borrower will never be able to pay back the debt because they will not have any more DebtTokens, and they will not be able to remove their real estate NFT without clearing the debt.
Manual Review
Since the scaledDebtBalance
increases over time because of the usageIndex
, I am not sure how to implement this correctly. Currently, the scaledDebtBalance
only stores the interest when they initially borrow the tokens, but this will not hold true with time.
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.