Complete Case Study: Euler Hooks (External Liquidity Example)

⚠️ Important Context: Euler represents a hook with EXTERNAL LIQUIDITY. This case study demonstrates implementing custom metadata generators and parsers. If your hook is Composable and uses internal PoolManager liquidity, your hook should be already indexed by Tycho.

This section provides a comprehensive walkthrough of the Euler hook integration as a real-world example of handling external liquidity.

Euler Vault Architecture

What is Euler? Euler is a lending protocol that allows users to deposit tokens into vaults to earn yield. Each vault is an ERC-4626 compliant contract that manages deposits and withdrawals.

Euler is a standalone protocol, that designed an interface to be Hook-compliant, allowing it to be accessible by UniswapV4 Pools. This is a common pattern with current hooks, and are considered by Tycho Hooks with External Liquidity.

You can learn more about the protocol here

Euler Hook Pattern (External Liquidity):

┌──────────────────────────┐
│  Uniswap V4 Euler Hook   │
│  (Liquidity Coordinator) │
└────────────┬─────────────┘

             │ Manages deposits/withdrawals

┌──────────────────────────┐
│  Euler Vault Contract    │  ← EXTERNAL liquidity storage
│  - Token0 deposited      │
│  - Token1 deposited      │
│  - Earns lending yield   │
└──────────────────────────┘

Contrast with Internal Liquidity:

Why Euler Requires Custom Implementation:

  1. External Balances: Tokens are in Euler vaults, not PoolManager → Need MetadataRequestGenerator

  2. Withdrawal Limits: Vaults have maximum withdrawal amounts → Need limits fetching logic

  3. Yield Accrual: Balances increase over time from lending yield → Need periodic balance updates

  4. Multiple Vaults: Each token pair might use different vault addresses → Need parser logic

What Euler Does NOT Need:

  • ❌ Custom Hook Orchestrator (default works fine)

  • ❌ Special entrypoint encoding (standard Uniswap V4 swaps)

  • ❌ Custom state transformations

Implementation Walkthrough

1. Balance Collection

Objective: Query the current token reserves in the Euler vaults.

Approach: Euler hooks implement a getReserves() function that returns the current balances of both tokens.

Code:

Response Format:

Parsing:

2. Limits Collection Using Lens Contract

Objective: Determine the maximum swap amounts for each direction (token0→token1, token1→token0).

Challenge: Euler vaults have withdrawal limits that depend on available liquidity, which requires complex calculations involving multiple contract calls.

Solution: Deploy a "lens" contract via state overrides that performs the calculation in a single eth_call.

Lens Contract Pattern:

Request Generation:

Response Format:

Parsing:

3. Entrypoint Generation with Detected Slots

Objective: Generate entrypoints that simulate swaps with correct balance overwrites for both PoolManager and external vault tokens.

Process:

  1. Estimate Swap Amounts (using limits):

  1. Detect Balance Slots (for wstETH, WETH, etc.):

  1. Build State Overrides:

  1. Create Entrypoint:

4. Full Processing Flow

Initialization (one-time):

Block Processing (per block):

Key Takeaways from Euler

  1. Balance Slot Detection: Essential for hooks with external token holdings

  2. Lens Contract Pattern: Powerful technique for complex multi-call queries using state overrides

  3. Limits-Based Estimation: Provides more accurate swap amount samples than balance-based

  4. Default Orchestrator: Often sufficient even for complex hooks like Euler

  5. State Override Composition: Combine router deployment, ERC6909 overwrites, and ERC20 overwrites in a single call

The Euler implementation demonstrates that with proper metadata collection and entrypoint generation, the Hooks DCI can handle even complex external liquidity scenarios.

Last updated