dapp丨defi丨nft丨LP流动性挖矿系统开发详细原理及源码

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 流动性挖矿  流动性挖矿是指将加密货币资产质押或出借,以产生额外加密货币形式的高回报或回报的做法。由于各种创新,这种去中心化金融的应用近大受欢迎。流动性挖矿是当前DeFi行业较大的增长驱动力。

流动性挖矿

  流动性挖矿是指将加密货币资产质押或出借,以产生额外加密货币形式的高回报或回报的做法。由于各种创新,这种去中心化金融的应用近大受欢迎。流动性挖矿是当前DeFi行业较大的增长驱动力。

  简而言之,流动性挖矿激励流动性提供者(LP)在一个基于智能合约的流动性池中持有或锁定他们的加密资产。

  流动性挖矿参与者获得代币奖励作为额外补偿时,流动性挖掘就会发生,并且在Compound向其平台用户发布其COMP治理代币后变得突出。

  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 pai

  (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)

  );

  }

  }

  原理比较简单,针对每一条路径,调用交易对的swap操作。

  Core逻辑

  Core逻辑实现了单个交易对的逻辑。通过UniswapV2Factory可以创建一个个Pair(交易池)。每个具体实现逻辑在UniswapV2Pair中。

  1.mint

  每个交易对创建流动性。

  function mint(address to)external lock returns(uint liquidity){

  因为在调用mint函数之前,在addLiquidity函数已经完成了转账,所以,从这个函数的角度,两种代币数量的计算方式如下:

  uint balance0=IERC20(token0).balanceOf(address(this));

  uint balance1=IERC20(token1).balanceOf(address(this));

  uint amount0=balance0.sub(_reserve0);

  uint amount1=balance1.sub(_reserve1);

  当前的balance是当前的reserve加上注入的流动性的代币数量。

  uint _totalSupply=totalSupply;//gas savings,must be defined here since totalSupply can update in _mintFee

  if(_totalSupply==0){

  liquidity=Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);

  _mint(address(0),MINIMUM_LIQUIDITY);//permanently lock the first MINIMUM_LIQUIDITY tokens

  }else{

  liquidity=Math.min(amount0.mul(_totalSupply)/_reserve0,amount1.mul(_totalSupply)/_reserve1);

  }

  _mint(to,liquidity);

  流动性liquidity的计算方式在第一次提供流动性时和其他时候稍稍不同。第一次提供流动性的计算公式如下:

  liquidity=sqrt(x0*y0)-min

  其中min是10^3。也就是说,第一次提供流动性是有最小流动性要求的。其他提供流动性的计算公式如下:

  liquidity=min((x0/reserve0totalsupply),(y0/reserve1totalsupply))

  也就说,按照注入的流动性和当前的reserve的占比一致。

  2.burn

  burn函数用在抽取流动性。burn逻辑和mint逻辑类似。

  function burn(address to)external lock returns(uint amount0,uint amount1){

  3.swap

  swap函数实现两种代币的兑换。

  function swap(uint amount0Out,uint amount1Out,address to,bytes calldata data)external lock{

  一个交易池的swap操作支持两个方向的兑换,可以从TokenA换到TokenB,或者TokenB换到TokenA。

  if(amount0Out>0)_safeTransfer(_token0,to,amount0Out);//optimistically transfer tokens

  if(amount1Out>0)_safeTransfer(_token1,to,amount1Out);//optimistically transfer tokens

  因为在swapExactTokensForTokens的getAmountOut函数已经确定兑换处的金额。所以,先直接转账。

  在不做swap之前,balance应该和reserve相等的。通过balance和reserve的差值,可以反推出输入的代币数量:

  uint amount0In=balance0>_reserve0-amount0Out?balance0-(_reserve0-amount0Out):0;

  uint amount1In=balance1>_reserve1-amount1Out?balance1-(_reserve1-amount1Out):0;

  确保反推的输入代币数量不小于零。

  require(amount0In>0||amount1In>0,'UniswapV2:INSUFFICIENT_INPUT_AMOUNT');

  区块链定义:

  区块链是英文“Blockchain”的翻译,这是一个合成词,原始的意思是由多个区块组成的链。广义上讲,区块链是利用链式数据区块结构验证和存储数据,利用分布式的共识机制和数学算法集体生成和更新数据,利用密码学保证了数据的传输和使用安全,利用自动化脚本代码(智能合约)来编程和操作数据的一种全新的去中心化的基础架构与分布式计算范式。

  区块链是共识算法、非对称加密算法、分布式存储技术、P2P网络技术等计算机技术在互联网时代的创新应用模式,区块链数据由所有节点共同维护,每个参与维护节点都能复制获得一份完整记录的拷贝,可以实现在没有中央权威机构的弱信任环境下,分布式地建立一套信任机制,保障系统内数据公开透明、可溯源和难以被非法篡改。

相关文章
|
安全 区块链 数据安全/隐私保护
LP流动性质押挖矿开发模式丨dapp流动性挖矿系统开发源码现成
什么是流动性mining?流动性mining主要是通过提供通证资产进而获取收益。简单来说就是,存入某些通证资产便可对其进行mining。存入某些通证资产便可对其进行mining。之所以会被称为mining也是因为保留了BTCmining的行业说法。流动性mining是一种有助于去中心化通证流通的途径,LP(流动性提供者)通过向流动capital池提供流动性/注入capital,
|
机器学习/深度学习 算法 区块链
DAPP/LP流动性质押挖矿系统开发(代码及案例)
DAPP/LP流动性质押挖矿系统开发(代码及案例)
|
编译器 区块链 数据安全/隐私保护
DAPP合约系统开发|DAPP流动性质押LP系统开发(成熟案例)
智能合约是一种基于区块链技术的代码执行程序,可以对数字资产进行自动化管理和交换
|
存储 区块链
DAPP/LP/DEFI智能合约流动性质押挖矿系统开发(详细及方案)丨源码案例
智能合约事实上是由计算机代码构成的一段程序,其缔结过程是:第一步,参与缔约的双方或多方用户商定后将共同合意制定成一份智能合约;
|
存储 前端开发 JavaScript
dapp/defi智能合约流动性LP质押挖矿系统开发(开发源码案例)丨成熟技术
Dapp:代表去中心化应用程序。它们是在去中心化网络或区块链上运行后端代码(主要用Solidity编写的智能合约)的应用程序。可以使用React、Vue或Angular等前端框架构建Dapp。
|
机器人 PyTorch 区块链
dapp/defi智能合约LP质押系统开发(开发说明)丨成熟技术及源码
 .The trading robot will automatically and continuously issue limit orders to profit from the price difference;
|
存储 算法 安全
dapp/lp/nft/defi质押挖矿开发运营版丨lp/nft/defi/dapp质押挖矿系统开发(逻辑及详情)丨质押挖矿成熟源码案例部署
SYSTEM_CONTRACT_DPOS_STAKE: 由于stake合约地址是由合约名通过sha256计算后base58编码得到的,为固定值;但base58的值可读、可写不便,容易配置出错,因此,对于stake合约的地址配置为合约名;链启动后可以通过该命令查询stake合约地址
|
缓存 算法 安全
浅谈defi/nft/lp/pil/dapp代币智能合约流动性质押挖矿系统开发(技术方案及逻辑)丨代码部署
// Proposal defined a consesensus proposal which can // be gossiped to other node and can be serilized // for persistent store. message Proposal {
|
人工智能 JSON 大数据
DAPP/LP智能合约挖矿分红开发运营版,DAPP/LP智能合约挖矿分红系统开发(详细逻辑及规则)
  Web3.0技术与核心特征:Web3.0是元宇宙的底座,技术包括区块链、人工智能、大数据等技术和用户共识社区(DAO)等,核心特征为用户隐私保护能力加强、去中心化组织形态、价值互联互通、“平行空间”成为现实
|
存储 前端开发 区块链
LP/DAPP单双币流动性质押挖矿开发程序,LP/DAPP单双币流动性质押挖矿系统开发实现技术原理及源码部署
 "Web3.0" is an improvement of "Web2.0". Under this environment, users do not need to create multiple identities on different centralized platforms, but can create a decentralized universal digital identity system to pass through various platforms.
LP/DAPP单双币流动性质押挖矿开发程序,LP/DAPP单双币流动性质押挖矿系统开发实现技术原理及源码部署