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

Lender can frontrun Borrower by interest rate increase before borrow

Summary

A lender can have a pool with attractive interest rates to entice potential borrowers. When the lender sees a borrow txt on the mempool, he can frontrun a usurious increase on the interest rates.

Vulnerability Details

The lender is allowed to update his pools interest rate at any time with the Lender.sol functions setPool() or updateInterestRate(). When the borrower calls the borrow() function, he will take the borrow with whatever the current pool interest rate is.

Take this scenario:

ETH price is 1000 USD.

  1. Lender creates a pool with 1% interest rate. The loan token is USDC and the collateral is ETH. Max loan ratio is 50%.

  2. Borrower decides to take a loan of 500 USDC and deposits 1 ETH as collateral.

  3. Lender frontruns the borrow tx and updates the interest rate to 1000%.

Everyday the interest on the repayment on the loan will increase by about 2.7%.
Considering that the price of ETH stays the same, in around 5 weeks the repayment double to 1000 USDC.

  1. Lender starts an auction. It is very likely that the borrower will not repay the loan and no other lender will take the position.

  2. After the auction has ended, the Lender calls seizeLoan() and takes the collateral.

Impact

The borrower will have a loan with unexpected high interest rates.

Tools Used

Manual review.

Recommendations

On the borrow() function, the borrower should pass by parameter the interest rate that they accept for the borrow. If the interest rate provided by the borrower is different than the interest on the pool, the function should revert with an error.

diff --git a/src/utils/Structs.sol b/src/utils/Structs.sol

struct Borrow {
@@ -29,6 +29,8 @@ struct Borrow {
    uint256 debt;
    /// @notice the amount of collateral to put up
    uint256 collateral;
+    /// @notice the interest rate per year in BIPs
+    uint256 interestRate;
}

diff --git a/src/Lender.sol b/src/Lender.sol

@@ -242,6 +242,14 @@ contract Lender is Ownable {
         if (debt < pool.minLoanSize) revert LoanTooSmall();
         if (debt > pool.poolBalance) revert LoanTooLarge();
         if (collateral == 0) revert ZeroCollateral();
+         // validate the expected interest rate 
+         if (borrows[i].interestRate != pool.interestRate) revert UnexpectedInterest();

Support

FAQs

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

Give us feedback!