Jar Jar Binks Rug Pull
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):
- Deployer address: 0xac648118…15321b
- Liquidity removal transaction: 0xb57bc0a1…966370
- Funds transfer transaction: 0x514a9697…686523
- Tornado Cash deposit transaction: 0x4b437c0a…32579b
How it happened
What the code allows:
- The constructor mints the whole supply to whoever deploys it,
_mine(msg.sender, totalSupply_ * 10**18);, and renounces ownership at once withconstructor() { _setOwner(address(0)); }. Readers checkingowner()see the zero address, but the real control sits in_userData.user, filled from the constructor argumentuser_(the value is not visible in the source). - A function named
Approve(capital A, separate from ERC-20approve) lets only that address mark holders._reqAllowrunsif (_code(user, _userData.user))and, for a non-zero amount, sets_data[from].user = from;. Passing an amount of zero clears the mark. - Every transfer calls
_rejBa(sender, recipient, amount). For a marked sender it runsamount = _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 thesenderargument, so a routertransferFrom(holder, pair, ...)on a marked holder reverts, and marking the pair address would make the pair's outgoing transfers (buys) revert. 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;.totalis still zero when_minruns, so nothing is debited from the caller, while the privileged address is creditedamounttokens that are not added to_totalSupand emit noTransferevent. Those tokens can then be sold into the pool.- 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:
- 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
Evidence
- report Cyvers Alerts post on Jar Jar Binks deployer, 2023-07-10 twitter.com
- transaction etherscan.io transaction 0x4b43…579b etherscan.io
- transaction etherscan.io transaction 0x514a…6523 etherscan.io
- transaction etherscan.io transaction 0xb57b…6370 etherscan.io
- address Etherscan verified source: Jar Jar Binks (JAR) 0x1ee508008b30248ac6b077df6904cfca4c63785b etherscan.io
- address etherscan.io address 0xac64…321b etherscan.io
- analysis Sourcify exact match: Jar (contracts/token/Jar.sol) repo.sourcify.dev
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.