# Migrating from a Uniswap V3 pool to a Uniswap V2 pool may revert

Doppler's Airlock.migrate underflows when protocol proceeds fee (0.1% of balance) exceeds 5% of accrued UniV3 fees, reverting V3→V2 liquidity migration and locking fees.

- Payout: Contest reward
- Severity: high
- Program: Doppler
- Credited: trachev
- Disclosed: 2025-02-18
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_doppler.pdf#3.1.6
- Library page: https://bugbountylibrary.com/r/cantina%3Adoppler%3A3.1.6
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:cantina sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** Airlock.migrate fee distribution in Doppler token sale migration
**Root cause:** protocolFees0 is set to max(5% of fees0, 0.1% of (balance0 - fees0)); when the proceeds-based term exceeds fees0, integratorFees0 = fees0 - protocolFees0 underflows and reverts.
**Steps:**
1. Deploy token via airlock.create with a low UniV3 fee tier (e.g. fee=500) and small tick spacing.
2. Seed the V3 pool and perform swaps so accrued fees0 are small relative to pool balance.
3. Call `airlock.migrate(asset)`.
4. Observe revert in `integratorFees0 = fees0 - protocolFees0` when `(balance0 - fees0)/1000 > fees0*5/100`.
**How found:** Code review of Airlock.sol#L220-L230 fee math; noticed protocolFees0 takes max of two differently-scaled terms and integratorFees0 subtracts it from fees0, then reasoned low-fee/low-volume pools make the 0.1% proceeds term dominate.
**Exploitation:** Not an attack; migration reverts, blocking V3→V2 liquidity migration and preventing protocol/integrator fee claims.
**Insight:** When a fee is computed as max() of two terms with different bases (percent of fees vs percent of balance), check the subsequent subtraction against the smaller base — underflow reverts are a reliable DoS in migration/settlement paths.
