Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,038 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Perp Infrastructure (GMX v1 Fork)

CI codecov

Perp-driven basket vaults backed by a shared perpetual liquidity pool, built on a GMX v1 fork.

Architecture

Hub-and-spoke topology: One hub chain runs the full perp stack (VaultAccounting, GMX pool, OracleAdapter, etc.). Spoke chains are deposit-only with StateRelay for routing weights and NAV adjustments; the layout can scale to many spokes as configured in config/chains.json. A keeper service posts state to all chains each epoch.

                    ┌─── Spoke ───────────────────────────────┐
                    │  Investor ──► BasketVault ──► StateRelay │
                    │       │         (deposit-only)           │
                    │  mint shares    RedemptionReceiver ◄─┐   │
                    └─────────────────────────────────────┼───┘
                                                         │ CCIP
┌─── Hub ────────────────────────────────────────────────┼───┐
│  Investor ──► BasketVault ──► VaultAccounting ──► GMX Pool │
│       │           │                │                       │
│  mint shares  StateRelay      position PnL                 │
│  (NAV-priced)                 (tracked per vault)          │
│                                                            │
│  Keeper ──► StateRelay.updateState() (routing + PnL)       │
└────────────────────────────────────────────────────────────┘

Basket Layer (src/vault/)

  • BasketVault -- GLP-style vault: deposit USDC, receive shares priced from vault NAV (including perp PnL)
  • BasketShareToken -- ERC20 shares (6 decimals)
  • BasketFactory -- Deploy new baskets (name + fees), then register assets explicitly

Perp Layer (src/perp/)

  • OracleAdapter -- Unified oracle for equities + commodities (Chainlink + custom relayer)
  • PricingEngine -- Oracle price + deterministic size-based slippage
  • VaultAccounting -- Per-vault capital tracking, PnL attribution, position management
  • FundingRateManager -- Oracle-anchored, imbalance-based funding rates
  • PerpReader -- Read-only aggregator for off-chain monitoring

Coordination Layer (src/coordination/)

  • StateRelay -- Keeper-posted routing weights and per-vault global PnL adjustments; deposit routing guard via getLocalWeight()
  • RedemptionReceiver -- CCIP receiver on spoke chains for keeper-bridged USDC redemption fills
  • PoolReserveRegistry -- TWAP-style pool depth tracking (hub, legacy)
  • CCIPReserveMessenger -- Delta-triggered reserve state sync over Chainlink CCIP (hub, legacy)
  • IntentRouter -- Deposit/redeem intent routing with escrow (hub only)
  • CrossChainIntentBridge, OracleConfigQuorum -- CCIP relay and quorum-based oracle config consensus (hub only)

Keeper Service (services/keeper/)

  • Off-chain Node.js epoch loop: reads all chains, computes inverse-proportional routing weights and per-spoke PnL adjustments, posts StateRelay.updateState() to every chain each epoch

Contracts per chain type

Exact hub/spoke rollout is defined in config/chains.json.

Contract Hub Spoke Notes
BasketFactory Yes Yes (no oracle) Spoke factory passes address(0) for oracle
BasketVault Yes Yes Spoke vaults have vaultAccounting = address(0)
BasketShareToken Yes Yes Created by factory per basket
VaultAccounting Yes No Perp capital tracking, hub only
OracleAdapter Yes No Price feeds, hub only
PricingEngine Yes No Execution quotes, hub only
FundingRateManager Yes No GMX funding, hub only
PriceSync Yes No Oracle→GMX sync, hub only
PerpReader Yes No Read aggregation, hub only
AssetWiring Yes No Asset bootstrap, hub only
GMX fork Yes No Shared liquidity pool, hub only
StateRelay Yes Yes Routing weights + PnL adjustments
RedemptionReceiver No Yes CCIP inbound for redemption fills
PoolReserveRegistry Yes (legacy) No Superseded by StateRelay
USDC (or MockUSDC) Yes Yes Deposit/redemption token

Hub deployments use script/Deploy.s.sol. Spoke deployments use script/DeploySpoke.s.sol (deploys only USDC, BasketFactory, and StateRelay). The scripts/deploy-all.sh script reads config/chains.json and selects the correct script per chain role.

GMX Fork (src/gmx/)

Forked GMX v1 contracts (Solidity 0.6.12) providing the core position engine: Vault, VaultUtils, Router, ShortsTracker, BasePositionManager.

Mainnet Readiness TODO

Smart Contracts

  • Engage audit firm (BasketVault, VaultAccounting, OracleAdapter, GMX integration, PriceSync, FundingRateManager, PricingEngine)
  • Address audit findings and re-verify fixes
  • Write mainnet deploy script (DeployMainnet.s.sol or chain-specific variant)
  • Deploy Gnosis Safe multi-sig as protocol owner
  • Deploy OpenZeppelin TimelockController for admin actions
  • Transfer all module ownership to multi-sig + timelock
  • Migrate oracle from Yahoo Finance relayer to Chainlink / Pyth / RedStone

Legal / Entity

  • Incorporate Foundation entity (Cayman Foundation Company)
  • Formalize Labs company
  • Execute Labs-Foundation services agreement and IP license
  • Draft and publish Terms of Service
  • Draft and publish risk disclosures
  • Implement frontend geo-blocking (U.S. + OFAC-sanctioned jurisdictions)
  • Integrate OFAC / sanctions wallet screening

Infrastructure

  • Production oracle integration (Chainlink / Pyth for all mainnet assets)
  • Monitoring and alerting (oracle staleness, reserve levels, pool utilization, position health)
  • Keeper redundancy (at least 2 independent operators)
  • Incident response runbook
  • Bug bounty program (Immunefi)

