GOATMOON Honeypot
What happened
De.Fi's REKT database lists GOATMOON on BNB Smart Chain as an Exit Scam/Honeypot, stating that the contract owner could disable the transfer function and so restrict users from selling. The verified source shows the mechanism: every transfer passes through a burnTokenCheck modifier, and a holder who is not whitelisted by the owner can only send tokens to a hard-coded router address or to the owner, not to a liquidity pool. The revert message reads "ERC20: transfer amount exceeds balance" even though the holder's balance is not the cause.
The contract was deployed on 2021-05-15 at 15:36 UTC in transaction 0x96a58552…bc4989. No loss figure is listed.
How it happened
- The owner address
_owneris set once in the constructor and the source has no function that changes it.transferandtransferFromboth call_approveCheck, which carries theburnTokenCheckmodifier. - The first transfer sent by the owner while
_owner == _safeOwnerpasses and runs_safeOwner = recipient. After that, transfers pass when the sender is_owneror_safeOwner, or when the recipient is_owner. - For every other sender, a transfer passes only if the sender is whitelisted (
_whiteAddress[sender] == true). Otherwise it must satisfyrequire((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"), where_unirouteris the hard-coded address 0x05fF2B0D…608C7F. A sale through a liquidity pool sends tokens to the pool, which neither exemption covers, so it reverts with a message that blames the balance. _sellAmountstarts at 0, so theamount < _sellAmountescape never applies until the owner sets it by transferring to itself (if (sender == _owner && sender == recipient){_sellAmount = amount;}). Once it is set, a non-listed holder can send amounts below it, and if the recipient is_safeOwnerthe sender is flagged:_blackAddress[sender] = true; _whiteAddress[sender] = false;. A blacklisted holder can then only send to_unirouteror_owner.- The owner alone controls the lists and the exemption target:
increaseAllowancewhitelists,addApproveblacklists,decreaseAllowance(address safeOwner)replaces_safeOwner, andmultiTransfercan whitelist receivers and set their allowance to_unirouterto the maximum. - The owner can also mint:
_mintispublic, requiresmsg.sender == _owner, and adds the amount to_balances[_owner]. The code shows this power; no transaction was opened showing it used.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.