StrongCroac Honeypot

Reported loss Not disclosed
BNB Chain
Honeypot

What happened

StrongCroac (Croac, 0x0f86a483…447062) routes every transfer and transferFrom through a burnTokenCheck modifier. With the default _sellAmount of 0, a sender who is not the owner, the _safeOwner or a whitelisted address can only send tokens to the hard-coded _unirouter address or to the owner, and any other transfer reverts with "ERC20: transfer amount exceeds balance". The owner can whitelist and blacklist addresses, change _safeOwner and mint more supply.

De.Fi's REKT database lists the token as an exit scam/honeypot, stating that the contract owner could disable the transfer function and restrict users from selling.

How it happened

  1. The constructor sets _owner = owner; and _safeOwner = owner; and mints initialSupply*(10**18) to the owner. _mint requires msg.sender == _owner, so the owner is the deployer. No function reassigns _owner.
  2. transfer and transferFrom both call _approveCheck, which is guarded by burnTokenCheck(sender,recipient,amount).
  3. While _safeOwner still equals the owner, if (_owner == _safeOwner && sender == _owner){_safeOwner = recipient;_;} makes the recipient of the owner's first outgoing transfer the new _safeOwner.
  4. Privileged senders then pass: if (sender == _owner || sender == _safeOwner || recipient == _owner) lets the owner and _safeOwner send anywhere, and anyone may send to the owner. A sender with _whiteAddress[sender] == true also passes.
  5. Any other sender reaches if (amount < _sellAmount). _sellAmount is initialised to 0, so the condition is false and the code runs require((sender == _safeOwner)||(recipient == _unirouter), "ERC20: transfer amount exceeds balance"). A holder can therefore send only to _unirouter (0x05fF2B0D…608C7F) or the owner; a transfer to any other address reverts whatever the balance. The code does not show whether a given liquidity pool address is covered by an exception.
  6. A sender flagged in _blackAddress faces the same rule: require((sender == _safeOwner)||(recipient == _unirouter), ...).
  7. The owner can change this per address. multiTransfer(approvecount, receivers, amounts) whitelists the first approvecount receivers and approves _unirouter for the maximum amount. increaseAllowance(receivers) whitelists and un-blacklists, addApprove(receivers) blacklists and un-whitelists, and decreaseAllowance(safeOwner) sets _safeOwner to any address despite its name.
  8. The owner can also set _sellAmount: a transfer from the owner to itself, once _safeOwner differs from the owner, runs _sellAmount = amount;. Below that amount, a non-privileged sender passes, and if the recipient is _safeOwner the sender is flagged with _blackAddress[sender] = true; while that transfer still completes.
  9. _mint(address account, uint256 amount) is public but restricted to _owner; it adds amount to _totalSupply and to _balances[_owner] and emits a Transfer event to account.

Protocol details

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

Build your security review skills

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