Governance

  • Foundation multi-sig (3-of-5 Gnosis Safe) deployed and funded
  • Security council members identified for Stage 1 expansion (4-of-7)
  • Progressive decentralization plan documented (see docs/TECHNICAL_ARCHITECTURE_AND_ROADMAP.md)
  • Governance token design (deferred to post-launch, design begins in Phase 2)

Documentation

Capital Formation

Two parallel raises feeding mainnet readiness. Strategic priorities are tracked in COMPANY.md §Strategic priorities (vc-outreach and lp-seed-liquidity); operational playbooks live in growth/.

VC Fundraise (Seed → Series A) — vc-outreach

Equity / token-warrant round for IndexFlow Labs. Gated on Foundation + Labs incorporation (see §Legal/Entity above). Playbook: growth/VC_OUTREACH_PLAYBOOK.md. Detailed checklist below under Growth › VC Pipeline.

  • Foundation + Labs incorporated (prerequisite — see §Legal/Entity)
  • Trackable deck hosted (Docsend / Notion) and risk-disclosure section reviewed
  • Tier 1 list validated against current portfolio activity (see playbook §Stage 1)
  • First Tier 1 outreach batch sent
  • First monthly investor update sent
  • First term sheet received
  • Round closed

LP Seed Liquidity (perp pool + basket vaults) — lp-seed-liquidity

Product-viability gate, not a growth nice-to-have: without LP capital in the shared perp OI pool, baskets cannot run their long/short hedge legs and the redeemable-NAV guarantee weakens. Playbook: growth/LP_OUTREACH_PLAYBOOK.md. Detailed checklist below under Growth › LP Outreach.

  • Per-LP risk-parameter envelope finalised in docs/PERP_RISK_MATH.md + docs/GLOBAL_POOL_MANAGEMENT_FLOW.md
  • Anchor-LP first-look terms decided (revshare % vs equity warrant vs service-fee credit — pick one primary mechanism)
  • Risk memo hosted (Docsend / Notion) — separate from the VC deck
  • Track A (perp-layer LPs) Tier 1 list of 10–20 MM/desk contacts built
  • Track B (basket-vault depositors) Tier 1 list of 30–50 DAO/treasury contacts built
  • First Tier 1 risk-walkthrough call scheduled
  • First perp-pool USDC deposit live onchain
  • First basket-vault deposit > $100k live onchain
  • Monthly pool-update email cadence established

Building in Public

IndexFlow runs as an Agent Company: every employee — human or AI — has a manifest entry in COMPANY.md, a monthly USD budget cap, and a human-gated approval for any public statement. The contracts are permissionless; the company that operates around them is auditable.

What is public, today, in git:

  • Manifest + governanceCOMPANY.md (schema: agentcompanies/v1) declares active employees, brainstorm slate, board, budgets, sync contract, and four governance.hardConstraints enforced on every heartbeat (no auto-commit, deployment-memory allowlist, public-channel human gate, scope boundary).
  • Trading agent stateagents/memory/<agent>/paperclip-heartbeat.json (per-run thesis, write actions, risk-officer verdicts), state.json (vault binding, fingerprint), and run-log.<network>.jsonl (full turn-by-turn audit trail) for every vault-managing agent. Pushed by the commit-results job in .github/workflows/vault-agent.yml.
  • Per-vault AI Operator panelapps/web/public/agent-metadata/<vault>.json feeds the "AI Activity" card on each /baskets/<vault> page (thesis, plus collapsed-by-default run details including no-action runs, reasoning summaries, tool-call traces, decisions, and tx justifications).
  • Deployment ledgerAGENT_DEPLOYMENT_MEMORY.md is the allowlist for every cloud / on-chain resource an agent may touch. Resources not listed there are read-only.
  • Growth pipeline — date-slotted Season 1 schedule in growth/X_CONTENT_CALENDAR.md, per-partner files in growth/partnerships/, and the basket concepts queue at growth/basket-concepts/queue/.

The public surface is indexflow.app/ops (apps/web/src/app/ops/page.tsx) — a server-rendered mirror that reads every file above and renders an org chart, live heartbeats, governance constraints, budgets, the CMO surface (calendar + partnerships + concepts), and a deployment ledger. The data source is git pull; no extra DB, no hosted control plane.

Permissionless protocol on-chain. Transparent operating company in git. No black boxes.

The local Paperclip dashboard (docs/PAPERCLIP_RUNBOOK.md) is an optional founder-only UI for tickets, budgets, and manual re-runs — not part of the public mirror. See docs/AGENTS_FRAMEWORK.md §Paperclip Integration for the architecture.

Growth

Progress tracker for the IndexFlow growth engine. Strategy, templates, and playbooks live in growth/.

Content Infrastructure

Social Channels

  • X / Twitter account live (@indexflowDAO)
  • Set up Discord server
  • Telegram community live
  • Public Agent Company mirror live at /ops (apps/web/src/app/ops/page.tsx) — server-rendered from COMPANY.md, agents/memory/, growth/, AGENT_DEPLOYMENT_MEMORY.md. Surfaces hard constraints, budgets, content calendar, partnerships, basket concepts.

