# SellToken01: fake-token sell() drains staking LP reserves

SellToken staking contract's sell() let attacker supply a fake token to drain real SELLC-QIQI LP tokens, netting ~$95k on BSC.

- Payout: Real-world hack
- Severity: high
- Program: SellToken01
- Analysis by: DeFiHackLabs
- Disclosed: 2023-05-11
- Write-up quality: 6/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2023-05/SELLC_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20230511-sellc
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:oracle-manipulation

**Target:** BSC staking rewards contract (addLiquidity/sell)
**Root cause:** StakingRewards.sell() trusted an attacker-registered token address and paid out real SELLC-QIQI LP tokens based on the fake token's manipulated pricing, without validating the token or the LP being withdrawn.
**Steps:**
1. Swap 3 WBNB to SELLC via official router; add SELLC-QIQI liquidity to get SellQILP.
2. Deploy fake SHITCOIN token; mint supply; call `StakingRewards.addLiquidity(address(this), address(MYTOKEN), 1e18)` to register the attacker contract as a listed token.
3. Create custom LP pair (attacker token / SellQILP) and seed it with minted tokens and SellQILP.
4. Loop: compute `swapAmountIn = Router.getAmountsIn(SellQILPAmount*99/100, path)[0]*2` and call `StakingRewards.sell(address(this), address(SellQILP), swapAmountIn)` to extract SellQILP from the staking contract.
5. Repeat sell() 23 times in process(), then transfer SellQILP to itself and `burn()` to redeem underlying SELLC.
6. Swap SELLC back to WBNB via official router.
**How found:** Likely code review of sell()/addLiquidity() showing no whitelist of accepted tokens and payout denominated in a valuable LP regardless of input token.
**Exploitation:** Attacker registered a worthless self-controlled token in the staking contract, built a custom LP against the protocol's SellQILP, then repeatedly invoked sell() with a computed input amount so the contract paid out its real SellQILP reserves; burning the LP redeemed SELLC which was swapped to WBNB for ~$95k.
**Escalation:** Iterative sell() loop (23x) amplified extraction; custom LP pricing let attacker dictate the exchange rate.
**Insight:** When a staking/rewards contract accepts arbitrary user-supplied token addresses and pays out a fixed valuable LP, register a worthless token and manipulate a custom pair to make sell() overpay; check whether addLiquidity validates the token against a whitelist.

