Disbalancer Honeypot

Reported loss Not disclosed
Ethereum
Honeypot

What happened

Disbalancer (DDOS) is an Ethereum token whose transfer logic, in the burnTokenCheck modifier, treats holders differently depending on owner-controlled lists. A holder who is on neither list, and whose amount is not below _sellAmount (which starts at 0), may only send tokens to the Uniswap V2 router address 0x7a250d56…F2488D or to the owner. A sale routed through the router calls transferFrom with the pair as recipient, which that check rejects with "ERC20: transfer amount exceeds balance".

The owner can whitelist or blacklist any address, repoint the _safeOwner privilege, and mint more supply with no cap. De.Fi's REKT database lists the token as an exit scam/honeypot dated 2021-04-15, describing the owner as able to disable the transfer function so users could not sell. The deployer minted 100,000,000 tokens (18 decimals) in the constructor.

How it happened

  1. The constructor sets _owner = msg.sender; and _safeOwner = msg.sender; and mints 100*1e6*(10**18) to the owner. _unirouter is hard-coded as 0x7a250d56…F2488D and _sellAmount starts at 0.
  2. Every transfer and transferFrom runs _approveCheck, which carries the burnTokenCheck modifier. If _owner == _safeOwner and the sender is the owner, the first branch runs _safeOwner = recipient; and the transfer passes, so the first owner transfer hands the _safeOwner privilege to whoever receives it. After that, a sender equal to _owner or _safeOwner, or any transfer to _owner, passes.
  3. For other senders, an address with _whiteAddress[sender] == true passes. A blacklisted sender must satisfy require((sender == _safeOwner)||(recipient == _unirouter), ...), so it can send only to the router (or to the owner, which passes earlier).
  4. A sender on neither list reaches if (amount < _sellAmount). With _sellAmount at 0 this is never true, so the else runs require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");. A router sell uses transferFrom(holder, pair, amount), so the recipient is the pair, not the router, and the call reverts. Whether the pair is the stored _safeOwner is not shown by the code; if it is, tokens leaving the pair to buyers pass at the sender == _safeOwner check.
  5. If _sellAmount is raised (an owner self-transfer sets it when _owner != _safeOwner), a non-listed holder may transfer amounts below it, and if the recipient is _safeOwner the holder is added to _blackAddress.
  6. The owner-only functions increaseAllowance (whitelist and un-blacklist), addApprove (blacklist and un-whitelist), decreaseAllowance (sets _safeOwner) and multiTransfer (whitelists the first approvecount recipients and gives each an unlimited allowance to the router) are named like ERC-20 allowance helpers but change these privileges. _mint is public and checks only msg.sender == _owner, adding any amount to the owner's balance. There is no function to renounce or transfer _owner.

What the code allows is shown above. De.Fi's REKT database lists the token as a honeypot; no transaction opened for this draft shows the owner using any of these functions or any holder's failed sell.

Protocol details

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

Build your security review skills

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