Greatest Of All Time (GOAT) Rug Pull
What happened
Greatest Of All Time (GOAT) is an ERC-20 meme token on Ethereum at 0xcc63f8f2…447d7e, deployed on 19 June 2023 by 0x76d83707…4c28D2, which the constructor also makes the _marketingWallet. Ownership is now renounced, but the verified source hides a function, removeFee, written in assembly on the same line as the end of swapTokensForEth, that only the marketing wallet can call. It overwrites the caller's own balance with any amount, without changing totalSupply or emitting a mint event, and raises _sellFee to 100%.
After that, the whole amount of an ordinary holder's sell is counted as fee, so the pair receives nothing and a router sale reverts. A direct transfer to the pair credits the marketing wallet with an equal amount of newly created tokens while the holder's balance is not debited. On 20 June 2023 the deployer swapped a very large GOAT amount (5,192,294,839,382,761 tokens per the record, far above the 5,000,000,000 supply) for 23.2148 WETH in transaction 0xa198cced…4ea0f6.
De.Fi reported that the creator took about 28.3 ETH ($54,296) in total, draining the pool, and sent it through several addresses to KuCoin; the record currently lists about $43,100 (about 23 ETH).
How it happened
- The constructor mints the full supply to the deployer and sets
_marketingWallet = _msgSender();, excluding that wallet from fees and limits. removeFee(uint256 amount)is appended afterswapTokensForEthon one line, so it reads like part of that function. Its guard isif iszero(eq(caller(), sload(_marketingWallet.slot))) {revert(0, 0)}, so only the marketing wallet can run it, and renouncing ownership does not affect it.- The function computes the caller's slot in
_balancesand runssstore(slot, amount), setting the marketing wallet's balance to any number without touching_totalSupply. - It also runs
sstore(_sellFee.slot, mul(0x64, 0x64)), setting_sellFeeto 10000 of a 10000 divisor. On a normal holder's sell,devFee = amount.mul(_sellFee).div(_divisor)equals the whole amount, and_transfercredits it with_balances[_marketingWallet] = _balances[_marketingWallet].add(devFee);but subtracts it only fromamount(amount = amount.sub(totalFee);), never from the sender. The pair receives 0 tokens, so a router sale reverts; a direct transfer to the pair leaves the holder's balance unchanged and credits the marketing wallet with an equal amount of new tokens. - The marketing wallet is excluded from fees, so it can still sell. On 20 June 2023 the deployer sold GOAT through the Uniswap V2 router for 23.2148 WETH; De.Fi puts the creator's total take at about 28.3 ETH, after which the pool held no meaningful value.
Protocol details
Evidence
- report @DeDotFiSecurity incident report twitter.com
- report De.Fi Antivirus Web3: $GOAT Token Rug Pull twitter.com
- transaction GOAT contract creation transaction etherscan.io
- transaction Etherscan transaction 0xa198cceda99cd6fd6ba6cf0997029568dfe57857a91a0c482766dfa97e4ea0f6 etherscan.io
- address GreatestOfAllTime verified source code etherscan.io
- address etherscan.io address 0xc74d…539c etherscan.io
- analysis Sourcify match for 0xcc63f8f2def2202f928b594ff80d8ba30d447d7e on Ethereum repo.sourcify.dev
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.