Doggy Token Honeypot

Reported loss Not disclosed
Ethereum
Honeypot

What happened

Doggy Token (DOGGY) is an Ethereum token whose transfer and transferFrom both run through a burnTokenCheck modifier that lets only the owner and addresses the owner whitelists move tokens freely. Any other holder can send tokens only to _unirouter (a hard-coded address) or to the owner, so a transfer to any other address, including a trading pair, reverts with "ERC20: transfer amount exceeds balance" even though the balance is sufficient. The owner can whitelist or blacklist addresses and can mint more supply to itself.

De.Fi's REKT database lists DOGGY as an exit scam / honeypot where the contract owner could disable the transfer function, which restricted users in selling their tokens.

How it happened

  1. The constructor stores _owner = owner; _safeOwner = owner; and mints the supply to the owner. Because the constructor calls _mint, which requires msg.sender == _owner, the owner is the deployer, 0xb943969c…132e0e.
  2. Both transfer and transferFrom call _approveCheck, which carries the burnTokenCheck modifier. If _owner == _safeOwner && sender == _owner, the modifier sets _safeOwner = recipient and lets the transfer run. So the recipient of the owner's first transfer becomes _safeOwner.
  3. For other senders, a transfer passes without further checks if sender == _owner || sender == _safeOwner || recipient == _owner, or if _whiteAddress[sender] == true.
  4. A sender with no whitelist entry (and not blacklisted) reaches if (amount < _sellAmount). _sellAmount is 0 until the owner sets it, so this is false and the code runs require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"). Such a holder can send tokens only to _unirouter (or to the owner, per step 3); any other recipient reverts and no balances change.
  5. A blacklisted sender (_blackAddress[sender] == true) faces the same require. The owner-only functions increaseAllowance (whitelists and un-blacklists), addApprove (blacklists and un-whitelists) and decreaseAllowance (sets _safeOwner) control who is exempt; multiTransfer can whitelist its first approvecount receivers and give _unirouter a maximum allowance over their tokens.
  6. When the owner transfers to itself, _sellAmount = amount is set. After that, a non-whitelisted holder can send an amount smaller than _sellAmount to any recipient; if that recipient is _safeOwner, the sender is moved to _blackAddress.
  7. _mint is public but limited to the owner, and credits _balances[_owner] whatever account is, so the owner can increase supply.

Protocol details

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

Build your security review skills

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