Content Production

  • First blog post published (cross-chain liquidity routing)
  • Second blog post published (five waves of on-chain exposure)
  • TradFi asset manager blog post published (/blog/if-you-run-money-the-old-way-crypto-question)
  • First X post live (Mon May 25 standalone, @indexflowDAO)
  • First X thread published
  • First LinkedIn post published
  • First Substack issue published
  • First YouTube video published
  • First podcast pitch sent
  • First Farcaster cast published
  • Cross-chain coordination layer content added to content calendar (blog, X threads, LinkedIn, Substack, YouTube)
  • Technical breakdown blog draft: cross-chain coordination layer (growth/drafts/2026-04-15-blog-cross-chain-coordination-layer.md)
  • X thread draft: cross-chain coordination layer (growth/drafts/2026-04-15-thread-cross-chain-coordination.md)
  • Autonomous-AI-agents-managing-vaults blog refreshed for OpenAI-powered agents with git-committed memory and static /agent-metadata/<vault>.json (content/blog/autonomous-ai-agents-managing-vaults.md)
  • Testnet live agents blog draft seeded (growth/drafts/2026-05-26-blog-two-ai-agents-live-on-testnet.md)
  • Testnet live agents blog published (/blog/two-ai-agents-live-on-testnet)
  • Theseus priority teaser draft seeded (growth/drafts/2026-06-11-tweet-theseus-priority-primer.md)

Season 1 Operator Trials (Curators Guild Soft Launch)

Galxe-only Curators Guild soft launch. Full design in growth/GALXE_CAMPAIGN_PLAN.md. Other guilds (Educators, Allocators, Engineers) deferred to Season 2.

  • Galxe space created (Operator Trials) and 4 Curator OATs uploaded (Genesis, Champion, Consistent, Veteran)
  • Galxe REST credential endpoint implemented (apps/web/src/app/api/galxe/credential/route.ts — deploy to Vercel)
  • Curator leaderboard GitHub Actions workflow (.github/workflows/curator-leaderboard.yml — weekly snapshot + commit to apps/web/public/)
  • Curator leaderboard worker scaffolded (services/leaderboard-worker/)
  • Curator weekly USDC pool funded ($200/month = $50/week)
  • Run first snapshot manually via Actions → Curator Leaderboard Snapshot → Run workflow
  • /operators page shows weekly rankings and OAT badges

Partnerships

Active partner relationships are tracked in growth/partnerships/ with YAML-frontmatter per-partner files (counterpart, status, co-marketing confirmation, funding intros, next milestone, co-branded surfaces, guilds touched). The master comparison table in growth/partnerships/README.md lists all partners in one view. The Season 1 partner slots concentrate in Week 2 (Mantle spoke demo) and Week 3 (the confidential-infra trinity: iExec compute, Secret state, Nox signing). Non-chain partners also include Theseus (vault-deploy-gated co-marketing; founders engaged). Chain partnerships (counterparts IndexFlow may deploy a hub or spoke onto — currently Mantle, Avalanche, BNB, Alephium, Sui) are tracked separately under growth/partnerships/chains/ because they have a deployment lifecycle (testnet → mainnet) on top of the usual co-tweet / Galxe / Boost surfaces; the chain-partner rows double as the index into AGENT_DEPLOYMENT_MEMORY.md.

Lead Capture (Layer 2)

  • Testnet gated pilot pathway (email capture at vault creation)
  • Operator waitlist for mainnet early access
  • Lead magnet PDF: "The Asset Manager's Playbook"
  • Lead magnet PDF: "From TradFi Funds to DeFi Vaults"
  • Video Sales Letter (VSL) recorded and hosted

Lead Management (Layer 3)

  • Email nurture platform selected (Customer.io or similar)
  • Welcome email sequence configured
  • Behavioral trigger sequences configured
  • Lead scoring model implemented (Clay / HubSpot)

VC Pipeline

Strategic priority: COMPANY.md §vc-outreach. Playbook: growth/VC_OUTREACH_PLAYBOOK.md.

  • Clay workspace set up with enriched VC list
  • Sending domains configured and warmed (Instantly.ai)
  • LinkedIn automation configured (Expandi / HeyReach)
  • Signal monitoring live (Trigify / Midbound)
  • Trackable deck hosted (Docsend / Notion)
  • First Tier 1 outreach batch sent
  • First monthly investor update sent

LP Outreach

Strategic priority: COMPANY.md §lp-seed-liquidity. Playbook: growth/LP_OUTREACH_PLAYBOOK.md. Two-track audience — perp-layer LPs (market makers) and basket-vault depositors (DAO treasuries + family offices).

  • Minestarters strategic audit + liquidity seed board proposal drafted (growth/MINESTARTERS_INDEXFLOW_AUDIT_LIQUIDITY_PROPOSAL.md)
  • Clay workspace configured with outreach_track: lp_perp | lp_basket tagging (shared with VC pipeline)
  • Track A list build: 10–20 Tier 1 market-maker contacts enriched (Wintermute, GSR, Amber, Selini, Auros, Cumberland, etc.)
  • Track B list build: 30–50 Tier 1 DAO treasury / fintech contacts enriched (via Defillama + Dune)
  • Onchain enrichment pipeline live (idle USDC balances per target wallet)
  • Risk memo hosted (Docsend / Notion) — counterparty-class variant for MM teams + DAOs
  • Live perp-pool stats dashboard ready to embed in outreach (Envio query → public URL)
  • Anchor-LP negotiation envelope documented (deposit caps, funding-rate floor, withdrawal queue, term mechanism)
  • Telegram/Discord outreach tracker (DAO treasuries — separate from LinkedIn rail)
  • First Tier 1 risk-walkthrough call scheduled
  • Monthly pool-update email cadence established
  • First perp-pool USDC deposit live onchain
  • First basket-vault deposit > $100k live onchain

Grants

