# SHOCO reflection token deliver() drains Uniswap pair

SHOCO reflection token's deliver() inflated pair balance, letting attacker swap out WETH for ~4 ETH profit.

- Payout: Real-world hack
- Severity: high
- Program: - SHOCO
- Analysis by: DeFiHackLabs
- Disclosed: 2023-01-19
- Write-up quality: 7/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2023-01/SHOCO_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20230119-shoco
- Tags: area:web3 domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity vuln:accounting-error vuln:business-logic

**Target:** ERC20 reflection token and Uniswap V2 pair
**Root cause:** The reflection token's deliver() function burns tokens from the caller and adjusts rTotal, but the pair's token balance is not synced, allowing an attacker to manipulate the pair's reserve accounting via reflection mechanics.
**Steps:**
1. Fork mainnet at block 16440978 and deal 2000 WETH to attacker.
2. Read rTotal from storage slot 14 and rExcluded for the pair address from mapping slot 3; compute rAmountOut = rTotal - rExcluded.
3. Convert rAmountOut to shocoAmountOut via tokenFromReflection, subtract 0.1 gwei.
4. Compute required WETH input via getAmountIn using pair reserves, transfer WETH to pair, and call swap(shocoAmountOut, 0, attacker, '').
5. Call shoco.deliver(shoco.balanceOf(attacker) * 99999 / 100000) to burn most tokens and inflate the pair's effective balance.
6. Re-read reserves, compute WETH out via getAmountOut using (shoco.balanceOf(pair) - reserve0), and call swap(0, wethAmountOut, attacker, '').
**How found:** Analysis of reflection token mechanics: the deliver() function alters balances without updating the Uniswap pair's reserves, creating a price discrepancy exploitable via a swap-burn-swap sequence.
**Exploitation:** Attacker flash-funded 2000 WETH, swapped WETH for a calculated amount of SHOCO from the pair, then called deliver() to burn 99.999% of the received SHOCO. This reflection burn increased the pair's SHOCO balance relative to reserves, so the attacker swapped the excess SHOCO back for WETH at an inflated rate, netting ~4 ETH.
**Insight:** Reflection tokens that burn via deliver() can desync Uniswap pair reserves; check if token balance changes (burn/mint) are reflected in pair reserves before swapping.

