火币链/波场链/OK链/币安链盲盒游戏开发功能版,火币链/波场链/OK链/币安链盲盒游戏系统开发(成熟及方案)

简介: The explanation of the new retail is that individuals and enterprises, relying on the Internet, upgrade and transform the production, circulation and sales process of goods by using advanced technical means such as big data, artificial intelligence and psychological knowledge, thus reshaping the bus

The explanation of the new retail is that individuals and enterprises, relying on the Internet, upgrade and transform the production, circulation and sales process of goods by using advanced technical means such as big data, artificial intelligence and psychological knowledge, thus reshaping the business structure and ecosystem, and deeply integrating online services, offline experience and modern logistics.

  //SWAP(supporting fee-on-transfer tokens)

  //requires the initial amount to have already been sent to the first pair

  //交易方法,支持转账扣手续费的代币

  //需要先将amounts[0]的金额已经转到第一个pair地址(即path[0]+path[1]组成的pair)!

  function _swapSupportingFeeOnTransferTokens(address[]memory path,address _to)internal virtual{

  for(uint i;i<path.length-1;i++){

  //得到进/出token地址

  (address input,address output)=(path,path[i+1]);

  //排序得到token0

  (address token0,)=UniswapV2Library.sortTokens(input,output);

  //获取pair

  IUniswapV2Pair pair=IUniswapV2Pair(UniswapV2Library.pairFor(factory,input,output));

  uint amountInput;//输入金额

  uint amountOutput;//输入金额

  {//scope to avoid stack too deep errors避免堆栈太深错误,用{}括部分临时变量

  //或许两个币的储备量

  (uint reserve0,uint reserve1,)=pair.getReserves();

  //根据input,token0得出inToken的储备量,outToken的储备量

  (uint reserveInput,uint reserveOutput)=input==token0?(reserve0,reserve1):(reserve1,reserve0);

  //查询交易对的inToken余额,减掉最后记录的储备量,就是交易对实际获取到的inToken数量(TODO和_swap的区别就在这里,不是使用计算来的amounts[0]作为输入,而是通过查询pair余额再减去最后更新的储备量得到实际pair到账额!)

  amountInput=IERC20(input).balanceOf(address(pair)).sub(reserveInput);

  //通过实际得到的input量,计算实际会输出的output数量

  amountOutput=UniswapV2Library.getAmountOut(amountInput,reserveInput,reserveOutput);

  }

  //根据token0,input得到amount0需要out,还是amount1是out,;注意其中之一一定是0,即入token的金额,不需要pair转出

  (uint amount0Out,uint amount1Out)=input==token0?(uint(0),amountOutput):(amountOutput,uint(0));

  //如果i小于path长度-2,就表示还需要继续交易,所以to是下一个交易对,如果一样就表示path结束了,to就是参数中的_to

  address to=i<path.length-2?UniswapV2Library.pairFor(factory,output,path[i+2]):_to;

  //调用pair的swap方法,其中一个out是0,另一个是要转出的金额,内部是转出输出量,并校验交易是否正确,更新储备量

  pair.swap(amount0Out,amount1Out,to,new bytes(0));

  }

  }

  /**

  TODO带supportingFeeOnTransfer方法都是通过余额的方式计算输入/出

  下面的三个方法,都是swapExactXXXForXX,而没有swapXXXForExactXX

  如果是自己开发合约调用,可以随意选用哪个swap

  在uniswap中,如果滑点改成49,会自动切换带supportingFeeOnTransfer的方法

  还有些其他情况也会自动切,这个会前端的可以看看代码,什么情况下,前端会选择使用带supportingFeeOnTransfer的方法去交易

  */

  //输入精确的token,换取另一个token,支持转账时扣手续费的token

  function swapExactTokensForTokensSupportingFeeOnTransferTokens(

  uint amountIn,//输入金额

  uint amountOutMin,//最小输出金额,该金额只要够小,交易就一定可以成功

  address[]calldata path,//交换路径

  address to,

  uint deadline

  )external virtual override ensure(deadline){

  //将输入金额转到第一个pair地址

  TransferHelper.safeTransferFrom(

  path[0],msg.sender,UniswapV2Library.pairFor(factory,path[0],path[1]),amountIn

  );

  //查询to用户当前最终输出token的余额

  uint balanceBefore=IERC20(path[path.length-1]).balanceOf(to);

  //调用内部交易方法

  _swapSupportingFeeOnTransferTokens(path,to);

  //通过查询余额的方式,校验交易前后的余额差,大于等于最小输出!

  require(

  IERC20(path[path.length-1]).balanceOf(to).sub(balanceBefore)>=amountOutMin,

  'UniswapV2Router:INSUFFICIENT_OUTPUT_AMOUNT'

  );

  }

  //输入精确eth换取另一个token

  function swapExactETHForTokensSupportingFeeOnTransferTokens(

  uint amountOutMin,

  address[]calldata path,

  address to,

  uint deadline

  )

  external

  virtual

  override

  payable

  ensure(deadline)

  {

  require(path[0]==WETH,'UniswapV2Router:INVALID_PATH');

  //将eth转成weth,并转给第一个pair地址

  uint amountIn=msg.value;

  IWETH(WETH).deposit{value:amountIn}();

  assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory,path[0],path[1]),amountIn));

  //跟上面方法一样,通过查询余额的方式校验

  uint balanceBefore=IERC20(path[path.length-1]).balanceOf(to);

  _swapSupportingFeeOnTransferTokens(path,to);

  require(

  IERC20(path[path.length-1]).balanceOf(to).sub(balanceBefore)>=amountOutMin,

  'UniswapV2Router:INSUFFICIENT_OUTPUT_AMOUNT'

  );

  }

  //输入精确token换取输出eth,

  function swapExactTokensForETHSupportingFeeOnTransferTokens(

  uint amountIn,

  uint amountOutMin,

  address[]calldata path,

  address to,

  uint deadline

  )

  external

  virtual

  override

  ensure(deadline)

  {

  require(path[path.length-1]==WETH,'UniswapV2Router:INVALID_PATH');

  TransferHelper.safeTransferFrom(

  path[0],msg.sender,UniswapV2Library.pairFor(factory,path[0],path[1]),amountIn

  );

  _swapSupportingFeeOnTransferTokens(path,address(this));

  uint amountOut=IERC20(WETH).balanceOf(address(this));

  require(amountOut>=amountOutMin,'UniswapV2Router:INSUFFICIENT_OUTPUT_AMOUNT');

  IWETH(WETH).withdraw(amountOut);

  TransferHelper.safeTransferETH(to,amountOut);

  }