Tech Stack

  • Solidity -- 0.6.12 (GMX fork) + ^0.8.24 (new contracts)
  • Foundry -- Build, test, deploy
  • OpenZeppelin 5.x -- ERC20, Ownable, ReentrancyGuard
  • Chainlink CCIP -- Cross-chain messaging for coordination layer (StateRelay sync, RedemptionReceiver fills, oracle config quorum)
  • Keeper service -- Node.js/TypeScript epoch loop for routing weights and PnL adjustments (services/keeper/)
  • Hub chain — public testnet (or equivalent) with the full perp stack; see config/chains.json
  • Spoke chains — additional networks, deposit-only with StateRelay; roles and RPC aliases are configured alongside the hub

Setup

# Install dependencies
forge install
npm install

# Formatting and lint checks run in CI (no local git hooks).
# See .github/workflows/test.yml for the full CI pipeline.

# Build
forge build

# Test
forge test -vv

Configuration

Environment templates (all variables documented with comments):

  • Repo root: copy .env.example to .env for Foundry RPC URLs, explorer keys, deploy overrides, agents, and scripts that read the root .env / .env.local.
  • Web app: copy apps/web/.env.example to apps/web/.env.local for NEXT_PUBLIC_* and Playwright/E2E vars.

For Forge scripts and root-level tooling, set RPC URLs and explorer API keys in .env using .env.example as the template; variable names align with foundry.toml [rpc_endpoints] and [etherscan].

Web App Environment

The Next.js web app reads apps/web/.env.local (or shell). Required and optional variables:

Variable Required Description
NEXT_PUBLIC_PRIVY_APP_ID Yes Privy app ID from dashboard.privy.io
NEXT_PUBLIC_ENVIO_URL Yes (for indexer-backed views) Envio HyperIndex GraphQL (Hasura) endpoint serving all chains, e.g. http://127.0.0.1:8080/v1/graphql locally or the deployed Envio Cloud URL. When unset, indexer-backed views fall back to RPC reads.
NEXT_PUBLIC_PUSH_SERVICE_URL No Cloud Run push-worker base URL used by /settings for preferences/subscription APIs
NEXT_PUBLIC_E2E_TEST_MODE No Set to 1 for deterministic E2E mock wallet

Push Worker Environment (apps/push-worker)

The push worker service (Cloud Run) requires:

Variable Required Description
VAPID_PUBLIC_KEY Yes Web Push VAPID public key (base64url)
VAPID_PRIVATE_KEY Yes Web Push VAPID private key (base64url)
VAPID_CONTACT_EMAIL Yes Contact identity passed to push services (for example mailto:ops@indexflow.app)
ENVIO_URL Yes Envio HyperIndex GraphQL endpoint for dispatch signal scans (Hasura).
DISPATCH_AUTH_TOKEN Yes Bearer token required by POST /v1/push/dispatch
OPEN_INTEREST_NEAR_CAP_BPS No Threshold for open-interest alerting (default 9000)
ORACLE_STALE_THRESHOLD_SECONDS No Oracle staleness threshold in seconds (default 2700)
LARGE_PNL_THRESHOLD_USD No Realized PnL threshold for large-PnL alerts (default 5000)
RESERVE_BREACH_COOLDOWN_MS No Cooldown window for reserve-breach repeat alerts (default 1800000)
PORT No HTTP listen port (default 8080)

Deployment

Hub vs spoke: Hub chains deploy the full perp stack via Deploy.s.sol. Spoke chains deploy deposit-only infrastructure via DeploySpoke.s.sol. The deploy-all.sh script reads config/chains.json and selects the correct script per chain role.

Deploy scripts pull a live Yahoo Finance quote for BHP.AX (8-decimal USD raw) via Node (scripts/fetch-yf-asset-price.js and Foundry ffi). The script writes cache/yf-seed-price.txt (gitignored); Solidity reads it with vm.readFile so the seed is not passed through ffi stdout (which can mis-decode decimal ASCII). Node must be on PATH, and the machine needs outbound network access unless you pin a seed.

  • Offline / no Yahoo: set SEED_PRICE_RAW to the 8-decimal raw integer (e.g. 4500000000 for $45.00) so deploy skips FFI.
# Deploy all chains (reads config/chains.json, picks Deploy.s.sol or DeploySpoke.s.sol per role)
./scripts/deploy-all.sh

# Deploy a single chain (<key> is the network id in config/chains.json)
./scripts/deploy-all.sh --chain <key>

# Local (Anvil, hub role)
npm run deploy:local

# Hub public testnet (writes apps/web/src/config/<target>-deployment.json for the hub key)
CHAIN=<hubKey> forge script script/Deploy.s.sol:Deploy --rpc-url <rpcAlias> --broadcast -vvv

# Additional deploy:* shortcuts (per configured network) live in package.json

<hubKey> must match the chain field for the hub entry in config/chains.json. <rpcAlias> must match an endpoint name in foundry.toml [rpc_endpoints] (the same alias you pass to forge script --rpc-url).

Local Development (Docker Compose)

Docker Compose runs the local chain (Anvil). Contracts deploy from the host, the Envio HyperIndex indexer runs on the host, and the UI runs on the host -- everything outside of Docker for native hot reload.

Prerequisites

  • Docker / Docker Compose
  • Node.js
  • Foundry (forge, cast) on PATH

Quick start

# 1. Start Anvil + deploy contracts (writes local-deployment.json)
npm run local:up

# 2. Start the Envio HyperIndex indexer (separate terminal)
npm run --prefix apps/envio dev:local

