Wu-Tang Financial Honeypot
What happened
Wu-Tang Financial (WUFI) is an Ethereum token whose transfers run through a burnTokenCheck modifier. The owner, a _safeOwner address, owner-whitelisted addresses and transfers into the owner pass freely. For other holders, the default path is a require that lets a transfer through only when the recipient is the Uniswap V2 router address hard-coded as _unirouter; otherwise it reverts with "ERC20: transfer amount exceeds balance".
A sell through a trading pair goes to the pair rather than the router, so by default it reverts for an ordinary holder. The owner can change this: a self-transfer by the owner sets _sellAmount, and after that a transfer from an ordinary holder with a smaller amount can pass without going to the router. The constructor also calls _mint eleven times, and the code credits all of that supply to _balances[_owner].
De.Fi's REKT database lists the token as an Exit Scam/Honeypot and says the contract owner could restrict users from selling.
How it happened
- The constructor sets
_ownerand_safeOwnerto theownerargument and calls_minteleven times withinitialSupply*(10**18). Each call emits aTransferevent to one of six distinct listed addresses (one address appears five times, another twice, and four appear once), but_mintadds the amount to_balances[_owner], so by the code all minted supply sits in the owner's balance. - Every
transferandtransferFromgoes through_approveCheck, which carries the modifierburnTokenCheck(sender,recipient,amount). - In the modifier, a sender that is
_ownerwhile_owner == _safeOwnerpasses and_safeOwneris set to the recipient. After that, a transfer passes ifsender == _owner || sender == _safeOwner || recipient == _owner; inside that branch, ifsender == _owner && sender == recipientit also sets_sellAmount = amount. So once_safeOwnerhas moved off the owner, the owner can set_sellAmountwith a self-transfer. - For any other sender, a whitelisted sender (
_whiteAddress[sender] == true) can transfer to any recipient. A blacklisted sender passes only ifsender == _safeOwnerorrecipient == _unirouter. - A sender that is neither whitelisted nor blacklisted is checked against
_sellAmount, which starts at 0, soamount < _sellAmountis false at first. The code then reachesrequire((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");, which reverts unless the recipient is the router (the owner as recipient was already allowed in step 3). If the owner has set_sellAmount, a transfer withamount < _sellAmountcan pass with no router requirement, and the sender is blacklisted and removed from the whitelist only ifrecipient == _safeOwner. A transfer withamount >= _sellAmountstill faces the routerrequire. - A sell through a pair is a
transferFrom(holder, pair, amount). The recipient is the pair, so by default, for a holder who is not whitelisted, the call reverts and the balance is not debited. Whether a given sell can pass depends on whether the owner has set_sellAmountand whetheramountis below it. Buys, where the pair is the sender, can only pass if the pair is_safeOwneror whitelisted, or if the_sellAmountpath applies; the source does not show which address the pair was or what_sellAmountwas set to. - The owner controls the lists:
increaseAllowancewhitelists,addApproveblacklists,decreaseAllowance(address safeOwner)sets_safeOwner, andmultiTransferwhitelists the firstapprovecountreceivers. The names do not describe what these functions do. _mintispublicand gated only byrequire(msg.sender == _owner, ...), so the owner can add supply to its own balance later. The source alone does not show whether this was done.- What happened on-chain (sell attempts, liquidity removal, losses, any
_sellAmountvalue) was not established by the opened sources. De.Fi's REKT database lists the token as a honeypot.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.