相关文章
|
3月前
|
Java 区块链 数据安全/隐私保护
马蹄链佛萨奇2.0开发运营版丨佛萨奇2.0马蹄链智能合约系统开发(详细及案例)丨佛萨奇2.0马蹄链源码
  FORCE原力第一个推出的是Classic经典矩阵   Classic经典矩阵总共有12个矩阵,最低的矩阵只要5U即可参与(早期加入的朋友都可以享受半价优惠),下一个矩阵的价格是上一级的两倍。
|
11月前
|
存储 算法 安全
BSC链质押项目系统开发|DAPP开发案例
区块链属于分布式账本技术的一种,每一条链都相当于一个独立的账本
|
存储 安全 算法
|
区块链
马蹄链智能合约系统DAPP开发源码实例分析
马蹄链智能合约系统DAPP开发源码实例分析
|
资源调度 前端开发 JavaScript
马蹄链智能合约系统开发功能需求丨MetaForce佛萨奇2.0波场链
马蹄链智能合约系统开发功能需求丨MetaForce佛萨奇2.0波场链
117 0
|
区块链 数据安全/隐私保护
马蹄链DAPP合约模式系统开发技术(原理)
马蹄链DAPP合约模式系统开发技术(原理)
DAPP马蹄链系统开发(方案及项目)丨DAPP马蹄链系统开发(源码详情)
  Metaverse is a virtual world constructed by humans using digital technology,mapped or transcended by the real world,and can interact with the real world.It is a digital living space with a new social system.
|
区块链 vr&ar
马蹄链开发方案丨马蹄链系统开发(说明及功能)丨马蹄链系统源码部署
智能合约是区块链技术世界不可或缺的一部分。 这些合约是软件程序,当满足了规定的条件时,在两个或多个参与方之间执行特定的任务。从本质上说,它就像一个自执行的常规合约,不需要中介,因为它依赖于它的编程值。
|
区块链 数据安全/隐私保护 网络协议
马蹄链dapp开发规则丨马蹄链智能合约dapp质押挖矿系统开发详细丨马蹄链dapp系统源码
区块链虽然是一个新兴的概念,但它依赖的技术一点也不新,如非对称加密技术、P2P 网络协议等。区块链本质上是一个基于 P2P 的价值传输协议