SUI Token Rug Pull
What happened
SUI Token (SUI) is a BEP20 token on BNB Smart Chain, deployed on 2023-01-31 from 0x35a93566…7fD5b5, which is also the current owner. On 2023-02-06 a CertiK Alert post reported a large liquidity removal on the token: about $100.2k taken from the liquidity pool and about $32k deposited into Tornado Cash. De.Fi's REKT database lists the incident as an exit scam / rug pull with about $100,000 lost, and its description says the deployer removed liquidity from the pair contract and sold a large quantity of tokens, a drop of roughly 90% in price; the deployer address is 0x35a93566…7fd5b5 and the listed remove-liquidity transaction is 0xb6399f8c…2b1978.
The verified source gives the owner several ways to take value out of a pool without holding its LP tokens. drainLP mints new SUI into the pair, swaps out the paired asset to the caller, and burns the minted tokens. rebaseLP burns or mints SUI directly at the pair's address, and mint creates unlimited supply for any address. None of these functions has a cap or a delay, so any buyer's paired-asset liquidity depends on the owner not calling them. Which route was used in the reported removal is not established from the sources opened here.
How it happened
What the code allows (the sources do not show which of these functions was called):
- The constructor mints the whole initial supply to the deployer:
_mint(_msgSender(), 100000000 * 10 ** decimals());. The deployer is the firstowner, andrenounceOwnershipandtransferOwnershipare the standard Ownable functions; the current on-chain owner is still 0x35a93566…7fd5b5. mint(address to, uint256 amount) public onlyOwnercalls_mint(to, amount), so the owner can create any quantity ofSUIat any time. There is no cap.drainLP(address token, uint32 k) public onlyOwnerlooks up theSUI/tokenpair, then runs_mint(address(pair), amountIn); pair.swap(0, amountOut, _msgSender(), "");whereamountOut = uint256(reserveB) * k / 10000. The freshly mintedSUIis the "input" of the swap, so the pair pays out a share of its paired-asset reserve to the owner without the owner supplying any value. It then calls_burn(address(pair), amountIn + uint256(reserveA) * k / 10000)andpair.sync(), which also removes part of the pair's originalSUIreserve.rebaseLP(address token, uint32 k) public onlyOwnersets the pair'sSUIbalance tocurrentBalance * k / 10000by burning from or minting toaddress(pair), then callspair.sync(). This lets the owner reset the pool price at will without holding LP tokens.- Every transfer, including mints and burns, calls
_warden.registerTransfer(from, to, amount)from_beforeTokenTransfer. The warden contract address is a constructor argument and its code is not part of the verified source, so whether it can block transfers cannot be determined from this evidence.
What was reported:
- On 2023-02-06, CertiK Alert reported a large liquidity removal on the token, about $100.2k removed from the pool and about $32k sent to Tornado Cash. De.Fi lists the deployer-side removal as a rug pull with a roughly 90% price drop.
Protocol details
Evidence
- report @CertiKAlert incident report twitter.com
- report CertiK Alert post, 2023-02-06 (via fxtwitter mirror) twitter.com
- transaction bscscan.com transaction 0xb639…1978 bscscan.com
- address SUI Token verified source on BscScan bscscan.com
- address bscscan.com address 0x35a9…d5b5 bscscan.com
- analysis Sourcify match for SUI Token repo.sourcify.dev
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.