20,000 USDC
View results
Submission Details
Severity: high

Unchecked ERC20 transfers in `repay()` allow malicious borrower to redeem collateral without paying the debt

Summary

The repay() function in Lender contract performs couple of different ERC20 transfers. The return values of those transfers are not checked. Some tokens do not revert on transfer failure, but return false instead. The lack of return value check may allow the malicious borrower to redeem collateral without paying back the debt.

Vulnerability Details

The following three ERC20 transfers occur in the repay() function:

  1. Transfer of loanToken from the borrower to the contract (paying back the debt)

  2. Transfer of loanToken from the borrower to the feeReceiver (protocol fees)

  3. Transfer of collateralToken from the contract to the borrower (collateral)

The return values of those calls are not checked. This is specially problematic with the 1st and 2nd transfer, as the function never confirms if the loanToken transfer was really successful. If that transfer has failed, for example because the borrower does not own enough loanToken to repay a loan, the borrower would still receive the collateral back.

The problematic unchecked transfers:
https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L317-L327

Impact

The malicious borrower can redeem the collateral without paying back the debt. This requires the loanToken of the pool not to revert on failure.

The unsafe ERC20 operations have been reported in the known issues section under low category, however this particular exploitation of them is a separate, high-risk issue.

Tools Used

Manual Review

Recommendations

Replace the transfer/transferFrom calls with the OpenZeppelin safeTransfer/safeTransferFrom.

Support

FAQs

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