Not all IERC20 implementations revert() when there's a failure in transfer()/transferFrom(). The function signature has a boolean return value and they indicate errors that way instead. By not checking the return value, operations that should have marked as failed, may potentially go through without actually making a payment.
There are 20 instances of this issue:
Lender.setPool(Pool) ignores return value by IERC20(p.loanToken).transfer(p.lender,currentBalance - p.poolBalance)
Lender.setPool(Pool) ignores return value by IERC20(p.loanToken).transferFrom(p.lender,address(this),p.poolBalance - currentBalance)
Lender.addToPool(bytes32,uint256) ignores return value by IERC20(pools[poolId].loanToken).transferFrom(msg.sender,address(this),amount)
Lender.removeFromPool(bytes32,uint256) ignores return value by IERC20(pools[poolId].loanToken).transfer(msg.sender,amount)
Lender.borrow(Borrow[]) ignores return value by IERC20(loan.collateralToken).transferFrom(msg.sender,address(this),collateral)
Lender.borrow(Borrow[]) ignores return value by IERC20(loan.loanToken).transfer(feeReceiver,fees)
Lender.borrow(Borrow[]) ignores return value by IERC20(loan.loanToken).transfer(msg.sender,debt - fees)
Lender.repay(uint256[]) ignores return value by IERC20(loan.loanToken).transferFrom(msg.sender,feeReceiver,protocolInterest)
Lender.repay(uint256[]) ignores return value by IERC20(loan.loanToken).transferFrom(msg.sender,address(this),loan.debt + lenderInterest)
Lender.repay(uint256[]) ignores return value by IERC20(loan.collateralToken).transfer(loan.borrower,loan.collateral)
Lender.giveLoan(uint256[],bytes32[]) ignores return value by IERC20(loan.loanToken).transfer(feeReceiver,protocolInterest)
Lender.buyLoan(uint256,bytes32) ignores return value by IERC20(loan.loanToken).transfer(feeReceiver,protocolInterest)
Lender.seizeLoan(uint256[]) ignores return value by IERC20(loan.collateralToken).transfer(loan.lender,loan.collateral - govFee)
Lender.seizeLoan(uint256[]) ignores return value by IERC20(loan.collateralToken).transfer(feeReceiver,govFee)
Lender.refinance(Refinance[]) ignores return value by IERC20(loan.loanToken).transferFrom(msg.sender,address(this),debtToPay - debt)
Lender.refinance(Refinance[]) ignores return value by IERC20(loan.loanToken).transfer(msg.sender,debt - debtToPay - fee)
Lender.refinance(Refinance[]) ignores return value by IERC20(loan.collateralToken).transfer(msg.sender,loan.collateral - collateral)
Lender.refinance(Refinance[]) ignores return value by IERC20(loan.loanToken).transfer(feeReceiver,protocolInterest)
Lender.refinance(Refinance[]) ignores return value by IERC20(loan.loanToken).transfer(feeReceiver,fee)
Lender.refinance(Refinance[]) ignores return value by IERC20(loan.collateralToken).transferFrom(msg.sender,address(this),collateral - loan.collateral)
Several tokens do not revert in case of failure and return false. If one of these tokens is used in MyBank, deposit will not revert if the transfer fails, and an attacker can call deposit for free..
Use SafeERC20, or ensure that the transfer/transferFrom return value is checked.
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.