Jewels Rug Pull

Reported loss $64K
Rugpull

What happened

Jewels (JWL) is an ERC20 token on Ethereum with a Uniswap V2 pool against WETH. PeckShield reported on 24 Nov 2023 that the address 0x3d6b0693…bD6522 swapped 1,000,000,000,000 JWL for about 31 WETH (about 64.3K USD), a quantity a thousand times the 1,000,000,000 JWL total supply. De.Fi's REKT database lists the loss as 63,794 USD (31.14 WETH) and an exit scam / rugpull, and lists the deployer as 0x537A494f…a90011, the funds holder as of Nov 27, 2023 as 0x1607644E…d4C29B, and a Binance withdrawal in transaction 0xcc5ceda2…622db2. De.Fi's listing also says the funds went to another EOA and then to Binance through several addresses, and that the deployer sent 2.13 ETH to the scammer's address a couple of minutes after the swap.

The code explains how a quantity above the supply can be sold. In _transfer, a sale to the pair from the hard-coded fee wallet revWallet sets taxOn = true, and later if(taxOn) amount -= amount; zeroes the amount that is debited from the seller, while the pair and the token contract are still credited. That wallet can therefore push tokens into the pool without holding them, and sell them for the pool's WETH.

How it happened

  1. The constructor hard-codes revWallet = payable(0xd1F28C4BE394729e248C90fc2ef6d5e8Ff3D4A4f); and sets _exFromMax[revWallet] = true;. No function in the contract changes _exFromMax, and revWallet is not in _exFromFees, so it is taxed like an ordinary seller.
  2. When tokens are sent to the pair (to == uniswapV2Pair), _transfer runs if (_exFromMax[from]) taxOn = true; and then sets _tax = taxFeeSell;. The constructor sets taxFeeSell = 24 and setFees allows the owner to change it.
  3. In the tax branch the code computes uint256 taxTokens = (amount * _tax) / 100; and uint256 transferAmount = amount - taxTokens;, then runs if(taxOn) amount -= amount;, so amount becomes 0. The line _balance[from] -= amount; therefore subtracts nothing from revWallet, while _balance[to] += transferAmount; and _balance[address(this)] += taxTokens; still credit the pair and the token contract. Nothing checks the seller's balance against the original amount, so tokens are created in the pool from nothing. For transferFrom the only limit is the allowance, which the holder of the allowance can set to any value with approve.
  4. A sale from revWallet through the Uniswap router with swapExactTokensForETHSupportingFeeOnTransferTokens then pays out WETH from the pool against tokens that were never debited from anyone. An ordinary holder selling to the pair does not hit taxOn, so their balance is debited normally.
  5. What happened: Etherscan shows transaction 0xfaf6c9d4…092e3b, sent by 0x3d6b0693…bD6522 to 0xd1F28C4B…3D4A4f (the revWallet address) via a save(uint256 amount) call, with token transfers of 970 billion JWL to the Uniswap V2 pool, 30 billion JWL to the token contract (a 3% tax on 1 trillion), and about 31.10 WETH out of the pool. PeckShield reported the same sale as 1,000,000,000,000 JWL for 31 WETH.

Protocol details

Classification Token
Protocol Type Exit Scam/Rugpull
Affected asset / contract JWL
Protocol links Website @JewelsCoin

Build your security review skills

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