20,000 USDC
View results
Submission Details
Severity: high
Valid

Protocol is incompatible with fee-on-transfer tokens

Summary

If fee-on-transfer tokens (such as STA, PAXG or USDT and USDC can also activate fees) are used as collateral or loan token, protocol will lose funds or users funds get stuck.

Vulnerability Details

Some tokens are getting fee's from transfer and transferFrom functions. However these tokens will cause problems in the protocol.

There are so many transfers are happening within protocol and during these transfers, poolBalance's and debt's are changing as much as transfer amount. One of such examples:

function addToPool(bytes32 poolId, uint256 amount) external {
if (pools[poolId].lender != msg.sender) revert Unauthorized();
if (amount == 0) revert PoolConfig();
_updatePoolBalance(poolId, pools[poolId].poolBalance + amount);
// transfer the loan tokens from the lender to the contract
IERC20(pools[poolId].loanToken).transferFrom(
msg.sender,
address(this),
amount
);
}

But since these tokens takes fee on transfer, transferred amount to the contract will be less than parameter amount, and when user wants to for example get their tokens back they will be able to get more than they actually deposited (if protocol has enough balance).

For example let's assume token takes %10 transfer fee and see what could go wrong:

User1 transfers 1e18 token and contract receives 9e17 token, User2 transfers 1e18 token and contract receives 9e17 token. Now contract has 1.8e18 tokens. User1 removeFromPool and contract sends 1e18 token to User1. There is only 8e17 token left in the contract and User2 lost his/her funds.

This was just one of scenarios that can occur with these tokens. With this example in mind, it is obvious that protocol don't work as expected with fee on transfer tokens.

Impact

Since protocol expected to work with any ERC20 token as mentioned by sponsor in discord and because using fee on transfer tokens lets users of the protocol to lose funds, I consider this as high.

Tools Used

Manual Review

Recommendations

Measure the contract balance before and after the call to transfer()/transferFrom(), and use the difference between the two as the amount, rather than the amount stated.

Support

FAQs

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