DeFI Decode: An Inside-out Explanation of Uniswap V4 Hook (with TWAMM as example)

Ben Liu
6 min readOct 23, 2023

By BitBlock Technology.

Smart contract development supposed to be permissionless. However, only few contracts, like uniswap, AAVE, MakerDAO, regularly attracts millions of active users. One reason is because gas-efficient/secure/user-friendly end to end on-chain development is complicated. Now Imagine there is a solution to simplify this, and imagine there is already a tested contract that you can plug your customized logic and used by millions users. Uniswap V4 Hook is one such tool/framework allowing us to realise this.

An infinite game is not played for winning, but for continuing the play.

— James Carse, Finite & Infinite Games 1986

The purpose of this article is not on how to write a Hook (some great material are listed here), but help you fundamentally understand better and connect the dots in order to write better hooks.

Let’s get started!

Picture credit. we add color to defi, making it more understandable.

Content

  • Overall Architecture of V4 Hooks & How they connect
  • Single settlement supported by lock/lockAquired callback
  • TWAMM Hook Design — Data & Logic walk through
  • Areas of Improvement

Overall Architecture of V4 Hooks & How they connected

when you develop a Hook, below are a few key things to remember:

  • The moment you create a hook, you always implicitly also create an underlying pool.
  • There is no direct way for you to link your own hook to other pools.
  • It is possible to mauually call swap of other pools (for problems like, your own pool is thin and you want to use other pool’s liquidity).
Figure: every hook comes with its own internal pool.

We then move on to explore individual hook (or equivalently hooked pool)’s data storage. With customization, the whole storage of data will coming from 2 sources: those defined by Uniswap and those defined by yourself:

  • Blue part is provided by Uniswap. It includes all the swap pool related data (indeed, they are same as v3).
  • Yellow part is your customised data & logic. In TWAMM example, customisation data includes TWAMM order pool (like you can have ETH/DAI and ETH/WBTC for different TWAMM pools)
Figure: individual hooks’s data structure (using TWAMM as example). and note PoolKey links everything together.

Take note on the importance of PoolKey (or PoolId), which links everything together. The definition of PoolKey and conversion into poolKey are given below.

Figure: poolKey defines a unique pool (can be with or without hook).
Figure: poolKey to poolId (for mapping key)

Note that other than data storage, the chart also apply to function & interfaces. The callback function interfaces are all provided (including lock callback, and hook callback). while user only provide hook specific logic and such logic and called through the linkage between callback functions. The linked, refered to as hook lifecycle, can be found in Unsiwap awesome hooks pages and snapshot below.

Figure: Hook lifecycle from uniswap awesome page.

Single settlement supported by lock/lockAquired callback

V4 also support single settlement after multiple calls (can be swap, modify position or others). Uniswap implement this through lock/lockAquired callback mechanism. Before we get into details, let’s find out why:

Question:

Say you find out an arbitrage opportunity, which requires swapping USDC first to ETH, then WBTC, finally back to USDC. And now you are the designer of the v4 Swap Protocol, how can you do this gas efficiently?

Pause … and think a bit here…

There are a few ways to do this:

  • Method 1: You provide a swap function. and every time when user call Swap(token1, token2), you settle. This is fine (and it’s V3 actually), but it consume gas every swap.
  • Method 2: You provide Swap and Settle separately, and allow users to sequentially call 3 swaps first (from USDC →ETH →WBTC →USDC) and then settle. this one, you run with risk: what if external users just call the first swap and run away?
  • Method 3: Above method is just half cooked and to complete it, you need to prevent runaway magically. Lock callback is the magic, within it, user can do any number of swap they like followed by user call settlement. So when it returns, protocol check and revert if not.

Chart below describe the difference between v3 and v4 in lock callback.

Figure: lock callback enable single settle for gas saving.

Back to solidity, lock function is implemented PoolManager.sol (link) and lockAquired (callback) is implemented in BaseHook contract (link).

figure: The lock function enable single settlement.
Figure: lockAquired callback in basehook.

TWAMM Hook Design — Data & Logic walk through

TWAMM.sol contract is well designed.

Software = Data + Logic.

Hence let’s go through these 2 parts.

Data

Uniswap minimize the TWAMM data storage for gas. The final data needes includes only:

  • Consolidated TWAMM orders on each side (State.OrderPool.State),
  • Individual TWAMM order (to support order modification (State.orders),
  • Collection of all individual TWAMM pools (twammStates).

Interested users can further check the details of OrderPool.State and orders. Uniswap design them in a way to minimize update needs (storage read/write costs!).

Logic

The critical logic in this hook is to get the TWAMM order fill price. Why? with the price:

  • Amount of swapped back token for either side of twamm orders,
  • How much leftover needed to leverage the inter pool.

Contrary to first initiative thought, TWAMM implementation math is not a simple logic of time-average due to a few reasons:

Figure: the twamm order-fill price formula. details in link.

Now back to the soldity code, function executeTWAMMOrders in TWAMM.sol do this fulfilment. As expected, it has 2 main steps:

  1. Calculate TWAMM fill price, and book-keep the earning (amount obtained when TWAMM order getfilled).
  2. Call pool.swap to fully settle the twamm order execution.

by now. we have explained the main part of Uniswap v4 Hook.

Areas of Improvement

Through investigation of TWAMM hook, we have identified 3 main issues:

  1. The gas cost of Hooks is higher than normal pool without Hook, plus who should economically bear such gas fee.
  2. The internal pool may have thin liquidity, leading to poor execution price for TWAMM users. Can we find a better pool for swap instead on only on internal pool.
  3. What is the right moment for triggering execution? TWAMM supposed to exectute at given TimeInterval. However, contract cannot call itself and needs EOA trigger.

Note that above issues are inter-linked. And it related to what EOA to call (and pay gas fee) plus when to call. The Account abstraction framework for smart wallet is actually design to solve such problem (we have an article here, link). Next, we will explore combine these two technologies together and share a github code repository for solution.

The End

By now, you should have decent understanding of the Uniswap Hook v4. Thanks for your time. Hope you find this useful!

BITBLOCK Technology targets to be the expert on DeFI smart contract development and audit. Contact us if you need help or have questions.

--

--