Charged Particles Protocol 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
- The constructor stores
_owner = owner; _safeOwner = owner;and mints the initial supply to the owner. No function changes or renounces_owner. - 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 withdecreaseAllowance(address safeOwner), which only sets_safeOwner. - In the next branch,
if (sender == _owner || sender == _safeOwner || recipient == _owner)passes, so the owner and_safeOwnercan send anywhere and anyone can send tokens to the owner. If_safeOwneris the pair, buys from the pair pass. A self-transfer by the owner sets_sellAmount = amountin this branch. - 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 ifamount < _sellAmount, and ifrecipient == _safeOwnerthat sender is then blacklisted; otherwise the samerequireapplies. _sellAmountis initialised to 0, soamount < _sellAmountis never true until the owner sets it. Until then an unlisted holder's sale to the pair, whererecipientis neither_unirouternor_owner, reverts, and so does a wallet-to-wallet transfer.- The owner controls the exceptions:
multiTransferwhitelists the firstapprovecountreceivers and approves_unirouterfor them;increaseAllowance(address[])whitelists;addApprove(address[])blacklists._mint(address account, uint256 amount)is owner-only and credits_balances[_owner]while emittingTransfer(address(0), account, amount). - 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
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.