Skip to content

ZaK3939/v4-workshop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Uniswap V4 Workshop - EDCON 2025

This repository is a monorepo for the Uniswap V4 Hooks workshop. It includes smart contracts, V4 SDK integration, Indexer, and Dashboard.

🎯 Workshop Overview

In this workshop, you'll deploy and test Uniswap V4's innovative "Hooks" feature, experiencing the complete Hook development lifecycle (development β†’ deployment β†’ testing β†’ analysis).

Duration: 35-55 minutes
Target Audience: Developers with basic Solidity knowledge

🎯 Workshop Goals

This workshop will help you achieve:

  1. Understanding how Uniswap V4 Hooks work
  2. Experiencing proper address deployment using HookMiner
  3. Mastering pool operations with V4 SDK
  4. Verifying JIT attack prevention with LiquidityPenaltyHook
  5. Learning analysis methods using Envio indexer

πŸ“… Timetable

Time Section Content
0-5 min Environment Setup Clone repository, install dependencies, configure environment variables
5-15 min Hook Deployment Deploy LiquidityPenaltyHook using HookMiner
15-25 min Pool Creation Create pool with deployed Hook
25-40 min Hands-on Operations Add/remove liquidity and swap using V4 SDK
40-45 min Analysis & Summary Check results with Indexer and Dashboard, Q&A

πŸ“š Full Workshop Script: See workshop-50min-script.md for a detailed 50-minute workshop guide with complete explanations and code examples.

πŸ—οΈ System Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Blockchain (Unichain)                           β”‚
β”‚  ・Hooks (LiquidityPenaltyHook, etc.)                               β”‚
β”‚  ・PoolManager, PositionManager                                     β”‚
β”‚  ・Universal Router                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚              β”‚
                      β”‚              β”‚
              Event Monitoring    Transaction Execution
                      β”‚              β”‚
                      β–Ό              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     INDEXER (Envio)         β”‚  β”‚      V4 SDK Scripts               β”‚
β”‚  http://localhost:8080      β”‚  β”‚  ・04-add-liquidity.ts            β”‚
β”‚  ・Event Collection          β”‚  β”‚  ・05-swap-universal-router.ts    β”‚
β”‚  ・Data Persistence          β”‚  β”‚  ・06-remove-liquidity.ts         β”‚
β”‚    (PostgreSQL)             β”‚  β”‚  ・check-pool-state.ts            β”‚
β”‚  ・GraphQL API               β”‚  β”‚                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚                                   β”‚
               β”‚ GraphQL API                       β”‚ Operations
               β”‚                                   β”‚
               β–Ό                                   β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”‚
β”‚      DASHBOARD APP          β”‚                    β”‚
β”‚   http://localhost:3000     β”‚                    β”‚
β”‚  ・Display Statistics       β”‚                    β”‚
β”‚  ・TVL Analysis             β”‚                    β”‚
β”‚  ・Hook Behavior            β”‚                    β”‚
β”‚    Visualization            β”‚                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
               β”‚                                   β”‚
               β”‚ Read-only                         β”‚
               β–Ό                                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  Users                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”¨ Foundry Deployment Flow

The smart contract deployment process uses Foundry's scripting capabilities:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Developer Machine                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚  β”‚                      Foundry Scripts                       β”‚     β”‚
β”‚  β”‚  01_DeployAndSave.s.sol β†’ Deploy hooks with HookMiner      β”‚     β”‚
β”‚  β”‚  02_CreatePool.s.sol    β†’ Create pools with deployed hooks β”‚     β”‚
β”‚  β”‚  03_ShowPoolInfo.s.sol  β†’ Display deployment information   β”‚     β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚                         β”‚                                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚  β”‚                   HookMiner                                β”‚     β”‚
β”‚  β”‚  ・Calculate deterministic addresses based on permissions  β”‚     β”‚
β”‚  β”‚  ・Find salt for CREATE2 deployment                        β”‚     β”‚
β”‚  β”‚  ・Encode hook flags in address (last 20 bits)             β”‚     β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚                         β”‚                                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚  β”‚              CREATE2 Deployer                              β”‚     β”‚
β”‚  β”‚  ・Deploy hooks at calculated addresses                    β”‚     β”‚
β”‚  β”‚  ・Ensure permission bits match address                    β”‚     β”‚
β”‚  β”‚  ・Save deployment info to .env files                      β”‚     β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚ Deploy & Initialize
                          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Unichain Blockchain                             β”‚
