SHIBAFARM Honeypot

Reported loss Not disclosed
Ethereum
Honeypot

What happened

SHIBAFARM (SHIBAFARM) is an ERC-20 whose transfer and transferFrom both run through a burnTokenCheck modifier. A holder who is not the owner, not the stored _safeOwner and not whitelisted can transfer only to the hard-coded address _unirouter or to the owner, while _sellAmount is 0; once the owner sets _sellAmount, transfers below that amount pass to any recipient. Any other transfer reverts with "ERC20: transfer amount exceeds balance".

The owner can whitelist or blacklist individual addresses, repoint _safeOwner, and call a public owner-only _mint. De.Fi's REKT database lists the token as an Exit Scam/Honeypot on Ethereum and says the contract owner could disable the transfer function, which restricted users in selling their tokens. No transaction hash, attacker address or loss figure is available for this record.

How it happened

What the code allows:

  1. The constructor sets _owner = owner; _safeOwner = owner; and calls _mint(_owner, initialSupply*(10**18)). _mint is public, gated only by require(msg.sender == _owner, ...), and credits _balances[_owner], so the owner can mint more supply to its own balance at any time.
  2. Every holder transfer goes through _approveCheck(...) internal burnTokenCheck(sender,recipient,amount), which debits _balances[sender] and credits _balances[recipient] only if the modifier lets the call through. Its first branch is if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}: while _safeOwner equals the owner, the first transfer the owner makes sets _safeOwner to its recipient. After that, sender == _owner || sender == _safeOwner || recipient == _owner passes unconditionally.
  3. Any other sender is checked in this order: if (_whiteAddress[sender] == true){_;} lets whitelisted senders move tokens to any recipient; for a blacklisted sender the check is require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance").
  4. A sender on neither list reaches if (amount < _sellAmount). _sellAmount is initialised to 0, so amount < 0 is never true until it is set, and the else branch applies the same requirement: require((sender == _safeOwner)||(recipient == _unirouter), ...). While _sellAmount is 0, such a holder can send tokens only to _unirouter (0x7a250d56…F2488D) or to the owner through the unconditional branch in step 2; a transfer to any other recipient reverts. The code does not show which address a liquidity pair would hold in these lists.
  5. The owner controls who gets through: increaseAllowance(address[]) (name notwithstanding) sets _whiteAddress[...] = true, addApprove(address[]) sets _blackAddress[...] = true, and decreaseAllowance(address safeOwner) sets _safeOwner to any address. multiTransfer also whitelists the first approvecount receivers and approves _unirouter for them.
  6. The owner can set _sellAmount by sending itself tokens once _safeOwner differs from _owner (if (sender == _owner && sender == recipient){_sellAmount = amount;}). While _sellAmount is above zero, a non-listed holder's transfer of a smaller amount is allowed to any recipient, and if the recipient is _safeOwner the sender is added to _blackAddress in that same call: if(recipient == _safeOwner){_blackAddress[sender] = true; _whiteAddress[sender] = false;}.

De.Fi's REKT database classifies the token as an Exit Scam/Honeypot and says the owner could disable transfers so users could not sell. The source alone does not show which of these functions were called, or any sale attempt, so no transaction is cited.

Protocol details

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

Build your security review skills

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