Skip to content

Commit

Permalink
feat: init contract code
Browse files Browse the repository at this point in the history
  • Loading branch information
yutingzhao1991 committed Aug 2, 2024
1 parent 162dc5c commit 180130b
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 25 deletions.
8 changes: 8 additions & 0 deletions demo-contract/contracts/wtfswap/Factory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ contract Factory is IFactory {
return pools[tokenA][tokenB];
}

function getPool(
address tokenA,
address tokenB,
uint32 index
) external view override returns (address) {
return pools[tokenA][tokenB][index];
}

function createPool(
address tokenA,
address tokenB,
Expand Down
45 changes: 37 additions & 8 deletions demo-contract/contracts/wtfswap/Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
pragma solidity ^0.8.24;

import "./interfaces/IPool.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "./interfaces/IFactory.sol";

contract Pool is IPool, ERC20 {
contract Pool is IPool {
/// @inheritdoc IPool
address public immutable override factory;
/// @inheritdoc IPool
Expand All @@ -26,32 +25,62 @@ contract Pool is IPool, ERC20 {
/// @inheritdoc IPool
uint128 public override liquidity;

// 用一个 mapping 来存放所有 Position 的信息
mapping(address => Position) public positions;

constructor() {
ERC20("Wtfswap", "WTF-SWAP");
// 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, fee, tickLower, tickUpper) = IFactory(
(factory, token0, token1, tickLower, tickUpper, fee) = IFactory(
msg.sender
).parameters();
}

function initialize(uint160 sqrtPriceX96_) 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
Position storage position = positions[msg.sender];
// 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,
Expand Down
86 changes: 79 additions & 7 deletions demo-contract/contracts/wtfswap/PositionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
Expand All @@ -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 足够的金额,这里才会成功
}
}
61 changes: 58 additions & 3 deletions demo-contract/contracts/wtfswap/SwapRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,76 @@ 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);
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 完成后这里统一把钱打给用户
}
}
6 changes: 6 additions & 0 deletions demo-contract/contracts/wtfswap/interfaces/IFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ interface IFactory {
address tokenB
) external view returns (address[] memory pools);

function getPool(
address tokenA,
address tokenB,
uint32 index
) external view returns (address pool);

function createPool(
address tokenA,
address tokenB,
Expand Down
6 changes: 6 additions & 0 deletions demo-contract/contracts/wtfswap/interfaces/IPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ interface ISwapCallback {
}

interface IPool {
struct Position {
uint128 liquidity;
uint256 tokensOwed0;
uint256 tokensOwed1;
}

function factory() external view returns (address);

function token0() external view returns (address);
Expand Down
16 changes: 9 additions & 7 deletions demo-contract/contracts/wtfswap/interfaces/IPositionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,13 @@ 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 owner;
address token0;
address token1;
uint32 index;
uint24 fee;
int128 liquidity;
// tick range
uint128 liquidity;
int24 tickLower;
int24 tickUpper;
uint256 tokensOwed0;
Expand Down Expand Up @@ -54,4 +50,10 @@ interface IPositionManager {
uint256 positionId,
address recipient
) external returns (uint256 amount0, uint256 amount1);

function mintCallback(
uint256 amount0,
uint256 amount1,
bytes calldata data
) external;
}
6 changes: 6 additions & 0 deletions demo-contract/contracts/wtfswap/interfaces/ISwapRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,10 @@ interface ISwapRouter {
function quoteExactOutput(
QuoteExactOutputParams memory params
) external returns (uint256 amountIn);

function swapCallback(
uint256 amount0In,
uint256 amount1In,
bytes calldata data
) external;
}

0 comments on commit 180130b

Please sign in to comment.