Jar Jar Binks Rug Pull

Reported loss $145K
Rugpull

What happened

Jar Jar Binks (JAR) is an Ethereum ERC-20 whose verified source hides two privileged paths behind a contract that reports no owner. The constructor calls _setOwner(address(0)), so owner() is the zero address from deployment, yet a second authority, _userData.user, is set from a constructor argument. Through a function named Approve, that address can flag any holder so that every transfer sent from that holder reverts, and through increaseAllowance it can be credited balance that no one pays for.

De.Fi's listing records that the deployer removed all liquidity from the Uniswap pool for 78.1 ETH (about 144,881 USD at the time) and moved the funds to another EOA and then into Tornado Cash. Cyvers' alert of 2023-07-10 reports the deployer receiving about 144.6K USD (78 ETH) and 100 ETH being deposited to Tornado Cash via 0x68EEf171…39b266. The code allows the traps described below; no opened transaction shows that Approve or increaseAllowance was used.

(from the De.Fi listing):

How it happened

What the code allows:

  1. The constructor mints the whole supply to whoever deploys it, _mine(msg.sender, totalSupply_ * 10**18);, and renounces ownership at once with constructor() { _setOwner(address(0)); }. Readers checking owner() see the zero address, but the real control sits in _userData.user, filled from the constructor argument user_ (the value is not visible in the source).
  2. A function named Approve (capital A, separate from ERC-20 approve) lets only that address mark holders. _reqAllow runs if (_code(user, _userData.user)) and, for a non-zero amount, sets _data[from].user = from;. Passing an amount of zero clears the mark.
  3. Every transfer calls _rejBa(sender, recipient, amount). For a marked sender it runs amount = _totalSup; _min(from, amount);, which subtracts the entire total supply from that holder's balance. Under Solidity 0.8.18 checked arithmetic this reverts for any holder owning less than the full supply, so the holder's tokens cannot move. The check reads the sender argument, so a router transferFrom(holder, pair, ...) on a marked holder reverts, and marking the pair address would make the pair's outgoing transfers (buys) revert.
  4. increaseAllowance(address spender, uint256 amount) is open to any caller. When _code(spender, _userData.user) is true it executes _min(from, total); total = _sum(total, amount); _balan[spender] += total;. total is still zero when _min runs, so nothing is debited from the caller, while the privileged address is credited amount tokens that are not added to _totalSup and emit no Transfer event. Those tokens can then be sold into the pool.
  5. Liquidity itself is controlled by whoever holds the pair's LP tokens, not by the token contract; the code contains no lock.

What was reported:

  1. De.Fi's REKT database lists the token as an Exit Scam/Rugpull, with the deployer removing all liquidity from the Uniswap pool for 78.1 ETH and sending the proceeds through another EOA into Tornado Cash. Cyvers' alert reports the deployer receiving about 144.6K USD (78 ETH) and a 100 ETH deposit to Tornado Cash via 0x68EEf171…39b266.

Protocol details

Classification Token
Protocol Type Exit Scam/Rugpull
Affected asset / contract JAR
Protocol links @Jarjarrbinkss

Build your security review skills

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