# Division-by-zero in long-leg collateral requirement can block solvency checks and dispatchFrom (liquidation/force-exercise) for tickSpacing==1 pools

In tickSpacing==1 Panoptic pools, a 1-tick-wide long leg evaluated at strike causes division-by-zero in RiskEngine margin math, reverting liquidation/force-exercise via dispatchFrom.

- Payout: Contest reward
- Severity: medium
- Program: Panoptic
- Credited: niffylord
- Disclosed: 2026-03-09
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2025-12-panoptic-next-core#m-05
- Library page: https://bugbountylibrary.com/r/c4%3A2025-12-panoptic-next-core%3AM-05
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** RiskEngine margin computation / PanopticPool.dispatchFrom solvency checks
**Root cause:** For width==1 long legs, distanceFromStrike = max(positionWidth/2, abs(atTick-strike)) becomes 0 when atTick==strike, and a later division by (distanceFromStrike * expValue) reverts.
**Steps:**
1. Target a pool with tickSpacing == 1.
2. Hold/create a long position with a 1-tick-wide leg (width == 1) and strike T.
3. Trigger dispatchFrom(...) which includes currentTick in its tick set.
4. When currentTick == T, margin evaluation calls RiskEngine long-leg branch (L1508/L1541) and reverts with division-by-zero, blocking liquidation/force-exercise.
5. Reproduce via PoC test test_poc_WidthOneLongAtStrike_DivisionByZero_BlocksLiquidation asserting stdError.divisionError.
**How found:** Code-reading of RiskEngine long-leg branch: noticed distanceFromStrike = max(positionWidth/2, abs(atTick-strike)) collapses to 0 for width==1 at strike, then traced the subsequent division and dispatchFrom's inclusion of currentTick.
**Exploitation:** Attacker holds a width==1 long leg at strike T in a tickSpacing==1 pool; when price reaches T, any third-party liquidation/force-exercise/settle action that evaluates solvency at currentTick reverts, blocking resolution at that price.
**Insight:** When margin formulas use max(width/2, distance) as a divisor, check the width==1 boundary where the floor term is zero and the distance term can also be zero at strike; also check whether solvency loops include currentTick, turning a math edge case into a liquidation DoS.
