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

Lender.sol#L292 : lack of re-entrancy protection during repay

Summary

During repay function call, either the borrower or anyone on behalf of the borrower can repay the debt.

Reay calculates the interest and fee and transfer the total debt + interest to the contract and fee to the fee receiver.
Collateral amount is transferred to the borrower.
at last the loan struct is deleted.

Vulnerability Details

function repay(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];
// calculate the interest
(
uint256 lenderInterest,
uint256 protocolInterest
) = _calculateInterest(loan);
bytes32 poolId = getPoolId(
loan.lender,
loan.loanToken,
loan.collateralToken
);
// update the pool balance
_updatePoolBalance(
poolId,
pools[poolId].poolBalance + loan.debt + lenderInterest
);
pools[poolId].outstandingLoans -= loan.debt; ----------------->> outstanding value update
// transfer the loan tokens from the borrower to the pool
IERC20(loan.loanToken).transferFrom(
msg.sender,
address(this),
loan.debt + lenderInterest ---------------------->> debt + interest to sent to contract
);
// transfer the protocol fee to the fee receiver
IERC20(loan.loanToken).transferFrom(
msg.sender,
feeReceiver,
protocolInterest -------------------------------->>> fee to fee receiver
);
// transfer the collateral tokens from the contract to the borrower
IERC20(loan.collateralToken).transfer(
loan.borrower,
loan.collateral ------------------------------------------------->> borrower is sent with collateral.
);
emit Repaid(
msg.sender,
loan.lender,
loanId,
loan.debt,
loan.collateral,
loan.interestRate,
loan.startTimestamp
);
// delete the loan
delete loans[loanId]; ---------------------------------->> loan is deleted.
}
}

Impact

Since the loan struct is deleted after making the transfer calls, borrower can re-eneter the repay function and drain out the contract funds.

Tools Used

Manual review.

Recommendations

Load the loan details in separate struct in local memory and delete the loan at the start of the function.
use the temporary struct data in further down process.

Support

FAQs

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