# 3. Start the UI dev server (separate terminal, hot reloads on file changes)
NEXT_PUBLIC_ENVIO_URL=http://127.0.0.1:8080/v1/graphql npm run local:dev

Open http://localhost:3000, log in via Privy (or connect MetaMask), and switch the deployment target to Anvil.

Redeploying after code changes

After changing Solidity contracts:

npm run redeploy:local

This re-deploys contracts to the running Anvil and updates apps/web/src/config/local-deployment.json. The Next.js dev server picks up new contract addresses via HMR -- no restart needed. If the Envio indexer is running, restart it so it picks up the new contract addresses from apps/envio/config.local.generated.yaml.

Other commands

# Stream Docker service logs (Anvil)
npm run local:logs

# Stop Anvil and wipe its volumes
npm run local:down

Service endpoints

Service URL
Anvil RPC http://127.0.0.1:8545
Envio GraphQL (Hasura) http://127.0.0.1:8080/v1/graphql
Envio playground http://127.0.0.1:8080
Web UI http://127.0.0.1:3000

How it fits together

  • docker-compose.local.yml runs Anvil only.
  • scripts/local/redeploy.sh deploys contracts from the host to Docker Anvil over localhost.
  • apps/envio runs the indexer on the host (managing its own Postgres + Hasura) via npm run --prefix apps/envio dev:local.
  • The UI runs on the host via npm run local:dev; pass NEXT_PUBLIC_ENVIO_URL so the app reads from the local Hasura endpoint.
  • apps/web/src/config/local-deployment.json is written by the deploy script and imported by the Next.js app at build/dev time. File changes trigger HMR.

Web app runtime contract wiring

  • Deployment target persists in localStorage and follows the network selector.
  • For each deployment target key, the app loads apps/web/src/config/<target>-deployment.json when that target is selected (see deploy script outputs under apps/web/src/config/).
  • apps/web/src/config/local-deployment.json is used when target is anvil.
  • Authentication uses Privy (email, Google, or external wallets like MetaMask). Set NEXT_PUBLIC_PRIVY_APP_ID from dashboard.privy.io.
  • The app is installable as a PWA (/manifest.webmanifest, public/sw.js). Notification preferences are managed in Settings (/settings).
  • iOS install note: use Safari → Share → Add to Home Screen. iOS Web Push requires Home Screen install.
  • For local Anvil testing, connect MetaMask through Privy with the pre-funded Anvil account (0xf39Fd6...).
  • In E2E mode (NEXT_PUBLIC_E2E_TEST_MODE=1), deployment target is locked to anvil and the deterministic mock wallet connector remains enabled for CI-stable signing.
  • When a wallet is connected on the wrong network, the app auto-requests a switch to the selected deployment chain.

Indexer Ops (Envio HyperIndex)

The Envio HyperIndex indexer lives at apps/envio and is the single indexer for every chain. It indexes BasketFactory, BasketVault (dynamically registered), VaultAccounting, OracleAdapter, and StateRelay across Sepolia, Fuji, and Anvil (locally) into one Hasura GraphQL endpoint.

# install + codegen
npm install --prefix apps/envio
npm run --prefix apps/envio codegen

# run against the multichain config (Sepolia + Fuji)
npm run --prefix apps/envio dev

# run against the local dual-Anvil generated config
npm run --prefix apps/envio dev:local

Deploying

Production indexing runs on Envio Cloud (or a self-hosted Envio). See apps/envio/README.md for the current deploy flow.

Set NEXT_PUBLIC_ENVIO_URL in Vercel (or apps/web/.env.local) to the Hasura endpoint -- the same URL is used for every deployment target because Envio is multichain.

Set ENVIO_URL on the push-worker (Cloud Run) to the same endpoint.

Runtime note:

  • The web app and push-worker both read from one Envio endpoint. When NEXT_PUBLIC_ENVIO_URL is unset, indexer-backed UI views fall back to RPC data paths; the push-worker /v1/push/dispatch endpoint returns 500 until ENVIO_URL is configured.
  • The "All Chains" view aggregates data from all chains the indexer covers, served by the same endpoint.
  • If "All Chains" shows no indexed baskets while baskets exist onchain (for example on Mantle Sepolia), verify the active Envio deployment has that network enabled with correct addresses/start blocks and required RPC env vars.

Operations

The GMX vault reads prices from SimplePriceFeed, not from OracleAdapter directly. After deploy, wire PriceSync as a keeper on SimplePriceFeed (setKeeper(address(priceSync), true)) and add PriceSync mappings (addMapping(assetId, gmxToken)) for each asset the pool trades.

Keeping perp prices aligned with the oracle

  • Chainlink-backed assetsOracleAdapter.getPrice reads the feed when called. Push that value into the vault feed by calling PriceSync.syncAll() or PriceSync.syncPrices(assetIds) on whatever cadence you need (anyone can send these txs).
  • Custom relayer assets — A keeper must call OracleAdapter.submitPrice / submitPrices first (requires setKeeper on the adapter), then run PriceSync.sync* as above.

Basket configuration still validates asset ids through OracleAdapter, but share mint/redeem pricing is NAV-based and perp-driven. The perp path only updates GMX on-chain feed storage when PriceSync runs.

For basket/perp operator responsibilities (capital allocation, position management controls, and investor liquidity implications), see docs/ASSET_MANAGER_FLOW.md.

Perp leverage risk

  • Effective leverage is approximately size / collateral for each opened leg.
  • Example: size = 10,000 and collateral = 2,000 is about 5x, so an approximately 10% favorable/adverse move is about +/-50% on collateral before fees/funding and execution effects.
  • For full mechanics and operator caveats, see docs/SHARE_PRICE_AND_OPERATIONS.md and docs/ASSET_MANAGER_FLOW.md.

