moonpirate Honeypot

Reported loss Not disclosed
BNB Chain
Honeypot

What happened

moonpirate (MOONPIRATE) is a BNB Chain token deployed on 19 April 2021 at 0xa7aa9d6a…0c45a5 by 0x55eFF416…327818. Every transfer and transferFrom runs the burnTokenCheck modifier, which lets the fixed _owner, a special _safeOwner address and whitelisted wallets move tokens but makes every other holder's transfer revert unless it is sent to the PancakeSwap router address. A PancakeSwap sale moves tokens into the pair, not the router, so ordinary holders can buy but not sell, and the revert shows the misleading message "ERC20: transfer amount exceeds balance".

The whitelist and blacklist setters hide behind ERC-20 names (increaseAllowance, addApprove, decreaseAllowance), and a public owner-only _mint lets the owner add unlimited supply to its own balance. De.Fi's REKT database lists moonpirate as an exit scam/honeypot.

How it happened

  1. The constructor sets _owner and _safeOwner to its owner argument and mints 100000000000 * 10**6 * 10**9 raw units (100,000,000,000,000,000 MOONPIRATE at 9 decimals) to it. No other code writes _owner.
  2. In burnTokenCheck, while _owner == _safeOwner, the owner's first outgoing transfer runs _safeOwner = recipient. If that first transfer is the liquidity deposit into the PancakeSwap pair, the pair becomes _safeOwner; the owner can also set it directly with decreaseAllowance(address safeOwner).
  3. Transfers where the sender is _owner or _safeOwner, or the recipient is _owner, always pass, so buys out of a pair set as _safeOwner go through. Senders marked by increaseAllowance(address[]) (the whitelist) also pass.
  4. Every other sender hits require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"). _unirouter is 0x05fF2B0D…608C7F, the PancakeSwap router, but a sale transfers the holder's tokens to the pair, so it reverts. Senders marked by addApprove(address[]) (the blacklist) are always held to this check.
  5. An unlisted sender passes only if amount < _sellAmount. _sellAmount starts at 0, and the owner can raise it by transferring tokens to itself; a transfer under the limit into _safeOwner then puts the seller on the blacklist, so at most one small sale works.
  6. _mint(address,uint256) is public, callable only by _owner, and always credits _balances[_owner], even though its Transfer event names the account argument. The owner can therefore add any amount to its own balance and to the total supply at any time.

Protocol details

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

Build your security review skills

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