We run a scoring pipeline on every ERC-20 contract created on Ethereum mainnet. New token deployed at block N - we have a 0-100 risk score and a flag list within seconds.
This post is the methodology behind that number. 8 analyzers, 52 individual signals, the heuristics each one uses, and the trade-offs we accept (false positives and false negatives we know about).
The signal catalogue is also publicly browsable at rektradar.io/signals - one page per signal with the technique and rationale.
The 8 analyzers
Each analyzer is an independent module that returns a riskScore + a list of riskFlags. The aggregate score is a weighted sum capped at 100, with a flag-count floor (6+ flags = at least 70, 5 = at least 60, etc.) so we don’t return a misleading low score when a token has many smaller red flags.
| Analyzer | Signals | Technique |
|---|---|---|
| honeypot | 10 | eth_call simulation of buy / sell / transfer on a local fork |
| deployer | 9 | Deployer wallet history: age, prior deployments, prior scams |
| etherscan | 7 | Source-code verification + regex patterns on Solidity source |
| liquidity | 7 | LP token concentration, bundling, lock / burn status |
| swap_activity | 7 | Buy/sell ratio from on-chain swap events |
| network | 5 | Deployer-funder graph: mass deployers, mixer funding, serial scammers |
| bytecode | 4 | Function selectors + known scam hashes for unverified contracts |
| distribution | 3 | First Transfer events: holder concentration, distribution skew |
Below is the technique each one actually uses. No marketing - this is what runs in production.
honeypot - eth_call simulation
The honeypot analyzer simulates a buy + a sell on the token’s Uniswap V2 pair (V3 as fallback) using eth_call against a forked state. We override the simulator’s ETH balance to 1000 ETH and use a non-zero gas price to defeat contracts that branch on tx.gasprice == 0 to detect simulation.
The flow:
- Find the V2 pair via
IUniswapV2Factory.getPair(token, WETH). If absent, try V3 fee tiers[3000, 10000, 500, 100]. - Simulate
swapExactETHForTokensSupportingFeeOnTransferTokenswith a small ETH input. - Capture the token output. Compute the implied buy tax (input vs output ratio).
- From the simulator address, simulate
approve(router, MAX)+swapExactTokensForETHSupportingFeeOnTransferTokensfor the token amount. - If the sell call reverts →
sell_blockedorsell_failedflag. If it succeeds but extracts less than 50 percent of value →extreme_sell_fee. If between 50 and 90 percent →elevated_sell_fee/moderate_sell_fee.
Signals from this analyzer include honeypot, buy_failed, sell_blocked, sell_failed, buy_only_pattern, amount_dependent (buy works at small amounts but fails at larger ones - common max-tx pattern), and the three sell-fee tiers.
Known limits
- False positives: tokens with anti-bot cooldowns or temporary whitelists that simulate-fail in the first few blocks but trade fine after. We re-score these later via the swap_activity analyzer.
- False negatives: time-delayed honeypots that flip after N transactions, owner-triggered kill switches, blacklist-on-demand. Static simulation can’t catch these - we rely on the deployer + network analyzers for that.
deployer - wallet history graph
For every token, we look up the deployer wallet and check four things:
- Age: block of the wallet’s first outgoing transaction (
first_tx_block). Wallets less than ~24h old funding a deployment arefresh_deployer_funded, less than 7 days =new_wallet. - Prior deployments: count of contracts deployed by this wallet. >5 =
mass_deployer. >80% of the wallet’s tx history being contract creation =mostly_deploys_contracts(this catches dedicated deployer wallets that never trade). - Prior scams: lookup in our own
token_analysistable for previous tokens by the same deployer that scored ≥70. 3+ prior scams =serial_scammer(the heaviest deployer flag, 40 points). - Funder chain: deployer → first funder → first funder, up to 2 hops. If any node in the chain is a Tornado Cash deposit address (or other mixer), we flag
mixer_funded/tornado_funded.
The data for steps 1 and 2 comes from a graph-crawler service that maintains a deployer→funder graph in real time using trace_filter calls on a local Erigon node.
bytecode - selector heuristics for unverified contracts
When the contract isn’t verified on Etherscan, we work directly on the deployed bytecode. We extract the function selectors (first 4 bytes of each JUMPI target preceded by PUSH4) and check them against a curated list of suspicious selectors:
0x44337ea1 blacklist(address)
0x0ecb93c0 blacklistAddress(address)
0x8a8c523c pause()
0x83197ef0 destroy()
0xfd9eb20a setMaxTxAmount(uint256)
0x6c19e783 setFee(uint256)
...
Selectors alone aren’t proof of malice - many legitimate tokens have pause(). The signal is combinatorial: an unverified contract with blacklist + pause + setFee selectors and no verified source scores higher than the same combination in a verified contract where we can read the implementation.
We also compute a hash of the cleaned bytecode (strip metadata + constructor args) and look it up against a library of known scam-template hashes. Verbatim copy of a known rug = known_scam_bytecode flag.
liquidity - bundling and LP ownership
Two checks here, both V2-only (V3 LP positions are NFTs and we treat them separately):
-
Bundling: was liquidity added in the same transaction as the
PairCreatedevent? Legit projects usually add liquidity in a separate tx after the pair is wired up. Bundling is a stealth-launch tell and correlates strongly with rug patterns. Flag:liquidity_at_creation. -
LP ownership: query the pair contract’s
totalSupply()andbalanceOf(deployer), plus balances of known LP locker contracts (Unicrypt, Team.Finance, PinkLock) and the dead address0x000…dEaD. If the deployer holds >80% of LP supply →creator_holds_all_lp. If the LP is sent to a known locker →lp_locked(positive signal). If burned →lp_burned(positive signal).
A token that’s liquidity_at_creation + creator_holds_all_lp + no_renounce_ownership is a textbook rug setup.
swap_activity - on-chain trade pattern
This one is our hedge against honeypot-simulation false negatives. We query the events table for the most recent ~100 swaps on the token’s pair and compute the buy/sell ratio.
- 100% buys, 0 sells, with >10 swaps:
buy_only_patternflag, 40 points (highest single-flag weight). This catches cases like $FWD and $SLTE where the honeypot simulator passed but real on-chain activity showed nobody could sell. -
95% buys:
high_buy_ratio, warning level.
The simulation lies; the on-chain reality doesn’t.
network - deployer cluster graph
Last layer, slightly different shape: we ask the scoring-engine service for a graph score that aggregates funder-level data. The signals:
mass_deployer_network: deployer’s funder has financed ≥5 deployersscam_factory_funder: the funder has financed ≥10 deployers who each scored ≥70serial_scammer: the deployer itself has ≥3 prior tokens flagged scammixer_funded/tornado_funded: any node in the 2-hop funding chain is a known mixer deposit addressdisposable_wallet: wallet age < 24h + only-deploys-then-vanishes pattern
The score from this analyzer is capped at 50 so it doesn’t override the honeypot signals if those fire.
etherscan - source-code patterns + distribution
The Etherscan analyzer fetches the verified source (if any) and runs a small regex set:
function blacklist/mapping(address => bool) (private )?_?(isBlackListed|blacklisted)→blacklist_detectedfunction setMaxTxAmount+require(amount <= _maxTxAmount)→name_mimics_known_tokenif the name also matches a known popular ticker
If the source is not verified, we fall back to the bytecode analyzer. An unverified contract that’s been live for >7 days without verification is treated more suspiciously than a fresh one (legit projects usually verify within 24-48h).
distribution - initial Transfer events
The smallest analyzer. We pull the first ~200 Transfer(address,address,uint256) log entries and look at where the initial supply went:
- One wallet (excluding
0x0,dEaD, the pair) gets >50% of supply:creator_holds_all_supply→ high concentration risk - Top 5 wallets cumulatively hold >90%: warning flag
- More than 20 unique recipients in the first 200 transfers: positive signal (broad initial distribution)
What we can’t catch (yet)
Being honest:
- Soft rugs: legit-looking tokens that get abandoned with deployer dumping over weeks. Our deployer history catches them retroactively, but not at launch.
- Sophisticated upgradable proxies: a UUPS proxy that points to a benign implementation today and a malicious one tomorrow. We flag
beacon_proxy/proxy_contractbut we don’t simulate the upgrade outcome. - Off-chain rugs: deployer abandons the project, social channels go silent, contract stays “safe” on-chain. Out of scope.
- Cross-chain replays: a token deployed on mainnet that was previously rugged on BSC. We’re mainnet-only for now.
The catalog
Every signal above has its own page with the rationale, the threshold, and the severity:
Drop any address on rektradar.io to see which of these fire for a specific token - risk score, the full flag list with weights, and the deployer cluster as a 3D graph. No signup.
If you’ve shipped a similar pipeline and see signals we’re missing - especially in the off-chain / proxy upgrade space - we’d love to compare notes.