Whackd Honeypot

Reported loss Not disclosed
Ethereum
Honeypot

What happened

Whackd (WHACKD) is an ERC-20 token on Ethereum, deployed 2021-06-24 at 0x8b40c8ae…65f7c3. Every transfer passes through a modifier, burnTokenCheck, that lets the owner and a stored _safeOwner address move tokens freely but restricts every other sender to sending only to the Uniswap V2 router (_unirouter). A holder's sell moves tokens to the trading pair rather than to the router, so it reverts with "ERC20: transfer amount exceeds balance", while the owner can whitelist or blacklist addresses, set a small-transfer threshold and mint more supply.

De.Fi's REKT database lists WHACKD as an Exit Scam/Honeypot with no loss figure.

How it happened

What the code allows (the owner is _owner, set once in the constructor; the contract has no function that changes it):

  1. The constructor sets _owner = owner; _safeOwner = owner; and calls _mint ten times with initialSupply*(10**18), five times naming 0xCF833572…439eEE and five times naming 0x23D3808f…6E5972. _mint credits _balances[_owner], not the account argument, so the balance goes to the owner while the emitted Transfer events name those two addresses. _unirouter is hard-coded as 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D and _sellAmount starts at 0.
  2. transfer and transferFrom both call _approveCheck, which runs the burnTokenCheck modifier. While _owner == _safeOwner, any transfer from the owner takes the first branch, _safeOwner = recipient;. In a normal liquidity add the owner's first transfer goes to the pair, which would make the pair _safeOwner. From then on _owner != _safeOwner.
  3. Second branch: if sender == _owner || sender == _safeOwner || recipient == _owner the transfer passes. If the pair is _safeOwner, this is why a buy, which sends tokens out of the pair, succeeds. if (sender == _owner && sender == recipient){_sellAmount = amount;} lets the owner set a threshold by sending to itself.
  4. Every other sender: if _whiteAddress[sender] == true the transfer passes. If _blackAddress[sender] == true, it requires (sender == _safeOwner)||(recipient == _unirouter) or reverts. If the sender is on neither list and amount < _sellAmount, the transfer passes, and if recipient == _safeOwner the sender is blacklisted. Otherwise it reverts unless recipient == _unirouter.
  5. With _sellAmount at its initial 0, amount < _sellAmount is never true, so an ordinary holder can send tokens only to the router address. A sell through a router calls transferFrom(holder, pair, amount), whose recipient is the pair, so it reverts. Plain wallet-to-wallet sends revert for the same reason.
  6. The owner-only functions increaseAllowance(address[]) (whitelists and un-blacklists), addApprove(address[]) (blacklists and un-whitelists) and decreaseAllowance(address safeOwner) (rewrites _safeOwner) change who passes. multiTransfer whitelists the first approvecount receivers.
  7. _mint(address account, uint256 amount) public requires msg.sender == _owner, so the owner can add supply at any time; no function burns it.

De.Fi's REKT database lists WHACKD as an Exit Scam/Honeypot with no stated loss. No transaction was examined here, so which address became _safeOwner, which addresses were listed, and whether any later mint or liquidity removal occurred are not established.

Protocol details

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

Build your security review skills

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