20,000 USDC
View results
Submission Details
Severity: high

Flawed debt check allows refinancing to additionally charge a pool

Summary

A flawed check allows the user to put the pool they are refinancing into insolvency by not making the new debt, which is equal to the old debt + interest and fees pay anything additional.

Vulnerability Details

Lender.sol's refinance() has a flawed check, which is supposed to transfer tokens from the user and to the user based on whether the loan debt has been lowered or raised. Instead of checking loan.debt > debt it checks debtToPay > debt.

uint256 debtToPay = loan.debt + lenderInterest + protocolInterest;
...
// @audit not charging the user anything if the debt == debt + interest and fees
if (debtToPay > debt) {
// we owe more in debt so we need the borrower to give us more loan tokens
// transfer the loan tokens from the borrower to the contract
IERC20(loan.loanToken).transferFrom(
msg.sender,
address(this),
debtToPay - debt
);
} else if (debtToPay < debt) {
//We have excess loan tokens so we give some back to the borrower
// first we take our borrower fee
uint256 fee = (borrowerFee * (debt - debtToPay)) / 10000;
IERC20(loan.loanToken).transfer(feeReceiver, fee);
// transfer the loan tokens from the contract to the borrower
IERC20(loan.loanToken).transfer(msg.sender, debt - debtToPay - fee);
}
...

This check is fundamentally flawed as it will allow someone to refinance their loan to an amount that is debt == debtToPay, which will not make the user pay anything additional to the protocol for the higher debt.

Impact

Direct loss of funds that is easily exploitable by any borrower.

Tools Used

Manual Review

Recommendations

Consider changing the if statement's conditions to the following:

if (loan.debt > debt) {
...
} else if (loan.debt < debt) {
...
}

Also, consider making the borrower pay for their accrued interest within this function.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.