From 86de20d7327bd7828af453a38b0afdf05207e404 Mon Sep 17 00:00:00 2001 From: "tingzhao.ytz" Date: Mon, 5 Aug 2024 11:40:20 +0800 Subject: [PATCH] feat: update init contract --- P102_InitContracts/code/Factory.sol | 31 +++- P102_InitContracts/code/Pool.sol | 83 +++++++--- P102_InitContracts/code/PoolManager.sol | 44 +++--- P102_InitContracts/code/PositionManager.sol | 86 ++++++++++- P102_InitContracts/code/SwapRouter.sol | 62 +++++++- .../code/interfaces/IFactory.sol | 28 ---- P102_InitContracts/code/interfaces/IPool.sol | 98 ------------ .../code/interfaces/IPoolManager.sol | 51 ------ .../code/interfaces/IPositionManager.sol | 57 ------- .../code/interfaces/ISwapRouter.sol | 55 ------- P102_InitContracts/readme.md | 146 +++++++++--------- 11 files changed, 318 insertions(+), 423 deletions(-) delete mode 100644 P102_InitContracts/code/interfaces/IFactory.sol delete mode 100644 P102_InitContracts/code/interfaces/IPool.sol delete mode 100644 P102_InitContracts/code/interfaces/IPoolManager.sol delete mode 100644 P102_InitContracts/code/interfaces/IPositionManager.sol delete mode 100644 P102_InitContracts/code/interfaces/ISwapRouter.sol diff --git a/P102_InitContracts/code/Factory.sol b/P102_InitContracts/code/Factory.sol index 5317046..7520491 100644 --- a/P102_InitContracts/code/Factory.sol +++ b/P102_InitContracts/code/Factory.sol @@ -4,22 +4,45 @@ pragma solidity ^0.8.24; import "./interfaces/IFactory.sol"; contract Factory is IFactory { + mapping(address => mapping(address => address[])) public pools; + + // parameters 是用于 Pool 创建时回调获取参数用 + // 不是用构造函数是为了避免构造函数变化,那样会导致 Pool 合约地址不能按照参数计算出来 + // 具体参考 https://docs.openzeppelin.com/cli/2.8/deploying-with-create2 + // new_address = hash(0xFF, sender, salt, bytecode) function parameters() external view override - returns (address factory, address token0, address token1, uint24 fee) + returns ( + address factory, + address token0, + address token1, + int24 tickLower, + int24 tickUpper, + uint24 fee + ) {} function getPool( address token0, address token1, - uint24 fee - ) external view override returns (address pool) {} + uint32 index + ) external view override returns (address) { + return pools[token0][token1][index]; + } function createPool( address token0, address token1, + int24 tickLower, + int24 tickUpper, uint24 fee - ) external override returns (address pool) {} + ) external override returns (address pool) { + // 先调用 getPools 获取当前 token0 token1 的所有 pool + // 然后判断是否已经存在 tickLower tickUpper fee 相同的 pool + // 如果存在就直接返回 + // 如果不存在就创建一个新的 pool + // 然后记录到 pools 中 + } } diff --git a/P102_InitContracts/code/Pool.sol b/P102_InitContracts/code/Pool.sol index 434c693..bd8937b 100644 --- a/P102_InitContracts/code/Pool.sol +++ b/P102_InitContracts/code/Pool.sol @@ -2,45 +2,84 @@ pragma solidity ^0.8.24; import "./interfaces/IPool.sol"; +import "./interfaces/IFactory.sol"; contract Pool is IPool { - function factory() external view override returns (address) {} + /// @inheritdoc IPool + address public immutable override factory; + /// @inheritdoc IPool + address public immutable override token0; + /// @inheritdoc IPool + address public immutable override token1; + /// @inheritdoc IPool + uint24 public immutable override fee; + /// @inheritdoc IPool + int24 public immutable override tickLower; + /// @inheritdoc IPool + int24 public immutable override tickUpper; - function token0() external view override returns (address) {} + /// @inheritdoc IPool + uint160 public override sqrtPriceX96; + /// @inheritdoc IPool + int24 public override tick; + /// @inheritdoc IPool + uint128 public override liquidity; - function token1() external view override returns (address) {} + // 用一个 mapping 来存放所有 Position 的信息 + mapping(address => Position) public positions; - function fee() external view override returns (uint24) {} + constructor() { + // constructor 中初始化 immutable 的常量 + // Factory 创建 Pool 时会通 new Pool{salt: salt}() 的方式创建 Pool 合约,通过 salt 指定 Pool 的地址,这样其他地方也可以推算出 Pool 的地址 + // 参数通过读取 Factory 合约的 parameters 获取 + // 不通过构造函数传入,因为 CREATE2 会根据 initcode 计算出新地址(new_address = hash(0xFF, sender, salt, bytecode)),带上参数就不能计算出稳定的地址了 + (factory, token0, token1, tickLower, tickUpper, fee) = IFactory( + msg.sender + ).parameters(); + } - function tickLower() external view override returns (int24) {} - - function tickUpper() external view override returns (int24) {} - - function sqrtPriceX96() external view override returns (uint160) {} - - function tick() external view override returns (int24) {} - - function liquidity() external view override returns (uint128) {} - - function initialize( - uint160 sqrtPriceX96_, - int24 tickLower_, - int24 tickUpper_ - ) external override {} + function initialize(uint160 sqrtPriceX96_) external override { + // 初始化 Pool 的 sqrtPriceX96 + sqrtPriceX96 = sqrtPriceX96_; + } function mint( address recipient, uint128 amount, bytes calldata data - ) external override returns (uint256 amount0, uint256 amount1) {} + ) external override returns (uint256 amount0, uint256 amount1) { + // 基于 amount 计算出当前需要多少 amount0 和 amount1 + // TODO 当前先写个假的 + (amount0, amount1) = (amount / 2, amount / 2); + // 把流动性记录到对应的 position 中 + positions[recipient].liquidity += amount; + // 回调 mintCallback + IMintCallback(recipient).mintCallback(amount0, amount1, data); + // TODO 检查钱到位了没有,如果到位了对应修改相关信息 + } function collect( address recipient - ) external override returns (uint128 amount0, uint128 amount1) {} + ) external override returns (uint128 amount0, uint128 amount1) { + // 获取当前用户的 position,TODO recipient 应该改为 msg.sender + Position storage position = positions[recipient]; + // TODO 把钱退给用户 recipient + // 修改 position 中的信息 + position.tokensOwed0 -= amount0; + position.tokensOwed1 -= amount1; + } function burn( uint128 amount - ) external override returns (uint256 amount0, uint256 amount1) {} + ) external override returns (uint256 amount0, uint256 amount1) { + // 修改 positions 中的信息 + positions[msg.sender].liquidity -= amount; + // 获取燃烧后的 amount0 和 amount1 + // TODO 当前先写个假的 + (amount0, amount1) = (amount / 2, amount / 2); + positions[msg.sender].tokensOwed0 += amount0; + positions[msg.sender].tokensOwed1 += amount1; + } function swap( address recipient, diff --git a/P102_InitContracts/code/PoolManager.sol b/P102_InitContracts/code/PoolManager.sol index 937983a..dcfaa5b 100644 --- a/P102_InitContracts/code/PoolManager.sol +++ b/P102_InitContracts/code/PoolManager.sol @@ -3,33 +3,35 @@ pragma solidity ^0.8.24; pragma abicoder v2; import "./interfaces/IPoolManager.sol"; +import "./Factory.sol"; -contract PoolManager is IPoolManager { - function getPools() - external - view - override - returns (PoolKey[] memory pools) - {} +contract PoolManager is Factory, IPoolManager { + Pair[] public pairs; - function getTokens() + function getPairs() external view override returns (Pair[] memory) { + // 返回有哪些交易对,DApp 和 getAllPools 会用到 + return pairs; + } + + function getAllPools() external view override - returns (address[] memory tokens) - {} - - function getTokenPools( - address token - ) external view override returns (PoolKey[] memory pools) {} - - function getPoolInfo( - address token0, - address token1, - uint24 fee - ) external view override returns (PoolInfo memory poolInfo) {} + returns (PoolInfo[] memory poolsInfo) + { + // 遍历 pairs,获取当前有的所有的交易对 + // 然后调用 Factory 的 getPools 获取每个交易对的所有 pool + // 然后获取每个 pool 的信息 + // 然后返回 + // 先 mock + poolsInfo = new PoolInfo[](pairs.length); + return poolsInfo; + } function createAndInitializePoolIfNecessary( CreateAndInitializeParams calldata params - ) external payable override returns (address pool) {} + ) external payable override returns (address pool) { + // 如果没有对应的 Pool 就创建一个 Pool + // 创建成功后记录到 pairs 中 + } } diff --git a/P102_InitContracts/code/PositionManager.sol b/P102_InitContracts/code/PositionManager.sol index 58db3f2..befbdd5 100644 --- a/P102_InitContracts/code/PositionManager.sol +++ b/P102_InitContracts/code/PositionManager.sol @@ -2,13 +2,24 @@ pragma solidity ^0.8.24; pragma abicoder v2; +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "./interfaces/IPositionManager.sol"; +import "./interfaces/IPool.sol"; +import "./interfaces/IPoolManager.sol"; -contract PositionManager is IPositionManager { - function getPositions( - address owner - ) external view override returns (uint256[] memory positionIds) {} +contract PositionManager is IPositionManager, ERC721 { + // 保存 PoolManager 合约地址 + IPoolManager public poolManager; + constructor(address _poolManger) ERC721("WTFSwapPosition", "WTFP") { + poolManager = IPoolManager(_poolManger); + } + + // 用一个 mapping 来存放所有 Position 的信息 + mapping(uint256 => PositionInfo) public positions; + + // 通过 positionId 获取 Position 信息,positionId 就是 NFT 的 tokenId + // 如果要获得某个用户的所有的 Position 信息,需要自己遍历所有的 tokenId,可以通过 ZAN 的节点服务来获取 function getPositionInfo( uint256 positionId ) external view override returns (PositionInfo memory positionInfo) {} @@ -25,14 +36,75 @@ contract PositionManager is IPositionManager { uint256 amount0, uint256 amount1 ) - {} + { + // mint 一个 NFT 作为 position 发给 LP + // NFT 的 tokenId 就是 positionId + // 通过 MintParams 里面的 token0 和 token1 以及 index 获取对应的 Pool + // 调用 poolManager 的 getPool 方法获取 Pool 地址 + address _pool = poolManager.getPool( + params.token0, + params.token1, + params.index + ); + IPool pool = IPool(_pool); + // 通过获取 pool 相关信息,结合 params.amount0Desired 和 params.amount1Desired 计算这次要注入的流动性 + // TODO: 计算 _liquidity,这里只是随便写的 + uint128 _liquidity = uint128( + params.amount0Desired * params.amount1Desired + ); + // data 是 mint 后回调 PositionManager 会额外带的数据 + // 需要 PoistionManger 实现回调,在回调中给 Pool 打钱 + bytes memory data = abi.encode("todo"); + (amount0, amount1) = pool.mint(params.recipient, _liquidity, data); + positionId = 1; + liquidity = _liquidity; + // TODO 以 NFT 的形式把 Position 的所有权发给 LP + } function burn( uint256 positionId - ) external override returns (uint256 amount0, uint256 amount1) {} + ) external override returns (uint256 amount0, uint256 amount1) { + // TODO 检查 positionId 是否属于 msg.sender + // 移除流动性,但是 token 还是保留在 pool 中,需要再调用 collect 方法才能取回 token + // 通过 positionId 获取对应 LP 的流动性 + uint128 _liquidity = positions[positionId].liquidity; + // 调用 Pool 的方法给 LP 退流动性 + address _pool = poolManager.getPool( + positions[positionId].token0, + positions[positionId].token1, + positions[positionId].index + ); + IPool pool = IPool(_pool); + (amount0, amount1) = pool.burn(_liquidity); + // 修改 positionInfo 中的信息 + positions[positionId].liquidity = 0; + positions[positionId].tokensOwed0 = amount0; + positions[positionId].tokensOwed1 = amount1; + } function collect( uint256 positionId, address recipient - ) external override returns (uint256 amount0, uint256 amount1) {} + ) external override returns (uint256 amount0, uint256 amount1) { + // TODO 检查 positionId 是否属于 msg.sender + // 调用 Pool 的方法给 LP 退流动性 + address _pool = poolManager.getPool( + positions[positionId].token0, + positions[positionId].token1, + positions[positionId].index + ); + IPool pool = IPool(_pool); + (amount0, amount1) = pool.collect(recipient); + // 修改 positionInfo 中的信息 + positions[positionId].tokensOwed0 = 0; + positions[positionId].tokensOwed1 = 0; + } + + function mintCallback( + uint256 amount0, + uint256 amount1, + bytes calldata data + ) external override { + // 在这里给 Pool 打钱,需要用户先 approve 足够的金额,这里才会成功 + } } diff --git a/P102_InitContracts/code/SwapRouter.sol b/P102_InitContracts/code/SwapRouter.sol index 0e9cbb8..e19dde1 100644 --- a/P102_InitContracts/code/SwapRouter.sol +++ b/P102_InitContracts/code/SwapRouter.sol @@ -3,21 +3,77 @@ pragma solidity ^0.8.24; pragma abicoder v2; import "./interfaces/ISwapRouter.sol"; +import "./interfaces/IPool.sol"; +import "./interfaces/IPoolManager.sol"; contract SwapRouter is ISwapRouter { + IPoolManager public poolManager; + + constructor(address _poolManager) { + poolManager = IPoolManager(_poolManager); + } + + // 确定输入的 token 交易 function exactInput( ExactInputParams calldata params - ) external payable override returns (uint256 amountOut) {} + ) external payable override returns (uint256 amountOut) { + // 用 index 记录当前正在读取的 index + uint256 index = 0; + // while 循环遍历 indexPath,获取每个 pool 的价格 + while (index < params.indexPath.length) { + address _pool = poolManager.getPool( + params.tokenIn, + params.tokenOut, + params.indexPath[index] + ); + IPool pool = IPool(_pool); + // TODO 交易 + bytes memory data; + // 交易的钱统一转给本合约,最后都完成之后在 swapCallback 中打给用户 + pool.swap(msg.sender, true, 12, 12, data); + amountOut += 2; + index++; + } + } + // 确定输出的 token 交易 function exactOutput( ExactOutputParams calldata params ) external payable override returns (uint256 amountIn) {} + // 确认输入的 token,估算可以获得多少输出的 token function quoteExactInput( QuoteExactInputParams memory params - ) external override returns (uint256 amountOut) {} + ) external view override returns (uint256 amountOut) { + // 用 index 记录当前正在读取的 index + uint256 index = 0; + // while 循环遍历 indexPath,获取每个 pool 的价格 + while (index < params.indexPath.length) { + address _pool = poolManager.getPool( + params.tokenIn, + params.tokenOut, + params.indexPath[index] + ); + IPool pool = IPool(_pool); + uint160 sqrtPriceX96 = pool.sqrtPriceX96(); + // TODO 计算 amountOut + amountOut = sqrtPriceX96; + // 更新 index + index++; + } + } + // 确认输出的 token,估算需要多少输入的 token function quoteExactOutput( QuoteExactOutputParams memory params - ) external override returns (uint256 amountIn) {} + ) external view override returns (uint256 amountIn) {} + + function swapCallback( + uint256 amount0In, + uint256 amount1In, + bytes calldata data + ) external override { + // 每次 swap 后 pool 会调用这个方法 + // 最后一次 swap 完成后这里统一把钱打给用户 + } } diff --git a/P102_InitContracts/code/interfaces/IFactory.sol b/P102_InitContracts/code/interfaces/IFactory.sol deleted file mode 100644 index 467dc09..0000000 --- a/P102_InitContracts/code/interfaces/IFactory.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.24; - -interface IFactory { - function parameters() - external - view - returns (address factory, address token0, address token1, uint24 fee); - - event PoolCreated( - address indexed token0, - address indexed token1, - uint24 indexed fee, - address pool - ); - - function getPool( - address token0, - address token1, - uint24 fee - ) external view returns (address pool); - - function createPool( - address token0, - address token1, - uint24 fee - ) external returns (address pool); -} diff --git a/P102_InitContracts/code/interfaces/IPool.sol b/P102_InitContracts/code/interfaces/IPool.sol deleted file mode 100644 index 293620a..0000000 --- a/P102_InitContracts/code/interfaces/IPool.sol +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.24; - -interface IMintCallback { - function mintCallback( - uint256 amount0Owed, - uint256 amount1Owed, - bytes calldata data - ) external; -} - -interface ISwapCallback { - function swapCallback( - int256 amount0Delta, - int256 amount1Delta, - bytes calldata data - ) external; -} - -interface IPool { - function factory() external view returns (address); - - function token0() external view returns (address); - - function token1() external view returns (address); - - function fee() external view returns (uint24); - - function tickLower() external view returns (int24); - - function tickUpper() external view returns (int24); - - function sqrtPriceX96() external view returns (uint160); - - function tick() external view returns (int24); - - function liquidity() external view returns (uint128); - - function initialize( - uint160 sqrtPriceX96, - int24 tickLower, - int24 tickUpper - ) external; - - event Mint( - address sender, - address indexed owner, - uint128 amount, - uint256 amount0, - uint256 amount1 - ); - - function mint( - address recipient, - uint128 amount, - bytes calldata data - ) external returns (uint256 amount0, uint256 amount1); - - event Collect( - address indexed owner, - address recipient, - uint128 amount0, - uint128 amount1 - ); - - function collect( - address recipient - ) external returns (uint128 amount0, uint128 amount1); - - event Burn( - address indexed owner, - uint128 amount, - uint256 amount0, - uint256 amount1 - ); - - function burn( - uint128 amount - ) external returns (uint256 amount0, uint256 amount1); - - event Swap( - address indexed sender, - address indexed recipient, - int256 amount0, - int256 amount1, - uint160 sqrtPriceX96, - uint128 liquidity, - int24 tick - ); - - function swap( - address recipient, - bool zeroForOne, - int256 amountSpecified, - uint160 sqrtPriceLimitX96, - bytes calldata data - ) external returns (int256 amount0, int256 amount1); -} diff --git a/P102_InitContracts/code/interfaces/IPoolManager.sol b/P102_InitContracts/code/interfaces/IPoolManager.sol deleted file mode 100644 index 83c65c3..0000000 --- a/P102_InitContracts/code/interfaces/IPoolManager.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.24; -pragma abicoder v2; - -interface IPoolManager { - struct PoolKey { - address token0; - address token1; - uint24 fee; - } - - function getPools() external view returns (PoolKey[] memory pools); - - function getTokens() external view returns (address[] memory tokens); - - function getTokenPools( - address token - ) external view returns (PoolKey[] memory pools); - - struct PoolInfo { - // the current protocol fee as a percentage of the swap fee taken on withdrawal - // represented as an integer denominator (1/x)% - uint8 feeProtocol; - // tick range - int24 tickLower; - int24 tickUpper; - // the current tick - int24 tick; - // the current price - uint160 sqrtPriceX96; - } - - function getPoolInfo( - address token0, - address token1, - uint24 fee - ) external view returns (PoolInfo memory poolInfo); - - struct CreateAndInitializeParams { - address token0; - address token1; - uint24 fee; - int24 tickLower; - int24 tickUpper; - uint160 sqrtPriceX96; - } - - function createAndInitializePoolIfNecessary( - CreateAndInitializeParams calldata params - ) external payable returns (address pool); -} diff --git a/P102_InitContracts/code/interfaces/IPositionManager.sol b/P102_InitContracts/code/interfaces/IPositionManager.sol deleted file mode 100644 index 3791d88..0000000 --- a/P102_InitContracts/code/interfaces/IPositionManager.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.24; -pragma abicoder v2; - -interface IPositionManager { - function getPositions( - address owner - ) external view returns (uint256[] memory positionIds); - - struct PositionInfo { - // address owner; - address token0; - address token1; - uint24 fee; - int128 liquidity; - // tick range - int24 tickLower; - int24 tickUpper; - uint256 tokensOwed0; - uint256 tokensOwed1; - } - - function getPositionInfo( - uint256 positionId - ) external view returns (PositionInfo memory positionInfo); - - struct MintParams { - address token0; - address token1; - uint24 fee; - uint256 amount0Desired; - uint256 amount1Desired; - address recipient; - uint256 deadline; - } - - function mint( - MintParams calldata params - ) - external - payable - returns ( - uint256 positionId, - uint128 liquidity, - uint256 amount0, - uint256 amount1 - ); - - function burn( - uint256 positionId - ) external returns (uint256 amount0, uint256 amount1); - - function collect( - uint256 positionId, - address recipient - ) external returns (uint256 amount0, uint256 amount1); -} diff --git a/P102_InitContracts/code/interfaces/ISwapRouter.sol b/P102_InitContracts/code/interfaces/ISwapRouter.sol deleted file mode 100644 index bcddf12..0000000 --- a/P102_InitContracts/code/interfaces/ISwapRouter.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity ^0.8.24; -pragma abicoder v2; - -interface ISwapRouter { - struct ExactInputParams { - address tokenIn; - address tokenOut; - address recipient; - uint256 deadline; - uint256 amountIn; - uint256 amountOutMinimum; - uint160 sqrtPriceLimitX96; - } - - function exactInput( - ExactInputParams calldata params - ) external payable returns (uint256 amountOut); - - struct ExactOutputParams { - address tokenIn; - address tokenOut; - address recipient; - uint256 deadline; - uint256 amountOut; - uint256 amountInMaximum; - uint160 sqrtPriceLimitX96; - } - - function exactOutput( - ExactOutputParams calldata params - ) external payable returns (uint256 amountIn); - - struct QuoteExactInputParams { - address tokenIn; - address tokenOut; - uint256 amountIn; - uint160 sqrtPriceLimitX96; - } - - function quoteExactInput( - QuoteExactInputParams memory params - ) external returns (uint256 amountOut); - - struct QuoteExactOutputParams { - address tokenIn; - address tokenOut; - uint256 amount; - uint160 sqrtPriceLimitX96; - } - - function quoteExactOutput( - QuoteExactOutputParams memory params - ) external returns (uint256 amountIn); -} diff --git a/P102_InitContracts/readme.md b/P102_InitContracts/readme.md index 5eb90bb..2d3b304 100644 --- a/P102_InitContracts/readme.md +++ b/P102_InitContracts/readme.md @@ -30,92 +30,85 @@ Wtfswap 的合约开发我们继续基于之前在[《合约本地开发和测 // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.24; -interface IMintCallback { - function mintCallback( - uint256 amount0Owed, - uint256 amount1Owed, - bytes calldata data - ) external; -} - -interface ISwapCallback { - function swapCallback( - int256 amount0Delta, - int256 amount1Delta, - bytes calldata data - ) external; -} - -interface IPool { - function factory() external view returns (address); - - function token0() external view returns (address); - - function token1() external view returns (address); - - function fee() external view returns (uint24); - - function tickLower() external view returns (int24); - - function tickUpper() external view returns (int24); - - function sqrtPriceX96() external view returns (uint160); - - function tick() external view returns (int24); - - function liquidity() external view returns (uint128); - - function initialize( - uint160 sqrtPriceX96, - int24 tickLower, - int24 tickUpper - ) external; - - event Mint( - address sender, - address indexed owner, - uint128 amount, - uint256 amount0, - uint256 amount1 - ); +import "./interfaces/IPool.sol"; +import "./interfaces/IFactory.sol"; + +contract Pool is IPool { + /// @inheritdoc IPool + address public immutable override factory; + /// @inheritdoc IPool + address public immutable override token0; + /// @inheritdoc IPool + address public immutable override token1; + /// @inheritdoc IPool + uint24 public immutable override fee; + /// @inheritdoc IPool + int24 public immutable override tickLower; + /// @inheritdoc IPool + int24 public immutable override tickUpper; + + /// @inheritdoc IPool + uint160 public override sqrtPriceX96; + /// @inheritdoc IPool + int24 public override tick; + /// @inheritdoc IPool + uint128 public override liquidity; + + // 用一个 mapping 来存放所有 Position 的信息 + mapping(address => Position) public positions; + + constructor() { + // constructor 中初始化 immutable 的常量 + // Factory 创建 Pool 时会通 new Pool{salt: salt}() 的方式创建 Pool 合约,通过 salt 指定 Pool 的地址,这样其他地方也可以推算出 Pool 的地址 + // 参数通过读取 Factory 合约的 parameters 获取 + // 不通过构造函数传入,因为 CREATE2 会根据 initcode 计算出新地址(new_address = hash(0xFF, sender, salt, bytecode)),带上参数就不能计算出稳定的地址了 + (factory, token0, token1, tickLower, tickUpper, fee) = IFactory( + msg.sender + ).parameters(); + } + + function initialize(uint160 sqrtPriceX96_) external override { + // 初始化 Pool 的 sqrtPriceX96 + sqrtPriceX96 = sqrtPriceX96_; + } function mint( address recipient, uint128 amount, bytes calldata data - ) external returns (uint256 amount0, uint256 amount1); - - event Collect( - address indexed owner, - address recipient, - uint128 amount0, - uint128 amount1 - ); + ) external override returns (uint256 amount0, uint256 amount1) { + // 基于 amount 计算出当前需要多少 amount0 和 amount1 + // TODO 当前先写个假的 + (amount0, amount1) = (amount / 2, amount / 2); + // 把流动性记录到对应的 position 中 + positions[recipient].liquidity += amount; + // 回调 mintCallback + IMintCallback(recipient).mintCallback(amount0, amount1, data); + // TODO 检查钱到位了没有,如果到位了对应修改相关信息 + } function collect( address recipient - ) external returns (uint128 amount0, uint128 amount1); - - event Burn( - address indexed owner, - uint128 amount, - uint256 amount0, - uint256 amount1 - ); + ) external override returns (uint128 amount0, uint128 amount1) { + // 获取当前用户的 position,TODO recipient 应该改为 msg.sender + Position storage position = positions[recipient]; + // TODO 把钱退给用户 recipient + // 修改 position 中的信息 + position.tokensOwed0 -= amount0; + position.tokensOwed1 -= amount1; + } function burn( uint128 amount - ) external returns (uint256 amount0, uint256 amount1); - - event Swap( - address indexed sender, - address indexed recipient, - int256 amount0, - int256 amount1, - uint160 sqrtPriceX96, - uint128 liquidity, - int24 tick - ); + ) external override returns (uint256 amount0, uint256 amount1) { + // 修改 positions 中的信息 + positions[msg.sender].liquidity -= amount; + // 获取燃烧后的 amount0 和 amount1 + // TODO 当前先写个假的 + (amount0, amount1) = (amount / 2, amount / 2); + positions[msg.sender].tokensOwed0 += amount0; + positions[msg.sender].tokensOwed1 += amount1; + } function swap( address recipient, @@ -123,9 +116,8 @@ interface IPool { int256 amountSpecified, uint160 sqrtPriceLimitX96, bytes calldata data - ) external returns (int256 amount0, int256 amount1); + ) external override returns (int256 amount0, int256 amount1) {} } - ``` 其它合约对应的代码可以参考 [code](./code/) 查看。