Doggy Token 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
- The constructor stores
_owner = owner; _safeOwner = owner;and mints the supply to the owner. Because the constructor calls_mint, which requiresmsg.sender == _owner, the owner is the deployer, 0xb943969c…132e0e. - Both
transferandtransferFromcall_approveCheck, which carries theburnTokenCheckmodifier. If_owner == _safeOwner && sender == _owner, the modifier sets_safeOwner = recipientand lets the transfer run. So the recipient of the owner's first transfer becomes_safeOwner. - For other senders, a transfer passes without further checks if
sender == _owner || sender == _safeOwner || recipient == _owner, or if_whiteAddress[sender] == true. - A sender with no whitelist entry (and not blacklisted) reaches
if (amount < _sellAmount)._sellAmountis 0 until the owner sets it, so this is false and the code runsrequire((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. - A blacklisted sender (
_blackAddress[sender] == true) faces the samerequire. The owner-only functionsincreaseAllowance(whitelists and un-blacklists),addApprove(blacklists and un-whitelists) anddecreaseAllowance(sets_safeOwner) control who is exempt;multiTransfercan whitelist its firstapprovecountreceivers and give_uniroutera maximum allowance over their tokens. - When the owner transfers to itself,
_sellAmount = amountis set. After that, a non-whitelisted holder can send an amount smaller than_sellAmountto any recipient; if that recipient is_safeOwner, the sender is moved to_blackAddress. _mintispublicbut limited to the owner, and credits_balances[_owner]whateveraccountis, so the owner can increase supply.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.