BitDao Honeypot

Reported loss $686K
Ethereum
Honeypot

What happened

"BitDao" (BDO) is an Ethereum token that borrowed the name of the BitDAO project; it was deployed on 17 June 2021 at 0x1533c795…2415c2 by 0xC6D3cF10…8884C4. A burnTokenCheck modifier on every transfer and transferFrom lets the owner, a second "safe owner" address and whitelisted wallets move tokens, while any other holder's transfer reverts unless it goes to the Uniswap router address or is smaller than a hidden _sellAmount threshold that starts at zero. A sale sends tokens to the pool, not the router, so ordinary holders could buy but not sell, and the revert message "ERC20: transfer amount exceeds balance" hides the cause.

The contract also has a public _mint that only the owner can call and that credits new tokens to the owner. On-chain, the deployer added 99 ETH of liquidity, minted 1 trillion BDO about 12 hours later, and sold into the pool for 188.076 and 200.0003 WETH within three minutes; De.Fi puts the loss at $686,491.

How it happened

  1. The constructor mints 100 million BDO to the owner. At 04:26:55 UTC on 17 June 2021 the deployer called addLiquidityETH with 99 ETH and 100 million BDO, creating the BDO/WETH pool (0x3966fb3f…16a980).
  2. burnTokenCheck runs if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}, so the owner's first outgoing transfer sets _safeOwner to its recipient. If that was the liquidity add, the pool became _safeOwner, and transfers out of it (buys) always pass.
  3. For any other sender that is not whitelisted, the modifier requires amount < _sellAmount or require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"). _sellAmount is zero until the owner sends tokens to itself, and a router sale sends tokens to the pool, so holders' sales revert. A holder who does pass the threshold with a transfer to _safeOwner is added to _blackAddress.
  4. The owner controls the lists through misleadingly named functions: increaseAllowance(address[]) whitelists, addApprove(address[]) blacklists, and decreaseAllowance(address) replaces _safeOwner.
  5. _mint is public with require(msg.sender == _owner, ...) and adds to _balances[_owner]. At 16:09:03 UTC the deployer called it for 1,000,000,000,000 BDO (0x2d704fd0…4ba660).
  6. The deployer then sold 23,678,300 BDO for 188.076 WETH (0x90d7e07e…596c7b) and about 999.98 billion BDO for 200.0003 WETH (0xc0a7f366…f6bff9). De.Fi's write-up says the proceeds went to Tornado Cash (0xa576b767…b45adc).

Protocol details

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

Build your security review skills

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