# wLp tokens could be stolen 

removeCollateralWLpTo only checks tokenId ownership on full removal, letting anyone decollateralize another position's wLp and steal LP tokens plus rewards.

- Payout: Contest reward
- Severity: high
- Program: INIT Capital
- Credited: sashik\_eth
- Disclosed: 2024-01-16
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-12-initcapital-findings/issues/31
- Library page: https://bugbountylibrary.com/r/c4%3A2023-12-initcapital%3AH-02
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** PosManager.removeCollateralWLpTo / decollateralizeWLp
**Root cause:** The tokenId-belongs-to-position check (ids[_wLp].remove) only runs when newWLpAmt == 0; partial withdrawals skip it, so any tokenId can be unwrapped against the caller's position.
**Steps:**
1. Open a position with dust wLp (tokenId 2) via _openPositionWithLp(ALICE, 1).
2. Victim holds a large wLp position (tokenId 1, amount victimAmt).
3. Call `initCore.decollateralizeWLp(alicePosId, wLp, 1, victimAmt - 1, ALICE)` using the victim's tokenId with amount one less than full to avoid the line-257 check.
4. Receive victim's unwrapped LP tokens and accrued rewards to ALICE.
**How found:** Code reading of removeCollateralWLpTo: noticed the ids[_wLp].remove ownership check is nested inside the `if (newWLpAmt == 0)` full-removal branch, so partial removals never verify the tokenId belongs to the position.
**Exploitation:** Attacker supplies dust wLp to create a position, then calls decollateralizeWLp referencing the victim's tokenId with amt = victimBalance - 1 so newWLpAmt != 0 and the ownership check is skipped; unwrap sends the victim's LP tokens and harvested rewards to the attacker. Same path via liquidateWLp harvests victim rewards.
**Insight:** When an ownership/containment check is placed inside a branch that only executes on a boundary condition (full removal, zero balance), test the non-boundary path with a foreign tokenId and an amount just under the victim's balance to bypass it.
