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.
The following three ERC20 transfers occur in the repay()
function:
Transfer of loanToken
from the borrower to the contract (paying back the debt)
Transfer of loanToken
from the borrower to the feeReceiver
(protocol fees)
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
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.
Manual Review
Replace the transfer
/transferFrom
calls with the OpenZeppelin safeTransfer
/safeTransferFrom
.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.