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

Malicious lender can frontrun calls to `borrow` to deceive borrowers into accepting a higher interest rate

Summary

Lenders are able to call updateInterestRate to change the interest rate of their pool at any time. Therefore a malicious lender can observe a transaction to borrow their loan in the mempool, and frontrun it with a call to set interestRate to the max rate. The borrower, expecting a much lower interest rate, will have locked in a loan at a higher rate than they agreed to. They may not even realise that this happened, and hold the loan for a long time without realising that they owe more than they realise.

Vulnerability Details

updateInterestRate allows lenders to change the interest rate on pool that they have already created. The only restrictions in place are that the caller must be the lender, and the interestRate is below the MAX_INTEREST_RATE. This means that there is nothing stopping a malicious lender from frontrunning borrow transactions to trick borrowers into accepting higher than advertised interest rates.

File: src\Lender.sol
221: function updateInterestRate(bytes32 poolId, uint256 interestRate) external {
222: if (pools[poolId].lender != msg.sender) revert Unauthorized();
223: if (interestRate > MAX_INTEREST_RATE) revert PoolConfig();
224: pools[poolId].interestRate = interestRate;
225: emit PoolInterestRateUpdated(poolId, interestRate);
226: }

When a user calls borrow, the interest rate of the pool at the time of execution is locked in for the duration of the loan; a Loan object is created with this interest rate and pushed to the loans array. A borrower may see a loan with a low interest rate that they are comfortable with, call borrow to borrow the loan, and involuntarily take the loan at a much higher interest rate.

Impact

Lenders can force borrowers to accept up to the max interest rate (1000%).

Tools Used

Manual review

Recommendations

There are two solutions that make sense. The simpler is to remove the ability for lenders to adjust the interest rate of already created pools entirely, which makes this exploitation impossible but also removes some functionality from the protocol.

Alternatively, the Borrow struct could add an element maxInterestRate that defines the largest interest rate that the borrower is willing to accept. Change borrow to revert if the pools interestRate is greater than the callers specified maxInterestRate.

Support

FAQs

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