Coordinape Honeypot
What happened
The token Coordinape (CAPE), contract 0x5674d453…9f3597 on Ethereum, wraps every transfer in a burnTokenCheck modifier. The owner, _safeOwner and whitelisted addresses are not restricted, and anyone may send tokens to the owner. Any other holder can send only to the hard-coded _unirouter address, or, if not blacklisted, in amounts below _sellAmount, which starts at 0; every other transfer, including one into a liquidity pool, reverts with an error that reads like a balance problem.
The owner can whitelist, blacklist, repoint _safeOwner, set _sellAmount and call a public _mint; the constructor itself calls _mint ten times. De.Fi's REKT database lists the token as an Exit Scam/Honeypot dated 2021-04-18; its text speaks of disabling the transfer function, which the code does through this modifier. The contract was deployed on 2021-04-18 at 20:19:53 UTC.
How it happened
- The constructor sets
_owner = owner; _safeOwner = owner;and then calls_mintten times withinitialSupply*(10**18): one for_ownerand nine more naming 0x2D407dDb…47d45C._mintadds the amount to_balances[_owner]whateveraccountis, so all ten amounts land in the owner's balance, while theTransferevents for nine of them name 0x2D407dDb…47d45C._owneris not assigned anywhere else, and the contract has no ownership-transfer or renounce function. transferandtransferFromboth call_approveCheck, which carriesburnTokenCheck. Its first branch isif (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}: while the two are equal, the owner's first outgoing transfer, to any recipient, sets_safeOwnerto that recipient and passes. An owner self-transfer in this state is caught here and does not touch_sellAmount.- Once
_safeOwnerdiffers from_owner,if (sender == _owner || sender == _safeOwner || recipient == _owner)lets the owner,_safeOwner, and anyone sending to the owner (blacklisted senders included) transfer freely. In this branch, if the owner sends to itself,_sellAmount = amountis set; that is possible only while_safeOwner != _owner. - Every other sender (not the owner, not
_safeOwner, recipient not the owner) is checked in order. A whitelisted address passes any transfer, even if it is also blacklisted. A blacklisted, non-whitelisted address passes only if the recipient is_unirouter(0x7a250d56…F2488D), because thesender == _safeOwnerhalf of therequire((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance")is always false here; it cannot use the_sellAmountpath. An address on neither list passes ifamount < _sellAmount, otherwise it faces the samerequire. With_sellAmountat its initial 0, an unlisted holder can therefore send only to_unirouteror the owner; a transfer to a pool reverts, so the sender's balance is not debited. Whether buys from the pool succeed depends on whether the pool is_safeOwneror the buyer is whitelisted, which the code does not show. - When
_sellAmounthas been set and an unlisted sender transfers less than it to_safeOwner, the code runs_blackAddress[sender] = true; _whiteAddress[sender] = false;and still completes the transfer. From then on that sender can send only to_unirouteror the owner. Only senders on neither list reach this branch. - Owner-only functions:
increaseAllowance(address[])whitelists and un-blacklists,addApprove(address[])blacklists and un-whitelists,decreaseAllowance(address safeOwner)sets_safeOwner, andmultiTransfersends tokens and whitelists the firstapprovecountreceivers while approving_unirouterfor the maximum amount. _mint(address account, uint256 amount)ispublicand requiresmsg.sender == _owner, so the owner can create further tokens for itself at any time.- What happened: the supplied sources do not show sale attempts, blacklisting transactions, later minting or liquidity removal for this token. De.Fi's REKT database lists it as an Exit Scam/Honeypot on 2021-04-18.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.