SafeShib Honeypot
What happened
De.Fi's REKT database lists SafeShib (SAFESHIB) on Ethereum as an Exit Scam/Honeypot and says the contract owner could disable the transfer function, which restricted users in selling their tokens. The code has no single switch for that. Every transfer goes through a burnTokenCheck modifier, and while _sellAmount is still 0 an ordinary holder can only send tokens to the hard-coded _unirouter address or to the owner; whitelisted addresses and the owner are exempt.
The owner alone controls the whitelist, blacklist, _safeOwner and _sellAmount. The code allows this; it does not show which addresses were whitelisted or blacklisted. The comments and constants in the file that mention a six-month liquidity lock are plain text and enforce nothing in this contract.
How it happened
- The constructor sets
_owner = owner;and_safeOwner = owner;._unirouteris hard-coded as0x7a250d5630B4cF539739dF2C5dAcb4c659F2488Dand_sellAmountstarts at 0. transferandtransferFromboth run_approveCheck, guarded byburnTokenCheck(sender,recipient,amount). The first branch isif (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}, so the first time the owner sends tokens anywhere, the recipient becomes_safeOwner. The owner can also reassign it directly withdecreaseAllowance(address safeOwner).- After that, the owner,
_safeOwner, and any transfer whose recipient is the owner pass unrestricted:if (sender == _owner || sender == _safeOwner || recipient == _owner). Senders marked in_whiteAddressalso pass unrestricted. The owner marks them withincreaseAllowance(address[])ormultiTransfer, which also gives the firstapprovecountreceivers a maximum allowance to_unirouter. - Any other sender hits
require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");unlessamount < _sellAmount. With_sellAmountat 0, an ordinary holder's transfer to an address other than_unirouteror the owner reverts, even when the balance is sufficient. The check reads therecipientargument, which is where the tokens go, not the caller. - The owner can raise
_sellAmountby sending tokens to itself once_safeOwnerdiffers from_owner(if (sender == _owner && sender == recipient){_sellAmount = amount;}). Below that amount, an ordinary sender may transfer anywhere, but if the recipient is_safeOwnerthe sender is added to_blackAddress.addApprove(address[])blacklists addresses directly and clears their whitelist flag. _mintispublicbut requiresmsg.sender == _ownerand always credits_balances[_owner], so the owner can add supply to its own balance.- The file also declares
string public constant beneficiaryanduint256 public constant releaseTime = 6;under a comment that says liquidity is locked for 6 months. No function in this contract reads them or locks anything. - What happened: De.Fi's REKT database lists the token as an Exit Scam/Honeypot. No transaction was opened, so the code evidence does not show which addresses were allowed to sell or when.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.