β”‚  ・Deployed Hooks at deterministic addresses                        β”‚
β”‚  ・Initialized Pools with hook integration                          β”‚
β”‚  ・Ready for V4 SDK interaction                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Deployment Steps:

  1. Environment Setup

    cd contracts
    source .env
    export ETH_FROM=$(cast wallet address --private-key $PK)d
  2. Hook Deployment (01_DeployAndSave.s.sol)

    • Uses HookMiner to calculate addresses
    • Deploys via CREATE2 for deterministic addresses
    • Saves addresses to scripts/.deployment.env
  3. Pool Creation (02_CreatePool.s.sol)

    • Reads deployed hook addresses
    • Creates pools with proper hook integration
    • Saves pool info to scripts/.pool.env
  4. Verification (03_ShowPoolInfo.s.sol)

    • Displays all deployment information
    • Confirms hook permissions and pool configuration

πŸͺ What are Uniswap V4 Hooks?

V4's Innovative Architecture

Uniswap V4 adopts a "singleton" architecture where all pools are managed by a single PoolManager contract. This enables:

  • Improved Gas Efficiency: Optimized multi-hop swaps between pools
  • Customizability: Free extension of pool behavior through Hooks
  • Capital Efficiency: Temporary borrowing via flash accounting

Hook Features

Hooks are custom logic executed at specific points in a pool's lifecycle:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   User Action   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
    β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ Pool     β”œβ”€β”€β”€β”€β–Ίβ”‚ Hook Contractβ”‚
    β”‚ Manager  │◄───── (Your Logic) β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

14 Extension Points:

  • beforeInitialize / afterInitialize
  • beforeAddLiquidity / afterAddLiquidity
  • beforeRemoveLiquidity / afterRemoveLiquidity
  • beforeSwap / afterSwap
  • beforeDonate / afterDonate
  • Delta return flags (for fee and swap amount adjustments)

πŸ“¦ Three Hooks Covered in the Workshop

1. LiquidityPenaltyHook - JIT Attack Prevention

Problem: Just-In-Time (JIT) Attacks

  • Attackers add liquidity just before large swaps
  • They immediately remove liquidity after capturing swap fees
  • This steals revenue from long-term liquidity providers

Solution: Time-based Penalty

penalty = fees * (1 - (currentBlock - lastAddedBlock) / blockNumberOffset)

Imposes penalties on early liquidity removal, decreasing over time (0% after 10 blocks).

2. AntiSandwichHook - MEV Protection

Prevents sandwich attacks by limiting price manipulation within blocks. Checkpoints prices at the start of each block and prevents trades at advantageous prices within the same block.

3. LimitOrderHook - Pseudo Limit Orders

Enables on-chain limit orders that automatically execute when specific prices are reached.

πŸš€ Quick Start

1. Setup Environment Variables

# Or manually create each .env file
cp contracts/.env.example contracts/.env
cp apps/indexer/.env.example apps/indexer/.env

Required settings for contracts/.env:

  • PK: Private key for deployment (never commit this!)
  • ETHERSCAN_API_KEY: For contract verification

Required settings for apps/indexer/.env:

2. Install Dependencies

# Install using Bun
bun install

3. Setup and Start Indexer (First Time Only)

# Setup indexer
cd apps/indexer
pnpm install  # Indexer requires pnpm
bun run codegen
bun run dev

4. Start Dashboard

# In a new terminal, start Dashboard (http://localhost:3000)
cd apps/dashboard
pnpm install
bun run dev

Note:

  • The indexer requires Docker Desktop to be running
  • GraphQL endpoint will be available at http://localhost:8080/v1/graphql once the indexer is ready
  • For subsequent runs, you can simply use bun run dev in the indexer directory

πŸ“ Project Structure

uniswap-v4-workshop/
β”œβ”€β”€ contracts/        # Uniswap V4 Hooks smart contracts
β”‚   β”œβ”€β”€ src/         # Hook implementations (LiquidityPenaltyHook, etc.)
β”‚   └── script/      # Deployment and operation scripts
β”œβ”€β”€ scripts/         # V4 SDK integration scripts
β”‚   β”œβ”€β”€ utils/       # Common utilities
β”‚   β”œβ”€β”€ 04-add-liquidity.ts      # Add liquidity
β”‚   β”œβ”€β”€ 05-swap-universal-router.ts # Execute swaps
β”‚   └── 06-remove-liquidity.ts    # Remove liquidity
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ indexer/     # Blockchain indexer (Envio)
β”‚   └── dashboard/   # Analytics dashboard (Next.js)
β”œβ”€β”€ deployments/     # Contract addresses by network
└── docs/           # Workshop documentation

