MOON Token Rug Pull
What happened
MOON is a copycat BEP20 token on BNB Smart Chain, traded on PancakeSwap, that CertiK Alert and De.Fi's REKT database list as a deployer liquidity removal of about 42k USD on 2023-02-10, with the price falling 99%. As written, its _transfer calls a checking function that makes a transfer from an ordinary wallet do nothing at all unless the sender is the creator, is sending to the creator, or has been given a separate allowance by an admin. Tokens sent out of the pair (buys) go through, but a holder's tokens sent into the pair (sells) are silently skipped while the call still reports success. A second admin address is hard-coded inside the role-granting code and receives the admin role whenever a role is granted, including in the constructor.
De.Fi's listing says the deployer removed liquidity worth 42,117 USD in three transactions and moved the funds to multiple externally owned accounts. Scammer address: 0x40997449…806f12. Malicious transactions: 0x22eb5d71…792b87, 0xdb36ea76…a212da, 0x4eb0e908…99da5d.
How it happened
What the code allows:
- The constructor mints the whole supply to the deployer through
ERC20(_name, _symbol,_totalSupply,_msgSender()), which calls_mint(creater_,totalSupply_*10**decimals()), then setscreater=msg.sender;and grants the admin role with_grantRole(DEFAULT_ADMIN_ROLE, _msgSender());. The on-chain total supply is 100,000,000 tokens and the contract has no other mint function. MOON._transferoverrides the standard transfer:if(checking(from,to,amount)){return;}. Whencheckingreturns true the function exits before any balance is changed and before any event, and no revert occurs, sotransferandtransferFromstill return true.checkingreturns false (the transfer proceeds) in three cases: the sender has an admin-set allowance,uint256 AFG=BHG[from]; if(AFG>0 && AFG>=amount){BHG[from]=AFG-amount;return false;}; the sender is a contract,if(isContract(from) && mask[from]!=108){return false;}(maskis never written, becausesetMaskis declaredviewand only contains the comparisonmask[user]==108;, so the condition holds for every contract); or the creator is on either side,else if(from==creater || to==creater){return false;}. Every other case ends inreturn true;, which is the silent skip.- A buy moves tokens out of the pair, which is a contract, so it proceeds. A sell through the router calls
transferFrom(holder, pair, amount)with the holder, an ordinary wallet, asfrom; that wallet has noBHGallowance, is not a contract, and is notcreater, and the pair is notcreatereither, socheckingreturns true and nothing is moved while the router's allowance is still decremented. A standard PancakeSwap pair then receives no input tokens, and its swap requires a positive input amount, so the sell cannot complete. Wallet-to-wallet transfers between ordinary holders are skipped the same way. - Only the admin role can lift the restriction for a wallet with
function setDDD(address user, uint256 amount) public onlyRole(DEFAULT_ADMIN_ROLE){ BHG[user]=amount*10**decimals(); }. The role is held by the deployer and by a second address written into the role code:_roles[DEFAULT_ADMIN_ROLE].members[0x9C59B43C8642e9087965B7f1773470be8ee33960]=true;inside_grantRole, which runs the first time any account is granted a role, including the constructor's own grant. - Nothing in the contract restricts removing liquidity: tokens leave the pair as a transfer from a contract, which
checkinglets through, and LP tokens are standard PancakeSwap LP tokens outside this contract.
What was reported:
- CertiK Alert reported a 99% drop in the MOON price with the deployer removing liquidity for about 42k USD. De.Fi's REKT database lists three liquidity removal transactions worth 42,117 USD and the funds moved to multiple externally owned accounts. No transaction page was opened, so this analysis does not show whether any holder actually tried to sell and failed, whether
setDDDwas ever called, or who held the LP tokens.
Protocol details
Evidence
- report CertiK Alert post on slippage and deployer liquidity removal on MOON token twitter.com
- transaction bscscan.com transaction 0x22eb…2b87 bscscan.com
- transaction bscscan.com transaction 0x4eb0…da5d bscscan.com
- transaction bscscan.com transaction 0xdb36…12da bscscan.com
- address MOON verified contract source, MOON.sol, BscScan bscscan.com
- address bscscan.com address 0x4099…6f12 bscscan.com
- analysis Sourcify match for MOON contract on BSC repo.sourcify.dev
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.