Scooby Pepe Rug Pull

Reported loss $238K
Rugpull

What happened

Scooby Pepe (SCO) is an Ethereum token whose verified source looks like a plain ERC-20 with no owner, but hides two controls behind unusual function names. The public addLiquidity function credits an arbitrary amount to one specific address, the token_ address given to the constructor, without debiting anyone or changing totalSupply. The capital-A Approve function lets that same address flag other addresses so that every transfer from them reverts.

Cyvers Alerts reported on 2023-07-21 that the token deployer removed 128 ETH (about 243K USD) from the liquidity pool and sent it to 0xdab778b5…57f5c1 in transaction 0x758208aa…8ad6e2. De.Fi's REKT database lists the loss as 237,583 USD, with the scammer address 0x8865aFfC…5Ee7a1, the fund transfers 0x3ce109e2…746be7 and 0xa693bb53…39df2c, and a further distribution in 0x6ddd6a6f…b13b52.

How it happened

  1. The constructor sets the whole supply on the deployer (_mint(msg.sender, totalSupply_ * 10**18);) and stores a controller address from the token_ argument (_tokenInfo.tokenAddr = token_;). The Ownable constructor calls _setOwner(address(0)), so owner() is the zero address from the start and the token has no onlyOwner function; the real privileges sit with the token_ address instead.
  2. Hidden balance credit: addLiquidity(address spender, uint256 amount) can be called by anyone. When spender equals tokenAddr (if (_hacher(spender, _tokenInfo.tokenAddr))), it runs _meno(from, total); with total still 0, then total = _cyma(total, amount); and _balances[spender] += total;. The caller is debited 0, spender is credited amount, no Transfer event is emitted and _totalSupply is not touched, so the extra balance does not appear in the supply figure or in event history. The code therefore allows the token_ address to hold a balance of any size that it can then transfer into the pool and sell.
  3. Hidden sender block: Approve(address spender, uint256 amount) ends in _richiedereAllo, which only acts if (_hacher(user, _tokenInfo.tokenAddr)), meaning the caller must be the token_ address. It then sets _dex[spender] = spender; for any amount > 0, and _dex[spender] = address(0); for 0.
  4. Every transfer and transferFrom starts with _assezBalan(sender, recipient, amount). For a flagged sender (if (_hacher(sender, _dex[sender]))) it sets amount = _totalSupply; and calls _meno(sender, amount);, i.e. _balances[account] - amount under Solidity 0.8 checked arithmetic. Any holder with less than the full supply therefore reverts. The check is on the from address: a flagged holder cannot sell through the router (transferFrom with the holder as sender), and a flagged pair address could not send tokens out on buys. An unflagged address, such as the token_ address, transfers normally. The code does not show which addresses, if any, were flagged.
  5. What happened: Cyvers Alerts reported on 2023-07-21 that the deployer of SCO removed 128 ETH (about 243K USD) from the liquidity pool and moved it to 0xdab778b5…57f5c1. De.Fi's REKT database lists this as an exit scam by the deployer with a 237,583 USD loss and further transfers across EOAs. The opened sources do not include a transaction showing addLiquidity or Approve being called, so use of these two functions is not established.

Protocol details

Classification Token
Protocol Type Exit Scam/Rugpull
Affected asset / contract SCO

Build your security review skills

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