Filtering Risky Tokens: Fee-on-Transfer Detection and Rug Pull Defense
Run an on-chain arbitrage bot long enough and you'll hit trades where the quote was perfect and the outcome was a loss. Often the culprit is the token itself. It looks like an ordinary ERC-20, but it quietly skims a fee on every transfer, or it's built so you can never sell it at all. The newer the chain, the more of these mines are buried in it. This article is about clearing them.
The Silent Sniper — Fee-on-Transfer Tokens
Send 100 of a standard ERC-20 and 100 arrives. Send 100 of a fee-on-transfer token and only 97 arrives — the other 3 goes somewhere else. Your bot's quoting logic budgeted for 100, receives 97, and comes up short at the repayment step of the arbitrage, which reverts the entire transaction. Best case you burn gas for nothing; worst case the accounting goes sideways and you take a real loss.
Detection is straightforward. Compare balances before and after an actual transfer, and if the amount received is less than the amount sent, flag it as a taxed token.
// fee-on-transfer detection: actual amount received vs. nominal amount sent
func isFeeOnTransfer(balanceBefore, balanceAfter, sentAmount *big.Int) bool {
received := new(big.Int).Sub(balanceAfter, balanceBefore)
// Receiving less than you sent means a fee was skimmed in transit
return received.Cmp(sentAmount) < 0
}
These tokens need to be caught at the simulation stage, via eth_call, before real capital is committed. You're doing a trial run of "can I actually round-trip this token?"
Blacklist — Once Burned, Remember
Re-deciding on every encounter is both inefficient and risky. Once a token has been filtered out, put it on a blacklist so it's excluded from candidacy from then on. Early in a port to a new chain the list starts empty and fills in as you operate and discover.
// Known risky tokens — excluded outright from scanning and entry candidates
var blacklistedTokens = map[string]bool{
// Addresses get added as they're discovered in operation (placeholder)
"0xFEE0NTRANSFER_TOKEN_ADDR": true, // confirmed fee-on-transfer
"0xHONEYPOT_TOKEN_ADDR": true, // honeypot, cannot sell
}
func isTradeable(token string) bool {
return !blacklistedTokens[strings.ToLower(token)]
}
Rug Pulls and Honeypots — Traps You Can't Exit
Nastier still is the honeypot: a token designed so you can buy but cannot sell. There appears to be liquidity, the price even rises, but sell transactions specifically get reverted. A rug pull is the related move where the developer pulls the entire liquidity one day and leaves the token worthless.
Perfect detection ahead of time isn't possible, but several heuristics hold up in practice.
- Round-trip simulation — test not only the buy but the sell back with
eth_call. If the sell reverts, suspect a honeypot - Minimum liquidity floor — exclude anything below a set pool size. Rug pulls generally run on thin liquidity
- Liquidity lock and holder distribution — check whether liquidity is locked and whether a handful of wallets hold the supply
- Contract verification status — treat tokens with unpublished, unverified source far more conservatively
The Governing Rule — When in Doubt, Skip
A missed arbitrage opportunity is a mild regret; stepping on a mine is a loss. The payoff is asymmetric, which is exactly why skipping ambiguous tokens outright wins over the long run. "Maybe it'll work" is worse than "if I'm not sure, I pass."
// Final gate before entry: any single failure means skip
if !isTradeable(token) { return } // blacklist
if isFeeOnTransfer(before, after, amt) { return } // transfer tax
if !passesRoundTripSim(token) { return } // cannot sell (honeypot)
if liquidity.Cmp(minLiquidity) < 0 { return } // insufficient liquidity
Summary
- Detect fee-on-transfer by comparing balances before and after, and head off repayment failures
- Once a token is filtered out, blacklist it so it never re-enters selection
- Defend against honeypots and rug pulls with round-trip simulation, liquidity floors, and holder distribution checks
- The default is when in doubt, skip — a mine you stepped on costs far more than an opportunity you missed
Opportunities on emerging chains are sweet, and they come with an equal share of unvetted tokens. A risky-token gate isn't glamorous, but it's the most practical line of defense standing between your bot and its balance.
This article is for educational and informational purposes and is not investment advice. Automated DeFi trading carries a risk of principal loss, and the outcomes are your own responsibility.
댓글
댓글 쓰기