How To Check If a Token Is Safe

How To Check If a Token Is Safe With Evidence

DYOR isn’t a vibe; it’s a workflow. This guide gives you a repeatable, evidence-based checklist to judge token safety using on-chain data, contract source, ownership controls, liquidity locks, holder distribution, trading constraints, and provenance. Every step links to external tools so you can back up your conclusion with screenshots and hashes.

Beginner → Intermediate Risk & Due Diligence • ~30–40 min read • Updated: 2025-11-13
TL;DR A token is “safer” when: (1) the contract source is verified and matches the deployed bytecode, (2) dangerous admin powers (mint, blacklist, maxTax) are removed, timelocked, or multisig-governed, (3) liquidity is locked or burned, (4) holder distribution is not hyper-concentrated, (5) buys and sells simulate successfully with normal slippage, (6) deployer and linked contracts have clean histories, and (7) the project communicates risks clearly with signed, timestamped references. If two or more of these fail, walk away.

The 7-Point Evidence Framework

1) Contract verified & identical

  • Verified source (Etherscan, BaseScan, Arbiscan)
  • Exact compiler version + optimizer settings
  • Bytecode match (no “partial match” ambiguity)

2) Admin powers controlled

  • No arbitrary mint() or unlimited setTax()
  • Owner role in a multisig or timelock
  • Blacklist/pause functions removed or controlled with timelock

3) Liquidity is sticky

  • LP tokens burned or locked for a meaningful period
  • No dev-held LP outsized share
  • Pair contracts known and liquid across venues

4) Holder distribution sane

  • No top wallet controlling > 20–30% (excluding contracts)
  • Team/treasury addresses disclosed and bound by vesting
  • No sudden top-holder inflows pre-announcement

5) Trading works normally

  • Buy/sell simulate OK (no honeypot toggles)
  • Taxes if any are reasonable (< 10% typical)
  • No hidden maxTx/maxWallet traps at live supply

6) Clean provenance

  • Deployer history free of rugs
  • If proxy, implementation audited & immutable upgrades (timelock)
  • Known templates (OpenZeppelin) with minimal edits

7) Transparent comms

  • Signed deploy posts (GPG/PGP, EIP-4361 “Sign-In”)
  • Audit reports (with findings & fixes)
  • Timelock & governance addresses public

Safety Flowchart (When to Stop)

Token Safety Flow Start: Paste token address Source verified? Bytecode exact match? Admin powers safe? (no mint/blacklist, timelock) Liquidity locked/burned? Adequate lock period? Holders OK? No whale >30% (non-contract) Buy/Sell simulate OK? Taxes <= 10%? Deployer clean? No rug history Communications OK Audit + timelock shared If any red step is “NO”, stop or size risk accordingly.
A single fail doesn’t prove “scam,” but two or more critical fails = avoid.

Step 1 — Contract Source & Bytecode Match

Start on the official explorer for the chain: Etherscan (ETH), BaseScan (Base), Arbiscan (Arbitrum), BscScan (BSC), etc. Paste the token address.

  1. Look for “Contract: Verified” and a green check. Click “Contract” tab → “Code.” Confirm:
    • Compiler version (e.g., v0.8.24+commit) & equals what the deployer claims
    • Optimizer settings (enabled, runs count)
    • License (MIT/Apache-2.0); non-license ≠ scam, but standard licenses are a plus
  2. Bytecode match: Explorers display “Matches deployed bytecode at …”. If partial or “similar,” be cautious.
  3. Diff from OpenZeppelin: If it’s an ERC-20, compare functions to OpenZeppelin ERC-20. Non-standard additions like setTax(), enableTrading(), excludeFromFee(), setMaxTx() warrant careful review.
  4. Proxy? If the contract says “Proxy,” check “Read as Proxy” → implementation address. Audit that implementation too.

Yellow flag: Unverified source means you can’t see what functions exist. Many rugs hide mint/blacklist logic behind unverified contracts.

Step 2 — Admin Powers (Mint, Pause, Blacklist, Taxes)

Rug mechanics frequently rely on hidden or overpowered admin functions. In the Contract “Read/Write” tabs, and in the verified code, search for:

Dangerous patterns

  • mint(address,uint256) without caps or roles → infinite dilution
  • blacklist(address,bool) or setTradingEnabled(bool) → can block sells
  • setTax(uint256) with no sane bounds → 99% tax honeypot
  • setMaxTxAmount() or setMaxWallet() that can be lowered post-launch → traps
  • Upgradeable proxy with upgradeTo() fully under dev EOA → can swap logic

