BitLord Rug Pull
What happened
Bitlord (BITLORD) is a hand-written ERC-20 whose supply is minted through an owner-only function named removeLimits, whose Transfer events do not match the real balance changes, and which includes a hard-coded address that can move any holder's balance to the zero address. On 2023-08-05, about 15 hours after deployment, Etherscan shows the deployer address 0x870C07aD…292D90 calling removeLiquidityETHWithPermit on Uniswap V2 Router 2 and withdrawing 308.99 ETH from the BITLORD/ETH pool in transaction 0x78db4a91…ba7d07. De.Fi's alert describes this as a rug pull of about 567,000 USD (its listing says 566,201 USD) and adds that the price stayed stable because the token appears to be a honeypot.
De.Fi's listing also states the withdrawn funds were swapped to WETH and moved to another externally owned account, 0x837fbff1…18f124; that transfer was not opened here.
How it happened
- The contract hard-codes the owner and a team address:
address public _Owner = 0x870C07aD0B092A38b72bD9d6Bd2E5304a7292D90;andteam_addr = 0x808877B83A698F0d866E69591fDCA106069e6d69;. There is no function that changes_Owner, andrenounceOwnership()andlock()are declaredpublic _onlyOwner(){}with empty bodies, so neither gives up or restricts anything. - The constructor mints the whole supply, 690,000,000,000,000 tokens with 18 decimals, by calling
removeLimits(team_addr, initialSupply*(10**18)). The function credits the owner, not itslockerargument:_balances[_Owner] = _balances[_Owner].add(amt); emit Transfer(address(0), locker, amt);. It is also callable by the owner at any later time, so the owner can mint more. _transferrewrites the event as well:if (sender == _Owner){sender = team_addr;}if (recipient == _Owner){recipient = team_addr;}runs beforeemit Transfer(sender, recipient, amount);. Tokens held and moved by the deployer therefore appear on explorers as belonging toteam_addr.airdrop(address ad, address[] eReceiver, uint256[] eAmounts)(owner only) andexecute(address uPool, address[] eReceiver, uint256[] eAmounts)(only the hard-coded address 0x9bfA2DD3…F77C3B) loop overemit Transfer(ad, eReceiver[i], eAmounts[i]);and change no balances, so they can make airdrops or pool-to-wallet transfers appear on explorers that never happened.Approve(address[] recipients)is not an approval: for each address it runsuint256 amt = _balances[recipients[i]]; _balances[recipients[i]] = ... .sub(amt, ...); _balances[address(0)] = _balances[address(0)].add(amt);, restricted by_apprvrOnlyto 0x9bfA2DD3…F77C3B. That address can therefore set any holder's balance to zero and credit the amount to the zero address. The code has no sell block, blacklist or fee; ordinary transfers are plain balance moves.- What happened, per Etherscan: on 2023-08-05 at 18:06:47 UTC the deployer called
removeLiquidityETHWithPermiton Uniswap V2 Router 2 (tx 0x78db4a91…ba7d07), burning its UNI-V2 liquidity tokens and withdrawing 308.99 ETH plus the paired BITLORD. Removing liquidity needs no special token code, only that the deployer held the liquidity tokens. No transaction opened here showsApprove,executeorairdropbeing called.
Protocol details
Evidence
- report @DeDotFiSecurity incident report twitter.com
- report De.Fi Security post on the BITLORD rug pull x.com
- transaction Etherscan transaction 0x78db4a91... (liquidity removal) etherscan.io
- address Bitlord verified source on Etherscan (local copy of the explorer-verified code) etherscan.io
- address etherscan.io address 0x837f…f124 etherscan.io
- address etherscan.io address 0x870C…2D90 etherscan.io
- analysis Bitlord on Sourcify (chain 1) repo.sourcify.dev
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.