Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions docs/Vulnerabilities_list_tokenomics.md
Original file line number Diff line number Diff line change
Expand Up @@ -486,16 +486,18 @@ Branch (2) is **not** closed by the runbook. An already-seeded pool that experie
**Planned code fix (single `LiquidityManagerCore` implementation upgrade, applied via `changeImplementation` on the existing zero-position proxies).** The fix:

1. **Removes both fail-open early returns** from `checkPoolAndGetCenterPrice` and reverts (`NotEnoughHistory`) when a 30-minute TWAP cannot be verified. Every price-consuming caller (`convertToV3`, `changeRanges`, `increaseLiquidity`, and the permissionless `BuyBackBurner.buyBack`) inherits the revert: on an unverifiable pool the call fails, and no liquidity is added or traded at a price the contract cannot stand behind.
2. **Keeps exits and fee collection live** — the one structural consequence of (1). `decreaseLiquidity` stops depending on the guard and takes **owner-supplied `minAmount0` / `minAmount1`** (set by governance in the same transaction), so a withdrawal succeeds in every pool state and stays sandwich-bounded without a TWAP; `collectFees` likewise drops the guard gate and burns only the just-collected fee.
3. **Anchors add/withdraw slippage to a trusted price** — `_increaseLiquidity`'s `amountMin` is derived from the TWAP center rather than raw `slot0`.
2. **Keeps exits and fee collection live** — the one structural consequence of (1). `decreaseLiquidity` does not use the fail-closed guard; instead it derives its slippage floor **at execution** from a *deviation-gated slot0* price (`_getExitSqrtPrice`): on a verifiable pool it reverts if `slot0` is more than `MAX_ALLOWED_DEVIATION` off the 30-minute TWAP (anti-manipulation gate), otherwise it skips the gate (quiet / fresh pool). In both cases it returns the raw `slot0` price, and `amountMin` is computed from that same `slot0` — the exact price the position manager withdraws at — so a fair exit is always satisfiable within the gate and never goes stale across a governance delay. `collectFees` likewise drops the guard gate and burns only the just-collected fee.
3. **Anchors the entry slippage floor to a trusted price** — `_increaseLiquidity`'s `amountMin` is derived from the TWAP center rather than raw `slot0`.

The revert in (1) is a refusal, not a permanent denial — a single subsequent swap on the pool repopulates the observation buffer, the TWAP becomes verifiable again, and the next call proceeds normally. No on-chain action by the DAO is required to "unstick" the contract.

Steps (2)–(3) also close items **#15** (`collectFees` burn-all) and **#16** (spot-derived `amountMin`) in the same release; both will be removed from this list once the implementation is live.
Step (2) closes item **#15** (`collectFees` burn-all) and the entry side of item **#16** (spot-derived `amountMin` on `increaseLiquidity` / re-seed); the exit side of #16 (`decreaseLiquidity`) is *improved* — its floor is now soft-priced against the TWAP on a verifiable pool and only falls back to `slot0` (capital-bounded on a liquid pool) when the pool is quiet, rather than being unconditionally spot-derived. #15/#16 disposition is finalised when the implementation is live.

**Deployment sequencing (preserves "no funds at risk").** The "no third-party extraction on the deployed system" property above holds only while the LiquidityManager is unseeded and non-custodial. The rollout deploys the fixed implementation **before** any protocol-owned liquidity is seeded — the migration runbook's seed step runs only after the fixed impl is live — so there is never a window in which standing value sits behind the unfixed guard.

**Post-fix liveness (accepted residual).** After the fix, a pool with no trade for >30 minutes reverts entries/trades (`increaseLiquidity` / `changeRanges` / `buyBack`) until the next swap. This is intended fail-closed behaviour: it never locks funds, exits always succeed, and it self-heals on the next swap with no operator action.
**Post-fix liveness (accepted residuals).** Two intended, self-healing liveness cases, neither of which locks funds:
- **Quiet pool → entries/trades revert.** A pool with no trade for >30 minutes reverts `increaseLiquidity` / `changeRanges` / `buyBack` (fail-closed) until the next swap repopulates the observation buffer. Exits are unaffected here (the exit gate is skipped on a quiet pool).
- **Extreme move → exit temporarily blocked.** On a *verifiable* pool the exit deviation gate cannot distinguish manipulation from a genuine fast market move, so `decreaseLiquidity` reverts (`Overflow`) while `slot0` sits >`MAX_ALLOWED_DEVIATION` (10%) from the lagging 30-minute TWAP. Funds are never at risk; the exit succeeds once the pool re-converges within the bound (the TWAP catches up or arbitrage restores price). Acceptable because POL exits are governance-timed, not block-time-critical; a decrease proposal that lands in an extreme window is simply re-submitted after re-convergence.

**Interim operational mitigation.** As with the fresh-pool case, before submitting any owner-initiated `convertToV3` / `increaseLiquidity` / `changeRanges` transaction the DAO confirms the pool exposes a working 30-minute TWAP and a recent trade (the migration-runbook pre-flight generalises to any subsequent owner-initiated liquidity op on the same pool).

Expand Down
Loading
Loading