Mechanism
_exposureGate1D runs after the swap-pricing instruction. At or below maxExposureBps it does nothing. Between max and halt it scales the fill down linearly. At haltExposureBps or above it reverts. There is no branch where it can make the fill bigger.Simulation · same math as ExposureGate.sol (lib/xyc.ts)
Move the reading. Watch the gate.
- Ungated curve
- …
- Gated fill
- …
Loading Strategy A's live Aqua reserves… Gated is never above ungated, whatever the reading.
Gate band
◐ Derated — smaller fill
v4 dynamic fee
7888 pips · 0.789%
Illustrative profile. The live maker uses 50/90. Click the curve to set a reading.
The pipeline
- 1
on-chain
Aqua
The maker commits balances to every strategy via ship / pull.
- 2
subgraph
The Graph
ExposurePosition joins commitments, oracle readings and v4 swaps.
- 3
off-chain
Keeper
keeper/pushExposure.ts sums the maker's commitments and pushes one reading.
- 4
on-chain
ExposureOracle
Only the keeper can write. Stale readings revert. The maker can pause.
- 5
SwapVM opcode
_exposureGate1D
Derates or halts the fill. Never improves it.
→ 1inch SwapVM
Direct swap, no pool. The maker's program runs with the gate inside it.
→ Uniswap v4 · AquaV4Hook
The pool holds no liquidity of its own. Every fill is sourced live from the same strategy.
Strategy P · a sophisticated position
_xycSwapXD
prices the swap
constant product from live Aqua reserves
_oraclePriceAdjuster1D
can only improve
toward Chainlink ETH/USD, capped at +3%
_exposureGate1D
can only worsen
toward the maker's real risk, down to a halt
Schematic, not to scale. Proof: test/SophisticatedPosition.t.sol · live strategy hash 0xe3f9…cd88
Why it isn't just a v4 hook
Aqueduct
A normal hook