Uniswap Hook Incubator — Technical Introduction- #1

Zuhaib Mohammed
4 min readJul 29, 2024

--

Currently I am part of cohort organized by Atrium Academy and Uniswap Foundation wherein we get to learn about Uniswap v4. At the point of me writing this blog, v4 is not deployed on mainnet yet. The main idea behind writing this a self study in the future. Hope it helps you guys out as well.

Singleton Design

You might have heard that v4 follows a Singleton design pattern in contrast to v3. In addition to this v3 introduced the concentrated liquidity which allows to create capital efficient markets since LPs are not forced to provide liquidity across the entire price range like in the case of v2. But a multi hop swap would always be expensive, since the swapped tokens from each single swap needs to be sent to a new pool.

In v4, there exists PoolManager contract. It stores the mapping of the all the pools deployed. These pools kind of live inside the PoolManager instead of being their own contracts. This is possible because pools now are implemented as Solidity libraries and calling functions through those libraries rather than deploying new contracts.

Flash Accounting

With Singleton architecture, there is no more need of external calls to transfer the tokens from one pool to another. v4 introduces flash accounting wherein users sends token to the PoolManager which later performs the single/multi-hop swap and only the final output tokens need to be withdrawn from the PoolManager.

Locking

To ensure correctness and atomicity in complex operations, v4 uses a locking mechanism. If an user wants to perform swap or change liquidity, they need to unlock the PoolManager. A periphery(Router) contact calls the unlock function and checks if the PoolManager isn't unlocked already. If not, it unlocks it with a callback. Inside the callback the swap/liquidity operations are performed and at the end of it PoolManager checks if all the balances are settled and then proceeds to lock it.

Transient Storage

EIP-1153 introduces two new OPCODES to the EVM i.e.,TSTORE and TLOAD which recently got merged into mainnet. Basically, it only exists in the context of the transaction and does not persist after the transaction is complete and due to this it is really cheap to read/write to.

ERC-6909 Claims

It is a multi-token contract standard. In v4, it to represent claim tokens. Imagine you are a high frequency trader performing regular swaps with your tokens, instead of moving this in and out of the PoolManager, you can use the claim tokens. For future swaps, based on the output, the old claim tokens are burned and new claim tokens are minted. you might still think its not so gas efficient as there is still transfer of tokens happening via mint/burn but the main advantage is the custom logic of popular tokens like USDT/USDC is bypassed making it gas efficient over multiple swaps.

Types Of Hooks

These are the hook function that v4 supports. The names of the functions should be self-descriptive to help understand what they do !

  • beforeInitialize
  • afterInitialize
  • beforeAddLiquidity
  • afterAddLiquidity
  • beforeRemoveLiquidity
  • afterRemoveLiquidity
  • beforeSwap
  • afterSwap
  • beforeDonate
  • afterDonate
  • beforeSwapReturnDelta
  • afterSwapReturnDelta
  • afterAddLiquidityReturnDelta
  • afterRemoveLiquidityReturnDelta

The v4 design follows a design pattern wherein whether a specific hook smart contract supports one of the above hooks or not is done via bitmap technique of the deployed smart contract. Therefore, when deploying hooks to an actual network — we need to do a little bit of address mining to find a proper deployment address for our hook which can properly represent the functions we have implemented in our hooks.

Example of how a swap works ?

User calls the Router Contract to initiate a swap, this unlocks the PoolManager, triggering the manager to call unlockCallback on the periphery. Inside the callback function, the periphery executes swap on the manager. The manager checks the hook address attached to the pool. Suppose beforeSwap is set to true as part of the bitmap of the deployed contract address. After beforeSwap hook is run, the actual swap is conducted inside the manager contract. This BalanceDelta is returned to the periphery contract, which actually settles the balances. Now, the periphery contract is done with the callback and re-enter the execution context of the unlock function from the manager. The PoolManager ensures no balances remain unsettled, locks itself again, and the transaction completes

The BalanceDelta value is simply two int values and not uint.A positive value implies a positive balance change for the user i.e. the PoolManager owes money to the user, and a negative value implies a negative balance change for the user i.e. the user owes money to the PoolManager.

This brings me to the end of the blog. I hope you enjoyed reading it. The information provided above should give you a good foundation to start exploring on your own.

Thanks for Reading ! Stay Tuned for the next blog !

Connect with me: https://linktr.ee/zuhaib44

--

--