πŸ› οΈ Available Commands

# Contract-related
bun run contracts:build       # Build contracts
bun run v4:deploy            # Deploy hooks with HookMiner
bun run v4:pool              # Create pool with deployed hook
bun run v4:info              # Show pool information

# V4 SDK operations
bun run v4:check             # Check pool state
bun run v4:add               # Add liquidity (create Position NFT)
bun run v4:swap              # Execute swap via Universal Router
bun run v4:remove            # Remove liquidity

# Application startup
bun run indexer          # Start indexer (requires Docker)
bun run dashboard            # Start dashboard

Script Details

Foundry Scripts:

// v4:deploy (01_DeployAndSave.s.sol) - Hook Deployment
- Deploy at proper address using HookMiner
- Deterministic address generation via CREATE2
- Save deployment results to .deployment.env

// v4:pool (02_CreatePool.s.sol) - Pool Creation
- Create pool using deployed Hook
- ETH/USDC pair, 0.3% fee setting
- Save pool information to .pool.env

// v4:info (03_ShowPoolInfo.s.sol) - Display Pool Information
- Display Hook address and enabled permissions
- Pool ID and current price
- Generate explorer links

V4 SDK Scripts:

// v4:check (check-pool-state.ts) - Check Pool State
- Display current price, liquidity, and fees
- Verify Hook address and settings

// v4:add (04-add-liquidity.ts) - Add Liquidity
- Create Position NFT
- Gasless approval via Permit2
- Provide liquidity to specified price range

// v4:swap (05-swap-universal-router.ts) - Execute Swap
- Quote via V4 Quoter (revert data processing)
- Build actions with V4Planner
- Execute via Universal Router

// v4:remove (06-remove-liquidity.ts) - Remove Liquidity
- Withdraw liquidity from Position NFT
- Handle LiquidityPenaltyHook penalties
- Support partial or complete removal

πŸ”§ Hook-Specific Deployment Process

The most unique aspect of V4 Hooks is that permission information is encoded in the address itself:

Hook Address: 0x0050E651C7b8662f4E17C589B6387db8f7488503
                                                    ^^^^
         Lowest bits (right side) represent permissions

Example: Lowest 14 bits of 0x...8503

  • Binary: 1000 0101 0000 0011
  • This indicates the following permissions:
    • bit 0 (0x1): AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA
    • bit 1 (0x2): AFTER_ADD_LIQUIDITY_RETURNS_DELTA
    • bit 8 (0x100): AFTER_REMOVE_LIQUIDITY
    • bit 10 (0x400): AFTER_ADD_LIQUIDITY

How HookMiner Works

  1. Permission Declaration:
function getHookPermissions() public pure returns (Hooks.Permissions memory) {
    return Hooks.Permissions({
        afterAddLiquidity: true,
        afterRemoveLiquidity: true,
        afterAddLiquidityReturnDelta: true,
        afterRemoveLiquidityReturnDelta: true,
        // ... all others false
    });
}
  1. Address Calculation:
// HookMiner finds the proper address using CREATE2
uint160 flags = Hooks.AFTER_ADD_LIQUIDITY_FLAG |
                Hooks.AFTER_REMOVE_LIQUIDITY_FLAG | ...;

(address hookAddress, bytes32 salt) = HookMiner.find(
    CREATE2_DEPLOYER,
    flags,
    bytecode,
    constructorArgs
);
  1. Validation: Permissions are validated with validateHookAddress().

πŸ“Š Indexing with Envio

Event Processing Flow

PoolManager β†’ Event Emitted β†’ Envio Indexer β†’ PostgreSQL β†’ GraphQL β†’ Dashboard

Key Events Tracked

  1. Initialize: Pool creation (including Hook address)
  2. Swap: Trade execution and Hook intervention
  3. ModifyLiquidity: LP operations and penalty application
  4. Donate: Fee donations

πŸ“š Documentation

πŸ† Uniswap Related Grant

After completing the workshop, consider applying for the Unichain Hook Grant!

Grant Overview

  • Organizers: Uniswap Foundation & Atrium
  • Target: Innovative Hooks running on Unichain
  • Categories: DeFi Innovation, Liquidity Optimization, MEV Protection, New AMM Designs
  • Grants Info

πŸ“š Workshop Documentation

πŸ”— Related Links


Building the Future of DeFi with Uniswap V4

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors