HOPE Honeypot
What happened
HOPE ($HOPE) is an Ethereum token deployed on 31 March 2021 at 0xf2bb8bc4…818ba8 by 0x1a92b9dd…3c1861. Every transfer and transferFrom runs the burnTokenCheck modifier, which lets the fixed _owner, a stored _safeOwner address and whitelisted wallets move tokens but makes every other holder's transfer revert unless it is sent to the Uniswap V2 router address. A Uniswap sale moves tokens into the pair, not the router, so ordinary holders can buy but not sell, and the revert shows the misleading message "ERC20: transfer amount exceeds balance".
The constructor also emits five mint events naming 0x88faAC16…1d7129, but the mint function credits every one of them to the owner, so event-based holder lists show a second large holder that has no balance. De.Fi's REKT database lists HOPE as an exit scam/honeypot.
How it happened
- The constructor sets
_ownerand_safeOwnerto itsownerargument and calls the public_mintsix times._mintrequiresmsg.sender == _owner, so deployment only succeeds whenowneris the deploying account. _mintruns_balances[_owner] = _balances[_owner].add(amount)but emitsTransfer(address(0), account, amount). The five calls to_mint(0x88faAC1678c864d080d592BC15d1CdAdf01d7129, ...)therefore add supply to the owner while the event log shows it going to 0x88faAC....- In
burnTokenCheck, while_owner == _safeOwner, the owner's first outgoing transfer runs_safeOwner = recipient. If that first transfer is the liquidity deposit into the Uniswap pair, the pair becomes_safeOwner; the owner can also set it directly withdecreaseAllowance(address safeOwner). - Transfers where the sender is
_owneror_safeOwner, or the recipient is_owner, always pass, so buys out of a pair set as_safeOwnergo through. Senders whitelisted byincreaseAllowance(address[])or by the owner'smultiTransferalso pass. - Every other sender hits
require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance")._unirouteris 0x7a250d56…F2488D, the Uniswap V2 router, but a sale transfers the holder's tokens to the pair, so it reverts. Senders on theaddApprove(address[])blacklist are always held to this check. - An unlisted sender passes only if
amount < _sellAmount, which starts at 0 and which the owner can raise by transferring to itself; a transfer under the limit into_safeOwnerthen blacklists the seller. The public owner-only_mintremains callable after deployment.
Protocol details
Evidence
- report Token Sniffer post 1374999601485291522 (seed link) twitter.com
- transaction HOPE contract creation transaction etherscan.io
- address HOPE ($HOPE) verified contract code on Etherscan etherscan.io
- analysis Sourcify match for 0xf2bb8bc4dee85c27854779a38edabb4919818ba8 on Ethereum repo.sourcify.dev
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.