Filtering Risky Tokens: Fee-on-Transfer Detection and Rug Pull Defense

한국어로 읽기

TECH INSIGHT / EXPLAINED

Token screening is evidence gathering, not proof of safety. A token can implement an ERC-20-shaped interface while applying transfer fees, restrictions or upgradeable behavior that a simple pool quote does not capture.

Three adult colleagues explain token risk
AI-generated teaching illustration, not an actual operating screen or performance record.

A balance delta is an observation

If a controlled transfer nominally sends 100 units and the receiver’s balance increases by 97, record a short receipt. Do not conclude that every transfer always has a 3% tax: sender, recipient, route, amount and block state can matter. Rebasing, concurrent movements and unusual balance reporting can also affect a delta. The function below labels evidence rather than certifying the token.

def observed_receipt(before, after, nominal):
    if any(type(v) is not int or v < 0 for v in (before, after, nominal)):
        raise ValueError("nonnegative integer base units required")
    if nominal == 0 or after < before:
        return "inconclusive"
    received = after - before
    return "short_receipt" if received < nominal else "no_shortfall_observed"

assert observed_receipt(1000, 1097, 100) == "short_receipt"
assert observed_receipt(1000, 1100, 100) == "no_shortfall_observed"
assert observed_receipt(1000, 999, 100) == "inconclusive"

Simulate the whole round trip in one state

Separate eth_call operations do not persist one call’s state changes into the next. To test buy then sell, execute them within one simulation contract call or a controlled fork that carries state forward. Match sender, route, amount, approvals and block. A success only describes that scenario; a privileged actor may change restrictions later. A revert can also mean a wrong route or insufficient allowance, so classify its cause before calling it a honeypot.

Store a decision with its scope

Key screening records by chain ID and validated token address, normalizing consistently on both insert and lookup. Store reason, evidence block/hash, code or implementation identity, tested amounts and review time. A denylist is useful for known failures but unknown tokens should not become approved automatically. A reviewed allowlist with explicit retesting rules is a clearer default for a limited bot.

Liquidity and verified source are partial evidence

A large pool, locked LP tokens, or verified source does not rule out minting privileges, blacklists, proxy upgrades or other controls. Inspect actual administrative capabilities and relevant liquidity positions. Do not generalize that newer chains necessarily have more malicious tokens without data. Apply size caps and minimum received amounts, and avoid interpreting one passed simulation as a guarantee against a rug pull.

Separate return handling from the economic result

A low-level call can report success while an ERC-20 function returns false. Record three separate layers: call completion, interpretation of return data, and the balance change. The ERC-20 specification explicitly requires callers to handle false. A legacy implementation returning no data and a response with an invalid length are different cases.

SafeERC20 helps handle return conventions. Its successful completion does not prove that the recipient received the nominal amount. Keep the return-handling result separate from any receipt shortfall in the test report. Otherwise, a compatibility issue can become confused with a transfer-amount issue, making both diagnosis and retesting less reliable.

The integer boundary a tiny transfer misses

Suppose a synthetic token computes its fee as nominal * 3 // 100. The following results come from an independent Python integer experiment, not an investigation of a deployed token. Testing only 1 or 33 raw units would show zero fee and miss the modeled deduction. Include values immediately below and above a boundary.

Nominal raw unitsFeeReceived
101
33033
34133
1,00030970

This table demonstrates rounding, not a universal algorithm for discovering token fees. If a maximum transfer amount exists, add its boundary; if buying and selling use different routes, test both directions as separate conditions. Preserve differences of one raw unit even when the formatted decimal display makes the results look identical.

Change one condition at a time

When designing a controlled fork experiment, establish sufficient balance, allowance, and a valid route first. Then change one factor at a time. Separating a sale that fails with insufficient allowance from one that fails with sufficient allowance narrows the diagnosis. Also distinguish calls from a direct account and calls through a helper contract: introducing the helper may change the msg.sender observed by the token.

Record the expected failure reason and actual return bytes. An undecodable revert should remain an unresolved failure rather than immediately becoming a malicious-token verdict. Approval, purchase, and sale must share continuing state within the scenario. Listing independent eth_call requests in sequence does not reproduce that experiment. Use the execution scope described in the eth_call documentation to classify the test harness correctly.

Define when evidence becomes stale

A screening record can move from unknown to conditionally passed to retest required, or to rejected. Besides expiry, implementation changes, administrative changes, and unexpected receipts should trigger reevaluation. A proxy's exterior code hash can remain unchanged while its implementation changes, so a cache that checks only the exterior address is insufficient.

The implementation and beacon slots and change events in ERC-1967 provide observation points for proxies using that standard. They do not describe every proxy architecture. Leave an unrecognized structure unresolved, and prevent automatic reuse of an earlier pass while retesting is pending. This evidence lifecycle cannot guarantee protection from subsequent privilege changes or losses.

Documentation and next steps

Content and examples reviewed: 2026-10-01

댓글