DoucheCoin Honeypot

Reported loss Not disclosed
BNB Chain
Honeypot

What happened

DoucheCoin (DOUCHE) is a BNB Smart Chain token whose transfers pass through a burnTokenCheck modifier that lets the owner, a _safeOwner address, and a whitelist move tokens freely while an ordinary holder can only send to the hard-coded _unirouter address, to the owner, or in amounts below an owner-set _sellAmount (zero by default). The owner controls the whitelist, the blacklist, _safeOwner and _sellAmount, and can also call a public _mint. De.Fi's REKT database lists DoucheCoin as an Exit Scam/Honeypot in which the contract owner could disable transfers and so restrict holders from selling.

How it happened

  1. The constructor sets _owner = owner and _safeOwner = owner, then calls _mint, which itself requires msg.sender == _owner, so the deploying address is the owner. The only assignment to _owner in the file is in the constructor, and the contract has no function that changes it.
  2. All transfers run _approveCheck(...) guarded by burnTokenCheck. While _owner == _safeOwner, the first transfer sent by the owner takes the first branch, if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}, and records that recipient as _safeOwner. The code does not show which address that was.
  3. For every later transfer, the owner, _safeOwner, or anyone sending to the owner passes. An owner self-transfer also sets _sellAmount = amount.
  4. Any other sender who is on _whiteAddress passes. A non-whitelisted holder reaches require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"), so the transfer reverts unless the recipient is _unirouter or the amount is below _sellAmount. _sellAmount starts at 0, so amount < _sellAmount is never true until the owner raises it. A transfer to any other address, including a liquidity pair that is neither the owner nor _unirouter, therefore reverts for a non-whitelisted holder.
  5. When amount < _sellAmount and the recipient is _safeOwner, the sender is added to _blackAddress and removed from _whiteAddress after the transfer. A blacklisted sender can then only send to _unirouter.
  6. The owner manages the lists. increaseAllowance(address[]) whitelists addresses (despite its name), addApprove(address[]) blacklists them, decreaseAllowance(address) overwrites _safeOwner, and multiTransfer whitelists the first approvecount recipients and gives them a maximum allowance to _unirouter.
  7. _mint(address account, uint256 amount) is public and owner-only, and it credits _balances[_owner] regardless of account, so the owner can increase supply.
  8. Everything above is what the code allows. The code alone does not show which addresses were whitelisted or blacklisted, who _safeOwner became, or whether _mint was called.

Protocol details

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

Build your security review skills

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