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

A User/Lender Can force someone else pool to take their outstanding loan

Summary

A User/Lender Can force someone else pool to take their outstanding loan by calling buyLoan() with someone else poolid

Vulnerability Details

lets say alice has a outstanding loan which she has taken form bob who is the lender now bob decide to auction alice loan for someone else to buy by calling startAuction:
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L437

function startAuction(uint256[] calldata loanIds) public {
for (uint256 i = 0; i < loanIds.length; i++) {
uint256 loanId = loanIds[i];
// get the loan info
Loan memory loan = loans[loanId];
// validate the loan
if (msg.sender != loan.lender) revert Unauthorized();
if (loan.auctionStartTimestamp != type(uint256).max)
revert AuctionStarted();
// set the auction start timestamp
loans[loanId].auctionStartTimestamp = block.timestamp;
emit AuctionStart(
loan.borrower,
loan.lender,
loanId,
loan.debt,
loan.collateral,
block.timestamp,
loan.auctionLength
);
}
}

Now instead of letting someone else buy loan bob will call buyLoan function with someone else poolid lets say mark's id and he will pay small amount of protocol interest , now the loan debt is added to the mark's pool instead of adding in bobs pool and bobs pooldebt will be reduced by the loan which alice has taken also the poolbalance will be increased and he will get the lender interest also (see audit tag):
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L489C1-L505C72

_updatePoolBalance(poolId, pools[poolId].poolBalance - totalDebt);//@audit alice loan is being added to mark's pool
pools[poolId].outstandingLoans += totalDebt;
// now update the pool balance of the old lender
bytes32 oldPoolId = getPoolId( //@audit this will return bob's pool id
loan.lender,
loan.loanToken,
loan.collateralToken
);
_updatePoolBalance(
oldPoolId,
pools[oldPoolId].poolBalance + loan.debt + lenderInterest
);
pools[oldPoolId].outstandingLoans -= loan.debt; //@audit alice loan is being deducted from bob's pool
// transfer the protocol fee to the governance
IERC20(loan.loanToken).transfer(feeReceiver, protocolInterest);

now bob will became the lender of loan but the loan is being imposed on mark's pool without him knowing even if mark wants to auction alice loan he will not be able to because bob is now the lender :
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L518

loans[loanId].lender = msg.sender;

bob can repeat this process and increase it poolbalance also decrease it's pool debt to 0 and taking the lender interest also because the old pool id will be same because lender collateraltoken and loantoken is not changed :
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L493-L497

bytes32 oldPoolId = getPoolId(
loan.lender,
loan.loanToken,
loan.collateralToken
);

If alice decide to pay her debt the repaid amount will be added into bob's pool balance instead of mark's pool
https://github.com/Cyfrin/2023-07-beedle/blob/main/src/Lender.sol#L303-L307

Impact

a lender can increase its poolbalance and reducing its debt by imposing its pool debt to someone else

Tools Used

vs

Recommendations

original lender should not be able to buy loan and also someone else should not be able to buy loan on someone else behalf(poolid)

Support

FAQs

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