PEPEHUB Rug Pull

Reported loss $255K
Rugpull

What happened

PEPEHUB (PEHUB) is an Ethereum token (contract 0xc3c51c07…b27311) whose verified source contains two privileged functions that change balances without a matching debit: refund(), which credits any address with a fixed 7.8e35 raw units, and burnFromAddresses(), which divides the balances of chosen accounts by an amount the owner picks. On July 3, 2023 the creator address 0x87f60e57…600177 called burnFromAddresses (transaction 0xc1d5cbe8…e583fc, 07:53 UTC) on three addresses and, at 10:30 UTC, refund with its own address as recipient (0x1fff577a…a99263). At 10:33 UTC it swapped 1.35 billion PEHUB for about 21 WETH on Uniswap V2 (0xb7a54b6f…5720ba).

De.Fi's post of July 6, 2023 describes a $255,000 rug pull in which the contract creator sold about 133.7 ETH worth of tokens, drained the LP and moved the funds to 2 addresses; De.Fi's database listing instead says four wallets received the funds. Two further swap transactions listed by the De.Fi listing are 0x4f78b8cf…72a38f and 0x32e481ee…9148c6; they were not opened here.

How it happened

  1. Roles: the constructor gives the entire supply to the deployer and hard-codes _ownr = 0x87f60E577a4B5eE6A2F3156CBc8261D103600177. Two powers hang off that address: onlyowner (the deployer, _owner) and SafeCalls.checkCaller(_msgSender(), _ownr).
  2. Hidden mint: function refund(address recipient) external { SafeCalls.checkCaller(_msgSender(), _ownr); uint256 refundAmount = baseRefundAmount; _balances[recipient] += refundAmount; } with baseRefundAmount = 780000000000000000000000000000000000. It credits any address with 7.8e35 raw units, emits no event and leaves _totalSupply unchanged. The on-chain total supply was 5e18 raw units, so one call exceeds the whole recorded supply by many orders of magnitude.
  3. Balance wipe: burnFromAddresses requires _balances[accounts[i]] <= amount and then runs _balances[accounts[i]] /= amount; it divides rather than subtracts, nothing is credited to the burn address, and it emits a Transfer to the burn address for amount. With an amount at or above a holder's balance the balance becomes 0 (or 1 if equal).
  4. Trading gate: transfer requires _isTradeEnabled || _msgSender() == owner(), and enableTrading() can only be called by _ownr. Calling renounceownership() moves only _owner to the dead address; _ownr is a constant-like hard-coded address with no setter, so refund and enableTrading stay callable by it.
  5. What happened, per opened transactions: on July 3, 2023 at 07:53 UTC the creator called burnFromAddresses for three accounts with amount 1e37 (decoded from the input data); at 10:30 UTC it called refund with its own address; at 10:33 UTC it sent 1.35 billion PEHUB into the Uniswap V2 pool and received 20.9997 WETH. De.Fi reports about 133.7 ETH of tokens sold in total, with the LP drained and funds forwarded. Which of the three burned accounts were LP or other holders, and why the creator's own balance was topped up before selling, are not established by the opened pages.

Protocol details

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

Build your security review skills

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