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.