Zodiac Credit Rug Pull

Reported loss $77K
Rugpull

What happened

Zodiac Credit (ZOC) is a BNB Chain token deployed on 5 April 2023 at 0x76401604…a11717 by 0xfAd248B5…f8a28E. Its transfer function lets anyone buy from the pool but blocks sales from flagged wallets with the misleading error "Block is busy, please try again". Buyers are flagged automatically when their gas price is above an owner-set threshold, and the owner can flag every recorded buyer at once with Bonous() or halt all selling with DepositTransfer().

Wallet-to-wallet transfers by holders always revert, and the deployer is exempt from every check through a second, hidden _owner variable. On 9 April 2023 CertiK reported that the deployer removed liquidity in 8 transactions, profiting about $77K; De.Fi's REKT database adds that the deployer also sold ZOC and the price fell about 90% (liquidity removals include tx 0xb7fcda93…63170d, 0xec4c14d4…7d381a and 0x6e950143…99ac0d).

How it happened

  1. The constructor mints the whole supply to the deployer and also records the deployer in BCR's own _owner variable, separate from the one in Ownable. Every check in _transfer is skipped when _owner is the sender or recipient, and no function changes this _owner.
  2. onlyOwner passes for owner() or _root, and _root is also fixed to the deployer, so renounceOwnership() would not remove the deployer's powers.
  3. The owner sets the pool address with SwapContract(address swap_). On each buy (from==_swap), the code records the buyer in haveToken, and if(from==_swap &&_currprice>_defaultPrice){isStatus[to]=true;} flags the buyer when tx.gasprice.mul(100) exceeds _defaultPrice. The owner can change that threshold with the misnamed setCurrPrice; set to 0, every buyer is flagged.
  4. A sale sends tokens to the pool, and if(to==_swap){ if(isStatus[from]){require(false,"Block is busy, please try again");} } makes a flagged wallet's sale revert. Bonous() calls AirDropGift for every recorded buyer, flagging them all; AirDropGift and AirDrop flag and unflag single wallets.
  5. DepositTransfer() sets tradeStatus=true, after which if(tradeStatus && from!=_swap){require(false,"Block is busy, please try again");} blocks every transfer except buys out of the pool.
  6. A transfer between two wallets hits airtokenlist[from]=true and then if(airtokenlist[from]){require(false,...)}, so it always reverts; holders cannot move tokens to another wallet to sell from there.
  7. On 9 April 2023 the deployer removed liquidity in 8 transactions, profiting about $77K, according to CertiK.

Protocol details

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

Build your security review skills

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