Honeypot Crypto Testing with Simulated Trades
If you have been around a few DEX launches, you have seen it: a chart that only goes up, a Telegram full of “wen CEX” spam, and a wall of holders who cannot sell. Classic honeypot. The trick is simple. The token lets you buy, then quietly blocks or traps your sell. Good scammers wrap it in “anti-bot” or “anti-whale” logic. Sloppy ones just blacklist everyone who is not on their whitelist.
You do not need to be a solidity wizard to protect yourself. Simulating trades, reading a few contract patterns, and checking liquidity around the pool will catch most of these. Below is how I approach honeypot token detection using simulated buys and sells, plus what the code usually looks like under the hood.
What a honeypot actually isHoneypots show up in different wrappers, but the effect is the same: buyers can acquire tokens, then when they try to sell, the transfer or transferFrom path reverts or silently siphons the output to a fee or dead address. The most common mechanisms I run into on Ethereum and BSC:
Hard blacklist or bot list, often toggled by an owner function like setBlacklist, setBot, or a mapping such as _isBlacklisted[address] = true. Whitelist only sells, where a boolean like tradingEnabled or sellAllowed is enforced, but only for addresses flagged in _isExcludedFromFee or _isTrusted. Punitive sell tax via setFeeTx or setTax that sets a huge sell fee, often 90 to 100 percent, routed to the dev wallet or burned in a way that makes your sale net near zero. Max transaction or cooldown that prevents sells through conditions like _maxTxAmount, isTxLimitExempt, or a timestamp anti-snipe that never clears for regular users. Pair-aware logic that treats transfers to the pool address differently. If to == pair, it reverts or takes the full amount as a fee.On-chain, a blocked sell usually manifests as a revert from the token contract during transferFrom called by the DEX router. On Uniswap and PancakeSwap, the router ultimately relies on your token allowing a transferFrom from your wallet to the pair. If that path fails, the swap fails.
Why simulate trades instead of trusting a scannerA safe token scanner or honeypot token checker can be helpful, but they still miss edge cases. Scammers purposely design sell restrictions to pass naive checks, then flip a switch after the first wave of buyers arrive. They also push updates through proxies. Simulated trades give you ground truth: if a buy and a sell would work at this block, you will see it.
I use two approaches depending on how fast I need an answer: call-level simulation with a remote service or a local mainnet fork with a custom script.
Pre-trade static checks that save you timeBefore spinning up a fork, I do a few quick reads in a block explorer. These do not replace a full test, they just filter the obvious traps.
Etherscan or BscScan: open the contract, read “Contract” and “Read/Write Proxy” tabs, and check owner(), getPair(), and whether renounceOwnership was ever called. If ownership is still active and there is a setBlacklist or setMaxTx function, assume risk. Liquidity sanity: on DexScreener, confirm which pair is trading, how deep the pool is, and whether LP tokens are locked. If LP is unlockable at any time, a rug is easy. Code flags: search for onlyOwner around fee setters like setFeeTx, setTax, or variables with names like _marketingWallet. Track if sell paths have extra conditions around to == pair. Transfer semantics: in “Read Contract,” fetch values like _maxTxAmount or trading gates such as tradingEnabled. If the contract exposes isTxLimitExempt(address), check whether the router or pair is exempt but you are not. Social and alerts: quick scan on X for mentions of the token name, and look at warnings shared by firms like PeckShield or CertiK when something large is trending.If anything smells off at this stage, move to simulation.
Simulating buys and sells on a forkA mainnet fork gives you the closest copy of reality. You impersonate a funded wallet, approve the router, do a tiny buy, then try a sell. If the sell reverts or returns a weird output amount, you already answered your question.
Foundry makes this smooth, but Hardhat or Tenderly work too.
Setup with Foundry or HardhatRun a fork of the relevant chain. For Ethereum, point to an archive RPC. For BSC honeypot check work, use a BSC archive RPC. Fund a local test wallet with forked ETH or BNB, then run a script that hits the live router and pair.
The minimal flow looks like this:
Discover the router and pair for the token’s primary pool, for example UniswapV2Router02 or PancakeRouterV2. Confirm via Etherscan or BscScan under “Read Contract,” getPair(token, WETH/WBNB). Simulate a buy using swapExactETHForTokensSupportingFeeOnTransferTokens with a tiny input and very high slippage. If the buy succeeds, proceed. Approve the router to spend your token using approve(router, amount). Simulate a sell with swapExactTokensForETHSupportingFeeOnTransferTokens. If it reverts or nets close to zero, label it unsafe.Inside the token, a failing sell is often due to a require that checks to == pair or an if (from == pair) branch that bypasses fees for buys but not for sells. When you sell, the router triggers transferFrom(yourWallet, pair, amount). If your wallet is blacklisted, or if sell tax routes almost the entire amount to a tax wallet, the swap will fail or produce dust.
Example test logicYou do not need a full harness to spot trouble, but a small script helps. Pseudocode:
Query pair = IFactory.getPair(token, WETH). Buy: call router swapExactETHForTokensSupportingFeeOnTransferTokens with minOut set to 0 to avoid slippage issues. Approve: IERC20(token).approve(router, MAX_UINT). Sell: call router swapExactTokensForETHSupportingFeeOnTransferTokens with a small part of your bought balance. Catch the revert reason. Tokens frequently throw custom errors or plain require failures. Anything like “TransferHelper: TRANSFER FROMFAILED”, “UniswapV2: K”, or a custom “Sell not allowed” is a giant red flag.Tenderly is great if you do not want to run local infra. Paste the router call, pick the sender as your simulated wallet, and watch the trace. If the path dies in token.transferFrom, expand the internal step. You will often see an owner-only whitelist that you are not part of.
What the bad code looks likeI keep a mental list of sell-restriction patterns. A few you will recognize instantly:
Blacklist gate:

