TRT Rug Pull

Reported loss $93K
Rugpull

What happened

TRT (contract 0x52f56100…C4F668) is a BEP-20 token on BNB Smart Chain. On 2023-04-05 CertiK's Skynet alert reported a large liquidity removal, with 99% slippage, saying the deployer removed liquidity in four transactions for a profit of about 93,000 USD and that the token appeared to be a honeypot. De.Fi's listing describes the same event as a liquidity-removal scam by the team managing liquidity, with the deployer removing a large share of the LP and dumping the token, which fell by about 90% from its initial price. The verified source mints the whole supply to the deployer, who is also granted the admin role at construction, and its _transfer blocks wallet-to-wallet transfers while an admin-set _usdtPair address controls which trades are allowed, so the admin role can both stop ordinary holders from selling and tax every transfer; no opened transaction shows those functions being called.

Deployer named by De.Fi: 0x4de9ff82…3f49ce. Liquidity-removal transactions listed by De.Fi: 0x2e845ee2…69a832 and 0xf6505fe6…269358.

How it happened

  1. The constructor mints the full supply to the deployer and makes it the admin: _mint(creater_,totalSupply_*10**decimals()); and _grantRole(DEFAULT_ADMIN_ROLE, _msgSender());. On-chain totalSupply is 100,000,000 TRT, so the deployer can supply the pool and keep the rest.
  2. _transfer only lets a transfer through when the sender has an admin-granted quota, is a contract, or one side is _usdtPair: }else if(isTxt(from)){ ... }else if(from==_usdtPair||to==_usdtPair){ ... require(false,"Block is busy, please try again");. Ordinary wallet-to-wallet transfers revert, and trades with the pair pass only while _usdtPair points at the real pool.
  3. The admin can repoint that variable at any time: function setUsdtPair(address Pair_) public onlyRole(DEFAULT_ADMIN_ROLE){ _usdtPair=Pair_;. If it is set to another address, a sell from a wallet to the real pool matches none of the allowed cases and reverts with Block is busy, while buys still pass because the pool is a contract and isTxt(from) is true. setBotHMDArr can grant chosen addresses a transfer quota that bypasses the check.
  4. The admin can also set an uncapped tax: _scale=scale_; with super._transfer(recipient, _destroyAddress, tAmount.div(100).mul(_scale)); and tAmount = tAmount.div(100).mul(100-_scale);. The sender is debited the full amount and the recipient loses _scale percent to the dead address; at 100 the recipient keeps nothing, and above 100 the subtraction underflows and every such transfer reverts.
  5. The token contract has no liquidity lock, so whoever holds the LP tokens can remove the pool at any time. CertiK reports that the deployer removed liquidity in four transactions, a 99% slippage event and roughly 93,000 USD profit, and De.Fi lists the same removal as a rug pull with the token falling about 90%. Whether the pair switch or the tax was used before or during the removal is not shown by any opened source.

Protocol details

Classification Token
Protocol Type Exit Scam/Rugpull
Affected asset / contract TRT

Build your security review skills

Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.