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

Reentrancy in seizeLoan in Lender.sol

Summary

seizeLoan function in Lender.sol file, doesn't follow the CEI pattern and updates loans after an external call.

Vulnerability Details

The implementation does not strictly follow the Checks-Effects-Interactions (CEI) pattern.
Malicious attackers and unsuspecting ecosystem participants can lend a loan with ERC-777 tokens (which have a callback that can take control) as collateral and in sieze a loan exploit this vulnerability.
A malicious user can drain a contract from loan.collateralToken with the following steps.

  1. A user lend a loan.

  2. sieze a loan

  3. contract transfer collateral to loan.lender

  4. as the loans and pools aren't updated

  5. A user reenter again and get collateral again

IERC20(loan.collateralToken).transfer(
loan.lender,
loan.collateral - govFee
);
bytes32 poolId = keccak256(
abi.encode(loan.lender, loan.loanToken, loan.collateralToken)
);
// update the pool outstanding loans
pools[poolId].outstandingLoans -= loan.debt;
emit LoanSiezed(
loan.borrower,
loan.lender,
loanId,
loan.collateral
);
// delete the loan
delete loans[loanId]; l
}

Impact

  1. drain a contract and steel all loan.collateralToken the from contract

  2. change Pool outstanding deb

Tools Used

manual review

Recommendations

follow CEI pattern and update state changes before external call.

// calculate the fee
uint256 govFee = (borrowerFee * loan.collateral) / 10000;
+ delete loans[loanId];
+ bytes32 poolId = keccak256(
+ abi.encode(loan.lender, loan.loanToken, loan.collateralToken)
+ );
+
+ // update the pool outstanding loans
+ pools[poolId].outstandingLoans -= loan.debt;
// transfer the protocol fee to governance
IERC20(loan.collateralToken).transfer(feeReceiver, govFee);
// transfer the collateral tokens from the contract to the lender
IERC20(loan.collateralToken).transfer(
loan.lender,
loan.collateral - govFee
);
- bytes32 poolId = keccak256(
- abi.encode(loan.lender, loan.loanToken, loan.collateralToken)
- );
- // update the pool outstanding loans
- pools[poolId].outstandingLoans -= loan.debt;
emit LoanSiezed(

Support

FAQs

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