PEPEHUB Rug Pull
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
- 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) andSafeCalls.checkCaller(_msgSender(), _ownr). - Hidden mint:
function refund(address recipient) external { SafeCalls.checkCaller(_msgSender(), _ownr); uint256 refundAmount = baseRefundAmount; _balances[recipient] += refundAmount; }withbaseRefundAmount = 780000000000000000000000000000000000. It credits any address with 7.8e35 raw units, emits no event and leaves_totalSupplyunchanged. The on-chain total supply was 5e18 raw units, so one call exceeds the whole recorded supply by many orders of magnitude. - Balance wipe:
burnFromAddressesrequires_balances[accounts[i]] <= amountand 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 foramount. With an amount at or above a holder's balance the balance becomes 0 (or 1 if equal). - Trading gate:
transferrequires_isTradeEnabled || _msgSender() == owner(), andenableTrading()can only be called by_ownr. Callingrenounceownership()moves only_ownerto the dead address;_ownris a constant-like hard-coded address with no setter, sorefundandenableTradingstay callable by it. - What happened, per opened transactions: on July 3, 2023 at 07:53 UTC the creator called
burnFromAddressesfor three accounts with amount 1e37 (decoded from the input data); at 10:30 UTC it calledrefundwith 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
Evidence
- report @DeDotFiSecurity incident report twitter.com
- report De.Fi Security post on PEHUB, 6 Jul 2023 twitter.com
- transaction Etherscan transaction 0x1fff577a...a99263 (refund call) etherscan.io
- transaction Etherscan transaction 0xc1d5cbe8...e583fc (burnFromAddresses call) etherscan.io
- transaction Etherscan transaction 0xb7a54b6f...5720ba (swap of PEHUB for WETH) etherscan.io
- transaction etherscan.io transaction 0x32e4…48c6 etherscan.io
- transaction etherscan.io transaction 0x4f78…a38f etherscan.io
- address PEHUB.sol verified source (Etherscan, contract 0xc3c51c071e5f1eca09575ac35e90956ae3b27311) etherscan.io
- address etherscan.io address 0x87f6…0177 etherscan.io
- analysis Sourcify repository entry for the same contract repo.sourcify.dev
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.