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

buyLoan does not verify the caller

Summary

By function definition, buyLoan can be called by anyone, but caller needs to own the pool and bugLoan's object is that pool.
But there's no correlation check in the function, and caller can optionally specify a pool it doesn't own, and set loans[loanId].lender caller.
If caller does not own the pool, the calculated poolId does not exist, and the lender cannot get their collateral back anymore.

Vulnerability Details

// 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();
// update the loan with the new info
loans[loanId].lender = msg.sender;
loans[loanId].interestRate = pools[poolId].interestRate;
loans[loanId].startTimestamp = block.timestamp;
loans[loanId].auctionStartTimestamp = type(uint256).max;
loans[loanId].debt = totalDebt;

As you can see from the code, there is no validation for msg.sender.
The caller only needs to specify a poolId to pass the above verification, and then he can point the loan.lender to himself, causing the lender to be unable to redeem the collateral, because caller does not own a pool.

Impact

Malicious users can call buyLoan to permanently lock the collateral and the corresponding pool get debt.

// now update the pool balance of the old lender
bytes32 oldPoolId = getPoolId(
loan.lender,
loan.loanToken,
loan.collateralToken
);
_updatePoolBalance(
oldPoolId,
pools[oldPoolId].poolBalance + loan.debt + lenderInterest
);
pools[oldPoolId].outstandingLoans -= loan.debt;

Because last line of code overflowed, the attacker could not sell the loan directly, but they could then manually create pool and borrow, then sell the loan.

Tools Used

Manual review

Recommendations

Should verify that the specified pool is owned by caller.

Support

FAQs

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