Token Whitelisting Flaws
id: LS48H
title: Token Whitelisting Flaws
baseSeverity: H
category: validation
language: solidity
blockchain: [ethereum, polygon, bsc, arbitrum, optimism]
impact: Unauthorized tokens accepted, leading to fund loss, exploit, or market manipulation
status: draft
complexity: medium
attack_vector: external
mitigation_difficulty: medium
versions: [">=0.4.0", "<=0.8.25"]
cwe: CWE-284
swc: SWC-135
π Description
- Token Whitelisting Flaws occur when protocols rely on a whitelist to determine which ERC20 tokens are allowed in specific functions (e.g., swaps, staking, rewards, vaults), but fail to enforce, validate, or update the whitelist securely. Common issues include:
- Tokens not being properly validated against the whitelist
- Tokens whitelisted but later replaced via proxies
- Tokens with unexpected transfer behavior (e.g., fee-on-transfer) that bypass assumptions
- Contracts using transferFrom() or transfer() without whitelist enforcement
π¨ Vulnerable Code
mapping(address => bool) public isWhitelisted;
function deposit(address token, uint256 amount) external {
// β Missing check: isWhitelisted[token]
IERC20(token).transferFrom(msg.sender, address(this), amount);
}
π§ͺ Exploit Scenario
Step-by-step exploit process:
- Protocol claims to only accept whitelisted tokens, but forgets to enforce require(isWhitelisted[token]).
- Attacker deploys a malicious ERC20 token that always returns true for transferFrom() but doesn't actually transfer any tokens.
- They call deposit() with their fake token.
- Protocol records a deposit, triggering unearned rewards or share issuance.
- Attacker calls withdraw() or claim(), receiving real assets (e.g., ETH, USDC).
Assumptions:
- The protocol uses whitelists for accepted tokens but does not enforce them at the point of usage.
- The attacker can supply custom or malicious tokens with ERC20 interfaces.
- There is no validation of actual transfer success or balance deltas.
β Fixed Code
function deposit(address token, uint256 amount) external {
require(isWhitelisted[token], "Token not approved");
uint256 before = IERC20(token).balanceOf(address(this));
IERC20(token).transferFrom(msg.sender, address(this), amount);
uint256 after_ = IERC20(token).balanceOf(address(this));
require(after_ - before == amount, "Token transfer mismatch");
}
π§ Contextual Severity
- context: "Default"
severity: H
reasoning: "Improper token validation can break accounting and enable fake liquidity."
- context: "DeFi yield farm or DEX"
severity: C
reasoning: "Attacker can drain liquidity or mint rewards with invalid tokens."
- context: "Private app with strict onboarding"
severity: L
reasoning: "If access is tightly controlled, risk is significantly reduced."
π‘οΈ Prevention
Primary Defenses
- Always check whitelist status (require(isWhitelisted[token])) in every function accepting tokens.
- Validate token behavior using balance deltas, not just return values.
- Reject non-standard or unverified tokens, especially those with delegatecall, mint, or transferFrom overrides.
Additional Safeguards
- Lock the whitelist with governance voting or timelock before protocol launch.
- Use immutable registries or hash-based token validation (e.g., hashed bytecode).
- Simulate transfers with known tokens in testnet forks and coverage tools.
Detection Methods
- Static analysis: missing require(isWhitelisted[token]) or unchecked token usage.
- Runtime monitoring of unexpected token addresses or abnormal transferFrom() behavior.
- Tools: Slither (unchecked-token), MythX, Echidna fuzzing for ERC20 edge cases
π°οΈ Historical Exploits
- Name: dYdX Fake Token Listing Attempt
- Date: 2022
- Loss: $9 million
- Post-mortem: Link to post-mortem
π Further Reading
β Vulnerability Report
id: LS48H
title: Token Whitelisting Flaws
severity: H
score:
impact: 4
exploitability: 4
reachability: 4
complexity: 2
detectability: 3
finalScore: 3.85
π Justifications & Analysis
- Impact: Can directly compromise user funds or inflate rewards via fake tokens.
- Exploitability: Attacker simply needs to deploy and interact with a malicious ERC20.
- Reachability: Common in DeFi vaults, farms, or swaps accepting user-supplied token addresses.
- Complexity: Low to mediumβdeploy fake token or exploit proxy mutation.
- Detectability: Detectable via access control, input validation, and token behavior testing.