BabyElon Rug Pull

Reported loss $53K
Rugpull

What happened

BabyElon (BabyElon, 9 decimals, 10 billion fixed supply, BNB Smart Chain) restricts who can trade through its own _internalTransfer: wallets that are not "synced" can only trade with the PancakeSwap pair while the owner has trading switched on, and any synced wallet can flag a holder as _claimed, which makes that holder's sales revert. De.Fi's REKT database lists the incident as a rug pull by the contract creator 0x999fae84…32a7c1 for 183.35 BNB (about $52,852), with the tokens afterwards laundered through Tornado Cash. According to that listing, the token at 0x292e89d5…140b43 was paired with 100M BabyElon and 10 BNB in transaction 0x1d07387a…6acc80, the pool was then increased with 290 BNB and 2.9B BabyElon in transaction 0xfac7fa93…2bc03e (described as an attempt to push the price up), and the liquidity was removed in transaction 0xa3974709…d4feff for 484.35 BNB, of which 183.35 BNB was profit.

The listing adds that tokens were then moved in transaction 0xd25a56ea…9fb821. The token code has no function that holds or withdraws LP tokens, so the liquidity removal itself is a pair and router action that the source does not trace to a holder.

How it happened

What the code allows:

  1. The constructor gives the whole supply to the deployer and marks the owner as synced: _tokenBalances[_msgSender()] = _tokenTotalSupply; and _synced[owner()] = true;. There is no mint function and _isTradingOpen starts as false.
  2. Transfers where neither side is synced are gated: if (!_synced[sender] && !_synced[recipient]) { followed by require(_isTradingOpen);. Only the owner can change that flag with function openTrading(bool value) public onlyOwner, so the owner can open or close trading for every unsynced wallet.
  3. _isSwapEnabled is set to true in the constructor and has no setter, so require(sender == uniswapV2Pair || recipient == uniswapV2Pair); always applies: unsynced wallets can only trade with the pair, never send tokens wallet to wallet.
  4. On a sale (recipient == uniswapV2Pair) the code runs require(!_claimed[sender], "Claimed"); and require(!_claimed[_msgSender()], "Claimed");. Through a router, sender is the holder and _msgSender() is the router, so a flagged holder cannot sell and a flagged router would block everyone using it. The flags are set by function claim(address[] calldata wallet, bool value) external onlySynced, so the owner or any wallet already synced can set them. Balances are debited exactly by amount with no fee (_tokenBalances[sender] = _tokenBalances[sender].sub(amount);), so a flagged holder keeps a balance that cannot be sold. The source does not show that any wallet was flagged.

, as listed by De.Fi's REKT database: 5. The creator paired 100M BabyElon with 10 BNB, added 290 BNB and 2.9B BabyElon, then removed the liquidity and received 484.35 BNB (listed profit 183.35 BNB) before routing the tokens through Tornado Cash. Liquidity removal is performed on the pair, outside the token code.

Protocol details

Classification Token
Protocol Type Exit Scam/Rugpull
Affected asset / contract BabyElon
Protocol links Website @BabyElon_BSC

Build your security review skills

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