THANKS ELON Honeypot
What happened
THANKS ELON is a BNB Smart Chain token whose transferFrom is restricted by a switch, trans, that starts as false. While it is off, transferFrom only succeeds when the deployer is the sender or the recipient, or when the sender is the token's own liquidity pair, so a holder's swap through a router, which moves tokens with transferFrom, reverts. Only an account with MINTER_ROLE can turn the switch on with setTrans.
The functions renounceOwnership() and lockLiquidity() only emit events and change no state. De.Fi's REKT database lists THANKS ELON as an Exit Scam/Honeypot in which the contract owner could disable transfers and so restrict holders from selling.
How it happened
- The constructor stores the deployer in
moi, setstrans = false, gives the deployerDEFAULT_ADMIN_ROLE,PAUSER_ROLEandMINTER_ROLE, mints1000000000000 * 10 ** decimals()tokens to the deployer, and creates the token's pair on the router at the hard-coded address 0x05fF2B0D…608C7F, storing it in the immutableuniswapV2Pair. transferFromis overridden with this gate:require (trans || moi == sender || moi == recipient || sender == UNI);whereUNIisuniswapV2Pair. Whiletransis false, atransferFrompasses only if the deployer is the sender or recipient, or if the pair is the sender.- A holder who swaps tokens for BNB through a router makes the router call
transferFrom(holder, pair, amount). The holder is notmoi, the recipient is the pair rather thanmoi, and the sender is not the pair, so therequirefails and the sell reverts whiletransis false. Buys, where the pair is the sender, and transfers involving the deployer are not blocked by this line. - Plain
transferis not overridden and is not gated bytrans, so holder-to-holder transfers made withtransferare not stopped by this check. - Only
setTrans(bool value)changes the switch, and it requiresMINTER_ROLE:require(hasRole(MINTER_ROLE, msg.sender)); trans=value;. The deployer holds that role from the constructor, andDEFAULT_ADMIN_ROLEcan grant it to others. - Other owner-side powers:
piocher(address to, uint256 amount)mints new tokens for anyMINTER_ROLEholder, andpause()/unpause()(PAUSER_ROLE) toggle a pause that_beforeTokenTransferenforces throughwhenNotPaused, which blocks all transfers. renounceOwnership()(emit OwnershipRenounced(address(0), address(this));) andlockLiquidity()(emit liquidityLocked(uniswapV2Pair, address(0));) contain onlyemitstatements. They write nothing to storage and revoke no role, so calling them gives no on-chain effect other than the event.- These are the powers the code allows. The code alone does not show whether
transwas ever turned on, whetherpiocherorpausewas called, or who holds the liquidity tokens.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.