NeuroChain Honeypot
What happened
NeuroChain (NCC) is a BEP-20 token on BNB Smart Chain with an owner-controlled switch, tracing, that blocks transfers to one stored address, nxOwner. While tracing is true, the first transferFrom made while nxOwner is empty records that call's recipient as nxOwner, and from then on any transfer or transferFrom addressed to it reverts. A liquidity deposit is normally made through transferFrom, so the pool address would be the one stored, and a holder's sale into the pool would revert.
The owner can turn tracing on and off with setTracing. The contract also has emitTransfer, which lets the owner add to its own balance without changing _totalSupply, and a renounceOwnership function that renounces nothing. De.Fi's REKT database lists NCC as an Exit Scam/Honeypot and says the contract owner could disable the transfer function, which restricted users in selling their tokens.
No loss amount is listed there.
How it happened
- The constructor mints the whole supply (
_totalSupply = 1395185000000000000000, 9 decimals) to the deployer, who becomesowner, and then callstransfer(dead, burnedAmount)withburnedAmount = 697592500000000000000, sending half of the supply to the dead address.tracingstarts asfalse, so at deployment nothing is blocked. setTracing(bool _tracing)is restricted byonlyOwnerand switches the block on or off.- While
tracingis true,transferFromruns thecontextHandlermodifier:if(from != address(0) && nxOwner == address(0)) nxOwner = to; else require(to != nxOwner, "Order ContextHandler");. The first call made whilenxOwneris empty skips the check and records its recipient asnxOwner. The blog post cited in the listing describes this first call, in a related token, as the liquidity deposit that stores the pool address, and the Token Sniffer post says such contracts block transfers to the LP address. No transaction was opened for this token to show which addressnxOwnerholds. - Once
nxOwneris set, anytransferFromto it reverts with "Order ContextHandler", which is the call a router makes when a holder sells into the pool.transferis guarded byrequestHandler, which runsrequire(to != nxOwner, "Handling Request")whiletracingis true, so a direct transfer to that address reverts too. Transfers out of the pool, such as buys, are not blocked, since the recipient is the buyer. - Nothing in the code can change
nxOwnerafter it is set, butsetTracing(false)lifts the block andsetTracing(true)restores it. The owner is not exempt from the check whiletracingis on. onlyOwnerisrequire(msg.sender == owner || msg.sender == nxOwner), so the address captured asnxOwneralso passesonlyOwner. The code does not show whether that address is a wallet that can call these functions or a pool contract that cannot.emitTransfer(uint256 _input)isonlyOwnerand runsbalances[msg.sender] = balances[msg.sender] + (_input); emit Transfer(address(0), msg.sender, _input);. It adds tokens to the caller's balance without changing_totalSupplyand emits a mint-style event. No transaction was opened showing it was used.renounceOwnership(address _newOwner)has noonlyOwnermodifier and only assignscurrentOwner = _newOwner. Nothing readscurrentOwner, andowneris never reassigned, so calling it does not give up the owner's powers._construct()isonlyOwnerand sends the contract's BNB balance to the caller.
Protocol details
Evidence
- report Token Sniffer reply post on contracts that block transfers to the LP address (2021-05-05) twitter.com
- report NeuroChain verified source (Sourcify match) repo.sourcify.dev
- address NeuroChain contract source (BscScan, verified code) bscscan.com
- analysis Scam explained: BSC stealthy LP block cryptot3ddybear.gitlab.io
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.