PIethori Honeypot

Reported loss Not disclosed
Ethereum
Honeypot

What happened

This Ethereum token (PIethori, PLE, 100000000 tokens with 18 decimals) carries a hidden transfer filter in its burnTokenCheck modifier. Most holders can send tokens only to a hard-coded address (_unirouter) or to the owner, while the owner, a changeable _safeOwner address, and owner-whitelisted addresses are exempt. The owner can change who is exempt, whitelist or blacklist holders, and mint to itself.

De.Fi's REKT database lists the token as an exit scam/honeypot on 2021-05-03 and states that the owner could disable transfers so users could not sell; no loss amount is listed.

How it happened

  1. The constructor sets _owner = owner; _safeOwner = owner; and mints the supply to the owner. No function in the source changes or renounces _owner.
  2. Every transfer and transferFrom runs _approveCheck, which uses the burnTokenCheck modifier. While _owner == _safeOwner, any transfer sent by the owner executes _safeOwner = recipient, so whichever address receives the owner's first outgoing transfer becomes the privileged _safeOwner.
  3. After that, a transfer passes if sender == _owner || sender == _safeOwner || recipient == _owner. If the owner sends to itself (sender == _owner && sender == recipient), the amount is stored as _sellAmount.
  4. Any other sender who is in _whiteAddress passes. A sender in _blackAddress must satisfy require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"), which for a non-privileged sender means the recipient has to be _unirouter (or the owner, handled earlier).
  5. A sender in neither list passes only if amount < _sellAmount; _sellAmount starts at 0, so until the owner sets it nothing qualifies. Otherwise the same require applies and the recipient must be _unirouter. Selling through a router normally moves tokens to the liquidity pair rather than the router, so such a transfer reverts with the "transfer amount exceeds balance" message even though the sender's balance is untouched.
  6. If amount < _sellAmount and recipient == _safeOwner, the sender is added to _blackAddress and removed from _whiteAddress while the transfer still succeeds.
  7. Only the owner can adjust the lists and exemptions: increaseAllowance(address[]) whitelists, addApprove(address[]) blacklists, decreaseAllowance(address) sets _safeOwner, multiTransfer can whitelist recipients and approve _unirouter for them, and _mint lets the owner add to its own balance. The code allows this; no transaction was opened showing the owner using these functions.

Protocol details

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

Build your security review skills

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