OccamFi Honeypot
What happened
OccamFi (OCC) is a token on Ethereum with a supply of 500,000,000, deployed at 0x95e8165a…6c7ec4 in transaction 0x33e299bd…160f9f on 2021-04-14. Every transfer runs through a modifier named burnTokenCheck. With the default _sellAmount of zero, a holder who is not on the owner's whitelist can only send tokens to the hard-coded Uniswap V2 router address 0x7a250d56…F2488D or to the owner, so a sell, which moves tokens from the holder to the pair, reverts.
Whitelisted addresses are exempt and the owner can edit the lists. De.Fi's REKT database lists OCC as an Exit Scam/Honeypot.
How it happened
- The constructor sets
_owner = msg.sender;and_safeOwner = msg.sender;and mints 500,000,000 tokens to the owner with_mint(_owner, 500*1e6*(10**18));._sellAmountstarts at 0 and_unirouteris hard-coded to 0x7a250d56…F2488D. transferandtransferFromboth call_approveCheck, which is wrapped byburnTokenCheck. While_owner == _safeOwner, the owner's first outgoing transfer passes and re-points the exempt address:if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}.- Afterwards, the owner,
_safeOwnerand any transfer to the owner pass:if (sender == _owner || sender == _safeOwner || recipient == _owner){. Whitelisted senders also pass:if (_whiteAddress[sender] == true){ _;. - Every other sender must satisfy
require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");. Because_safeOwneralready passed in step 3, only a transfer to the router address gets through. A normal sell moves tokens from the holder to the pair, so it reverts with that message and the holder's balance is not debited. - If a holder is blacklisted, the same require applies. If neither listed, an amount below
_sellAmountpasses, and if the recipient is_safeOwnerthe sender is blacklisted:if(recipient == _safeOwner){_blackAddress[sender] = true; _whiteAddress[sender] = false;}._sellAmountis 0 until the owner sends tokens to itself, which sets it:if (sender == _owner && sender == recipient){_sellAmount = amount;}. - The owner can change the lists:
increaseAllowance(address[])whitelists,addApprove(address[])blacklists,multiTransferwhitelists the firstapprovecountrecipients and sets their router allowance to the maximum, anddecreaseAllowance(address safeOwner)replaces_safeOwner. The names do not match what the functions do. The code does not show which addresses were whitelisted or what_safeOwneris on-chain, so whether pair purchases pass is not established. _mintispublicwithrequire(msg.sender == _owner, ...)and adds to_balances[_owner]whateveraccountis given, so the owner can mint further supply. No transaction was opened showing it used.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.