20,000 USDC
View results
Submission Details
Severity: medium

Tokens that do not fully conform to the EIP20 standard brick the contract

Summary

The protocol is intended to allow users to lend and borrow any ERC20 token. However certain ERC20 tokens such as USDT will be totally incompatible with the protocol.

Vulnerability Details

Some tokens (like USDT) don't correctly implement the EIP20 standard and their transfer/transferFrom function returns void instead of a successful boolean. Calling these functions with the correct EIP20 function signatures will always revert, even if the transaction ought to have been successful.

Specifically, in Lender USDT is unable to be a valid loanToken or collateralToken. See below each code snippet that will guarantee a revert in such a situation.

File: src/Lender.sol
152: IERC20(p.loanToken).transferFrom(
153: p.lender,
154: address(this),
155: p.poolBalance - currentBalance
156: );
159: IERC20(p.loanToken).transfer(
160: p.lender,
161: currentBalance - p.poolBalance
162: );
187: IERC20(pools[poolId].loanToken).transferFrom(
188: msg.sender,
189: address(this),
190: amount
191: );
203: IERC20(pools[poolId].loanToken).transfer(msg.sender, amount);
267: IERC20(loan.loanToken).transfer(feeReceiver, fees);
269: IERC20(loan.loanToken).transfer(msg.sender, debt - fees);
271: IERC20(loan.collateralToken).transferFrom(
272: msg.sender,
273: address(this),
274: collateral
275: );
317: IERC20(loan.loanToken).transferFrom(
318: msg.sender,
319: address(this),
320: loan.debt + lenderInterest
321: );
323: IERC20(loan.loanToken).transferFrom(
324: msg.sender,
325: feeReceiver,
326: protocolInterest
327: );
329: IERC20(loan.collateralToken).transfer(
330: loan.borrower,
331: loan.collateral
332: );
403: IERC20(loan.loanToken).transfer(feeReceiver, protocolInterest);
505: IERC20(loan.loanToken).transfer(feeReceiver, protocolInterest);
563: IERC20(loan.collateralToken).transfer(feeReceiver, govFee);
565: IERC20(loan.collateralToken).transfer(
566: loan.lender,
567: loan.collateral - govFee
568: );
642: IERC20(loan.loanToken).transferFrom(
643: msg.sender,
644: address(this),
645: debtToPay - debt
646: );
651: IERC20(loan.loanToken).transfer(feeReceiver, fee);
653: IERC20(loan.loanToken).transfer(msg.sender, debt - debtToPay - fee);
656: IERC20(loan.loanToken).transfer(feeReceiver, protocolInterest);
663: IERC20(loan.collateralToken).transferFrom(
664: msg.sender,
665: address(this),
666: collateral - loan.collateral
667: );
670: IERC20(loan.collateralToken).transfer(
671: msg.sender,
672: loan.collateral - collateral
673: );

Impact

Tokens that don't correctly implement the latest EIP20 spec, like USDT, will be unusable in the protocol as they revert the transaction because of the missing return value.

Tools Used

Manual review

Recommendations

Use OpenZeppelin's SafeERC20 library for ERC20 transfers.

Support

FAQs

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