# HORS: fake router address drains LP tokens

HORS vulnerable contract trusted an attacker-supplied router address, letting the attacker drain its WBNB/HORS PancakeSwap LP tokens for 14.8 WBNB.

- Payout: Real-world hack
- Severity: high
- Program: HORS
- Credited: DeFiHackLabs
- Disclosed: 2025-01-08
- Write-up quality: 6/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2025-01/HORS_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20250108-hors
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** BSC token contract holding PancakeSwap LP tokens
**Root cause:** The vulnerable contract's addLiquidity-style function (selector 0xf78283c7) accepted a caller-controlled router/recipient address without validation, so it transferred its LP tokens to the attacker's contract.
**Steps:**
1. Flash-borrow 0.1 WBNB from PancakeV3 pool `0x172fcD41E0913e95784454622d1c3724f546f849`.
2. Call VULN_CONTRACT `0x6f3390c6C200e9bE81b32110CE191a293dc0eaba` with selector `0xf78283c7` and args `(HORS_ADDR, address(this), CAKE_LP)`.
3. Vulnerable contract transfers its CAKE_LP balance to attacker via the attacker-implemented addLiquidity callback.
4. Approve PancakeRouter and call `removeLiquidity(WBNB, HORS, balance, 0, 0, address(this), block.timestamp)`.
5. Repay 0.1 WBNB + flash fee to the pool and transfer remaining WBNB to attacker.
**Exploitation:** Attacker flash-loaned 0.1 WBNB, invoked the vulnerable contract's unvalidated function passing itself as the router, received the contract's LP tokens, removed liquidity via PancakeRouter, repaid the flash loan, and kept 14.8 WBNB.
**Insight:** When a contract takes a router/recipient address as a parameter, check whether it actually calls that router or just transfers tokens to it; passing your own contract as the 'router' can turn a liquidity helper into a token drain.
