uniswap v4 hooks详解

hooks的代码位置在这,它是是组织校验,调用用户创建钩子的类库。

标志位

首先看其中定义的常量:

    uint160 internal constant ALL_HOOK_MASK = uint160((1 << 14) - 1);

    uint160 internal constant BEFORE_INITIALIZE_FLAG = 1 << 13;
    uint160 internal constant AFTER_INITIALIZE_FLAG = 1 << 12;

    uint160 internal constant BEFORE_ADD_LIQUIDITY_FLAG = 1 << 11;
    uint160 internal constant AFTER_ADD_LIQUIDITY_FLAG = 1 << 10;

    uint160 internal constant BEFORE_REMOVE_LIQUIDITY_FLAG = 1 << 9;
    uint160 internal constant AFTER_REMOVE_LIQUIDITY_FLAG = 1 << 8;

    uint160 internal constant BEFORE_SWAP_FLAG = 1 << 7;
    uint160 internal constant AFTER_SWAP_FLAG = 1 << 6;

    uint160 internal constant BEFORE_DONATE_FLAG = 1 << 5;
    uint160 internal constant AFTER_DONATE_FLAG = 1 << 4;

    uint160 internal constant BEFORE_SWAP_RETURNS_DELTA_FLAG = 1 << 3;
    uint160 internal constant AFTER_SWAP_RETURNS_DELTA_FLAG = 1 << 2;
    uint160 internal constant AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG = 1 << 1;
    uint160 internal constant AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG = 1 << 0;

我们知道IHooks 接口中定义了 10 个核心方法,分别对应上面的标志位:

标志位 描述 对应的接口方法
BEFORE_INITIALIZE_FLAG 初始化前触发 beforeInitialize
AFTER_INITIALIZE_FLAG 初始化后触发 afterInitialize
BEFORE_ADD_LIQUIDITY_FLAG 添加流动性前触发 beforeAddLiquidity
AFTER_ADD_LIQUIDITY_FLAG 添加流动性后触发 afterAddLiquidity
BEFORE_REMOVE_LIQUIDITY_FLAG 移除流动性前触发 beforeRemoveLiquidity
AFTER_REMOVE_LIQUIDITY_FLAG 移除流动性后触发 afterRemoveLiquidity
BEFORE_SWAP_FLAG 交换前触发 beforeSwap
AFTER_SWAP_FLAG 交换后触发 afterSwap
BEFORE_DONATE_FLAG 捐赠前触发 beforeDonate
AFTER_DONATE_FLAG 捐赠后触发 afterDonate

这些标志位直接对应 IHooks 接口中的方法,用于标识 Hook 合约是否支持这些方法。

RETURNS_DELTA_FLAG

除了上述 10 个标志位,还有 4 个额外的标志位用于标识扩展功能。这些标志位与返回 Delta 值 的能力相关:

标志位 描述 扩展功能
BEFORE_SWAP_RETURNS_DELTA_FLAG 交换前返回 Delta 值 返回 BeforeSwapDelta
AFTER_SWAP_RETURNS_DELTA_FLAG 交换后返回 Delta 值 返回 int256 Delta 值
AFTER_ADD_LIQUIDITY_RETURNS_DELTA_FLAG 添加流动性后返回 Delta 值 返回 BalanceDelta
AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA_FLAG 移除流动性后返回 Delta 值 返回 BalanceDelta

这几个RETURNS_DELTA标志位用于标识 Hook 合约是否支持在特定操作后返回一个 Delta 值。Delta 值通常表示某种状态的变化,例如交易金额的调整、流动性变化或其他相关的数值。

举个例子,假设我们有一个 Hook 合约,它在交易(swap)之前动态调整交易金额。这个 Hook 合约会返回一个 Delta 值,用于修改交易的输入金额。
 

contract ExampleHook is IHooks {
    function beforeSwap(
        address sender,
        PoolKey calldata key,
        IPoolManager.SwapParams calldata params,
        bytes calldata hookData
    ) external returns (bytes4, int256 delta) {
        // 返回一个 Delta 值,用于调整交易金额
        delta = params.amountSpecified / 10; // 调整金额的 10%
        return (this.beforeSwap.selector, delta);
    }
}

此时我们创建合约的时候就要将BEFORE_SWAP_RETURNS_DELTA_FLAG设置为1。

这个时候hooks库在调用用户钩子的beforeSwap方法后,就可以从Hook 返回的数据中解析出 Delta 值并正确调整流动性提供者的余额。我们可以看到hooks库的beforeSwap方法对于BEFORE_SWAP_RETURNS_DELTA_FLAG的运用。

function beforeSwap(IHooks self, PoolKey memory key, IPoolManager.SwapParams memory params, bytes calldata hookData)
    internal
    returns (int256 amountToSwap, BeforeSwapDelta hookReturn, uint24 lpFeeOverride)
{
    amountToSwap = params.amountSpecified;

    if (self.hasPermission(BEFORE_SWAP_FLAG)) {
        bytes memory result = callHook(self, abi.encodeCall(IHooks.beforeSwap, (msg.sender, key, params, hookData)));

        // 检查返回数据的长度是否符合预期
        if (result.length != 96) InvalidHookResponse.selector.revertWith();

        // 如果启用了 RETURNS_DELTA 标志位,则解析 Delta 值
        if (self.hasPermission(BEFORE_SWAP_RETURNS_DELTA_FLAG)) {
            hookReturn = BeforeSwapDelta.wrap(result.parseReturnDelta());

            // 使用 Delta 值调整交易金额
            int128 hookDeltaSpecified = hookReturn.getSpecifiedDelta();
            if (hookDeltaSpecified != 0) {
                bool exactInput = amountToSwap < 0;
                amountToSwap += hookDeltaSpecified;

                // 确保交易类型(exact input/output)不发生变化
                if (exactInput ? amountToSwap > 0 : amountToSwap < 0) {
                    HookDeltaExceedsSwapAmount.selector.revertWith();
                }
            }
    
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值