OccamFi Honeypot

Reported loss Not disclosed
Ethereum
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

  1. 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));. _sellAmount starts at 0 and _unirouter is hard-coded to 0x7a250d56…F2488D.
  2. transfer and transferFrom both call _approveCheck, which is wrapped by burnTokenCheck. While _owner == _safeOwner, the owner's first outgoing transfer passes and re-points the exempt address: if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}.
  3. Afterwards, the owner, _safeOwner and any transfer to the owner pass: if (sender == _owner || sender == _safeOwner || recipient == _owner){. Whitelisted senders also pass: if (_whiteAddress[sender] == true){ _;.
  4. Every other sender must satisfy require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");. Because _safeOwner already 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.
  5. If a holder is blacklisted, the same require applies. If neither listed, an amount below _sellAmount passes, and if the recipient is _safeOwner the sender is blacklisted: if(recipient == _safeOwner){_blackAddress[sender] = true; _whiteAddress[sender] = false;}. _sellAmount is 0 until the owner sends tokens to itself, which sets it: if (sender == _owner && sender == recipient){_sellAmount = amount;}.
  6. The owner can change the lists: increaseAllowance(address[]) whitelists, addApprove(address[]) blacklists, multiTransfer whitelists the first approvecount recipients and sets their router allowance to the maximum, and decreaseAllowance(address safeOwner) replaces _safeOwner. The names do not match what the functions do. The code does not show which addresses were whitelisted or what _safeOwner is on-chain, so whether pair purchases pass is not established.
  7. _mint is public with require(msg.sender == _owner, ...) and adds to _balances[_owner] whatever account is given, so the owner can mint further supply. No transaction was opened showing it used.

Protocol details

Classification Token
Protocol Type Exit Scam/Honeypot
Affected asset / contract OCC

Build your security review skills

Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.