French Shiba Honeypot

Reported loss Not disclosed
Ethereum
Honeypot

What happened

French Shiba (USHlBA) is an Ethereum token whose transfer and transferFrom both pass through a burnTokenCheck modifier that treats senders differently. The owner-controlled variables _safeOwner, _sellAmount and two address lists decide whether a transfer reverts, and the revert text ("ERC20: transfer amount exceeds balance") is the one a balance problem would show. Unless the sender is the owner, _safeOwner, whitelisted, or sending to _owner, a transfer is accepted only when the recipient is the hard-coded router address 0x7a250d56…F2488D or the amount is below _sellAmount, which starts at 0.

The owner can whitelist or blacklist addresses and move _safeOwner. De.Fi's REKT database lists the token as an Exit Scam/Honeypot dated 2021-05-12 and says the owner could disable the transfer function, which restricted users in selling their tokens; the listing gives no loss figure. No transaction was opened to show which addresses were listed or what _safeOwner holds.

How it happened

  1. The constructor sets _owner = owner; _safeOwner = owner; and _unirouter = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D. It then calls _mint ten times; _mint credits _balances[_owner] whatever account is, so the nine calls naming 0xAb5801a7…9aeC9B only change the emitted Transfer events, not that address's balance.
  2. In burnTokenCheck, while _owner == _safeOwner, any transfer sent by the owner passes and runs _safeOwner = recipient;. This hands _safeOwner to the first address the owner sends tokens to.
  3. Afterwards a transfer passes unchecked if sender == _owner || sender == _safeOwner || recipient == _owner; when sender == _owner && sender == recipient, the amount is stored with _sellAmount = amount;.
  4. Any other sender passes if _whiteAddress[sender] == true. If the sender is blacklisted, or on neither list and the amount is not below _sellAmount, the call runs require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");, so it only succeeds when the recipient is the router. A transfer into any other address, such as a pair, reverts whatever the sender's balance is. With _sellAmount at its initial 0, amount < _sellAmount never holds.
  5. When amount < _sellAmount the transfer passes, and if(recipient == _safeOwner){_blackAddress[sender] = true; _whiteAddress[sender] = false;} blacklists a sender whose recipient is _safeOwner.
  6. The owner-only functions behind the lists have misleading names: multiTransfer whitelists the first approvecount receivers and approves the router for the maximum amount, increaseAllowance(address[]) whitelists and un-blacklists, addApprove(address[]) blacklists, and decreaseAllowance(address) sets _safeOwner. _mint(address,uint256) is public but requires msg.sender == _owner, and _owner has no setter in the code.

Protocol details

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

Build your security review skills

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