Charged Particles Protocol Honeypot

Reported loss Not disclosed
Ethereum
Honeypot

What happened

This ERC-20 (name Charged Particles Protocol, symbol IONX) routes every transfer and transferFrom through a burnTokenCheck modifier that decides by sender whether the move is allowed. Ordinary holders can only send tokens to the owner or to the address stored in _unirouter (0x7a250d56…F2488D); a router sale sends tokens to the liquidity pair instead, so it reverts with ERC20: transfer amount exceeds balance. The owner, a stored _safeOwner, and owner-whitelisted addresses are exempt, and the owner can whitelist or blacklist addresses and mint more tokens through functions with misleading names.

De.Fi's REKT database lists the token as an Exit Scam/Honeypot, noting that the contract owner could disable the transfer function, which restricted users in selling their tokens.

How it happened

  1. The constructor stores _owner = owner; _safeOwner = owner; and mints the initial supply to the owner. No function changes or renounces _owner.
  2. The first branch of the modifier is if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}: the owner's first transfer is unrestricted and its recipient becomes _safeOwner. If that first transfer is the liquidity deposit, the code allows the pair to become _safeOwner. The owner can later reset it with decreaseAllowance(address safeOwner), which only sets _safeOwner.
  3. In the next branch, if (sender == _owner || sender == _safeOwner || recipient == _owner) passes, so the owner and _safeOwner can send anywhere and anyone can send tokens to the owner. If _safeOwner is the pair, buys from the pair pass. A self-transfer by the owner sets _sellAmount = amount in this branch.
  4. Every other sender goes through the whitelist and blacklist. A whitelisted sender passes. A blacklisted sender hits require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"), so it can only send to _unirouter (or the owner). An unlisted sender passes only if amount < _sellAmount, and if recipient == _safeOwner that sender is then blacklisted; otherwise the same require applies.
  5. _sellAmount is initialised to 0, so amount < _sellAmount is never true until the owner sets it. Until then an unlisted holder's sale to the pair, where recipient is neither _unirouter nor _owner, reverts, and so does a wallet-to-wallet transfer.
  6. The owner controls the exceptions: multiTransfer whitelists the first approvecount receivers and approves _unirouter for them; increaseAllowance(address[]) whitelists; addApprove(address[]) blacklists. _mint(address account, uint256 amount) is owner-only and credits _balances[_owner] while emitting Transfer(address(0), account, amount).
  7. What happened: De.Fi's REKT database lists the token as an Exit Scam/Honeypot. No transaction was opened showing who was whitelisted or blacklisted, who held the liquidity, or any loss amount.

Protocol details

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

Build your security review skills

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