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

`buyLoan()` should check if a loan and pool have the same collateral/loan tokens.

Summary

buyLoan() doesn't validate collateral/loan tokens between a loan and a pool.

Vulnerability Details

Lenders can buy a loan during the auction period using buyLoan().

function buyLoan(uint256 loanId, bytes32 poolId) public { //@audit should validate collateral/loanToken
// get the loan info
Loan memory loan = loans[loanId];
// validate the loan
if (loan.auctionStartTimestamp == type(uint256).max)
revert AuctionNotStarted();
if (block.timestamp > loan.auctionStartTimestamp + loan.auctionLength)
revert AuctionEnded();
// calculate the current interest rate
uint256 timeElapsed = block.timestamp - loan.auctionStartTimestamp;
uint256 currentAuctionRate = (MAX_INTEREST_RATE * timeElapsed) /
loan.auctionLength;
// validate the rate
if (pools[poolId].interestRate > currentAuctionRate) revert RateTooHigh();
// calculate the interest
(uint256 lenderInterest, uint256 protocolInterest) = _calculateInterest(
loan
);
...
}

But this function doesn't validate if the loan and pool have the same collateral/loan tokens and attackers can steal funds from the contract.

  1. An attacker Alice notices the Lender contract has 10000 USDC for some pools.

  2. Then she creates a pool with collateral = ETH, loanToken = USDC using setPool() and deposits 10000 USDC.

  3. In the same transaction, she borrows 10000 USDC by providing 10 ETH using another account (called Alice2). Now the contract has 10 ETH and 10000 USDC.

  4. Then she starts an auction immediately and buys Alice2's loan after creating another pool. This pool has collateral = ETH, loanToken = FakeUSDC(zero cost) and she deposits 10000 FakeUSDC.

  5. After that, Alice2 repays the loan by depositing 10000 FakeUSDC with 0 costs and receives her 10 ETH(collateral).

  6. Also, Alice withdraws 10000 USDC from her original pool because there are no active loans. So the contract has 10000 FakeUSDC instead of 10000 USDC.

I've explained without any interest/protocol fees for simplicity but it shows attackers can steal any funds from the contract.

Impact

Attackers can steal all funds from the Lender contract using buyLoan().

Tools Used

Manual Review

Recommendations

We should validate collateral/loan tokens something like this.

Support

FAQs

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