Architecture
The system splits in two: an on-chain half that's autonomous once deployed, and an off-chain half that decides when to act.
OFF-CHAIN ── runs 24/7 ─────────────┐ ON ROBINHOOD CHAIN ── autonomous ────────────┐
│ │
KEEPER │ NAVOracle (one per LT) │
├─ holds/rebalances each perp on │ ▲ postNav(nav, sig) EIP-712 │
│ Lighter (margin in USDG) ├──────┘ │ latestNav() │
├─ computes NAV = equity / supply │ ▼ │
├─ signs + posts NAV ──────────────┤ LTVault ── mint/redeem at NAV │
├─ harvest / expand / reanchor ────┤ ▲ mint / redeem │
└─ buyback & burn ─────────────────┤ SingleSidedMemeV4 ── owns every coin's LP │
│ │
trader ── ETH ──▶ MinimalV4Router ─┼──▶ V4 pool (LpGuardHook) ──▶ MEME │
└────────────────────────────────────────────────┘The contracts
SingleSidedMemeV4 is the launcher. It creates coins, owns every coin's liquidity position, and executes harvest, expand, reanchor and buybackAndBurn, tracking per-coin backing in backingLtShares. LpGuardHook rides every pool it creates. LTFactory is the owner-gated registry that deploys a NAVOracle and an LTVault per leveraged token and exposes the isLt() gate. NavBatchRelay posts the whole fleet's NAV in one transaction per sweep, and MinimalV4Router is the swap path into the gated pools.
Everything here is immutable once deployed. There's no upgrade proxy on the launcher, no admin function that can move a user's tokens, and no path by which the keeper can withdraw a coin's pool to itself.
The keeper
The keeper is a supervised daemon. Each sweep it reads the fleet, decides what each market needs, and submits the resulting transactions. What makes it scale is one observation: the hedge is O(underlyings), the pools are O(coins).
Many coins can share one underlying's perp market, so the Lighter and NAV side scales with the number of markets — tens — while the pool side scales with the number of coins, potentially hundreds. Those are two different problems, so they're two different services. Hedge coordinators own a group of markets and their own Lighter account exclusively; exclusive ownership of a signer is the invariant that prevents nonce races, which produced the worst bugs found in live testing. Pool workers shard across coins and never touch Lighter — they read the published NAV and manage their pools locally, with no shared critical state.
Isolation
Isolation is the load-bearing property of the design. Each LT has its own vault, oracle and margin, so one wiping out can't freeze or drain another. Each live coin holds its own isolated perp position where slot capacity allows, so its outcome is its own bet rather than a stranger's, and slots are released only on proof that the position is closed and the margin is home. Each market's position is owned by one Lighter sub-account with one signer and one serialized nonce stream.
Why the pools are LP-gated
In live testing on canonical permissionless pools, a sniper LP'd its own position at the active tick — measured at roughly 23× the protocol's liquidity, 100% third-party — and captured the entire revenue path. Buys filled against the parasite's inventory, the price stayed pinned above the protocol's ladder, and the coin's hedge stopped growing. The keeper could detect and starve that, but it could not evict it.
LpGuardHook removes the vector at the root: beforeAddLiquidity reverts for every sender except the launcher, and beforeInitialize is gated the same way so no foreign pool can enroll the hook and wear it as a badge. The protocol is a pool's only possible LP by construction rather than by policy. Swaps carry no hook at all.
The accepted trade-off: these pools live on the protocol's own V4PoolManager, and aggregators and chart sites index the canonical Uniswap deployment. They do not appear on third-party trackers, and the canonicalSwapRouter02cannot reach them. Coins chart through the app and its subgraph instead. Swapping remains permissionless for any V4-aware router.
Fail-safe posture
The system is built to stop rather than to guess. A NAV stale past the bound makes the vault's money path revert and freezes mint/redeem. A keeper offline means no harvest, expand or buyback, while pools keep trading on existing depth. Missing buyback data means no buyback, never a guess. A slot unwind that stalls is marked STUCK, alerted, and kept occupied rather than silently recycled. A redeem exceeding the buffer is queued and settled on margin recall rather than reverted.
Verification
Solidity suites under test/ include full system-integration tests running a real signed oracle → vault → pool → router → harvest → buyback path. A pure Python risk engine with deterministic trajectories and an acceptance suite reproduces the numbers in NAV, decay & funding offline. Live validation runs on Robinhood Chain and Lighter mainnet against real capital are logged in the repository, including the failures that produced the current design.
The perp leg runs on Lighter under a known account and the signed hedge equity is published on-chain per LT, so the backing is auditable against the venue rather than asserted by a dashboard.
Deployed addresses — Robinhood Chain (chainId 4663)
SingleSidedMemeV4 | 0x4B6CB7c3Fd2B0378C121C11265FAf4a7F19F10B5 |
PoolManager (V4) | 0xA999FFb2e9046f11670e7d8C62e0523F46B036bb |
MinimalV4Router | 0xbD6D61f11C7Bf337Bf6cAB1CF8a1A05642518506 |
V4Quoter | 0x3ed514d12679dd627638a6E3921EaD6033bdce88 |
LTFactory | 0xc96c76898d2642a7c57d0f7676acb9409e00504c |
NavBatchRelay | 0x1AB833fFEa5BF661c369fBAb5D55f665AAcDb179 |
| USDG (settlement, 6 dp) | 0x5fc5360d0400a0fd4f2af552add042d716f1d168 |
Uniswap V3 SwapRouter02 (WETH/USDG leg) | 0xcaF681a66D020601342297493863E78c959E5cB2 |
Uniswap V3 QuoterV2 | 0x33e885ed0ec9bf04ecfb19341582aadcb4c8a9e7 |
| Hedge venue | Lighter, account 733718 |
LpGuardHook's address is CREATE2-mined for its permission bits and bound one-shot to the launcher — read it from SingleSidedMemeV4.lpGuard(). Per-LT vault and oracle addresses come from LTFactory.
