Fee-on-Transfer
Detects contracts that assume the received token amount equals the transferred amount, failing to account for fee-on-transfer tokens.
Fee-on-Transfer
Overview
The fee-on-transfer detector identifies contracts that call transferFrom() and use the requested amount for accounting without checking the actual received balance. Fee-on-transfer tokens (also called deflationary tokens) deduct a percentage on every transfer, so the contract receives less than the nominal amount. Using the pre-fee amount for internal bookkeeping creates an accounting mismatch that grows over time.
Why This Is an Issue
When a protocol credits a user with the full transfer amount but actually receives less due to the token’s fee, the contract becomes undercollateralized. The shortfall accumulates with each transfer until the contract cannot fulfill withdrawal requests. The last users to withdraw find the contract insolvent. Tokens like STA, PAXG, and USDT (with its optional fee flag) are common examples.
How to Resolve
// Before: Vulnerable — assumes full amount received
function deposit(address token, uint256 amount) external {
IERC20(token).transferFrom(msg.sender, address(this), amount);
balances[msg.sender] += amount; // Credits full amount
}
// After: Fixed — measure actual received amount
function deposit(address token, uint256 amount) external {
uint256 before = IERC20(token).balanceOf(address(this));
IERC20(token).transferFrom(msg.sender, address(this), amount);
uint256 received = IERC20(token).balanceOf(address(this)) - before;
balances[msg.sender] += received; // Credits actual received
}
Detection Methodology
- TransferFrom identification: Locates
transferFrom(address,address,uint256)calls targeting external token contracts. - Amount usage tracking: Traces whether the amount parameter (not the actual balance delta) is used in subsequent storage writes.
- Balance-check pattern: Looks for the recommended
balanceOf(before) ... transfer ... balanceOf(after)pattern. - Token classification: Cross-references known fee-on-transfer tokens when available.
Limitations
False positives: Contracts that only support a known whitelist of non-fee tokens are safe but may be flagged if the whitelist is not statically determinable. False negatives: Tokens with conditional fees (e.g., USDT’s fee is currently set to zero) may not trigger the detector because the fee pattern is dormant.
Related Detectors
- Rebasing Token — detects issues with elastic-supply tokens
- Precision Errors — detects rounding and precision loss