Search projects, hackathons, sponsors and tech

    ← All projects

    Indenture

    A Uniswap v4 hook that stops a hacked AI fund manager from trading outside its mandate, on Hedera

    Demo

    About

    Indenture is a compliance-enforced, AI-managed investment fund on Hedera - a pool that can say "no." AI agents are being handed real money, and every one of them can be prompt-injected. Today, if the model is tricked, the funds move. Indenture assumes the AI is already compromised and makes that irrelevant. The system has three trust tiers: 1. The Manager (untrusted): an LLM agent that reads the fund's state and proposes trades. It is deliberately treated as hostile - it has a low-privilege key and no ability to enforce anything. 2. The Validator (independent): a separate service that receives ONLY { poolId, swapParams } — never the prompt, never the AI's reasoning. A strict Zod schema rejects anything else, so injected English has no path to the thing that signs. It re-derives every fact from source (Hedera mirror node, on-chain pool state, Chainlink price feed) and either signs an EIP-712 receipt or refuses with a named reason. 3. The Hook (on-chain): a Uniswap v4 PolicyHook re-checks the receipt with ecrecover, binds it to the exact swap parameters and sequence number, and runs four fixed integer covenant checks (max position %, max trade notional, etc.) before any swap settles. It makes zero external calls, so it can never be down or manipulated. Result: even a fully jailbroken AI - or a stolen Validator key - cannot move funds outside the mandate. Investor access is also gated: fund shares are an ERC-3643 permissioned token, so the pool refuses buyers who aren't verified, not just managers who overstep. Every approval AND every refusal is permanently journaled to Hedera Consensus Service. Blocked attacks aren't hidden failures - they're a public, auditable part of the product. The web app includes a live Attack Console where you can type your own prompt injection, watch the AI manager fall for it completely, and watch the fund balance not move. The "Blocked" wall currently shows 15 attacks refused and $0.00 lost.

    How it's made

    Indenture is a TypeScript + Solidity monorepo: 8 contracts, 4 services, 4 shared packages and 221 passing tests, running on $0 of infrastructure with no database and no always-on server. On-chain, we deployed Uniswap v4-core's PoolManager, unmodified, on Hedera testnet. That only became possible once Hedera added transient storage (HIP-865), and as far as we could find nobody had done it before. On top of it sits PolicyHook, a v4 hook that makes no decisions itself: it's a routing table from PoolId to an IPolicy contract. MandatePolicy verifies an EIP-712 receipt with ecrecover, binds it to the exact swap params and a sequence number so it can't be replayed, then runs 4 integer covenant checks (max position %, min cash %, max trade size, daily volume). We check covenants in afterSwap, against the real settled amounts rather than the requested ones, and a revert there still unwinds the whole swap. IndentureVault is the fund and acts as its own v4 router using flash accounting. Fund shares are ERC-3643 tokens, and a custom compliance module freezes transfers whenever the mandate is breached. Off-chain there are three trust levels. The Manager is an LLM agent (any OpenAI-compatible API, with a pure-math fallback) that runs on a GitHub Actions cron and is treated as already hacked. The Validator is a Hono + Zod service on Cloudflare Workers / Vercel that signs with viem. Its only input is { poolId, swapParams }, parsed with Zod .strict(), so a prompt injection has no way to reach the signer. It re-derives everything else itself and signs or refuses. The Journaler writes every approval and every refusal to Hedera Consensus Service. The frontend is Next.js 15 + React 19 + wagmi + Tailwind with zero API routes, with GSAP, Lenis and OGL for motion. Partner tech: Uniswap v4 is the one enforcement point an attacker can't route around, because it runs inside the swap. Hedera HCS is our tamper-proof audit log, and the Mirror Node REST API is our entire database: no Postgres, no indexer, no backend. Chainlink Data Feeds give the Validator an independent price that doesn't come from the pool being traded, and it refuses to sign on stale data. Because the hook only trusts a signer address, the Validator can later be replaced by a Chainlink DON without changing any contract. Hacky bits: Foundry can't talk to Hedera's Hashio RPC relay directly, so we wrote a small Node JSON-RPC shim that rewrites requests between forge and Hashio. v4 hooks store their permissions in the address itself, so we brute-force a CREATE2 salt until the address has the right flag bits. To keep the EIP-712 struct identical across languages, we sign a test vector in TypeScript and recover it inside a Foundry test. Any drift breaks CI. Finally, there's a live attack button (a workflow input and an npm run inject CLI) that fires real prompt injections at the fund. You watch the AI fall for them and the balance stay put.