TradeStars Honeypot

Reported loss Not disclosed
Ethereum
Honeypot

What happened

TradeStars (TSX) at 0x1e542747…c25a21 is an ERC-20 whose transfer and transferFrom run through a burnTokenCheck modifier controlled by the owner. A holder who is on neither list can only send tokens to the hard-coded router address 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D or to the owner, so a sale that moves tokens to any other recipient reverts with "ERC20: transfer amount exceeds balance". The owner can whitelist or blacklist addresses, change the privileged _safeOwner address, set a _sellAmount threshold, and mint.

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

How it happened

  1. The constructor sets _owner = owner; _safeOwner = owner; and mints the initial supply to the owner. _mint is public but requires msg.sender == _owner and credits _balances[_owner], so the owner can mint more at any time.
  2. Both transfer and transferFrom call _approveCheck, which carries burnTokenCheck(sender, recipient, amount). The modifier lets through: the first owner transfer (if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;}), any transfer where sender == _owner || sender == _safeOwner || recipient == _owner, and any sender flagged _whiteAddress.
  3. A sender flagged _blackAddress may only send to _unirouter or when it is _safeOwner: require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance");.
  4. A sender on neither list is let through only if amount < _sellAmount; otherwise the same require applies. _sellAmount starts at 0 (uint256 private _sellAmount = 0;), so at first no unlisted holder passes unless the recipient is _unirouter or _owner. A sale via a pool whose address is not _unirouter, _owner or _safeOwner reverts; the code does not show whether the pool address is _safeOwner.
  5. The owner controls the lists and thresholds: increaseAllowance(address[]) whitelists, addApprove(address[]) blacklists, decreaseAllowance(address safeOwner) replaces _safeOwner, and multiTransfer can whitelist the first approvecount receivers and give them a router allowance. A holder who sends below _sellAmount to _safeOwner is blacklisted automatically: if(recipient == _safeOwner){_blackAddress[sender] = true; _whiteAddress[sender] = false;}. _owner has no setter or renounce function.

Protocol details

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

Build your security review skills

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