SHIBAFARM 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:
- The constructor sets
_owner = owner; _safeOwner = owner;and calls_mint(_owner, initialSupply*(10**18))._mintispublic, gated only byrequire(msg.sender == _owner, ...), and credits_balances[_owner], so the owner can mint more supply to its own balance at any time. - 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 isif (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}: while_safeOwnerequals the owner, the first transfer the owner makes sets_safeOwnerto its recipient. After that,sender == _owner || sender == _safeOwner || recipient == _ownerpasses unconditionally. - 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 isrequire((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"). - A sender on neither list reaches
if (amount < _sellAmount)._sellAmountis initialised to0, soamount < 0is never true until it is set, and theelsebranch applies the same requirement:require((sender == _safeOwner)||(recipient == _unirouter), ...). While_sellAmountis0, 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. - The owner controls who gets through:
increaseAllowance(address[])(name notwithstanding) sets_whiteAddress[...] = true,addApprove(address[])sets_blackAddress[...] = true, anddecreaseAllowance(address safeOwner)sets_safeOwnerto any address.multiTransferalso whitelists the firstapprovecountreceivers and approves_unirouterfor them. - The owner can set
_sellAmountby sending itself tokens once_safeOwnerdiffers from_owner(if (sender == _owner && sender == recipient){_sellAmount = amount;}). While_sellAmountis above zero, a non-listed holder's transfer of a smaller amount is allowed to any recipient, and if the recipient is_safeOwnerthe sender is added to_blackAddressin 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
Evidence
- report De.Fi REKT database listing, proof link (Token Sniffer tweet; could not be opened) twitter.com
- report Sourcify exact-match source for 0xbe3fbd14dc899fe457323fb6e4473cf3ab04e3c0 (contracts/shibafarm.sol) repo.sourcify.dev
- address Etherscan verified source: SHIBAFARM 0xbe3fbd14dc899fe457323fb6e4473cf3ab04e3c0 etherscan.io
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.