20,000 USDC
View results
Submission Details
Severity: high
Valid

Lender can steal the accumulated protocol interest via `giveLoan`

Summary

By abusing the giveLoan function, a lender can steal the accumulated protocol interest.

Vulnerability Details

The giveLoan method allows a lender to move a loan to another pool. First, the totalDebt is calculated, which consist of the borrowed amount plus pending interest:

(
uint256 lenderInterest,
uint256 protocolInterest
) = _calculateInterest(loan);
uint256 totalDebt = loan.debt + lenderInterest + protocolInterest;

Then, the totalDebt is moved into the new pool, by borrowing that amount:

// update the pool balance of the new lender
_updatePoolBalance(poolId, pool.poolBalance - totalDebt);
pools[poolId].outstandingLoans += totalDebt;

And finally, the protocolInterest gets sent to the feeReceiver:

IERC20(loan.loanToken).transfer(feeReceiver, protocolInterest);

The issue is that the protocolInterest is included in totalDebt. A lender can abuse this behaviour by giving the loan to himself, after which he will be the recipient of the previously accumulated protocolInterest when the borrower repays, since it is treated as debt.

Impact

This behaviour has multiple impacts:

  1. The lender can steal the accumulated protocolInterest

  2. Since the contract also transfers the protocolInterest in giveLoan without owning it, these tokens are effectively transferred from the balance of other depositors. Should all (or enough) lenders close their pools, the contract becomes insolvent.

  3. If the loanTokens from all pools are currently lent out, the function would always revert, as it would still try to transfer the loanTokens to the feeReceiver without having the balance.

Also note that the same faulty implementation is present in buyLoan.

Tools Used

None

Recommendations

The pending interest should not be treated as debt, but instead be tracked seperately. Additionally, the accumulated protocolInterest must not be transferred in giveLoan, as it has not been received yet. How exactly this is implemented is up to the developers to decide.

Support

FAQs

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