mapping(address => bool) private _isBlacklisted;
require(! isBlacklisted[from] && !isBlacklisted[to], "blacklisted");
Pair-aware tax:
if (to == pair) fee = amount.mul(sellTax).div(100);
if (to == pair && !isWhitelisted[from]) revert("sell blocked");
Hidden owner fee switch:
function setFeeTx(uint256 b, uint256 s) external onlyOwner buyTax = b; sellTax = s;
Trading enable bait:
require(tradingEnabled || _isExcludedFromFee[from] || _isExcludedFromFee[to], "trading off");
MaxTx and cooldown traps:
require(amount <= _maxTxAmount, "maxTx");
require(block.timestamp > lastTxTime[from] + cooldown, "cooldown");
If any of these exist and ownership is not renounced, the rules can change mid-trade. renounceOwnership reduces some risk, but proxies or roles via AccessControl can still override behavior.
Reading the trace like a forensic analystOn a simulated sell, expand the internal calls in your trace. You want to see:
Approve succeeds. If approve fails, there is a deeper ERC20 bug or you are interacting with a proxy wrong. Router pulls tokens via transferFrom. If this reverts, check the token’s allowance and balanceOf first. If both are fine, it is a sell restriction. Pair receives tokens, then transfers WETH or WBNB back. If the pair transfer out reverts with “K” or “INSUFFICIENT OUTPUTAMOUNT,” slippage or pool state changed. That is usually not a honeypot, just a trading parameter issue. If a huge fee is being taken on sell, you will see internal transfers to a fee or marketing wallet. Follow the amounts. If it is north of 50 percent and toggled by onlyOwner, you already have your answer.This is the level of detail audit firms like Consensys Diligence or Hacken will look for when assessing tokenomics mechanics. You do not need their full tooling to get the same signal from a single small trade.
The scanner problem and how to use them anywayThere are plenty of tools billed as honeypot token checker or safe token scanner. They are helpful for speed, but I treat them as a first pass only. Scanners struggle with:
Upgradable proxies where the logic changes after your scan. Owner-controlled switches that unlock trading only for a whitelist. Dynamic sell taxes that jump the moment liquidity grows.Use them alongside manual checks. A quick honeypot token detection from a third party plus your own forked buy-sell sim covers most traps. If both say safe and you still feel uneasy, put it on a watchlist and wait 12 to 24 hours. On-chain sleuths on X will often flag rugs quickly when volume is high.
BSC quirks worth notingBSC is the home of many “token cannot sell” tricks because costs are low for scammers and victims. PancakeSwap routers accept fee-on-transfer tokens through the SupportingFeeOnTransferTokens functions. That is fine for honest taxes, but it gives scammers a clean path to break only the sell side. When you run a bsc honeypot check, always test against PancakeRouterV2 and the exact pair the token trades on. Many fake routers exist.
Also, check if the LP tokens are locked. A pool with $50k liquidity and unlockable LP is almost always bait. DexScreener shows LP lock percentages for some pairs, and BscScan can show the LP token holder distribution. If the top LP holder is the token owner wallet, run.
Etherscan and BscScan tricks that save your stackThe explorer UI read more is better than people give it credit for. A fast etherscan contract check helps you avoid 80 percent of traps:
Click “Contract” then “Read as Proxy” if present. Tokens hide logic behind proxies to flip rules later. If it is a proxy, click the implementation. In “Read Contract,” look for owner, getOwner, or hasRole. Keep an eye on onlyOwner functions like setFeeTx, setMaxTx, setBlacklist, setTradingEnabled. In “Write Contract,” you can often see if functions exist to disable fees or open trading. You do not need to run them, just confirm their presence. Review token supply changes. If mint exists and the owner is active, the pool can be diluted at any time. Cross-check the router and pair addresses against verified Uniswap or Pancake contracts. Some scams spin up fake routers with familiar names. Limits of simulation and how to avoid false positivesSimulations are not perfect. They run at a static block height and sender context. Some tokens gate sells on quirks such as detecting isContract(msg.sender) or comparing gas left. If your sim wallet is a contract, the token might block the sell, while a human wallet would pass. That is rare but real.
Mitigate by simulating with an EOA sender, high gas limit, and realistic slippage. If possible, run two simulations on different recent blocks. If results differ, assume owner-controlled conditions are changing live. When I am still unsure, I will risk a microscopic live buy and sell from a fresh wallet, with tight slippage protection and a pre-set gas cap. If the sell fails, the loss is minimal and the data is certain.
A tiny operational playbook you can reuseKeep this short checklist handy when you need a fast call on a new token:
Explorer read: owner status, proxy, fee and blacklist functions, trading gates, mint ability. Liquidity: pair depth, real router, LP lock status, holder distribution for LP token. Simulate: fork buy, approve, fork sell, watch the internal trace. Social sanity: DexScreener chart for unnatural straight lines, X chatter from on-chain sleuths, any alerts from PeckShield, CertiK, or Consensys. Decision: if any sell restriction, oversized dynamic sell tax, or active owner with dangerous controls, skip. What to do if you already boughtIf you discover you cannot sell, do not panic sell into zero. First, try reducing the size and increasing gas and slippage a bit. Some “maxTx” traps fail only above a threshold. If the token requires a specific path, try selling through the exact router pairing on the chart, not a router aggregator.
If all attempts fail, assume a honeypot. Document your trace and report it. Post a short write-up with Etherscan or BscScan links. Tag community researchers on X who track scams. Security firms like PeckShield often boost credible warnings when a contract is actively trapping users.
Final thoughts from the audit trenchesHoneypots are not new, they just keep changing costumes. I have seen tokens that let early sellers out, then flip the switch after liquidity grows. I have also seen contracts that whitelist the dev’s wallets while the public gets throttled behind artificial cooldowns. None of this survives a disciplined process: quick explorer read, simulated buy, simulated sell, and a healthy bias against owner-controlled fee switches.
If you prefer automation, build your own lightweight honeypot token checker around a forked trade routine. It is just a few RPC calls and traces, and it will outperform most generic crypto scam detection dashboards in the chaotic first hour of a launch. The goal is simple, avoid crypto scams by proving you can exit before you enter.