MoonTerra Honeypot
What happened
De.Fi's REKT database lists MoonTerra (MOONTERRA) on BNB Smart Chain as an Exit Scam/Honeypot and says the contract owner could disable the transfer function. The verified source has no single switch, but every transfer passes a burnTokenCheck modifier whose branches let only a few senders move tokens freely: the owner, an owner-chosen _safeOwner, and addresses the owner whitelists. Any other holder can only send to the hard-coded _unirouter address, so a transfer to any other recipient, such as a liquidity pair that is not that address, reverts with "ERC20: transfer amount exceeds balance".
How it happened
- The constructor sets
_owner = owner; _safeOwner = owner;and mints the initial supply to the owner._mintispublicbut requiresmsg.sender == _owner, has no cap, and credits_balances[_owner]regardless of theaccountargument. - Both
transferandtransferFromcall_approveCheck, which carries theburnTokenCheckmodifier. If_owner == _safeOwner && sender == _owner, the modifier runs_safeOwner = recipient;, so the first transfer the owner makes moves_safeOwnerto that recipient. The code does not show which address that was. - Next branch:
if (sender == _owner || sender == _safeOwner || recipient == _owner)the transfer goes through, andif (sender == _owner && sender == recipient){_sellAmount = amount;}lets the owner set the_sellAmountthreshold by sending tokens to itself. Whitelisted senders (_whiteAddress[sender] == true) also pass unconditionally. - Every other sender hits
require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"). Since_sellAmountstarts at 0, the testamount < _sellAmountis false until the owner raises it, so such a holder can only send to_unirouter. A sale whose recipient is anything else reverts. - The owner controls the lists:
addApprove(address[] memory receivers)sets_blackAddress[...] = trueand clears the whitelist,increaseAllowance(address[] memory receivers)whitelists addresses and clears the blacklist, anddecreaseAllowance(address safeOwner)reassigns_safeOwner, despite their ERC20-style names.multiTransferwhitelists the firstapprovecountreceivers and approves_unirouterfor the maximum amount on their behalf. - When
amount < _sellAmountandrecipient == _safeOwner, the sender is added to_blackAddress; a blacklisted sender can then only send to_unirouteras well.
What the code allows is separate from what happened: the code shows the mechanism, and De.Fi's REKT database is the source for the honeypot classification. No transaction was opened that shows which of these functions the owner called.
Protocol details
Evidence
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.