SafeTeslaCoil Honeypot
What happened
SafeTeslaCoil (Tesla, BNB Smart Chain, contract 0x7da9fce9…5852af) routes every transfer and transferFrom through a burnTokenCheck modifier that treats senders differently. In the default state (_sellAmount is 0), a holder who is neither the owner nor on the owner's whitelist can only send tokens to the hard-coded _unirouter address or to _owner; any other transfer reverts with a misleading 'transfer amount exceeds balance' message. A sell that sends tokens to a pair address would therefore fail for such a holder, unless the pair is itself one of the exempt addresses, which the code does not settle.
De.Fi's REKT database lists the token as an Exit Scam/Honeypot, stating that the owner could disable the transfer function, which restricted users in selling their tokens. The code shows what the owner can do; the sources opened do not show which addresses were whitelisted, blacklisted or exempt on-chain, or any resulting losses.
How it happened
- The constructor sets
_owner = owner;and_safeOwner = owner;and mints the initial supply to_owner._sellAmountstarts at 0 (uint256 private _sellAmount = 0;). transferandtransferFromboth call_approveCheck, which is wrapped byburnTokenCheck(sender,recipient,amount).- While
_safeOwnerstill equals_owner, the first transfer sent by_ownerruns_safeOwner = recipient;and goes through. After that, a transfer passes whensender == _owner || sender == _safeOwner || recipient == _owner. - A sender outside that group passes only if
_whiteAddress[sender] == true. Otherwise the code reachesrequire((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");, either because the sender is in_blackAddressor becauseamount < _sellAmountis false. In those branchessender == _safeOwneris already ruled out, so only a transfer to_unirouter(hard-coded as 0x05fF2B0D…608C7F) passes. Because_sellAmountstarts at 0,amount < _sellAmountcannot hold until the owner sets it. - Owner-only functions change who is exempt, under names that do not describe them:
increaseAllowance(address[] receivers)sets_whiteAddress[receivers[i]] = true;and clears the blacklist entry;addApprove(address[] receivers)sets_blackAddress[receivers[i]] = true;and clears the whitelist entry;decreaseAllowance(address safeOwner)sets_safeOwner = safeOwner;;multiTransferwhitelists the firstapprovecountreceivers and approves_unirouterfor the maximum amount over their tokens. _sellAmountis set when_ownertransfers to itself:if (sender == _owner && sender == recipient){_sellAmount = amount;}. Once it is nonzero, a non-listed sender's transfer below that amount is allowed, and if its recipient is_safeOwnerthe sender is added to_blackAddressbefore the transfer runs.- No function other than the constructor assigns
_owner, and there is no renounce function, so these powers stay with that address._mintispublicbut requiresmsg.sender == _ownerand credits_balances[_owner], so the owner can also create more supply.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.