ForesightNews文章 2024年10月12日
Uniswap V4 Hook 介绍【修正版】
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

Uniswap发展到V4版本,每次升级都带来重大变化。V4提供了新功能,如Hook机制等,允许项目方实现自己的逻辑,衍生出各种有想象力的项目,改变了流动性池的创建和操作方式。

💧Uniswap V4中最重要的是Hook机制,项目方在创建交易池时可声明Hook合约,用户进行流动性操作和swap操作时会触发相应逻辑,从业务角度带来巨大变化。

🎯Uniswap V4中每个流动性池不再对应一个合约,而是统一在一个合约下。创建池时先声明PoolKey,其中除传入Token和手续费外,还传入Hook合约地址。

📜一个简单的Hook合约继承于BaseHook,通过重载getHookPermissions函数设置在哪些流程中添加逻辑,如在添加流动性前后进行操作。

🎉Hook极大扩展了流动性池的业务范围,可实现多种具备想象力的业务,如动态手续费、整合借贷平台、社区治理等。

隔三年,Uniswap 终于发展到 v4 版本。Uniswap 是一个非常有上进心的项目,每次升级都会带来很大的变化,比如从 V2 升级到 V3 实现了集中流动性,从而提高了资金的利用率,这使得 Uniswap 在 AMM 赛道中再次领先。

在 V4 中,这种野心也表现得淋漓尽致。V4 提供了很多新的功能,如 Hook 机制,单例合约,闪电记账等。其中最重要的是 Hook 机制。它允许项目方在创建交易池时,声明一个 Hook 合约,用户在这个池进行流动性操作和 swap 操作时,会触发对应的逻辑。这个改变并不大,从程序开发的角度来说,不过是回调的应用罢了。但从业务的角度来说,带来的变化是翻天覆地的。我们可以用 BTC 和 ETH 的关系作为类比,Bitcoin 实现了代币的持有和交换,而 Ethereum 在这个基础上附加了智能合约,最终衍生出 DeFi 这个庞大市场。在 Ethereum 之前,很难想象这些语法简单的 solidity 代码能够衍生出近千亿美元的产业。而 Uniswap V4 也是类似,在 V3 完善的交易机制上,允许项目方实现自己的逻辑,从而衍生出各具想象力的项目。

要认识 Hook,首先要看看 V4 中的流动性池是什么样子。Uniswap V4 中,每个流动性池不再对应一个合约,而是所有池统一在一个合约下。因此创建池的过程,也从部署合约,变成调用合约。这是官方创建池的例子。

// SPDX-License-Identifier: MITpragma solidity ^0.8.20;import {IPoolManager} from "v4-core/src/interfaces/IPoolManager.sol";import {IHooks} from "v4-core/src/interfaces/IHooks.sol";import {PoolKey} from "v4-core/src/types/PoolKey.sol";import {CurrencyLibrary, Currency} from "v4-core/src/types/Currency.sol";contract PoolInitialize {    using CurrencyLibrary for Currency;    // set the initialize router    IPoolManager manager = IPoolManager(address(0x01));    function init(        address token0,        address token1,        uint24 swapFee,        int24 tickSpacing,        address hook,        uint160 sqrtPriceX96,        bytes calldata hookData    ) external {        // sort your tokens! v4 requires token0  token1) {            (token0, token1) = (token1, token0);        }        PoolKey memory pool = PoolKey({            currency0: Currency.wrap(token0),            currency1: Currency.wrap(token1),            fee: swapFee,            tickSpacing: tickSpacing,            hooks: IHooks(hook)        });        manager.initialize(pool, sqrtPriceX96, hookData);    }}

在创建流动性池的过程中,先声明了一个 PoolKey,在 V4 中,PoolKey 是 Pool 的唯一 ID,也就是流动性池的身份证,在这个 ID 中,除了传入 Token 和手续费外,还传入了 Hook 合约地址。可见,对于同样的币对和手续费,如果 Hook 不同,会被看作不同的流动性池。这是和 V3 一个很大的区别。

