MoonSquad Honeypot

Reported loss Not disclosed
BNB Chain
Honeypot

What happened

MoonSquad (Mquad) is a BNB Smart Chain token (0xe327fd5c…cbb26d, deployed 2021-06-19 in transaction 0x0170f2c8…abca1c) with decimals of 0 and a supply of 69*10**15 credited to the deployer. Its transferFrom is guarded by a contextHandler modifier: while tracing is true, the recipient of the first transferFrom with a non-zero sender is stored in nxOwner, and from then on every transfer and transferFrom to that address reverts. If that first recipient is a liquidity pool, which the code does not itself establish, sales into the pool fail while transfers out of it to buyers do not.

Only the owner or nxOwner can call setTracing to switch the block off or back on. De.Fi's REKT database lists the token as an exit scam / honeypot dated 2021-06-19, saying the owner could disable the transfer function and that this restricted users in selling their tokens. No loss figure, attacker address or exploit transaction is established.

How it happened

  1. The constructor sets owner = msg.sender (in Owned), tracing = true and credits the whole supply to the owner: balances[owner] = _totalSupply;.
  2. While tracing is true, the first transferFrom with a non-zero sender records its recipient instead of checking it: if(from != address(0) && nxOwner == address(0)) nxOwner = to;. That line only assigns nxOwner while it is still the zero address, and no other function writes it, so once a non-zero recipient is stored nothing in the code changes it.
  3. From then on, while tracing is true, transferFrom reverts when the recipient is that address (else require(to != nxOwner, "Order ContextHandler");), and so does transfer (if(tracing) require(to != nxOwner, "Handling Request");). No sender is exempt, including the owner.
  4. A token sale through a router pulls tokens with transferFrom, so if nxOwner is the pool address the sale reverts with Order ContextHandler. A purchase moves tokens out of the pool with transfer to the buyer, whose address is not nxOwner, so it is not blocked by this check.
  5. The block can be lifted or re-armed by calling function setTracing(bool _tracing) onlyOwner public. The onlyOwner modifier is require(msg.sender == owner || msg.sender == nxOwner);, so the captured address is itself treated as an owner.
  6. Other owner-side controls: emitTransfer(uint256 _input) does balances[msg.sender] = balances[msg.sender] + (_input); without touching _totalSupply, and is callable by the owner or nxOwner. The deployed TokenBEP20 has no function that withdraws the contract's BNB, and its fallback is revert();.
  7. function renounceOwnership(address _newOwner) public only writes currentOwner = _newOwner;, is callable by anyone, and does not change owner, so it does not give up any power.
  8. What happened is only what the listing states: De.Fi's REKT database records the token as an exit scam / honeypot dated 2021-06-19. The Token Sniffer reply it links states that tokens it had flagged blocked transfers to the LP address; it does not name MoonSquad and predates this deployment. No transaction was examined, so the code shows how sales could be blocked, not when or by whom setTracing was used.

Protocol details

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

Build your security review skills

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