DipBitcoin Honeypot
What happened
DipBitcoin is a BEP-20 token on BNB Smart Chain, deployed from 0x514142F2…4B62c8 in transaction 0x5fee0476…11124c on 2021-05-19. De.Fi's REKT database lists it as an Exit Scam/Honeypot, saying the contract owner could disable the transfer function and so restrict users from selling. The verified source overrides transferFrom, the call a router uses to pull tokens from a seller, so that it requires the flag trans, the deployer, or the pool pair as sender; trans starts as false and only a holder of MINTER_ROLE can change it.
The functions named renounceOwnership and lockLiquidity only emit events and change nothing. The source does not show whether trans was ever switched or whether any sale failed.
How it happened
- The constructor creates the pool pair, stores the deployer as the private immutable
moi, setstrans = false, grants the deployer the admin, pauser and minter roles, and mints the supply to the deployer:_mint(msg.sender, 1000000000000 * 10 ** decimals());. transferFromis overridden with a gate:require (trans || moi == sender || moi == recipient || sender == UNI);, whereUNIisuniswapV2Pair. Whiletransisfalse, a holder who is not the deployer can pass it only when the recipient is the deployer; a call with the holder as sender and the pair as recipient reverts.- A sale through a router pulls the holder's tokens into the pair with
transferFrom, so it hits this require and reverts with no message. The revert happens before_transfer, so the holder's balance is not debited. Plaintransferis not overridden, so direct wallet-to-wallet transfers are not gated by this check. - Liquidity removal is not affected for the deployer, who is
moi; anytransferFromwhere the deployer is sender or recipient passes. setTrans(bool value)requireshasRole(MINTER_ROLE, msg.sender), so the minter can open or close the gate at any time. Whether it was opened is not shown by the source.- Further powers:
pause()andunpause()needPAUSER_ROLE, and while paused_beforeTokenTransferiswhenNotPaused, so every transfer reverts.piocher(address to, uint256 amount)mints new tokens for anyMINTER_ROLEholder, and the deployer holdsDEFAULT_ADMIN_ROLE, which can grant roles. renounceOwnership()isfunction renounceOwnership() public { emit OwnershipRenounced(address(0), address(this)); }andlockLiquidity()isemit liquidityLocked(uniswapV2Pair, address(0));. Both are callable by anyone, change no state and move no liquidity, so the events they emit do not show that ownership or liquidity changed.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.