而在真正创建池的时候 (manager.initialize(pool, sqrtPriceX96, hookData);),又传入了初始价格,以及 hookData。hookData 可以将一些初始化的参数传递给 Hook。

一个简单的 Hook 合约的例子如下:

// SPDX-License-Identifier: MITpragma solidity ^0.8.20;import {BaseHook} from "v4-periphery/src/base/hooks/BaseHook.sol";import {PoolKey} from "v4-core/types/PoolKey.sol";import {IPoolManager} from "v4-core/interfaces/IPoolManager.sol";import {Hooks} from "v4-core/libraries/Hooks.sol";contract SampleHook is BaseHook  {    constructor(IPoolManager _manager, string memory _name, string memory _symbol) BaseHook(_manager){     // do something    }    function getHookPermissions() public pure override returns (Hooks.Permissions memory) {        return Hooks.Permissions({            beforeInitialize: false,            afterInitialize: false,            beforeAddLiquidity: true,            beforeRemoveLiquidity: false,            afterAddLiquidity: true,            afterRemoveLiquidity: false,            beforeSwap: false,            afterSwap: false,            beforeDonate: false,            afterDonate: false,            beforeSwapReturnDelta: false,            afterSwapReturnDelta: false,            afterAddLiquidityReturnDelta: false,            afterRemoveLiquidityReturnDelta: false        });    }    function beforeAddLiquidity(        address sender,        PoolKey calldata key,        IPoolManager.ModifyLiquidityParams calldata params,        bytes override calldata hookData    ) external returns (bytes4){      // do something    }    function afterAddLiquidity(        address sender,        PoolKey calldata key,        IPoolManager.ModifyLiquidityParams calldata params,        BalanceDelta delta,        bytes calldata hookData    ) external override returns (bytes4, BalanceDelta); {       // do something    }}

从例子中我们可以看到,Hook 是一个合约,而且继承于 BaseHook。其中,BaseHook 的 getHookPermissions 函数是必须重载的。通过这个函数,可以设置在哪些流程中添加逻辑:

    初始化前后
    添加流动性前后
    移除流动性前后
    Swap 前后
    捐赠 ( 一个 V4 的新概念 ) 前后
    在 Swap 返回金额变动之前
    在 Swap, 添加流动性, 移除流动性的金额改变之后

比如我们想添加流动性之前和之后进行一些操作,因此将 beforeAddLiquidityafterAddLiquidity 设置为 True。

最后,重载 beforeAddLiquidity 和 afterAddLiquidity 函数,每次这个池发生添加流动性交易之后,就会执行这个函数中的逻辑。

整体流程如下图,其中橙色代表 PoolManager 合约,绿色代表 Hook 合约。

作为对比,V3 中,添加流动性的过程是这样的,其中蓝色代表 proxy 合约,橙色代表 pool 合约。

Hook 极大的扩展了流动性池的业务范围,可以实现很多具备想象力的业务。比如:

    基于波动率或者时间的动态手续费

    将借贷平台整合进来,把限制的流动性放入借贷平台做抵押,防止资金空置

    添加流动性的手续费享受复利

    收取一部分手续费用于社区治理

    Swap 交易使用限价单机制

    多签

    KYC

因此,只要想象力足够,完全可以依托 V4 平台,打造出自己的交易所,甚至发明新的衍生品类型。而 V4 可以提供流动性管理和交易的支持,减少构建新项目的成本。现在已经有很多团队开发了自己的 Hook。

uniswaphooks.com

但由于 V4 还没有发布,线上的资源还很少,连 API 文档都没发布。如果想要进一步了解,可以关注一下官方的介绍[1],以及官方的例子[2]。另外,我们也翻译了正式版白皮书

在后面的文章中,我会介绍如何编写 Hook。以及背后的机理。


参考资料
[1]

官方的介绍: https://docs.uniswap.org/contracts/v4/overview

[2]

官方的例子: https://www.v4-by-example.org/

笔者:Steven Sun,Zelos
点击左下方「阅读原文」/「Read More」,获取更多相关信息

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Uniswap V4 Hook机制 流动性池 创新业务
相关文章