# PositionManager's moveLiquidity can set wrong deposit time and permanently freeze LP funds moved

PositionManager.moveLiquidity copies source deposit time to destination, so if destination bucket went bankrupt later, moved LP shares are permanently frozen.

- Payout: Contest reward
- Severity: high
- Program: Ajna Protocol
- Credited: hyh
- Disclosed: 2023-06-29
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2023-05-ajna-findings/issues/494
- Library page: https://bugbountylibrary.com/r/c4%3A2023-05-ajna%3AH-02
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** PositionManager.moveLiquidity / redeemPositions (Solidity, EVM)
**Root cause:** moveLiquidity sets toPosition.depositTime = fromPosition.depositTime instead of the destination bucket's renewed deposit time, ignoring toIndex bankruptcy time. Later redeemPositions checks depositTime <= bankruptcyTime and reverts.
**Steps:**
1. Owner has LP in fromIndex with depositTime T.
2. toIndex bucket goes bankrupt at time B > T.
3. Call `moveLiquidity({pool, tokenId, fromIndex, toIndex, expiry})`; pool.moveQuoteToken succeeds and sets toPosition.depositTime = T.
4. Call `reedemPositions({indexes:[toIndex]})`; `_bucketBankruptAfterDeposit` returns T <= B true, reverting BucketBankrupt permanently.
**How found:** Code-reading: compared PositionManager.moveLiquidity's deposit-time handling against LenderActions.moveQuoteToken, which correctly uses max(fromBucketDepositTime, toBucketDepositTime) and resets to bankruptcyTime+1; noticed PositionManager copies source time blindly while redeem checks against destination bankruptcy.
**Exploitation:** Any LP owner performing a normal moveLiquidity into a bucket whose bankruptcy time exceeds their source deposit time permanently locks the moved shares; no attacker needed, loss is self-inflicted via routine operation.
**Insight:** When a wrapper contract mirrors pool accounting state, diff its bookkeeping against the underlying library's logic (here LenderActions) — any field the library recomputes (depositTime vs bankruptcyTime) is a candidate for stale/incorrect mirroring that later gates withdrawals.
