World Cup Rug Pull

Reported loss $132K
Rugpull

What happened

World Cup (Wcp) is a BNB Smart Chain token with a fixed supply of 21,000 tokens, all of which the constructor credits to the deployer, who is also fee-exempt. CertiK's alert of 2022-08-23 reported a rug pull on the project, a price drop of more than 98% and about 131,892 USD taken, and warned the token should not be confused with other World Cup projects. The live record attributes the rug pull to the project team, notes the token has no association with the official World Cup, and names the token deployer address 0xb2295593…cae9f1.

The verified code gives the owner a trading switch, an address-level sell blocker and a way to withdraw the USDT the token contract accumulates, all described below; no opened transaction shows any of them being used.

How it happened

What the code allows:

  1. The constructor sets address adminAddress = 0xb22955933dee31bb1982d6db980b33c263Cae9f1;, _tTotal = 21000* (10**uint256(_decimals)); and _tOwned[adminAddress] = _tTotal;. The deployer is the first owner (_owner = msgSender) and is fee-exempt, as is adminAddress (the same address per the explorer deployer field):_isExcludedFromFee[msg.sender] = true; _isExcludedFromFee[adminAddress] = true;. Excluded addresses skip the pair fees, the launch tax and the bot check in _transfer, so the full supply sits with an address that can sell without those frictions.
  2. Buying is gated by the owner: if(from == uniswapV2Pair) { require(0 < startTradeBlock, "!Trading"); }, and only startTrade() external onlyOwner sets startTradeBlock. Sales from a holder to the pair are not gated.
  3. For the first blocks after startTrade, non-exempt transfers pay a confiscatory tax: if (block.number <= startTradeBlock + 3) { _jokeyTransfer(from, to, amount, 9000); return; } debits the sender the full amount, sends 90% to marketAddr and 10% to the recipient; blocks startTradeBlock + 4 to + 6 do the same at 3000 (30%). The owner can repoint marketAddr and the payout token through setAddr(address[] memory addrs) { TOKEN = addrs[0]; marketAddr = addrs[0]; }.
  4. After that window, setBot(address account, bool value) public onlyOwner lets the owner flag any address. if (_isBot[from]) { revert("The bot address"); } blocks transfers whose sender is the flagged holder, so that holder's router sell (transferFrom(holder, pair, ...)) reverts.
  5. transferContracts() public onlyOwner { distributeDividend(owner(),IERC20(TOKEN).balanceOf(address(this))); } sends the contract's entire balance of the payout token (USDT by default, TOKEN = 0x55d398326f99059fF775485246999027B3197955) to the owner. That balance is produced by swapTokensForTokens, which swaps the token's own fee holdings into TOKEN. The current on-chain owner reads as 0xf3a3a10f…5fe0e8, not the deployer; when ownership moved is not established.
  6. Liquidity in the pair is controlled by whoever holds its LP tokens; the token code has no liquidity lock.

What was reported:

  1. CertiK's alert states a rug pull on World Cup (Wcp) with a price drop of more than 98% and approximately 131,892 USD taken. The sources opened do not show how the funds left or which of the owner-only functions, if any, were called.

Protocol details

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

Build your security review skills

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