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

Malicious Lender can frontrun borrow() tx, and this can lead to instant liquidation

Summary

Malicious Lender can change pool interest rate right before borrow transaction.

Vulnerability Details

The borrow() function allows a borrower to provide collateral to a pool created by a lender and borrow loan tokens. Later, upon repayment, the borrower returns the borrowed loan tokens along with the pool's interest and receives the collateral back, or lender can start auction.

If a borrower calls the borrow() function and a malicious lender frontruns the borrower's transaction and sets the pool's config to other values, like changing interest rate to the maximum and auctionLength To Minimum(1).

Change config by frontrunning will cause losses of borrower.

Scenario 1

  1. Alice(borrower) send borrow() tx to pool that has auctionLength of 3 days

  2. Malicious lender frontrun her tx and set auctionLength to 1 second.

  3. At the next block Mal lender start auction, and it will end after 1 second.

  4. Now Lender can seize the loan.

  5. Since the collateral value is more valuable than loan value, borrower will loss funds.

Scenario 2

  1. Alice(borrower) send borrow() tx with when interest rate is 1000

  2. Malicious lender frontrun her tx and set interest rate to MAX_INTEREST_RATE(100000)

  3. Alice borrow loanToken with intereste rate of MAX_INTEREST_RATE(100000)

  4. After a month later borrower want to repay his debt.

  5. Since interest rate was 1000% changed before his tx, he have to pay 100 times more interest than his actual interest.

Therefore, it is necessary to implement a verification process like slippage protection in Defi Protocol.

Impact

Users may have to pay a higher interest rate than they originally anticipated.

Tools Used

vs code

Recommendations

add a maxInterestRate in Borrow Structure, and compare with pool interest rate in borrow function.

struct Borrow {
/// @notice the pool ID to borrow from
bytes32 poolId;
/// @notice the amount to borrow
uint256 debt;
/// @notice the amount of collateral to put up
uint256 collateral;
/// @notice maximum interest rate
uint256 maxInterestRate;
/// @notice minimum auction length
uint256 minAuctionLength;
}
function borrow(Borrow[] calldata borrows) public {
...
if(borrows[i].maxInterestRate < pool[i].interestRate) revert();
if(borrows[i].minAuctionLength > pool[i].auctionLength) revert();
...
}

Support

FAQs

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