# 50 — The case of the JIT liquidity drain

> Scenario file: `scenarios/jit_liquidity_drain.yaml` Severity observed: HIGH Time-to-reproduce: 15 minutes

JIT — *just-in-time* — liquidity is the practice of supplying liquidity to a concentrated AMM range only for the duration of a single transaction, capturing the fees of that transaction, and withdrawing immediately. It is a legitimate strategy. It is also a vector for attacking protocols that *consume* concentrated liquidity without auditing where the liquidity comes from.

This case is the one most often misdiagnosed. Protocols see the symptom — passive LPs earning much less than they should — and conclude that the AMM is working as designed. The fuzzer finds the cause: a JIT operator is positioning around the protocol's own deposits to harvest fees that the protocol's users were paying for.

## The setup

A perpetuals protocol uses a concentrated AMM as its execution venue for liquidations. When a position liquidates, the protocol issues a swap into the AMM at the current oracle price. The AMM's fee is paid to whichever LP holds the active range at the moment of the swap.

The protocol assumes the LPs in that range are the protocol's own treasury or its passive LP partners.

## The attack

The adversary watches the protocol's mempool for a liquidation. The moment one appears, they:

1. mint a tight liquidity range straddling the oracle price;
2. let the liquidation swap execute against their range, capturing the fee;
3. burn the range and withdraw, returning the LP tokens.

All three steps happen in the same transaction or in two adjacent transactions in the same slot. The adversary's capital is at risk for one block. The fee they capture is the fee the protocol's passive LPs would otherwise have earned.

Over a week of monitoring on a major Solana perpetuals venue, we observed JIT operators capturing 60–80% of liquidation fees. The passive LPs — who had agreed to provide always-on liquidity in exchange for the fees — were earning 20–40% of what they had been quoted in the protocol's documentation.

## What the fuzzer does

`jit_liquidity_drain.yaml` runs 100 simulated liquidations against a parameterised AMM. The genetic fuzzer searches for the JIT operator's optimal range width. The fuzzer's invariant is that passive-LP fee share must remain above a configurable floor.

This is one of the cases where the fuzzer's findings depend on tuning. A protocol that *expects* JIT activity and prices it into its passive-LP terms will not break the invariant. A protocol that does not has no defence by default.

## The fix

JIT cannot be prevented; it is a permissionless strategy on a permissionless AMM. It can be priced.

**Liquidity-tier rebates.** Reward LPs whose liquidity has been in range for longer with a bonus on top of the AMM fee. The bonus is funded from a fee on JIT-eligible swaps. This re-balances the economics in favour of passive LPs without making JIT illegal.

**Anti-JIT swap routing.** Do not route the protocol's own swaps through the public AMM. Route them through a private RFQ or a request-for-fill mechanism that excludes JIT operators by construction. This is invasive and makes the protocol slower; it is the right call when the swaps are large and predictable.

**Disclose and accept.** Tell passive LPs honestly that JIT operators will harvest a known fraction of fees. Adjust the headline APR accordingly. This is the option most protocols quietly take in the end.

The hardening index entry is `JIT-1`.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://economicfuzz.gitbook.io/economicfuzz-docs/case-studies/50-case-jit-liquidity-drain.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
