时间:2023 年 9 月 1 日
作者:33357
fees 和 hooks 是 Uniswap-v4 core 的手续费和钩子合约,通过对该合约的解析可以了解其功能和对接方法。
- 外部函数(仅合约内部可以调用)
- setProtocolFeeController
- 代码解析
function setProtocolFeeController( IProtocolFeeController controller // controller 合约地址 ) external onlyOwner { // 设置 controller 合约地址 protocolFeeController = controller; // 触发 controller 合约地址更新事件 emit ProtocolFeeControllerUpdated(address(controller)); }
- 总结
函数
setProtocolFeeController
用于更新协议手续费控制合约地址。
- 代码解析
- setProtocolFeeController
- 外部函数(仅合约内部可以调用)
- collectProtocolFees
- 代码解析
function collectProtocolFees( address recipient, // 接收地址 Currency currency, // 提取货币 uint256 amount // 提取数量 ) external returns ( uint256 amountCollected // 返回已收数量 ) { // 只允许 owner 和 protocolFeeController 调用 if (msg.sender != owner && msg.sender != address(protocolFeeController)) revert InvalidCaller(); // 如果 amount 为 0 就提取全部协议手续费 amountCollected = (amount == 0) ? protocolFeesAccrued[currency] : amount; // 应计协议手续费更新 protocolFeesAccrued[currency] -= amountCollected; // 转账 currency currency.transfer(recipient, amountCollected); }
- 总结
函数
collectProtocolFees
用于提取协议手续费。
- 代码解析
- collectProtocolFees
- 外部函数(仅合约内部可以调用)
- collectHookFees
- 代码解析
function collectHookFees( address recipient, // 接收地址 Currency currency, // 提取货币 uint256 amount // 提取数量 ) external returns ( uint256 amountCollected // 返回已收数量 ) { address hookAddress = msg.sender; // 如果提取数量为 0 就提取全部 hook 手续费 amountCollected = (amount == 0) ? hookFeesAccrued[hookAddress][currency] : amount; // 如果 recipient 为 0 地址,就提取到 hook 地址 recipient = (recipient == address(0)) ? hookAddress : recipient; // 应计 hook 手续费更新 hookFeesAccrued[hookAddress][currency] -= amountCollected; // 转账 currency currency.transfer(recipient, amountCollected); }
- 总结
函数
collectHookFees
用于提取 hook 手续费。
- 代码解析
- collectHookFees
- 内部函数(仅合约内部可以调用)
-
_fetchProtocolFees
- 代码解析
function _fetchProtocolFees( PoolKey memory key /* struct PoolKey { Currency currency0; // pool 中数值较小的 currency 地址 Currency currency1; // pool 中数值较大的 currency 地址 uint24 fee; // 手续费 int24 tickSpacing; // tick 单位间距 IHooks hooks; // hooks 地址 } */ ) internal view returns ( uint8 protocolSwapFee, // 协议 swap 手续费 uint8 protocolWithdrawFee // 协议提取流动性手续费 ) { // protocolFeeController 不能为 0 地址 if (address(protocolFeeController) != address(0)) { // 剩余 gaslimit 必须大于等于 controllerGasLimit if (gasleft() < controllerGasLimit) revert ProtocolFeeCannotBeFetched(); // 获取协议 swap 手续费和协议提取流动性手续费 try protocolFeeController.protocolFeesForPool{gas: controllerGasLimit}(key) returns ( uint8 updatedProtocolSwapFee, uint8 updatedProtocolWithdrawFee ) { protocolSwapFee = updatedProtocolSwapFee; protocolWithdrawFee = updatedProtocolWithdrawFee; } catch {} // 检查协议 swap 手续费 _checkProtocolFee(protocolSwapFee); // 检查协议提取流动性手续费 _checkProtocolFee(protocolWithdrawFee); } }
- 总结
函数
_fetchProtocolFees
用于获取协议手续费数量。
- 代码解析
-
_checkProtocolFee
- 代码解析
function _checkProtocolFee( uint8 fee // 协议手续费 ) internal pure { if (fee != 0) { // fee0 是 fee 后 4 位数值 uint8 fee0 = fee % 16; // fee1 是 fee 前 4 位数值 uint8 fee1 = fee >> 4; // fee0 和 fee1 不为 0 的情况下不能低于 4 if ( (fee0 != 0 && fee0 < MIN_PROTOCOL_FEE_DENOMINATOR) || (fee1 != 0 && fee1 < MIN_PROTOCOL_FEE_DENOMINATOR) ) { revert FeeTooLarge(); } } }
- 总结
函数
_checkProtocolFee
用于检查协议手续费是否合规。
- 代码解析
-
- 内部函数(仅合约内部可以调用)
- _fetchHookFees
- 代码解析
function _fetchHookFees( PoolKey memory key /* struct PoolKey { Currency currency0; // pool 中数值较小的 currency 地址 Currency currency1; // pool 中数值较大的 currency 地址 uint24 fee; // 手续费 int24 tickSpacing; // tick 单位间距 IHooks hooks; // hooks 地址 } */ ) internal view returns ( uint8 hookSwapFee, // hook swap 手续费 uint8 hookWithdrawFee // hook 提取流动性手续费 ) { // 获取 hook swap 手续费 if (key.fee.hasHookSwapFee()) { hookSwapFee = IHookFeeManager(address(key.hooks)).getHookSwapFee(key); } // 获取 hook 提取流动性手续费 if (key.fee.hasHookWithdrawFee()) { hookWithdrawFee = IHookFeeManager(address(key.hooks)).getHookWithdrawFee(key); } }
- 总结
函数
_fetchHookFees
用于获取 hook 手续费数量。
- 代码解析
- _fetchHookFees
- 内部函数(仅合约内部可以调用)
-
isDynamicFee
- 代码解析
function isDynamicFee( uint24 self // 手续费 ) internal pure returns ( bool // 返回是否是动态费用 ) { // 是否是动态费用 return self & DYNAMIC_FEE_FLAG != 0; }
- 总结
函数
isDynamicFee
用于检查手续费是否是动态费用。
- 代码解析
-
hasHookSwapFee
- 代码解析
function hasHookSwapFee( uint24 self // 手续费 ) internal pure returns ( bool // 返回是否有 hook swap 手续费 ) { // 是否有 hook swap 手续费 return self & HOOK_SWAP_FEE_FLAG != 0; }
- 总结
函数
hasHookSwapFee
用于检查是否有 hook swap 手续费。
- 代码解析
-
hasHookWithdrawFee
- 代码解析
function hasHookWithdrawFee( uint24 self // 手续费 ) internal pure returns ( bool // 返回是否有 hook 提取流动性手续费 ) { // 是否有 hook 提取流动性手续费 return self & HOOK_WITHDRAW_FEE_FLAG != 0; }
- 总结
函数
hasHookWithdrawFee
用于检查手续费是否有 hook 提取流动性手续费。
- 代码解析
-
isStaticFeeTooLarge
- 代码解析
function isStaticFeeTooLarge( uint24 self // 手续费 ) internal pure returns ( bool // 返回是否静态手续费太高 ) { // 是否静态手续费太高 return self & STATIC_FEE_MASK >= 1000000; }
- 总结
函数
isStaticFeeTooLarge
用于检查手续费是否静态手续费太高。
- 代码解析
-
getStaticFee
- 代码解析
function getStaticFee( uint24 self // 手续费 ) internal pure returns ( uint24 // 返回静态手续费 ) { // 获取静态手续费 return self & STATIC_FEE_MASK; }
- 总结
函数
getStaticFee
用于获取手续费的静态手续费数量。
- 代码解析
-
- 内部函数(仅合约内部可以调用)
- validateHookAddress
- 代码解析
function validateHookAddress( IHooks self, // hook 地址 Calls memory calls /* struct Calls { bool beforeInitialize; // 是否有 beforeInitialize 的 hook bool afterInitialize; // 是否有 afterInitialize 的 hook bool beforeModifyPosition; // 是否有 beforeModifyPosition 的 hook bool afterModifyPosition; // 是否有 afterModifyPosition 的 hook bool beforeSwap; // 是否有 beforeSwap 的 hook bool afterSwap; // 是否有 afterSwap 的 hook bool beforeDonate; // 是否有 beforeDonate 的 hook bool afterDonate; // 是否有 afterDonate 的 hook } */ ) internal pure { // 检查 hook 地址是否匹配 calls if ( calls.beforeInitialize != shouldCallBeforeInitialize(self) || calls.afterInitialize != shouldCallAfterInitialize(self) || calls.beforeModifyPosition != shouldCallBeforeModifyPosition(self) || calls.afterModifyPosition != shouldCallAfterModifyPosition(self) || calls.beforeSwap != shouldCallBeforeSwap(self) || calls.afterSwap != shouldCallAfterSwap(self) || calls.beforeDonate != shouldCallBeforeDonate(self) || calls.afterDonate != shouldCallAfterDonate(self) ) { revert HookAddressNotValid(address(self)); } }
- 总结
函数
validateHookAddress
用于检查 hook 地址是否匹配 calls。
- 代码解析
- validateHookAddress
- 内部函数(仅合约内部可以调用)
- isValidHookAddress
- 代码解析
function isValidHookAddress( IHooks hook, // hook 地址 uint24 fee // 手续费 ) internal pure returns ( bool // 返回是否是正确的 hook 地址 ) { // return address(hook) == address(0) ? !fee.isDynamicFee() && !fee.hasHookSwapFee() && !fee.hasHookWithdrawFee() : ( uint160(address(hook)) >= AFTER_DONATE_FLAG || fee.isDynamicFee() || fee.hasHookSwapFee() || fee.hasHookWithdrawFee() ); }
- 总结
函数
isValidHookAddress
用于返回是否是有效的 hook 地址。
- 代码解析
- isValidHookAddress
- 内部函数(仅合约内部可以调用)
-
shouldCallBeforeInitialize
- 代码解析
function shouldCallBeforeInitialize( IHooks self // hook 地址 ) internal pure returns ( bool // 返回是否有 beforeInitialize 的 hook ) { // 是否有 beforeInitialize 的 hook return uint256(uint160(address(self))) & BEFORE_INITIALIZE_FLAG != 0; }
- 总结
函数
shouldCallBeforeInitialize
用于检查 hook 地址是否有 beforeInitialize 的 hook。
- 代码解析
-
shouldCallAfterInitialize
- 代码解析
function shouldCallAfterInitialize( IHooks self // hook 地址 ) internal pure returns ( bool // 返回是否有 afterInitialize 的 hook ) { // 是否有 afterInitialize 的 hook return uint256(uint160(address(self))) & AFTER_INITIALIZE_FLAG != 0; }
- 总结
函数
shouldCallAfterInitialize
用于检查 hook 地址是否有 afterInitialize 的 hook。
- 代码解析
-
shouldCallBeforeModifyPosition
- 代码解析
function shouldCallBeforeModifyPosition( IHooks self // hook 地址 ) internal pure returns ( bool // 返回是否有 beforeModifyPosition 的 hook ) { // 是否有 beforeModifyPosition 的 hook return uint256(uint160(address(self))) & BEFORE_MODIFY_POSITION_FLAG != 0; }
- 总结
函数
shouldCallBeforeModifyPosition
用于检查 hook 地址是否有 beforeModifyPosition 的 hook。
- 代码解析
-
shouldCallAfterModifyPosition
- 代码解析
function shouldCallAfterModifyPosition( IHooks self // hook 地址 ) internal pure returns ( bool // 返回是否有 afterModifyPosition 的 hook ) { // 是否有 afterModifyPosition 的 hook return uint256(uint160(address(self))) & AFTER_MODIFY_POSITION_FLAG != 0; }
- 总结
函数
shouldCallAfterModifyPosition
用于检查 hook 地址是否有 afterModifyPosition 的 hook。
- 代码解析
-
shouldCallBeforeSwap
- 代码解析
function shouldCallBeforeSwap( IHooks self // hook 地址 ) internal pure returns ( bool // 返回是否有 beforeSwap 的 hook ) { // 是否有 beforeSwap 的 hook return uint256(uint160(address(self))) & BEFORE_SWAP_FLAG != 0; }
- 总结
函数
shouldCallBeforeSwap
用于检查 hook 地址是否有 beforeSwap 的 hook。
- 代码解析
-
shouldCallAfterSwap
- 代码解析
function shouldCallAfterSwap( IHooks self // hook 地址 ) internal pure returns ( bool // 返回是否有 afterSwap 的 hook ) { // 是否有 afterSwap 的 hook return uint256(uint160(address(self))) & AFTER_SWAP_FLAG != 0; }
- 总结
函数
shouldCallAfterSwap
用于检查 hook 地址是否有 afterSwap 的 hook。
- 代码解析
-
shouldCallBeforeDonate
- 代码解析
function shouldCallBeforeDonate( IHooks self // hook 地址 ) internal pure returns ( bool // 返回是否有 beforeDonate 的 hook ) { // 是否有 beforeDonate 的 hook return uint256(uint160(address(self))) & BEFORE_DONATE_FLAG != 0; }
- 总结
函数
shouldCallBeforeDonate
用于检查 hook 地址是否有 beforeDonate 的 hook。
- 代码解析
-
shouldCallAfterDonate
- 代码解析
function shouldCallAfterDonate( IHooks self // hook 地址 ) internal pure returns ( bool // 返回是否有 afterDonate 的 hook ) { // 是否有 afterDonate 的 hook return uint256(uint160(address(self))) & AFTER_DONATE_FLAG != 0; }
- 总结
函数
shouldCallAfterDonate
用于检查 hook 地址是否有 afterDonate 的 hook。
- 代码解析
-