Funding — Keepers authorized on FundingRateManager call updateFundingRate so the GMX vault’s funding parameters stay in line with your policy (often on a schedule tied to fundingInterval).

Automation (e.g. cron, Gelato, Chainlink Automation) is optional: it only replaces manually sending the same transactions.

Cross-chain keeper service

The keeper service (services/keeper/) is required for hub-and-spoke operation:

# Start the keeper (reads all chains from config/chains.json)
# Set PRIVATE_KEY and the RPC env vars from .env.example for every network the keeper touches.
PRIVATE_KEY=0x... npm run keeper:start

# Configure epoch interval (default 60s)
EPOCH_INTERVAL_MS=30000 npm run keeper:start

Each epoch the keeper:

  1. Reads vault reserves and hub PnL across all deployed chains.
  2. Computes routing weights (inverse-proportional to idle USDC per chain).
  3. Computes per-vault global PnL adjustments (hub PnL distributed pro-rata).
  4. Posts StateRelay.updateState() to every chain.

The keeper also monitors pending redemptions on spoke chains and bridges USDC from the hub via CCIP to fill them through RedemptionReceiver.

Reserve liquidity controls

  • Basket owners can set a reserve target via setMinReserveBps to keep idle USDC available for redemptions.
  • allocateToPerp is reserve-aware and only allows allocations up to getAvailableForPerpUsdc().
  • Anyone can add non-dilutive reserve cash via topUpReserve(amount) (USDC transfer, no share mint).

GMX bufferAmounts policy (this repo)

  • bufferAmounts remains in the fork for compatibility.
  • This integration treats it as mostly unused and expects values to remain 0 unless you intentionally adopt swap-buffer constraints.
  • Local deploy now seeds a USDC buffer (200,000 USDC) in DeployLocal.s.sol to keep explicit swap headroom during testing.
  • Web admin exposes global pool controls in Admin → Pool:
    • setBufferAmount (gov-only, per whitelisted token)
    • direct pool funding via token transfer(gmxVault, amount) then directPoolDeposit(token) (per whitelisted token)

Run one-shot sync for all supported assets (local deployment config)

forge script script/SyncAllOraclePrices.s.sol:SyncAllOraclePrices --rpc-url local --broadcast

Hub deployment sync helpers — use the sync:* and submit-sync:* scripts in package.json; each sets DEPLOYMENT_CONFIG to the matching apps/web/src/config/<target>-deployment.json and --rpc-url for that target.

Default oracle profile (greenfield DeployLocal / hub testnet deploy)

  • Only BHP.AX is registered, as FeedType.CustomRelayer (stalenessThreshold=86400, deviationBps=2000), for the Yahoo Finance relayer path.
  • Add more symbols (including FeedType.Chainlink feeds on your hub network) via Admin → Assets or a customized deploy script; see docs/ORACLE_SUPPORTED_ASSETS.md.

Yahoo Finance price relayer (config-free, on-chain driven)

scripts/update-yahoo-finance-prices.js enumerates all active CustomRelayer assets from the OracleAdapter contract on-chain, reads their stored assetSymbols, fetches Yahoo Finance quotes, converts non-USD currencies via FX rates, and submits 8-decimal USD prices to submitPrices + syncAll. No local config file is needed.

Public testnets (hub / spoke)

Use the matching update-prices:* and update-prices:*:dry scripts in package.json; each wires DEPLOYMENT_CONFIG and RPC_URL for its target.

Local Anvil

npm run update-prices:local:dry
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 npm run update-prices:local

Config/env overrides: DEPLOYMENT_CONFIG, RPC_URL.

GitHub automation: .github/workflows/update-prices.yml runs every 15 minutes and serializes overlapping runs per network using Actions concurrency (queue policy, no in-progress cancellation).

Registering new assets via admin UI

The admin assets page (/admin/oracle) includes a Yahoo Finance search that lets operators discover any publicly-traded equity and register it on-chain as a CustomRelayer asset with an initial price seed. Ambiguous unsuffixed equities (for example BHP) are rejected and must be registered with an explicit exchange suffix (for example BHP.AX). Unique unsuffixed equities (for example AAPL) and non-equity symbols remain valid. Registered assets automatically appear in basket asset pickers.

Multi-Agent Framework

Agents are defined as markdown files in agents/ -- each file is a system prompt + YAML config specifying which MCP servers to use. No JavaScript required to create a new agent. Seven trading agents ship today and run in a CI round-robin against the Mantle Sepolia hub (one agent per hourly tick, indexed by HOUR_UTC % 7):

agents/vault-manager.md is retired from the CI matrix and remains available for local runs only (node scripts/agent-runner.mjs vault-manager).

All three use OpenAI (or any OpenAI-compatible chat-completions endpoint) for inference and sign transactions directly with PRIVATE_KEY. For deterministic behavior, agents can also define policy frontmatter (for example autoAllocateTargetBps, entryMode, entryMomentumPctMin, entryVolumeMin, entryMlScoreMin, entryQualityScoreMin, entryDirection, maxNewPositionsPerRun, rebalanceMode).

