harb/onchain/AGENTS.md
openhands e35a805138 fix: Investigate: VWAP not preventing IL crystallization during buy-only recenter cycles (#543)
Investigation findings:
- VWAP WAS being fed during buy-only cycles (shouldRecordVWAP = true on ETH inflow / price rising).
  Over 80 buy-recenter cycles VWAP converged toward the inflated current price.
- When VWAP ≈ currentTick, mirrorTick = currentTick + vwapDistance ≈ currentTick, placing
  the floor near the inflated price.  Adversary sells back through the high floor, extracting
  nearly all LM ETH.
- Optimizer parameters (anchorShare, CI) were not the primary cause.

Fix (LiquidityManager.sol):
  Flip shouldRecordVWAP from buy direction to sell direction.  VWAP is now recorded only when
  price falls (ETH outflow / sell events) or at initial bootstrap (cumulativeVolume == 0).
  Buy-only attack cycles leave VWAP frozen at the historical baseline, keeping mirrorTick and
  the floor conservatively anchored far from the inflated current price.

Also updated onchain/AGENTS.md to document the corrected recording direction.

Regression test (VWAPFloorProtection.t.sol):
  - test_vwapNotInflatedByBuyOnlyAttack: asserts getVWAP() stays at bootstrap after N buy cycles.
  - test_floorConservativeAfterBuyOnlyAttack: asserts floor center is far below inflated tick.
  - test_vwapBootstrapsOnFirstFeeEvent: confirms bootstrap path unchanged.
  - test_recenterSucceedsOnSellDirectionWithoutReverts: confirms sell-direction recenters work.

All 187 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 03:31:45 +00:00

4 KiB

Agent Brief: Kraiken Protocol

Protocol Philosophy & Business Logic

What KRAIKEN is: A token with a self-managing liquidity manager (LM) on Uniswap V3. The LM positions liquidity across three positions (floor, anchor, discovery) and recenters them as price moves. An optimizer adjusts parameters based on staking sentiment.

Revenue model: TRANSACTION FEES are the product.

  • Every swap through the LM's positions generates Uniswap LP fees
  • Fees (WETH + KRK) flow to feeDestination — this is what founders withdraw
  • Locked ETH in the protocol has NO value to founders — it's locked forever
  • The protocol WANTS active trading, even if traders extract some ETH

The optimization target is NOT "minimize trader PnL". It is "maximize fee revenue while keeping the protocol solvent."

Four optimizer parameters:

  • capitalInefficiency (CI) — adjusts VWAP for floor placement. Zero effect on fee revenue — pure risk lever. CI=0% is safest.
  • anchorShare (AS) — ETH split between floor and anchor
  • anchorWidth (AW) — anchor position width in ticks
  • discoveryDepth (DD) — discovery position liquidity density. Zero effect on floor safety.

See TECHNICAL_APPENDIX.md for floor placement formula, parameter safety frontier, and asymmetric slippage analysis.

OptimizerV3

src/OptimizerV3.sol — UUPS upgradeable. Binary bear/bull from staking sentiment.

Inputs: percentageStaked (0-100%), averageTaxRate (effective index 0-29)

Mapping:

  • staked <= 91% → always BEAR: AS=30%, AW=100, CI=0, DD=0.3e18
  • staked > 91%BULL if deltaS^3 * effIdx / 20 < 50: AS=100%, AW=20, CI=0, DD=1e18

The binary step avoids the AW 40-80 kill zone. ~94% of state space maps to bear.

Staking Triangle Cycle

The staking system traces a triangle in (staking%, avgTax) space:

  1. Fill up: Staking grows 0→100%, tax low. Optimizer stays bear. Bull at ~95%.
  2. Snatching wars: 100% staked, tax rises. Always bull.
  3. Collapse: Nervous exits. Cubic term snaps to bear within 4-6% staking drop.

System Snapshot

  • Kraiken ERC20 with mint/burn via LiquidityManager. VERSION=2.
  • LiquidityManager.sol: ANCHOR + DISCOVERY + FLOOR positions with asymmetric slippage.
  • VWAPTracker.sol: squared price in X96, compression, directional recording (price-fall / ETH-outflow events only — buy-only cycles must NOT update VWAP or the floor tracks the inflated price, crystallising IL; see issue #543).
  • OptimizerV3.sol: UUPS upgradeable, direct 2D binary mapping.
  • Stake.sol: self-assessed tax, snatching auctions, discrete brackets, UBI redistribution.

Development Workflow

  • Foundry: forge build, forge test, forge fmt, forge snapshot.
  • Repo: src/ (contracts), test/helpers/ (Uniswap/Kraiken bases), lib/uni-v3-lib (math), script/ (deploy).
  • Setup: git submodule update --init --recursive, npm install in lib/uni-v3-lib/, Foundry installed.
  • ABI flow: kraiken-lib/src/abis.ts imports from onchain/out/. Run forge build to update ABIs stack-wide.

Testing & Analysis

  • Fuzzing under analysis/: configurable trade/stake biases, adversarial attacks, parameter sweeps. See analysis/README.md.
  • Adversarial testing (run-adversarial.sh, run-v3-adversarial.sh) validates floor defense.
  • Background LP analysis (run-bglp-fee-test.sh) measures fee retention under LP competition.

Containerized Builds

  • Git submodules must be initialized before building.
  • lib/uni-v3-lib/ needs npm install for Uniswap interfaces.
  • Foundry image: ghcr.io/foundry-rs/foundry:latest (includes forge/cast/anvil, NOT jq/curl).
  • Volume permissions: use :z (shared SELinux label) for multi-container mounts.

Guardrails

  • Respect access controls (onlyLiquidityManager, owner).
  • token0isWeth flips amount semantics — confirm ordering before interpreting liquidity.
  • Floor uses vwapX96 directly (not sqrt) in fixed-point math.
  • Outstanding supply excludes LM position balances and KRK held by feeDestination/stakingPool.