MoonSquad 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
- The constructor sets
owner = msg.sender(inOwned),tracing = trueand credits the whole supply to the owner:balances[owner] = _totalSupply;. - While
tracingis true, the firsttransferFromwith a non-zero sender records its recipient instead of checking it:if(from != address(0) && nxOwner == address(0)) nxOwner = to;. That line only assignsnxOwnerwhile 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. - From then on, while
tracingis true,transferFromreverts when the recipient is that address (else require(to != nxOwner, "Order ContextHandler");), and so doestransfer(if(tracing) require(to != nxOwner, "Handling Request");). No sender is exempt, including the owner. - A token sale through a router pulls tokens with
transferFrom, so ifnxOwneris the pool address the sale reverts withOrder ContextHandler. A purchase moves tokens out of the pool withtransferto the buyer, whose address is notnxOwner, so it is not blocked by this check. - The block can be lifted or re-armed by calling
function setTracing(bool _tracing) onlyOwner public. TheonlyOwnermodifier isrequire(msg.sender == owner || msg.sender == nxOwner);, so the captured address is itself treated as an owner. - Other owner-side controls:
emitTransfer(uint256 _input)doesbalances[msg.sender] = balances[msg.sender] + (_input);without touching_totalSupply, and is callable by the owner ornxOwner. The deployedTokenBEP20has no function that withdraws the contract's BNB, and its fallback isrevert();. function renounceOwnership(address _newOwner) publiconly writescurrentOwner = _newOwner;, is callable by anyone, and does not changeowner, so it does not give up any power.- 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
setTracingwas used.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.