Atlas-backed agents read ATLAS_API_URL and ATLAS_API_KEY through atlas-ml-mcp / atlas-quality-mcp. Both MCPs support the same auth overrides: ATLAS_AUTH_MODE=basic with ATLAS_BASIC_AUTH or ATLAS_USERNAME / ATLAS_PASSWORD for nginx-protected Atlas deployments (with https://atlas.minestarters.com defaulting to a built-in Basic auth fallback), plus ATLAS_AUTH_MODE=header with ATLAS_AUTH_HEADER_NAME / ATLAS_AUTH_HEADER_VALUE for custom gateways. The mining manager can inspect historical ML runs and horizon experiments through the Atlas ML MCP; horizon evaluation is intentionally explicit/operator-driven because it can be expensive.

# Install MCP server deps (one-time)
npm --prefix apps/mcps/vault-manager install
npm --prefix apps/mcps/yfinance install
npm --prefix apps/mcps/atlas-ml install

# Uses repo-root .env / .env.local if present (see Configuration above)

# Run the vault manager agent (shortcut)
npm run agent:vault

# Dry-run mode (skips all on-chain writes)
npm run agent:vault:dry

# Run any agent by name
npm run agent:run -- vault-manager
npm run agent:run -- mining-manager
npm run agent:run -- quality-matrix-manager

# Write confirmations are ON by default (interactive TTY prompts before on-chain writes)
LLM_API_KEY=sk-... PRIVATE_KEY=0x... npm run agent:run -- vault-manager

# Non-interactive auto-execute override (off by default)
AGENT_NON_INTERACTIVE_WRITE_EXECUTE=1 LLM_API_KEY=sk-... PRIVATE_KEY=0x... npm run agent:run -- vault-manager

A GitHub Actions cron (.github/workflows/vault-agent.yml) fires hourly at minute :18 and picks one trading agent per tick via HOUR_UTC % 7 (each agent therefore runs every seven hours, ~3.4×/day). A workflow_dispatch event accepts any single agent slug for ad-hoc runs plus a dry_run toggle. A follow-up commit-results job in the same workflow pushes the updated agents/memory/ + apps/web/public/agent-metadata/ files back to the default branch under the vault-agent[bot] identity, so the next scheduled run starts from the prior state. See docs/AGENTS_FRAMEWORK.md for the full guide (creating agents, MCP tool reference, vault lifecycle, memory) and the slot-by-slot rotation table.

After run logs are committed, the self-improver issues channel scans hard errors[] entries; fresh runtime failures such as ATLAS_HTTP_ERROR become dedupe-friendly agent-finding investigations before broader speculative ideas.

Agent run history is network-scoped to avoid cross-network context bleed: each agent writes/reads agents/memory/<agent>/run-log.<network>.jsonl. Override with AGENT_NETWORK if needed. Dry runs (AGENT_DRY_RUN=1) do not update run logs.

Agent memory is deployment-aware: the runner fingerprints the active deployment context (network key + DEPLOYMENT_CONFIG content + RPC_URL). When that fingerprint changes (for example after redeploying contracts), it automatically invalidates stale memory for that network by rotating state.json and run-log.<network>.jsonl into agents/memory/<agent>/archive/, then starts from a fresh vault context.

Editing an agent markdown file does not, by itself, force a new vault. The runner updates the stored agent file hash for bookkeeping, but if the remembered vault address is still present and the deployment fingerprint is unchanged, subsequent runs keep managing the same vault.

Paperclip operator dashboard (optional, narrow scope). This repo is the canonical source of truth for the IndexFlow agent fleet. COMPANY.md (schema agentcompanies/v1, name: IndexFlow, scope: meta_and_growth_agents) declares the IndexFlow company identity, the engineering meta-agents Paperclip manages today (issue-implementer, self-improver-issues, plus their two prompt-only risk officers), and a brainstorm slate of growth/ops agents (content-publisher, partnership-tracker, broadcast-bot, docs-syncer, basket-ideator) that activate once their agents/<id>.md prompt files are authored. Trading agents (the seven vault-agent.yml rotation slugs plus their risk-officer) and the Minestarters vault family stay repo-managed via this very vault-agent.yml CI flow — Paperclip does not schedule or budget them. The boundary holds even for new vaults: basket-ideator proposes themes (growth/basket-concepts/queue/); the repo-managed trading-agent flow deploys them. A self-hosted Paperclip install plus the paperclip-agent-companies-plugin discovers and daily-auto-syncs COMPANY.md, schedules active employees via a shell adapter that invokes npm run agent:run -- <agent>, enforces per-employee monthly budgets, and surfaces tickets / approvals from a web UI. The runner writes agents/memory/<agent>/paperclip-heartbeat.json (schema paperclip.heartbeat/v1) on every run; the existing commit-results job in .github/workflows/vault-agent.yml pushes it back to main automatically. See docs/AGENTS_FRAMEWORK.md §Paperclip Integration for the architecture diagram and setup runbook.

Agent Infrastructure

The agent framework uses OpenAI (or any OpenAI-compatible chat-completions endpoint) for inference, signs transactions directly with the keeper PRIVATE_KEY via cast send, and persists state to the git repository so every run is auditable from git log.

Architecture:

┌─────────────────────────────────────────────────────────────────────────┐
│                        Agent Runner (agent-runner.mjs)                   │
│                                                                         │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────────────┐ │
│  │ OpenAI          │  │ MCP Servers     │  │ Memory                  │ │
│  │ (LLM Inference) │  │                 │  │                         │ │
│  │                 │  │ vault-manager   │  │ agents/memory/<agent>/  │ │
│  │ gpt-4o (default)│  │ yfinance        │  │ + per-network run-log   │ │
│  │ via LLM_API_KEY │  │                 │  │ (committed to git by CI)│ │
│  └────────┬────────┘  └────────┬────────┘  └─────────────────────────┘ │
│           │                    │                                        │
│           ▼                    ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                  Transaction Execution                          │   │
│  │  cast send --private-key $PRIVATE_KEY --rpc-url $RPC_URL ...    │   │
│  └─────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────┘

Required environment variables:

LLM_API_KEY=sk-...                  # OpenAI (or compatible) API key
PRIVATE_KEY=0x...                   # Keeper wallet that signs vault writes
RPC_URL=sepolia                     # RPC alias or full URL
DEPLOYMENT_CONFIG=apps/web/src/config/sepolia-deployment.json

# Optional:
LLM_BASE_URL=https://api.openai.com/v1
LLM_MODEL=gpt-4o

Documentation

  • Pitch deck (Google Slides) — investor and partner overview.
  • /primer — visual long-scroll explainer page distilling the whitepaper and pitch deck into animated sections with inline SVG diagrams.
  • In-app wiki (web app):
    • /docs — searchable index sourced directly from repository markdown under docs/*.md.
    • Canonical routes:
      • /docs/readme
      • /docs/technical-architecture-roadmap
      • /docs/investor-flow
      • /docs/asset-manager-flow
      • /docs/perp-risk-math
      • /docs/operator-interactions
      • /docs/price-feed-flow
      • /docs/oracle-supported-assets
      • /docs/global-pool-management-flow
      • /docs/deployments
      • /docs/e2e-testing
      • /docs/share-price-and-operations
      • /docs/pwa-push-notifications
      • /docs/regulatory-roadmap-draft
    • Legacy wiki slugs remain supported as compatibility aliases and redirect to canonical routes.
    • AI docs assistant: a floating chat widget on /docs pages lets users ask questions about the protocol. Powered by gpt-4o-mini, it ingests all docs and blog posts as context. Requires LLM_API_KEY in apps/web/.env.local.
  • Operator monitoring surfaces (web app):
    • /prices — live oracle status and current per-asset prices, with dynamic source badges (Chainlink or Custom Oracle).
    • /prices/[assetId] — per-asset historical PriceUpdated timeline + chart with 24H/7D/30D windows.
  • MODIFICATIONS.md — Detailed changes vs upstream GMX.
  • docs/TECHNICAL_ARCHITECTURE_AND_ROADMAP.md — Canonical IndexFlow technical architecture and roadmap document for basket-vault, shared-perp, oracle, monitoring, governance, and tokenomics design.
  • docs/INVESTOR_FLOW.md — Basket share holder journey, mint/redeem vs NAV, perp allocation, and what investors do not control.
  • docs/ASSET_MANAGER_FLOW.md — Basket/perp manager flow: setup, capital allocation, positions, risk controls, and implementation caveats.
  • docs/PERP_RISK_MATH.md — Leverage formulas, unit conventions, and liquidation caveats for operator sizing decisions.
  • docs/OPERATOR_INTERACTIONS.md — Per-contract interaction matrix with inputs, checks, state deltas, and post-tx verification steps.
  • docs/GLOBAL_POOL_MANAGEMENT_FLOW.md — Global GMX pool operations in Admin → Pool: buffer management and direct pool funding flow.
  • docs/PRICE_FEED_FLOW.md — OracleAdapter → PriceSync → SimplePriceFeed lifecycle, GMX vault reads, and admin wiring (Mermaid sequence diagrams).
  • docs/ORACLE_SUPPORTED_ASSETS.md — Asset registry for the current public testnet deployment: each supported symbol and its oracle source (Chainlink feed or Yahoo Finance relayer).
  • docs/DEPLOYMENTS.md — Deployment registry for live contracts, Subgraph indexing, and Google Cloud push-worker infrastructure (push notifications only).
  • docs/E2E_TESTING.md — Playwright + Anvil E2E runbook, CI wiring, and lifecycle scope.
  • docs/PWA_PUSH_NOTIFICATIONS.md — PWA install behavior, push worker architecture, notification categories, and staging verification runbook.
  • docs/REGULATORY_ROADMAP_DRAFT.md — Permissionless protocol launch pathway, foundation structure, progressive decentralization, and compliance requirements (draft).
  • docs/README.md — Maintainer-facing map of canonical /docs/* routes and legacy alias redirects.
  • Basket trade flows in the web app include icon-based Deposit/Redeem tabs, a stable quote area, and inline transaction feedback so users can verify what will happen before they submit.

E2E Tests

# Start an Anvil node
anvil --host 127.0.0.1 --port 8545

# Deploy local contracts to the running node
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 npm run deploy:local

# Run Playwright suite in deterministic E2E mode
NEXT_PUBLIC_E2E_TEST_MODE=1 E2E_RPC_URL=http://127.0.0.1:8545 npm run test:e2e:ci

For a local report, run forge coverage (use --ir-minimum if the compiler reports stack-too-deep). CI uploads Foundry LCOV to Codecov for the badge above, with Codecov project status scoped to Solidity paths (**/*.sol) and upload search disabled so only lcov.info is processed. The upload step is best-effort (non-blocking) and retried once on transient failure so Codecov outages do not fail overall CI. During Codecov incidents, the badge can remain stale until a later successful upload. CI also pins foundry-rs/foundry-toolchain to Foundry v1.5.1 (instead of floating stable) to keep forge/cast/anvil/chisel installs deterministic across runs. Local-anvil broadcast steps (deploy:local and friends) rely on the explicit [etherscan].local = { chain = 31337, url = ... } entry in foundry.toml so Foundry's Etherscan trace identifier doesn't bail with "No known Etherscan API URL for chain anvil-hardhat" (foundry-rs/foundry#11351); no placeholder explorer API key env vars are needed in CI.

About

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages