Winnie-the-Pot Honeypot

Reported loss Not disclosed
BNB Chain
Honeypot

What happened

Winnie-the-Pot (WTP) is a BNB Chain token whose verified source can reject transfers to one stored address, nxOwner. While the tracing flag is true, transferFrom records the recipient of the first call (with a non-zero from) in nxOwner, and from then on both transferFrom and transfer revert when the recipient is that address. A DEX router sells a holder's tokens into the pair with transferFrom, so if the first recorded recipient is the liquidity pair, sells into it revert while transfers to other addresses, including the pair paying out a buyer, are not blocked by this check.

The owner can flip tracing with setTracing. De.Fi's REKT database lists the token as an Exit Scam/Honeypot dated 2021-05-12 and says the owner could disable the transfer function, which restricted users in selling their tokens; the listing gives no loss figure. The code blocks one recipient rather than the whole transfer function, and no transaction was opened to show which address nxOwner holds.

How it happened

  1. The constructor sets symbol = "WTP", decimals = 9, credits _totalSupply = 10000000000000000000000 (raw units) to the deployer with balances[owner] = _totalSupply; and sends half of it to the dead address with transfer(dead, burnedAmount);. tracing starts as true and nxOwner is empty.
  2. The first transferFrom whose from is non-zero while nxOwner is still empty succeeds and stores its recipient: if(from != address(0) && nxOwner == address(0)) nxOwner = to;. The code does not say who that recipient is; in a router-based liquidity add it would be the pair.
  3. After that, while tracing is true, every transferFrom runs else require(to != nxOwner, "Order ContextHandler"); and every transfer runs require(to != nxOwner, "Handling Request");. A holder's sell routed to the stored address therefore reverts regardless of the holder's balance.
  4. setTracing(bool _tracing) onlyOwner public writes the flag, so the owner can lift or re-impose the block. The onlyOwner modifier is require(msg.sender == owner || msg.sender == nxOwner);, so the captured address also passes it.
  5. renounceOwnership(address _newOwner) has no access check and only writes currentOwner; nothing in the code changes owner, so it does not give up any power. emitTransfer(uint256 _input) onlyOwner adds _input to the caller's balance without changing _totalSupply.

Protocol details

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

Build your security review skills

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