Bulldoge Honeypot
What happened
Bulldoge (BDG) is a BEP-20 token on BNB Smart Chain deployed on 2021-05-05 at 0x5dd713d7…4165d3. De.Fi's REKT database lists it as an exit scam/honeypot dated 2021-05-07 and says the contract owner could disable the transfer function, which restricted users in selling their tokens. In the verified source, every transfer passes through a burnTokenCheck modifier.
By default, a holder who is not on the owner's whitelist can only send tokens to the hard-coded _unirouter address or to the owner, so a sale to any other pair address reverts with "ERC20: transfer amount exceeds balance" even though the balance is sufficient. The owner can whitelist or blacklist addresses, change _safeOwner, set _sellAmount, and mint.
How it happened
- The constructor sets
_owner = owner; _safeOwner = owner;and mints the supply to the owner._sellAmountstarts at 0 and_unirouteris hard-coded as 0x05fF2B0D…608C7F. - Every
transferandtransferFromgoes through_approveCheck(...) burnTokenCheck(sender,recipient,amount). While_owner == _safeOwner, the first transfer made by the owner runs_safeOwner = recipient;, so_safeOwnerbecomes whichever address the owner first sends to. The source does not say who that address is. - After that, a sender that is the owner, the
_safeOwner, or sends to the owner passes. A sender on_whiteAddresspasses. Everyone else reaches the final checks. - A sender on
_blackAddressrunsrequire((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"). Because_safeOwneralready passed in step 3, this means the recipient must be_unirouter. - A sender on neither list passes only when
amount < _sellAmount. With_sellAmountat its initial 0 this is never true, so such a sender faces the samerequireand can only send to_unirouteror the owner. In that case a transfer to any other address, such as a liquidity pair that is not_unirouter, reverts, and the sender's balance is not debited. If_sellAmountis set above the amount, the transfer passes, and ifrecipient == _safeOwnerthe sender is added to_blackAddressand removed from_whiteAddress. - The owner sets the state with owner-only functions:
increaseAllowance(address[])whitelists,addApprove(address[])blacklists,decreaseAllowance(address safeOwner)replaces_safeOwner, a transfer from the owner to itself sets_sellAmount = amount, andmultiTransferwhitelists the firstapprovecountreceivers and approves_unirouterfor the maximum amount for them._mintis public but requiresmsg.sender == _owner, and it adds the amount to_balances[_owner]. - The source has no function to change
_owneror renounce it. Whether the owner called any of these functions on this token is not shown by the code; no transaction was opened.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.