# moveQuoteToken updates pool state using intermediary LUP, biasing pool's interest rate calculations

Ajna's moveQuoteToken computes LUP after removal but before addition, feeding a stale intermediary LUP into interest-state EMA and biasing pool interest rates.

- Payout: Contest reward
- Severity: high
- Program: Ajna
- Credited: hyh
- Disclosed: 2023-04-20
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-04-ajna-judging/issues/87
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-04-ajna%3AH-3
- Tags: domain:web3 impact:integrity kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error

**Target:** LenderActions.moveQuoteToken / Pool.moveQuoteToken interest state update
**Root cause:** moveQuoteToken computes Deposits.getLup after removing liquidity from the source bucket but before adding it to the destination, so the returned LUP does not reflect the final pool state yet is passed to _updateInterestState.
**Steps:**
1. Call Pool.moveQuoteToken(maxAmount_, fromIndex_, toIndex_, expiry_) moving quote tokens between buckets.
2. In LenderActions.moveQuoteToken, _removeMaxDeposit removes liquidity from fromIndex.
3. lup_ = Deposits.getLup(deposits_, poolState_.debt) is computed on this intermediate state (post-removal, pre-addition).
4. Deposits.unscaledAdd adds movedAmount_ to toIndex, changing the true LUP.
5. The stale lup_ is returned and passed to _updateInterestState -> PoolCommons.updateInterestState, biasing lupt0DebtEma.
6. Repeated moves systematically skew target utilization tu = debtColEma_/lupt0DebtEma_ and thus _calculateInterestRate.
**How found:** Code reading of moveQuoteToken flow: noticed LUP is evaluated between the atomic removal and addition steps, so the value returned as newLup cannot match the final pool state used for interest accounting.
**Exploitation:** No direct theft; frequent legitimate moveQuoteToken calls systematically bias the pool's LUP*t0Debt EMA, distorting target utilization and interest rate dynamics for all borrowers/lenders.
**Insight:** In atomic multi-step state transitions (remove-then-add), any derived aggregate like LUP/EMA must be recomputed after the final mutation; check where getLup/getHtp-style values are captured relative to the last deposit write.
