# The transfer lock for leveraged position orders can be bypassed

Announcing a limit order then cancelling it unlocks a leveraged position NFT while a delayed close order is still pending, letting the seller dump the NFT and still cash out the collateral.

- Payout: Contest reward
- Severity: high
- Program: Flatmoney
- Credited: 0xVolodya
- Disclosed: 2023-12-11
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-12-flatmoney-judging/issues/48
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-12-flatmoney%3AH-1
- Tags: domain:web3 impact:funds-loss impact:integrity kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:access-control vuln:business-logic

**Target:** LeverageModule ERC721 position lock / DelayedOrder & LimitOrder
**Root cause:** The lock is a single boolean set by announce and cleared by cancel; cancelling a limit order clears the lock even though a separate delayed close order still holds it, so the two order paths don't share reference-counted lock state.
**Steps:**
1. Call `DelayedOrder.announceLeverageClose(tokenId, minFillPrice-100, keeperFee)` to lock the position.
2. Call `LimitOrder.announceLimitOrder(tokenId, 900e18, 1100e18)` to lock again.
3. Call `LimitOrder.cancelLimitOrder(tokenId)` — this unlocks the tokenId despite the pending delayed order.
4. Transfer/sell the position NFT via `leverageModProxy.transferFrom(alice, buyer, tokenId)`.
5. Wait `minExecutabilityAge`, then call `DelayedOrder.executeOrder(alice, priceUpdateData)` to close and withdraw collateral.
**How found:** Code review of the lock/unlock logic across DelayedOrder and LimitOrder: noticed cancelLimitOrder unconditionally unlocks without checking whether another order still requires the lock.
**Exploitation:** Attacker announces a delayed leverage close, then announces and cancels a limit order to clear the lock, sells the now-transferable position NFT to a third party, and finally executes the delayed close to withdraw the underlying collateral, leaving the buyer with a drained position.
**Insight:** When a protocol uses a single boolean lock shared across multiple order-entry paths, test whether cancelling one path clears the lock while another path's order is still live — reference-count or per-order lock tracking is needed.
