MoonTerra Honeypot

Reported loss Not disclosed
BNB Chain
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

  1. The constructor sets _owner = owner; _safeOwner = owner; and mints the initial supply to the owner. _mint is public but requires msg.sender == _owner, has no cap, and credits _balances[_owner] regardless of the account argument.
  2. Both transfer and transferFrom call _approveCheck, which carries the burnTokenCheck modifier. If _owner == _safeOwner && sender == _owner, the modifier runs _safeOwner = recipient;, so the first transfer the owner makes moves _safeOwner to that recipient. The code does not show which address that was.
  3. Next branch: if (sender == _owner || sender == _safeOwner || recipient == _owner) the transfer goes through, and if (sender == _owner && sender == recipient){_sellAmount = amount;} lets the owner set the _sellAmount threshold by sending tokens to itself. Whitelisted senders (_whiteAddress[sender] == true) also pass unconditionally.
  4. Every other sender hits require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"). Since _sellAmount starts at 0, the test amount < _sellAmount is false until the owner raises it, so such a holder can only send to _unirouter. A sale whose recipient is anything else reverts.
  5. The owner controls the lists: addApprove(address[] memory receivers) sets _blackAddress[...] = true and clears the whitelist, increaseAllowance(address[] memory receivers) whitelists addresses and clears the blacklist, and decreaseAllowance(address safeOwner) reassigns _safeOwner, despite their ERC20-style names. multiTransfer whitelists the first approvecount receivers and approves _unirouter for the maximum amount on their behalf.
  6. When amount < _sellAmount and recipient == _safeOwner, the sender is added to _blackAddress; a blacklisted sender can then only send to _unirouter as 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

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

Build your security review skills

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