A Uniswap v4 Hook that turns waiting capital into yield while hiding trade intent from MEV.
On-chain limit orders have two issues:
-
Everyone sees your target price. You place a limit order at $2,500. MEV bots see it, front-run when price approaches, and you get worse execution. MEV extraction costs Ethereum users ~$300K/day.
-
Your capital sits idle. Funds locked in orders earn nothing while waiting days or weeks for execution. Billions in DeFi capital sits dormant in pending orders.
GhostVault is a Uniswap v4 Hook with two order types:
YieldOrder — Price-triggered limit order
- Deposit USDC, set target price
- Funds route to MetaMorpho vault, earn ~4% APY
- When price hits target, agent executes swap
- You get WETH plus the yield you earned
GhostOrder — Time-delayed privacy swap
- Deposit USDC, set delay (1 hour, 1 day, etc.)
- Only a hash of your intent is stored on-chain
- After delay, agent reveals and executes
- MEV bots never knew what you were trading
You Chain MEV Bot
| | |
| commit(hash, amount) | |
|-------------------------------->| |
| | "Someone deposited 10k USDC" |
| | "Intent: 0x7f3a...c91d" |
| | (hash reveals nothing) |
| | |
| [time passes, yield accrues] | |
| | |
| reveal + execute | |
|-------------------------------->| |
| | Swap happens |
| |-------------------------------->|
| | | "A swap happened"
| | | (too late to front-run)
The hash is keccak256(targetPrice, direction, salt). You keep the plaintext. Agent gets it off-chain. MEV never sees it until execution.
| Approach | What It Does | The Gap |
|---|---|---|
| EulerSwap | Yield for LPs via Euler vaults | Targets liquidity providers, not order makers |
| CoW Protocol | MEV protection via batch auctions | No yield on waiting capital |
| Traditional limit orders | Basic price triggers | Both: no yield, visible intent |
GhostVault is the first to combine yield generation with intent hiding for limit orders on Uniswap v4.
┌─────────────────────────────────────────────────────────────────┐
│ GhostVaultHookV2 │
│ (Uniswap v4 beforeSwap + afterSwap) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ commitOrder() ERC-4626 Vault executeOrder() │
│ ─────────────> (MetaMorpho) <───────────── │
│ User deposits Earns yield Agent reveals │
│ Hash stored While waiting Swaps on v4 pool │
│ │
├─────────────────────────────────────────────────────────────────┤
│ Chainlink Oracle Batch Execution Solver Agent │
│ Price feeds Aggregate orders Monitors chain │
│ Staleness check Hide individual sizes Executes orders│
└─────────────────────────────────────────────────────────────────┘
| Layer | Technology |
|---|---|
| Hook | Solidity 0.8.26, Uniswap v4, OpenZeppelin |
| Yield | MetaMorpho ERC-4626 vault (Gauntlet USDC Prime) |
| Oracle | Chainlink ETH/USD price feed |
| Agent | TypeScript, viem, Node.js |
| Payments | x402 protocol (HTTP 402 agent marketplace) |
| Frontend | Next.js 16, wagmi v3, RainbowKit |
| Testing | Foundry, 35 tests (22 local + 13 fork) |
GhostVault implements intent-based trading: users express what they want (commit), agents compete to execute (solver model), and the chain only sees the final result.
We built an autonomous solver agent that:
- Monitors on-chain orders via event subscription
- Checks execution conditions (price from Chainlink, time delays)
- Calculates profitability (solver fee vs gas cost)
- Executes orders when profitable
- Runs 24/7 without human intervention
The agent makes independent decisions using on-chain state. It interacts directly with Uniswap v4 pools for trade execution.
We implemented:
- Commit-reveal pattern: Trade intent hidden until execution
- Temporal separation: GhostOrders enforce unpredictable execution timing
- Batch aggregation: Multiple orders combined into single swap, hiding individual sizes
- Off-chain reveal channel: Plaintext never touches the chain
These mechanisms reduce information leakage and protect against MEV extraction.
| Tool | Version | Installation |
|---|---|---|
| Foundry | Latest | curl -L https://foundry.paradigm.xyz | bash && foundryup |
| Make | 3.8+ | macOS: xcode-select --install / Linux: apt install build-essential / Windows: choco install make |
| Node.js | 20+ | nodejs.org or nvm install 20 |
git clone https://github.com/umershaikh123/hackmoney-2026.git
cd hackmoney-2026# Install Foundry dependencies
cd foundry
make installcd foundry
cp .env.example .env.local
# Edit .env.local and add your Base mainnet RPC:
# BASE_MAINNET_RPC=https://base-mainnet.g.alchemy.com/v2/YOUR_KEYcd foundry
make test-v2-mock # 14 tests (no RPC needed)
make test-v2-fork # 7 tests (requires BASE_MAINNET_RPC)
make test-morpho # 3 tests (requires BASE_MAINNET_RPC)Terminal 1 — Start Anvil fork:
cd foundry
make demo-anvilTerminal 2 — Deploy contracts (wait for Anvil to start):
cd foundry
make demo-mockAfter deployment, you'll see output like:
HOOK: 0x1032dEC72453447221cf8f9034b6b3c5775880c0
ORACLE: 0x0c6B4F1Eb417A6b660BC5B8c3cd2a146Ac182439
Copy these addresses for the next step.
Agent (agent/.env):
cd agent
cp .env.example .envEdit agent/.env:
HOOK_ADDRESS=0x1032dEC72453447221cf8f9034b6b3c5775880c0
ORACLE_ADDRESS=0x0c6B4F1Eb417A6b660BC5B8c3cd2a146Ac182439
Frontend (frontend/.env):
cd frontend
cp .env.example .envEdit frontend/.env:
NEXT_PUBLIC_GHOST_VAULT_ADDRESS=0x1032dEC72453447221cf8f9034b6b3c5775880c0
NEXT_PUBLIC_ORACLE_ADDRESS=0x0c6B4F1Eb417A6b660BC5B8c3cd2a146Ac182439
Terminal 3 — Start agent:
cd agent
npm install
npm run startTerminal 4 — Start frontend:
cd frontend
npm install
npm run dev- Open http://localhost:3000
- Import Anvil test account into Rabby/MetaMask:
- Private key:
0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 - This account has 10 WETH + 100,000 USDC
- Private key:
Note: Every time you restart Anvil, delete the imported account from your wallet, re-import it, and clear pending transactions in wallet settings.
hackmoney-2026/
├── foundry/ # Smart contracts
│ ├── src/
│ │ ├── GhostVaultHookV2.sol # Main hook contract
│ │ ├── SimpleYieldVault.sol # Demo yield vault
│ │ └── MockChainlinkOracle.sol # Demo oracle
│ └── test/ # 35 tests
├── agent/ # Solver agent + x402 gateway
│ └── src/
│ ├── index.ts # Daemon entry point
│ ├── checker.ts # Condition monitoring
│ ├── executor.ts # Order execution
│ └── gateway.ts # x402 HTTP server
├── frontend/ # Demo UI
│ └── src/
│ ├── components/
│ └── stores/ # Zustand for reveal data
└── README.md
Current (Hackathon MVP): Users share reveal data with a trusted solver agent. The agent is economically incentivized (earns fees) to execute honestly.
Future (Roadmap): Agent registry with staking. Agents post collateral, get slashed for privacy violations or failed execution. See FUTURE.md for where we go from here.
Slippage Protection: The contract supports minAmountOut for slippage protection, but the demo frontend hardcodes it to 0. For GhostOrders with time delays, the price can move during the wait period. In production, users would set their own slippage tolerance or the frontend would auto-calculate based on current price.
Mock Contracts: The demo uses MockChainlinkOracle and SimpleYieldVault because real Chainlink freezes after Anvil time-warp and real MetaMorpho has liquidity constraints. Fork tests prove compatibility with real contracts.
- Future Steps — Where we go from here
- Contract Documentation — Technical details
- agent/src/index.ts — Main agent daemon loop
- agent/src/checker.ts — Condition checking
- agent/src/executor.ts — On-chain execution
- agent/src/gateway.ts — x402 payment gateway
- GhostVaultHookV2.sol#L291-L334 — executeOrder
- GhostVaultHookV2.sol#L515-L544 — PoolManager interaction
- GhostVaultHookV2.sol#L247-L285 — commitOrder (hash only)
- GhostVaultHookV2.sol#L296-L297 — Hash verification
- GhostVaultHookV2.sol#L302 — Time delay enforcement
- GhostVaultHookV2.sol#L347-L423 — Batch execution
- use-ghost-vault.ts — Client-side salt generation
- reveal-data-store.ts — Local reveal storage
MIT
