DeFi

Fee-on-Transfer Token

A fee-on-transfer token deducts a fee during transfer, so the recipient receives less than the amount requested by the sender.

A contract may ask to receive 100 tokens, but only 99 arrive because the token charges a transfer fee.

Fee-on-Transfer Token Explained in Detail

A fee-on-transfer token charges a fee when tokens move. The sender may request a transfer of amount, but the recipient receives less than amount.

This is valid behavior for some tokens, but it breaks integrations that credit users by the requested transfer amount instead of the actual amount received.

Smart contract example

function deposit(uint256 amount) external {
    token.transferFrom(msg.sender, address(this), amount);
    shares[msg.sender] += amount;
}

If the token deducts a transfer fee, the vault receives less than amount but credits the user for the full amount.

Fee-on-Transfer Token in Auditing

Fee-on-transfer behavior can break deposits, swaps, lending collateral, rewards, and ERC-4626 vault share math. The right accounting pattern usually measures the contract's balance before and after the transfer.

SafeERC20 can make call handling safer, but it does not prove that the contract received the requested amount.

Red flags in code

  • Deposits credit amount without checking the actual balance increase.

  • Swaps assume exact input or output without accounting for transfer fees.

  • Vault shares are minted from requested transfer amounts.

  • Reward accounting assumes transferred amounts equal received amounts.

  • The supported token list includes unknown or user-supplied ERC-20s.

How to test or review it

  • Test with a mock token that deducts a fee on every transfer.

  • Compare balanceOf(address(this)) before and after deposits and withdrawals.

  • Review whether slippage checks use actual received amounts.

  • Confirm unsupported fee-on-transfer assets are rejected explicitly.

  • Check interactions with non-standard ERC-20 behavior and paused or blacklisted tokens.

Sources