Project

Bundl

With this project I ended between the winners of the Uniswap Hook Incubator. Earning a price and the acknowledgment of the Uniswap Foundation.

uniswap-v4soliditydefihooksfoundrynext.js

Winner of the Uniswap Hook Incubator hackathon, with recognition from the Uniswap Foundation.

Bundl is a permissionless tokenized index protocol built natively on Uniswap V4. Each index is a standard ERC-20 token (e.g. bBLUE, bBEU) whose price is always equal to its Net Asset Value (NAV), enforced on every swap by a custom Uniswap V4 hook and without reliance on external arbitrageurs.

How it works

Instead of relying on an AMM curve to price the index token, the BundlHook intercepts every swap via beforeSwap and acts as the sole market maker:

User (USDC)


SwapRouter / BundlRouter


PoolManager ──beforeSwap──► BundlHook

                 ┌───────────────┼───────────────┐
                 ▼               ▼               ▼
           WBTC/USDC       WETH/USDC       WUNI/USDC

Architecture

ContractDescription
BundlFactoryOne-click deployment of hook + token + pool. Mines CREATE2 salt to satisfy Uniswap V4 hook permission bits.
BundlHookCore contract: Uniswap V4 hook + collateral vault + NAV market maker.
BundlTokenMinimal ERC-20 index token. Only its paired BundlHook can mint/burn.
BundlRouterStateless sell router. Handles the two-phase unlock -> deposit -> swap -> take flow for sells.

Key design decisions

NAV-priced market maker: BundlHook uses BeforeSwapDelta to completely override the Uniswap V4 AMM curve. There is no AMM liquidity in the IndexToken/USDC pool; every swap resolves at exact NAV, eliminating spread between market price and backing value.

CREATE2 salt mining: Uniswap V4 encodes hook permissions in the hook’s address (lower bits). BundlFactory mines the correct salt on-chain during createBundl(). A per-index hookSalt prevents collisions across deployments.

Asymmetric routing: Buys use a standard SwapRouter (hook mints inside beforeSwap). Sells use BundlRouter: index tokens must be deposited into the PoolManager before the swap so the hook can take and burn them.

No external liquidity: beforeAddLiquidity reverts for any caller that is not the hook itself. The pool exists solely as a routing surface.

Stack

Solidity 0.8.26 · Foundry · Uniswap V4 · OpenZeppelin · Next.js · wagmi · viem