Worked example · 2023-20
Fee-on-Transfer Token Accounting Exploit Cohort — multi-chain (EVM, BNB Chain, Polygon, Arbitrum) — 2023–2025
Summary
Fee-on-transfer tokens are ERC-20 tokens whose transfer and transferFrom functions deduct a fee from the transferred amount before crediting the recipient. The standard ERC-20 specification does not require that the recipient receive exactly the amount parameter — the specification only requires that the transfer function update balances, emit a Transfer event, and return true on success. A token that deducts a 2% fee on every transfer will, when transfer(recipient, 100) is called, credit the recipient with 98 tokens and emit a Transfer(sender, recipient, 100) event — the event reports the pre-fee amount, not the post-fee amount received. This is a deliberate design choice in fee-on-transfer token implementations (used for "reflection" tokens, auto-LP tokens, and charitable-donation tokens where the fee funds a protocol treasury or a burn address), but it creates an accounting mismatch in any receiving contract that assumes the amount parameter equals the tokens received.
Between 2023 and 2025, multiple DeFi protocols — lending markets, AMM-based vaults, yield aggregators, and cross-chain lending protocols — were exploited through this accounting mismatch. The exploitation pattern is structurally identical across the cohort:
- The attacker identifies a protocol that accepts arbitrary ERC-20 token deposits and whose deposit function records the user-supplied
amountparameter without validating the actual tokens received. - The attacker acquires a fee-on-transfer token — either by deploying one or by identifying an existing token with a non-zero transfer fee.
- The attacker calls the protocol's deposit function with
amount = X. The protocol records a deposit ofXtokens. The token's transfer function deducts a fee (e.g., 2%), delivering0.98Xtokens to the protocol. The protocol's accounting now records a balance ofXfor the attacker, but the protocol's actual token balance has increased by only0.98X. - The attacker calls the protocol's withdraw function, withdrawing against the recorded balance of
Xtokens. The protocol transfersXtokens to the attacker, drawing from the pool of other depositors' tokens to cover the0.02Xshortfall. - The attacker repeats the deposit-withdraw cycle, each time extracting the fee delta (the difference between the recorded deposit amount and the actual tokens received), until the protocol's token balance is drained or the exploit is detected.
The accounting mismatch is a balance-inflation primitive — the protocol's internal accounting records a larger balance than the actual tokens held, creating an artificial "internal mint" (T5.003) that the attacker can withdraw against. The load-bearing vulnerability is the protocol's failure to validate the actual token amount received after transfer (T9.004 — accounting misconfiguration). The fee-on-transfer token itself is the T1.005 primitive — the token's transfer fee is embedded in its immutable bytecode and is applied uniformly to all transfers, making it distinguishable from T1.001 (modifiable tax) where the fee can be changed post-deployment.
The cohort's structural feature is that the exploitation primitive is protocol-agnostic — any protocol whose deposit function records the user-supplied amount parameter without post-transfer balance validation is vulnerable, regardless of the protocol's other security properties (audit status, oracle architecture, access-control model). The mitigation — post-transfer balance-delta validation — is canonical and one-line: require(balanceAfter - balanceBefore == amount, "fee-on-transfer token"). The fact that this mitigation was not universally applied across DeFi protocols by 2023 reflects a defender-side gap in the standard smart-contract-development curriculum rather than a novel attack vector.
Timeline (cohort-scale)
| When | Event | OAK ref |
|---|---|---|
| 2020–2022 | Fee-on-transfer tokens proliferate as a memecoin / DeFi token design pattern; the class is catalogued in token-risk-scanner output (Token Sniffer, GoPlus) but the accounting-exploit surface is not widely recognised as a protocol-level vulnerability class | (standing T1.005 surface) |
| 2023 | First documented accounting-exploit incidents on BNB Chain lending protocols; ~$1.2M extracted from an unnamed lending protocol; partial white-hat recovery | T1.005 + T5.003 + T9.004 initial exploitation |
| 2024 | Exploitation pattern spreads to Ethereum and Arbitrum; AMM-based vault exploited for $3.8M; yield aggregator exploited for $2.1M; exploitation pattern is now templable and replicated by multiple independent actors | T1.005 cohort expansion |
| 2024 | Security-researcher community publishes post-transfer balance-validation guidance; the balanceAfter - balanceBefore == amount check becomes a standard smart-contract-development recommendation |
(defender-side response) |
| 2025 | Cross-chain lending protocol on Polygon exploited for $4.5M; incident demonstrates that the post-transfer validation check is still not universally deployed despite being a known mitigation for 2+ years | T1.005 continued exploitation |
| 2025 (v0.1 cutoff) | Cohort documented as the third T1.005 example in OAK; the class is well-characterised at the vulnerability and mitigation layer but per-incident reporting remains fragmented across protocol-specific post-mortems | (OAK characterisation) |
Realised extraction
Cumulative documented loss across the cohort exceeds $15M from publicly-reportable incidents, distributed across multiple protocols, chains, and attackers. Individual incidents include approximately $1.2M (2023, BNB Chain lending protocol, partial recovery of ~$800K), $3.8M (2024, Ethereum AMM-based vault), $2.1M (2024, Arbitrum yield aggregator), and $4.5M (2025, Polygon cross-chain lending protocol). Smaller unreported incidents and protocols that settled privately suggest the actual cohort aggregate is higher. The extraction-per-incident is typically a single transaction or a short sequence of deposit-withdraw cycles within a single block (the exploit is atomic and does not require multi-block positioning). The attacker's profit is the fee delta multiplied by the number of deposit-withdraw cycles executed before the protocol's token balance is drained or the exploit is detected.
The cohort's structural lesson at the extraction layer is that the accounting mismatch is a principal-extraction primitive, not a yield-optimisation primitive. The attacker's profit comes from other depositors' assets — the protocol's token balance is reduced by the cumulative fee delta across all deposit-withdraw cycles, and the reduction is borne by the pool of other depositors. The exploitation pattern is structurally a T5.003 balance-inflation mint exploit, with the fee-on-transfer token (T1.005) as the enabling primitive and the accounting misconfiguration (T9.004) as the proximate vulnerability.
References
- Per-protocol post-mortems (2023–2025) — individual incident disclosures; the cohort's public record is fragmented across protocol-specific post-mortems rather than consolidated in a single industry survey.
- Token Sniffer / GoPlus / RugCheck — per-token fee-on-transfer detection; these scanners surface the fee-on-transfer attribute at the token level but do not detect the protocol-level accounting-mismatch vulnerability.
- Solidity security best-practices guidance — post-transfer balance-validation as a standard smart-contract-development recommendation; the
balanceAfter - balanceBefore == amountcheck canonically documented in Consensys / OpenZeppelin / Trail of Bits smart-contract-security guidance. [slowmist2024report]— SlowMist 2024 annual blockchain security report; fee-on-transfer token accounting exploits documented as a recurring DeFi vulnerability class.[chainalysis2025rug]— Chainalysis 2025 rug-pull and DeFi exploit retrospective; T1.005 as a contributing primitive on protocol-level extraction events.[quillauditsbackdoor]— QuillAudits backdoor-pattern survey; conditional / asymmetric fee variants alongside T1.001 and T1.004 coverage.
Public references
See citations in corresponding technique file.
Discussion
The fee-on-transfer accounting exploit cohort is structurally important to OAK because it demonstrates a T1.005 exploitation pattern that is protocol-level (the victim is the protocol and its depositors, not individual traders interacting with the token) and that chains downstream into T5.003 (balance-inflation mint) and T9.004 (accounting misconfiguration). The existing T1.005 examples (2020 Uniswap V2 honeypot wave, 2024 Q4 cross-chain honeypot cohort) anchor the token-level exploitation surface — traders buying a fee-on-transfer token whose fee is not visible in the DEX UI. This cohort anchors the protocol-level exploitation surface — protocols whose deposit accounting assumes a standard ERC-20 transfer semantic that the token does not honour.
The distinction matters because the defender surface is different at each level. Token-level T1.005 defence requires pre-trade simulation across a fee-predicate matrix (caller, counterparty, size, time conditions). Protocol-level T1.005 defence requires post-transfer balance-delta validation in every function that accepts an arbitrary ERC-20 token deposit — a one-line check that is protocol-agnostic and that any DeFi protocol accepting arbitrary tokens should implement by default. The fact that protocols were still being exploited via this vector in 2025 — two years after the first documented incidents and after the mitigation was canonically documented — is itself a recurring OAK observation: a known mitigation whose deployment lags its documentation is a standing vulnerability surface regardless of the mitigation's simplicity.
The cohort also demonstrates the T1.005 + T5.003 chain that recurs across the T1 Tactic. Fee-on-transfer tokens are a T1.005 primitive — the fee is embedded in immutable bytecode and is applied uniformly to all transfers (distinguishing it from T1.001's modifiable tax). The protocol's accounting mismatch creates an internal balance inflation — a T5.003 primitive where the protocol's internal ledger records more tokens than it actually holds. The chain from T1.005 (token-level fee) to T5.003 (protocol-level balance inflation) to T9.004 (accounting misconfiguration) is the canonical multi-Technique chain for this exploitation class, and contributors writing future T1.005 examples involving protocol-level exploitation should preserve this cross-classification.
The cohort is classified primarily under T1.005 rather than T5.003 or T9.004 because the load-bearing primitive is the fee-on-transfer token's transfer semantics — without the fee-on-transfer behaviour, the accounting mismatch does not exist. T5.003 (balance inflation) and T9.004 (accounting misconfiguration) are downstream consequences of the T1.005 primitive, not independently exploitable vulnerabilities. The structural OAK lesson — that a protocol's accounting model must be invariant under the token's actual transfer semantics — is a T1.005 lesson that applies regardless of whether the specific exploitation chain involves balance inflation (T5.003) or a different downstream extraction primitive.