fee-on-transferlisted
Install: claude install-skill iktok90-design/ai-smart-contract-auditor
# Fee-on-transfer token accounting detection
## When this applies
Trigger on any of:
- Deposit/stake/`addLiquidity` that records the `amount` argument after `transferFrom`
- Vault/ERC-4626 `deposit` minting shares proportional to the requested assets, not received
- AMM/router updating reserves with the input amount rather than actual receipt
- Lending protocols crediting collateral by passed amount
- Bridges locking/burning `amount` then minting the same amount on the far side
- Any flow assuming `received == amount` for arbitrary ERC-20s
## Detection patterns
### Credit passed amount, not delta (HIGH)
```solidity
function deposit(uint256 amount) external {
token.transferFrom(msg.sender, address(this), amount);
balanceOf[msg.sender] += amount; // ← amount, but FoT token delivered less
totalDeposited += amount;
}
```
**Signal:** the contract believes it holds more than it does. On a fee-on-transfer token (USDT with fee switch enabled, PAXG, many meme tokens), `totalDeposited` exceeds the real balance — last withdrawers are insolvent, or an attacker mints excess shares/LP.
### AMM reserve desync (HIGH)
Router records input `amountIn` into reserves but the pair received `amountIn - fee`. `k` invariant is computed on phantom reserves, mispricing the swap and letting an attacker drain the shortfall over time (the Uniswap-V2-style "supports FoT" `*SupportingFeeOnTransferTokens` functions exist precisely because of this).
### Rebasing double-count