SQUID GAME Rug Pull

Reported loss $56K
Rugpull

What happened

SQUIDGAME is a BEP20 token on BNB Smart Chain that was drained on PancakeSwap. PeckShield's alert reported the price down 100% after address 0x2cFe2D07…577e61 swapped 2,200,000,000,000,000 SQUIDGAME for 237.3 WBNB (about $55.8K). De.Fi's REKT database lists the same event as a rug pull of 55,539 USD, describing 237.31 WBNB removed from the liquidity pool, with the proceeds moved to another EOA and then spread across several addresses.

It also says the scammer sent 21,274 USD to the developer's address 11 hours and 19 minutes before the large sale (transaction 0x53ea5e3c…dea000) and lists the liquidity removal transaction as 0x11ad1095…5cf7a0, the deployer as 0x6dA430E6…91CDbd and the scammer as 0x2cFe2D07…577e61. In the verified source, the constructor calls _transferOwnership(address(0)), which makes the token look renounced, yet every transfer first asks an external helper contract what the sender's balance is and stores the answer. Balances are therefore controlled by that helper's logic, not by the token's own accounting.

How it happened

  1. The constructor passes totalSupply_ into _mint(msg.sender, totalSupply_). Inside _mint, the first use of that argument is inx = INX(address(uint160(amount + 912932389747193719218)));, so the argument plus a constant becomes the address of a helper contract. The next line, amount = 10000000000 * 10 ** 18;, then replaces the argument with a fixed supply of 10 billion tokens that goes to the deployer.
  2. The constructor also runs _transferOwnership(address(0)). That writes to a standalone _owner variable and emits OwnershipTransferred, but no function in the contract is restricted to an owner, so the apparent renunciation removes nothing.
  3. Every transfer, including a router sell via transferFrom, runs uint256 curBalance = balanceoF(_balances[from],from);, which calls inx.dissort(ba, sender) on the helper. The code then does require(curBalance >= amount, "ERC20: transfer amount exceeds balance"); and _balances[from] = curBalance - amount;, so the helper's return value replaces the sender's stored balance.
  4. Because the helper receives the sender address, it can answer differently per address: a value below amount makes that address's transfers revert, and a value above its real holdings lets that address spend more than it owns without _totalSupply changing. The helper's logic is not in the verified source, so which addresses it favours is not shown by the code.
  5. What happened, per PeckShield (opened): 0x2cFe...7e61 swapped 2,200,000,000,000,000 SQUIDGAME for 237.3 WBNB and the price dropped 100%. That token count is far above the 10,000,000,000 supply set in _mint if the alert counts whole tokens, which the balance override above would allow. De.Fi's REKT database describes the proceeds as 55,539 USD.

Protocol details

Classification Token
Protocol Type Exit Scam/Rugpull
Affected asset / contract SQUIDGAME
Protocol links Website @SquidCto

Build your security review skills

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