SafeAmerica Honeypot
What happened
SafeAmerica (SAFEAMERICA) is a token on BNB Smart Chain whose burnTokenCheck modifier wraps every transfer. Under the default state (_sellAmount = 0) a holder who is neither whitelisted nor the owner or _safeOwner can only send tokens to the hard-coded _unirouter address or to the owner; any other transfer reverts with "ERC20: transfer amount exceeds balance". The owner controls the whitelist, blacklist, _safeOwner and _sellAmount, and can mint more tokens.
De.Fi's REKT database lists the token as an exit scam/honeypot in which the contract owner could disable the transfer function, which restricted users in selling their tokens.
How it happened
- The constructor sets
_owner = owner; _safeOwner = owner;and mints the initial supply to the owner._owneris assigned only there; the contract has no function to transfer or renounce it. transferandtransferFromboth call_approveCheck, which carries theburnTokenCheck(sender,recipient,amount)modifier.- If
_owner == _safeOwner && sender == _owner, the modifier runs_safeOwner = recipient;and lets the transfer through. After that, transfers wheresender == _owner || sender == _safeOwner || recipient == _owneralso pass, and a self-transfer by the owner runs_sellAmount = amount;. - A sender in
_whiteAddressalways passes. Every other sender reachesif (amount < _sellAmount). With the default_sellAmount = 0that is never true, so the final branch runsrequire((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");and, for a sender who is not_safeOwner, the transfer reverts unless the recipient is_unirouter(or the owner, handled earlier). A blacklisted sender faces the samerequire. - If the owner sets
_sellAmountabove zero, a non-listed sender sending less than that amount passes, and if the recipient is_safeOwnerthat sender is moved to_blackAddressby_blackAddress[sender] = true; _whiteAddress[sender] = false;. The owner can also whitelist (increaseAllowance), blacklist (addApprove), and re-point_safeOwner(decreaseAllowance), andmultiTransferwhitelists the firstapprovecountreceivers and approves_unirouterfor the maximum allowance on their behalf. _mintispublicand credits_balances[_owner]regardless of theaccountargument, so the owner can add supply at any time; theTransferevent namesaccountrather than the owner. The code alone does not show whether any of these functions was used or which address the pair is relative to_safeOwner.
Protocol details
Evidence
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.