Safer controls

  • Roles via Ownable/AccessControl but owner is a multisig (Safe)
  • Timelock on critical functions (e.g., 24–48h) (OZ Timelock)
  • Bounded taxes (e.g., require(_tax <= 10_00) for ≤10%)
  • Renounced ownership (trade-off: no upgrades) or governance process documented

Evidence to save: Screenshots of the functions, the owner address (and that it’s a multisig/timelock), and any require bounds on tax/limits.

Step 3 — Liquidity: Lock, Burn, or Rugable?

If the team can remove liquidity, price can nuke to zero. Check the main DEX pairs (Uniswap v2/v3, Base/Arbitrum variants) on Dexscreener or DexTools, then click the LP token:

  1. Is LP burned? Look for LP tokens sent to 0xdead or 0x0000...dead.
  2. Is LP locked? If locked, find the locker (e.g., Unicrypt, Team.Finance). Record lock duration and % locked.
  3. Residual LP risk: Even with locks, verify that a meaningful % (e.g., >60–80% on early launches) is locked for months, not days.
Red flag: LP held mostly by the deployer or a fresh EOA. If 70%+ LP sits in a single unverified wallet, assume it’s rugable.
LP Ownership Snapshot (example) Locked (65%) Burned (25%) Dev Wallet (10%)
Prefer LP burned or locked for months. Dev-held LP beyond ~10% is risky.

Step 4 — Holder Distribution & Smart Money

In the explorer “Holders” tab, export the distribution. Exclude known contracts (LP, router, CEX wallets) and re-weight human wallets:

  • Top holder threshold: A single externally owned account (EOA) > 20–30% is risky unless explained (vesting/treasury).
  • Team wallets: If disclosed, they should be time-locked or vesting. Verify the timelock address.
  • Smart money: Look for reputable funds/wallets with long holding periods. Tools: Dune, Nansen (paid), DeBank.

Evidence: CSV of holders (annotate contracts vs EOAs), and a note on any whale concentration.

Step 5 — Buy/Sell Simulation & Honeypot Tests

Before you risk capital, simulate a buy and a sell. Use multiple tools:

What to confirm

  • A small buy and a small sell both succeed (no revert)
  • Taxes (if any) are within stated bounds
  • Router isn’t a malicious custom router (prefer Uniswap v2/v3, Sushi, etc.)
  • No dynamic blacklists that flip after buys

Red flags

  • Buys succeed, sells revert (honeypot)
  • 99% “fee” on sell
  • MaxTx/MaxWallet changed right after you buy
  • Trading paused by owner post-launch

Note: Some automated scanners produce false positives or miss proxy upgrades. Always corroborate with the contract code and a live micro-trade.

Step 6 — Deployer & Provenance (Clones, Upgrades)

Click the token’s “Contract Creator” link. Review the deployer’s other contracts and activity:

  • Prior rugs? If the same deployer rugged before (liquidity pulled, mint abuse), weight heavily against.
  • Clone templates: Many tokens clone standard templates. Diff vs a known-good commit (OpenZeppelin). Minimal diffs are safer.
  • Proxy upgrades history: If upgradable, check change logs and who can upgrade (timelock? multisig?).

Evidence: Deployer address notes, list of previous contracts, and any news/audit links.

Step 7 — Communications & Commitments

Legit teams tend to leave verifiable breadcrumbs:

  • Signed deploy announcements (e.g., EIP-4361 “Sign-In with Ethereum”)
  • Public multisig/timelock addresses with instructions
  • Audits from reputable firms (CertiK, Trail of Bits, OpenZeppelin, SlowMist)
  • Clear disclosures on tokenomics/vesting with on-chain vesting contracts
Caveat: An “audit badge” image is meaningless. Always open the PDF and confirm the contract address, commit hash, and scope match the live token.

Your Toolkit

Explorers

Scanners & Risk

CLI Recipes (Automate Key Checks)

ethers.js — Read owner, totalSupply, and try to detect dangerous functions

import { ethers } from "ethers";

// Set your RPC (Infura, Alchemy, Ankr, QuickNode, etc.)
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);

// Minimal ABI: ERC-20 + common risky functions
const ABI = [
  "function name() view returns (string)",
  "function symbol() view returns (string)",
  "function totalSupply() view returns (uint256)",
  "function decimals() view returns (uint8)",
  "function owner() view returns (address)",
  "function getOwner() view returns (address)",

  // suspected risky
  "function mint(address,uint256)",
  "function setTax(uint256)",
  "function setMaxTxAmount(uint256)",
  "function blacklist(address,bool)",
  "function pause()",
  "function unpause()"
];

