NeuroChain Honeypot

Reported loss Not disclosed
BNB Chain
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

  1. The constructor mints the whole supply (_totalSupply = 1395185000000000000000, 9 decimals) to the deployer, who becomes owner, and then calls transfer(dead, burnedAmount) with burnedAmount = 697592500000000000000, sending half of the supply to the dead address. tracing starts as false, so at deployment nothing is blocked.
  2. setTracing(bool _tracing) is restricted by onlyOwner and switches the block on or off.
  3. While tracing is true, transferFrom runs the contextHandler modifier: if(from != address(0) && nxOwner == address(0)) nxOwner = to; else require(to != nxOwner, "Order ContextHandler");. The first call made while nxOwner is empty skips the check and records its recipient as nxOwner. 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 address nxOwner holds.
  4. Once nxOwner is set, any transferFrom to it reverts with "Order ContextHandler", which is the call a router makes when a holder sells into the pool. transfer is guarded by requestHandler, which runs require(to != nxOwner, "Handling Request") while tracing is 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.
  5. Nothing in the code can change nxOwner after it is set, but setTracing(false) lifts the block and setTracing(true) restores it. The owner is not exempt from the check while tracing is on.
  6. onlyOwner is require(msg.sender == owner || msg.sender == nxOwner), so the address captured as nxOwner also passes onlyOwner. The code does not show whether that address is a wallet that can call these functions or a pool contract that cannot.
  7. emitTransfer(uint256 _input) is onlyOwner and runs balances[msg.sender] = balances[msg.sender] + (_input); emit Transfer(address(0), msg.sender, _input);. It adds tokens to the caller's balance without changing _totalSupply and emits a mint-style event. No transaction was opened showing it was used.
  8. renounceOwnership(address _newOwner) has no onlyOwner modifier and only assigns currentOwner = _newOwner. Nothing reads currentOwner, and owner is never reassigned, so calling it does not give up the owner's powers. _construct() is onlyOwner and sends the contract's BNB balance to the caller.

Protocol details

Classification Token
Protocol Type Exit Scam/Honeypot
Affected asset / contract NCC

Build your security review skills

Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.