Architecture
A Uniswap v4 hook that creates impact-differentiated liquidity via milestone-gated fee routing. Seven hook callbacks, five funding channels, five contracts across three chains, and an autonomous AI verification agent.
afterSwap fee routing, LP fee skim via afterAddLiquidity, donate skim via afterDonate, milestone tracking, 3 verification paths, loyalty discounts, heartbeat expiration, project templates
Implements IArbiter from the Zellic-audited Alkahest escrow protocol. Gates grant release on verified milestone state from ImpactHook.
Subscribes to MilestoneSubmitted events on origin chain. Emits cross-chain callbacks to ImpactHook on Unichain. No bridges needed.
Deployed on any supported origin chain. Emits MilestoneSubmitted events that Reactive Network relays to Unichain.
Clean swap(key, zeroForOne, amountIn, minAmountOut) interface with slippage protection. Handles afterSwapReturnDelta internally so callers don't need to.
Origin Chain Reactive Network Destination Chain (any supported) (ReactVM) (Unichain Sepolia) MilestoneOracle --> MilestoneReactor --> ImpactHook emits event subscribes & verifyMilestoneReactive() MilestoneSubmitted emits Callback updates milestone state
Authorization: Reactive Network overwrites the first callback argument with the ReactVM ID. The hook checks msg.sender == callbackProxy and rvmId == project.verifier.
Three verification paths
Verifier calls verifyMilestone() directly on Unichain. Simple, gas-efficient. Works for EOAs, multisigs, DAOs, and AI agents.
MilestoneOracle on origin chain emits event. MilestoneReactor on Reactive Network subscribes and triggers verifyMilestoneReactive() on Unichain. No bridges.
Verifier creates an Ethereum Attestation Service attestation with evidence. Anyone can then call verifyMilestoneEAS() permissionlessly. Credibly neutral.
Hook callbacks
Seven Uniswap v4 hook callbacks: beforeInitialize, afterSwap + afterSwapReturnDelta, afterAddLiquidity + afterAddLiquidityReturnDelta, afterRemoveLiquidity + afterRemoveLiquidityReturnDelta, afterDonate.
// Fee on TOP of LP fee — LPs earn full yield
uint16 feeBps = _getCurrentFeeBps(poolId);
uint256 feeAmount = (uint256(uint128(outputAmount))
* feeBps) / 10_000;
// Take fee from pool manager
poolManager.take(feeCurrency, address(this), feeAmount);
accumulatedFees[poolId][feeCurrency] += feeAmount;
// Return delta — reduces swapper output
return (this.afterSwap.selector,
int128(int256(feeAmount)));// LP collects fees -> hook skims a %
function afterAddLiquidity(
..., BalanceDelta feesAccrued, ...
) {
return _skimLpFees(key, feesAccrued);
}
// Swap pricing stays identical
// Routers have no reason to skip this pool
// LPs opt in, swappers don't pay extraFee model
The hook charges a fee on top of the standard Uniswap v4 LP fee via afterSwapReturnDelta. LP yield is completely unaffected. Fee rate is determined by the current verified milestone's projectFeeBps. Maximum capped at 5% (500 BPS).
LP Fee Skim (Dual Funding Model)
Pools can skim a percentage of LP fees for the impact project via afterAddLiquidity and afterRemoveLiquidity return deltas. When LPs collect accrued fees, the hook transparently routes a configurable share to the project.
- Swap pricing stays identical to regular pools
- Routers have no reason to skip or avoid these pools
- LPs opt in by providing liquidity to the pool
- Swappers don't pay any extra fees
- Configurable per pool, max 50% skim rate
Traditional impact funding hooks add a swap fee that makes the pool uncompetitive for routers. LP fee skimming funds impact projects without touching swap pricing at all. The pool looks identical to any other v4 pool from the router's perspective, so it gets normal trade flow.
Native v4 Donate Skim
The afterDonate hook intercepts PoolManager.donate() calls. When users tip LPs via the native v4 donate mechanism, a configurable percentage is routed to the impact project.
Safety and accountability
Projects must send periodic proof-of-life transactions. If the heartbeat interval passes without a signal, fee collection stops automatically until the project proves it is still active.
Any individual project can be paused without affecting other projects on the same hook. Paused projects stop accumulating fees immediately.
Milestones must be verified in order. A project cannot skip ahead or verify out of sequence. Each milestone can only be verified once.
All state-changing functions follow the checks-effects-interactions pattern. Static analysis with Slither confirms no reentrancy or state ordering issues.
Behavior-customizable templates
Templates define lpSkimBps, donateSkimBps, heartbeatInterval, and swapFeeEnabled per project type. One hook deployment serves different impact verticals with appropriate defaults.
| Template | LP Skim | Heartbeat | Swap Fees | Use Case |
|---|---|---|---|---|
| Climate | 10% | 30 days | Enabled | Long-term environmental |
| Emergency Relief | 20% | 7 days | Disabled | Crisis response, router-competitive |
| Open Source | 0% | None | Enabled | Traditional swap-fee dev grants |
Evidence storage and impact records
Milestone evidence (reports, images, data) uploaded to Filecoin/IPFS via Storacha or Filecoin Pin. CIDs stored onchain via setMilestoneEvidence().
Verified milestones mint Hypercerts on Ethereum, creating composable, tradeable impact certificates. Metadata auto-populated from onchain state: project name, milestone, contributors, evidence CIDs.
Evidence persists in three places: ImpactHook contract (Unichain), Hypercert metadata (Ethereum), and EAS attestation data (Unichain). Each independently verifiable.
Autonomous verification agent
A standalone Bun service that monitors EvidenceAttached events, retrieves evidence from Storacha/IPFS, analyzes it with Claude, and submits verifyMilestone() when confidence exceeds the threshold. Reports stored permanently on Filecoin. Agent memory persists on Storacha across sessions.
Evidence uploaded Agent detects Claude analyzes Report stored
to Storacha/IPFS --> EvidenceAttached --> evidence vs --> on Filecoin Pin
event onchain milestone criteria (Calibration)
|
confidence >= 70%?
yes / \ no
/ \
verifyMilestone() store report,
submitted onchain defer to humanAgent state, past verifications, and project knowledge persist on Storacha. On restart, the agent loads its memory from the latest CID and resumes where it left off.
Every verification produces a structured JSON report stored on Filecoin via Synapse SDK. Reports include per-criterion analysis, confidence scores, and reasoning.
When the agent verifies a milestone, MilestoneArbiter.checkObligation() returns true, automatically releasing gated escrow funds. Fully autonomous funding cycle.
Confidence threshold gating (only auto-verifies above 70%), dry-run mode for analysis without onchain transactions, structured execution logs, budget-aware operation.
Test coverage
- + Registration
- + Fee routing (both dirs)
- + Milestone progression
- + Withdrawal
- + Impact tracking
- + LP fee skim
- + Verifier auth
- + Recipient auth
- + Callback proxy
- + Owner checks
- + Heartbeat expiry
- + Per-project pause
- + MilestoneArbiter (3)
- + Reactive callbacks (5)
- + Oracle events (4)
- + EAS verification (7)
- + Evidence storage (7)
- + Loyalty discounts (6)
- + Templates (7)
- + Donations (8)
- + Fuzz tests
- + HookMiner (7)
- + Edge cases
Deployed contracts
| Contract | Chain | Address |
|---|---|---|
| ImpactHook | Unichain Sepolia | 0xC8A18E4A64224D2785D505c77923ed8c1d4F2557 |
| MilestoneArbiter | Unichain Sepolia | 0xF51197176Fc8B8D4F780Dc67E431a90E85Fc52Fb |
| MilestoneOracle | Ethereum Sepolia | 0xDd5c349fb1dcc3Daf60cC7a5ff73175ef9567cBc |
| MilestoneReactor | Reactive Lasna | 0x19D5bfa64Ff4992e917FC627B246eBdDf6A7d872 |
| ImpactSwapRouter | Unichain Sepolia | 0x66452162B01442d92fc77d607EE2Cff3e76043c2 |