JAGUAR Honeypot

Reported loss Not disclosed
BNB Chain
Honeypot

What happened

De.Fi's REKT database lists JAGUAR (BNB Chain, contract 0x7f916bc9…39bb90) as an Exit Scam/Honeypot and says the contract owner could disable the transfer function, which restricted users in selling their tokens. The verified source overrides transferFrom so that, while the trans flag is false (its value set in the constructor), the call succeeds only if the sender or recipient is moi (the deployer) or the sender is the liquidity pair. A holder selling through the router, which moves the holder's tokens with transferFrom, therefore reverts until an account holding MINTER_ROLE calls setTrans(true).

The same role-holders can also pause every transfer and mint more tokens through piocher, and the functions named renounceOwnership and lockLiquidity only emit events and change no state.

How it happened

  1. The constructor sets moi = _msgSender(); and trans = false;, grants DEFAULT_ADMIN_ROLE, PAUSER_ROLE and MINTER_ROLE to the deployer, mints 1000000000000 * 10 ** decimals() to it, and creates the token's pair through the factory of the router at 0x05fF2B0D…608C7F.
  2. transferFrom is overridden with require (trans || moi == sender || moi == recipient || sender == UNI);, where UNI is uniswapV2Pair. While trans is false, a call is allowed only when the deployer is on either side or the pair is the sender.
  3. A holder selling into the pair through the router makes the router call transferFrom(holder, pair, amount). Here trans is false, the holder is not moi, the recipient is the pair rather than moi, and the sender is not the pair, so the require fails and the call reverts with no message. transfer is not overridden.
  4. setTrans(bool value) requires hasRole(MINTER_ROLE, msg.sender) and sets trans=value, so the role-holder alone decides when the restriction is lifted or re-applied.
  5. pause() requires PAUSER_ROLE and _beforeTokenTransfer is declared whenNotPaused, so a pause blocks every transfer, mint and burn.
  6. piocher(address to, uint256 amount) requires MINTER_ROLE and calls _mint(to, amount), so supply can be increased after deployment.
  7. renounceOwnership() contains only emit OwnershipRenounced(address(0), address(this)); and lockLiquidity() contains only emit liquidityLocked(uniswapV2Pair, address(0));. Neither changes roles or locks anything, although the events suggest otherwise.

Protocol details

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

Build your security review skills

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