当前位置:网站首页>IDO代币预售合约系统开发技术详细
IDO代币预售合约系统开发技术详细
2022-08-02 21:56:00 【DD_MrsFu123】
Uniswap代码结构
Uniswap智能合约代码由两个github项目组成。一个是core,一个是periphery。
core偏核心逻辑,单个swap的逻辑。periphery偏外围服务,一个个swap的基础上构建服务。单个swap,两种代币形成的交易对,俗称“池子”。每个交易对有一些基本属性:reserve0/reserve1以及total supply。reserve0/reserve1是交易对的两种代币的储存量。total supply是当前流动性代币的总量。每个交易对都对应一个流动性代币(LPT - liquidity provider token)。简单的说,LPT记录了所有流动性提供者的贡献。所有流动性代币的总和就是total supply。Uniswap协议的思想是reserve0*reserve1的乘积不变。
Periphery逻辑
核心逻辑实现在UniswapV2Router02.sol中。称为Router,因为Periphery实现了“路由”,支持各个swap之间的连接。基本上实现了三个功能:1/ add liquidity(增加流动性)2/remove liqudity (抽取流动性) 3/ swap(交换)。
1. add liqudity
增加流动性,就是同时提供两种代币。因为代币有可能是ETH,针对不同情况有不同的接口。逻辑类似。
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external virtual override ensure(deadline) returns (uint amountA, uint amountB, uint liquidity)
add liqudity查看之前有没有创建相应的交易对。如果有相应的交易对,确定目前的兑换比例在希望的范围内(期望amountDesired和不低于amountMin)。如果兑换比例OK,将相应的代币转入对应的交易对池子,并调用其的mint函数。
2. remove liqudity
提供流动性的相反的操作就是抽取流动性。也就是说,流动性提供者不再提供相应的流动性:
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) public virtual override ensure(deadline) returns (uint amountA, uint amountB) {
liquidity是抽取的流动性的量。amountMin是抽取代币的最小的个数。to是抽取代币的目标地址。deadline是个有意思的设计:抽取的操作有时效性。超过了一定的deadline(区块高度),这次抽取操作看成无效。
先收回需要抽取的Token,并且销毁:
IUniswapV2Pair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair
(uint amount0, uint amount1) = IUniswapV2Pair(pair).burn(to);
3. swap
swap是普通用户进行代币交易的操作。普通用户通过swap操作实现两种token之间的交易。
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external virtual override ensure(deadline) returns (uint[] memory amounts) {
Uniswap支持多种代币的交换。具体的含义是,Uniswap提供了多级交易池的路由功能。举个例子,已有两个交易对TokenA-TokenB,以及TokenB-TokenC,通过swap接口,可以实现TokenA-TokenC的交换,其中经过的TokenA-TokenB,TokenB-TokenC,称为路径(path)。amountIn是路径中的第一个代币的数量,amountOutMin是期望的交换后的最少的数量。
amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT');
amounts是每个路径上的交换后的数量。amounts[amounts.length-1]也就是最后一条路径的输出数量。注意,UniswapV2Library.getAmountsOut的实现(在获取每个交易对的reserve信息后,调用getAmountOut函数):
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
uint amountInWithFee = amountIn.mul(997);
uint numerator = amountInWithFee.mul(reserveOut);
uint denominator = reserveIn.mul(1000).add(amountInWithFee);
amountOut = numerator / denominator;
}
注意,其中的997/1000的系数。在进入每个交易池之前,进入的金额先扣除了0.3%的本金。这个就是交易费。注意的是,路径上的交易池,每个池子都收。有点像高速收费站,一段段的收。
TransferHelper.safeTransferFrom(
path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]
);
将代币path[0],转入到交易对,数量为amounts[0]。转入代币后,进行真正的swap操作:
function _swap(uint[] memory amounts, address[] memory path, address _to) internal virtual {
for (uint i; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0,) = UniswapV2Library.sortTokens(input, output);
uint amountOut = amounts[i + 1];
(uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0));
address to = i < path.length - 2 ? UniswapV2Library.pairFor(factory, output, path[i + 2]) : _to;
IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output)).swap(
amount0Out, amount1Out, to, new bytes(0)
);
}
}
边栏推荐
- 用于中文文本分类的中文停用词
- 成功解决TypeError: can‘t multiply sequence by non-int of type ‘float‘
- RuoYi-App启动教程
- Yocto系列讲解[实战篇]85 - 制作ubi镜像和自动挂载ubifs文件系统
- 宝塔搭建实测-基于ThinkPHP5.1的wms进销存源码
- GameStop NFT 市场分析
- [Dry goods] Best practice of sub-library and sub-table
- In-depth study TypeScript TypeScript 】 【 class (under)
- Win10怎么开启自带的游戏录屏功能?
- 学习基因富集工具DAVID(3)
猜你喜欢
“百日行动”进行时:700余交通安全隐患被揪出
gdb调试简要总结
测试ESP32-Zigbee转发命令 : 滑轨、继电器控制
了解 NFT 质押:Web3 中赚取被动收益的另一种方式
「X」to「Earn」:赛道现状与破局思路
【使用pyside2遇到的问题】This application failed to start because no Qt platform plugin could be initialized.
【Unity】Unity开发进阶(六)UnityEvent使用与源码解析
Flink优化的方方面面
【STM32学习3】DMA基础操作
【TypeScript】深入学习TypeScript类(上)
随机推荐
软件测试到底自学还是报班?
Add and delete all these years, finally planted in MySQL architecture design!
如何通过开源数据库管理工具 DBeaver 连接 TDengine
【STM32学习3】DMA基础操作
执子手,到永恒
IP Protocol (Internet Protocol)
CS5213 chip | HDMI to VGA converter chip data sharing
What is the core business model of the "advertising e-commerce" that has recently become popular in the circle of friends, and is the advertising revenue really reliable?
一个很少见但很有用的SQL功能
万物智联时代,悄然走入生活
牛客每日刷题之链表
网络运维系列:健康检查的方式
Auto.js脚本程序打包
go exec 包
测试ESP32-Zigbee转发命令 : 滑轨、继电器控制
IP协议(网际协议)
FastCorrect:语音识别快速纠错模型丨RTC Dev Meetup
MySQL删除数据后,释放磁盘空间
【STM32学习2】存储器相关概念与操作
浅读一下dotenv的主干逻辑的源码