const token = new ethers.Contract(process.env.TOKEN, ABI, provider);

(async () => {
  const [name, symbol, supply] = await Promise.all([
    token.name().catch(() => "n/a"),
    token.symbol().catch(() => "n/a"),
    token.totalSupply().catch(() => 0n)
  ]);

  // Try different owner functions
  let owner = "n/a";
  try { owner = await token.owner(); } 
  catch { try { owner = await token.getOwner(); } catch {} }

  console.log({ name, symbol, totalSupply: supply.toString(), owner });

  // probe risky functions by checking if they exist (will fail if not)
  const probe = async (sig) => {
    try { await token[sig](); return true; } catch { return false; }
  };

  const risky = {
    mintExists: await probe("mint"),
    setTaxExists: await probe("setTax"),
    setMaxTxExists: await probe("setMaxTxAmount"),
    blacklistExists: await probe("blacklist"),
    pauseExists: await probe("pause")
  };
  console.log({ risky });
})();

viem — Check proxy implementation & owner (EIP-1967)

import { createPublicClient, http, getStorageAt, isAddress } from "viem";
import { mainnet } from "viem/chains";

// EIP-1967 implementation slot = bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
const IMPLEMENTATION_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";

const client = createPublicClient({ chain: mainnet, transport: http(process.env.RPC_URL) });

const toChecksum = (hex) => "0x" + hex.slice(-40);

const main = async () => {
  if (!isAddress(process.env.TOKEN)) throw new Error("Bad address");
  const slot = await getStorageAt(client, { address: process.env.TOKEN, slot: IMPLEMENTATION_SLOT });
  if (slot && slot !== "0x0") {
    const impl = toChecksum(slot);
    console.log({ proxy: true, implementation: impl });
  } else {
    console.log({ proxy: false });
  }
};
main();

Foundry — Simulate a small swap (sell) to catch honeypot

# Pseudocode pattern; actual script depends on router ABI/paths
# Use a forked RPC (anvil --fork-url $RPC) and cast/anvil to simulate a real swap.
# If the sell path reverts, investigate tax/maxTx/blacklist toggles.

# Example idea:
# 1) Approve router for token
# 2) SwapExactTokensForETHSupportingFeeOnTransferTokens
# 3) Observe if revert happens or output is ~expected with stated tax

CLI automation won’t catch everything (e.g., upgradeable behind timelocks), but it accelerates your first-pass scan.

Risk Scoring Rubric (Printable)

CategoryGreen (+2)Yellow (+1)Red (0)
Source/Bytecode Verified, exact match, OZ-based Verified but heavy custom logic Unverified/partial
Admin Powers Multisig + timelock; bounded taxes; no blacklist Owner EOA but timelock or bounds Unlimited mint/tax/blacklist; upgradeable by EOA
Liquidity LP burned/locked ≥ 60% for months LP partly locked LP held by dev/fresh EOA
Holders No non-contract whale > 20% Largest whale 20–30% > 30% whale or sudden concentration
Trading Buys/sells normal; tax ≤ 10% Tax 10–15% or tight maxTx Honeypot/99% tax/reverts
Provenance Clean deployer; audited; known template Unknown deployer; minor history Prior rugs; opaque history
Comms Signed posts, audit PDFs, addresses Some docs but unsigned Badges only; no verifiable docs

Interpretation: 11–14 = Lower risk (still crypto); 7–10 = Caution; ≤6 = Avoid.

FAQ: Common Myths & Edge Cases

“Renounced ownership = safe.”

Not always. If code already has malicious logic (e.g., anti-sell), renouncing won’t remove it. Safer when paired with simple, immutable code.

“Audited = safe.”

Audits reduce risk but don’t eliminate it. Validate the audited commit matches the deployed bytecode and that critical HIGH issues were fixed.

“Big liquidity = safe.”

Only if LP is locked or burned. Big but dev-controlled LP can still be pulled.

“TokenSniffer score is low instant scam?”

Automated scores are a screen, not a verdict. Use them to prioritize deeper manual checks.

“Taxes make it a scam.”

Many tokens levy small buy/sell taxes for treasury or LP. The issue is unbounded or secretly changeable taxes post-launch.

External Links & References

Recap

  • Don’t ask “Is it safe?” ask “What evidence says it’s not dangerous?”
  • Verify source & bytecode, control admin powers, secure liquidity, check holders, simulate trades, review provenance, and demand verifiable comms.
  • Two or more critical fails → walk away. Screenshots + hashes = your audit trail.

Want us to run this checklist on a specific token and deliver an evidence pack (PDF + links + hashes)?

Request a Token Safety Report →