Skip to content

Odushhh/vault-flow

Repository files navigation

VaultFlow — Agentic Vaults for European SMEs

No-code treasury automation on Solana. Connect a wallet, deposit EURC, and an AI agent continuously allocates idle capital across the highest-yield DeFi protocols — automatically, on-chain, and MiCA-compliant.

Built for the Colosseum Frontier 2026 hackathon (April 6 – May 11, 2026).

Program ID (devnet): Fvs33of5snzzjFjgyY6id1RQ7sqgxX8WDvU2FMECaVqy


What It Does

European SMEs hold an estimated $3.2 trillion in idle working capital that earns zero yield. VaultFlow lets a finance team create a treasury vault in minutes — no DeFi knowledge required:

  1. Connect a Phantom wallet
  2. Deposit EURC (Circle's MiCA-compliant euro stablecoin)
  3. AI agent monitors live APY across Kamino, Drift, and Raydium, rebalancing automatically when yields shift by more than 200 bps
  4. Payroll runs on a configurable schedule — recipients are paid automatically when the interval elapses
  5. Off-ramp back to a SEPA bank account via Transak's fiat widget

The Moat

Each individual component has competitors. The intersection does not:

Layer What VaultFlow built Why it matters
EU SME focus EURC-native vaults, Transak SEPA on/off-ramp 58% of EU institutions integrating stablecoins by 2026; USDT/EURT are delisted post-MiCA
AI-agentic reallocation On-chain agent authorization, live APY oracle, bps-threshold rebalancing Removes the DeFi knowledge barrier for SME finance teams
MiCA-compliant fiat rails Transak widget — SEPA → EURC on-ramp and EURC → SEPA off-ramp No KYB/KYC integration required; Transak handles regulatory compliance

Repository Structure

vault_flow/
├── programs/vault/          # Anchor smart contract (Rust)
│   └── src/
│       ├── instructions/    # 7 program instructions
│       ├── state/           # VaultAccount + PayrollSchedule PDAs
│       ├── protocols/       # Kamino / Drift / Raydium CPI stubs
│       ├── errors.rs
│       └── lib.rs
├── agents/                  # AI agent engine (TypeScript)
│   └── src/
│       ├── yield-oracle.ts  # Live APY fetcher (Kamino, Drift, Raydium)
│       ├── allocation-engine.ts
│       ├── vault-agent.ts   # Poll loop + on-chain reallocate tx
│       ├── config.ts
│       ├── logger.ts
│       ├── retry.ts
│       ├── health.ts
│       └── main.ts
├── app/                     # Next.js 16 frontend (App Router, Tailwind v4)
│   ├── app/                 # Routes: /, /create, /positions, /payroll, /fiat, /report, /settings
│   ├── components/          # Vault dashboard, allocation sliders, payroll panel, fiat widgets
│   ├── hooks/               # useVault, usePayroll, useYieldRates, useEurRate
│   └── lib/                 # Anchor setup, constants, demo helpers
├── tests/
│   └── vault.ts             # 13 Anchor integration tests (Mocha)
├── scripts/
│   ├── smoke-devnet.ts      # End-to-end devnet smoke test (6 steps)
│   └── set-upgrade-authority.sh
├── Anchor.toml
├── Cargo.toml
├── package.json             # npm workspaces root
└── SUBMISSION.md

Smart Contract

Instructions

Instruction Who can call Description
initialize_vault Owner Creates VaultAccount PDA ([b"vault", owner, mint]); validates allocation weights sum to 10,000 bps
deposit Owner SPL token transfer from owner into vault ATA; checked_add accounting
withdraw Owner PDA-signed transfer back to owner
reallocate Agent only Sets reentrancy guard (is_locked), computes allocation deltas, calls protocol CPIs (mainnet feature flag), updates tracking fields
schedule_payroll Owner Creates/updates PayrollSchedule PDA ([b"payroll", vault]) with recipients and interval
execute_payroll Anyone (permissionless once due) PDA-signed SPL transfers to each recipient; advances next_execution
pause_vault / resume_vault Owner Circuit breaker; withdrawals always remain available regardless of pause state

State Accounts

VaultAccount (185 bytes) — owner, mint, token_account, agent, allocation weights (Kamino/Drift/Raydium bps), deposited_amount, yield_earned, kamino_deployed, drift_deployed, raydium_deployed, is_locked, is_active, bump

PayrollSchedule — vault, next_execution (Unix timestamp), interval_seconds, recipients (Vec, max 50), bump

Protocol CPI Layer

CPIs to Kamino, Drift, and Raydium are gated behind --features mainnet-protocols. On localnet, reallocate only updates weights and tracking fields — all 13 integration tests pass without any external protocol programs deployed.

Protocol Program ID Notes
Kamino KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD deposit / withdraw via invoke_signed; discriminators verified against live IDL
Drift dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH EURC spot market index 54; driftSigner account required for withdraw
Raydium CLMM CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK increase_liquidity_v2 / decrease_liquidity_v2 (Token-2022 / EURC compatible)

Security Design

  • Reentrancy guardis_locked is set before any CPI and explicitly cleared on every error path; a failing CPI can never permanently lock a vault
  • Agent authorization — only the agent pubkey stored in VaultAccount can call reallocate; the owner cannot override this
  • Overflow protectiondeposited_amount uses checked_add; payroll total uses try_fold + checked_add; all delta math uses saturating_*
  • ATA validationexecute_payroll reads raw SPL token account bytes (mint @[0..32], owner @[32..64]) rather than trusting account labels — recipients cannot be spoofed
  • Eventsemit!() macros on all state-changing instructions (VaultDeposited, VaultWithdrawn, VaultReallocated, PayrollExecuted) for indexer / analytics

AI Agent Engine

How It Works

every 60 seconds (configurable):
  1. fetchRates()       — live APY from Kamino strategies API, Drift spot-markets API,
                          Raydium CLMM pools API (5-min TTL cache; stale fallback on failure)
  2. computeAllocation()— proportional APY weighting; minReserveBps liquidity floor always kept liquid
  3. fetchVaultState()  — read current on-chain allocation via Anchor
  4. if any field drifts > REALLOC_THRESHOLD_BPS (default 200):
       send reallocate tx

Configuration

Copy agents/.env.example to agents/.env and fill in:

# Required
AGENT_KEYPAIR_PATH=~/.config/solana/agent.json   # must match VaultAccount.agent pubkey
VAULT_ADDRESSES=<vault-pda-1>,<vault-pda-2>

# Optional (defaults shown)
RPC_ENDPOINT=https://api.devnet.solana.com
TICK_INTERVAL_MS=60000
REALLOC_THRESHOLD_BPS=200
MIN_RESERVE_BPS=1000
DRIFT_EURC_MARKET_INDEX=54
LOG_LEVEL=info
HEALTHZ_PORT=8080

# Dead-man's-switch alerting via ntfy.sh (free, no account needed)
NTFY_TOPIC=vaultflow-agent-abc123

Observability

  • Structured JSON logging to stdout/stderr (configurable level)
  • /healthz HTTP endpoint for external monitoring
  • ntfy.sh push alerts if no successful reallocation in 4+ hours
  • Exponential backoff with full jitter on all RPC and API failures

Frontend

Next.js 16 (App Router, TypeScript, Tailwind v4, shadcn/ui).

Route Description
/ Vault dashboard: balance, yield earned, protocol allocation bar, deposit/withdraw sidebar
/create No-code vault creation: token selector, live allocation sliders (sum validated to 100%), agent pubkey input
/positions All vault positions
/payroll View, schedule, and execute payroll; recipient list editor
/fiat SEPA on-ramp (buy EURC) and off-ramp (sell EURC → EUR wire) via Transak widget
/report Yield and reallocation history
/settings Vault and agent configuration
/onboarding Guided wallet connect → first deposit flow

Demo mode (NEXT_PUBLIC_DEMO_MODE=true) shows simulated APY data on devnet so the UI is always demonstrable without real on-chain state.

Frontend Configuration

Copy app/.env.example to app/.env:

NEXT_PUBLIC_RPC_ENDPOINT=https://api.devnet.solana.com
NEXT_PUBLIC_DEMO_MODE=true

# Transak fiat widget (free sandbox — no approval needed)
NEXT_PUBLIC_TRANSAK_API_KEY=
NEXT_PUBLIC_TRANSAK_ENV=STAGING

Test Coverage

Suite Tests Status
Smart contract — Anchor/Mocha (tests/vault.ts) 13 Passing
Agent engine — Jest (agents/src/__tests__/) 31 Passing
Devnet smoke test (scripts/smoke-devnet.ts) 6 steps Passing

Smart contract tests cover: initialize vault, deposit, withdraw, reallocate, agent auth rejection, allocation overflow, schedule payroll, execute payroll (valid + early + wrong recipient count + insufficient funds)

Agent unit tests cover: AllocationEngine (11), YieldOracle (6), VaultAgent (5), retry (6), integration (3)

Devnet smoke test golden path:

initialize vault → deposit 10,000 tokens → reallocate allocation →
schedule payroll → execute payroll (recipient receives 500 tokens) → withdraw 3,000 tokens

Getting Started

Prerequisites

# Add Solana to PATH (add to ~/.zshrc for persistence)
export PATH="/Users/$USER/.local/share/solana/install/active_release/bin:$PATH"

# Verify setup
solana config get
solana config set --url devnet
solana airdrop 2   # fund devnet wallet

Install

git clone https://github.com/<your-handle>/vault_flow
cd vault_flow
npm install   # installs all workspace deps (root + app + agents)

Smart Contract

anchor build                              # compile + generate IDL
anchor test                               # build + localnet + 13 tests
anchor deploy --provider.cluster devnet   # deploy (already deployed — see Program ID above)

# Build with real protocol CPIs (devnet/mainnet only)
anchor build -- --features mainnet-protocols

AI Agent

cp agents/.env.example agents/.env
# Edit: AGENT_KEYPAIR_PATH, VAULT_ADDRESSES, RPC_ENDPOINT

npm run agent:start       # start agent engine
# or for development:
cd agents && npm run dev  # ts-node-dev with hot reload

Frontend

cp app/.env.example app/.env
npm run app:dev           # Next.js dev server at http://localhost:3000
npm run app:build         # production build

Devnet Smoke Test

npm run smoke:devnet
# Runs: initialize → deposit → reallocate → schedule payroll → execute payroll → withdraw

Architecture Decisions

Why EURC over USDC/USDT? USDT and EURT are both delisted from EU exchanges post-MiCA enforcement. EURC is Circle's MiCA Electronic Money Institution-licensed euro stablecoin, valid across all 27 EU member states. EURC has seen 1000%+ growth since late 2025.

Why agent-authorized reallocation? Storing a separate agent pubkey in VaultAccount and restricting reallocate to that key means the vault owner cannot accidentally override an in-flight rebalance, and a compromised owner wallet cannot drain via manipulated allocations.

Why --features mainnet-protocols gate? Kamino, Drift, and Raydium programs are not deployed on localnet. Gating CPIs behind a feature flag means anchor test runs cleanly on a local validator without any external dependencies — the contract logic is fully testable in isolation.

Why Transak instead of Circle API directly? Transak's widget handles KYC, SEPA transfer instructions, and order status entirely client-side via an iframe — no server-side API routes, no webhook infrastructure, and no KYB approval wait before sandbox testing.


Deployment

Devnet deployment — already live:

  • Program ID: Fvs33of5snzzjFjgyY6id1RQ7sqgxX8WDvU2FMECaVqy
  • Deploy signature: 5xzn89ZnadfTgYsxyYchpjbGSPUZgqkXEP1rwVDxfoswK9zFEQ9PvMD511BQic7QWZyQAdrnZRMLWFMvXge3HR1d
  • View on Solana Explorer

Agent hostingrender.yaml included for one-click deploy to Render. Also compatible with Railway and Fly.io.


Roadmap

Mainnet readiness (in progress):

  • CPI smoke test against live Kamino/Drift/Raydium devnet deployments
  • 2-of-3 Squads multi-sig upgrade authority before mainnet deploy
  • Professional smart contract audit (Sec3, OtterSec, or Certik)
  • Switch agent to paid Helius/QuickNode RPC endpoint

Production polish:

  • Replace demo-mode mock data with live on-chain reads
  • Mobile responsive audit (allocation sliders break below 768px)
  • Global transaction status toast system
  • Sentry/Axiom frontend error tracking

Legal & compliance:

  • Terms of Service + Privacy Policy (GDPR-compliant)
  • Legal consultation on MiCA CASP obligations for AI-managed treasury vaults
  • EU/UK legal entity registration

Tech Stack

Layer Technology
Smart contract Rust, Anchor 0.31.1
Token standard SPL Token, EURC (Token-2022)
Yield protocols Kamino Finance, Drift Protocol, Raydium CLMM
AI agent TypeScript, Node.js, @coral-xyz/anchor, @solana/web3.js
Frontend Next.js 16, React 19, Tailwind v4, shadcn/ui, Radix UI
Wallet @solana/wallet-adapter (Phantom)
Fiat rails Transak SDK v4 (SEPA on/off-ramp)
Stablecoin EURC (Circle, MiCA EMI licensed)
Testing Anchor/Mocha (smart contract), Jest (agent), ts-mocha

License

MIT

About

Set-and-forget yield infrastructure for earning higher interests/APY on idle EURC

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors