阿凡達泰山眾籌商城開發(系統)丨阿凡達泰山眾籌系統開發(開發穩定版)

xiaofufu發表於2023-03-01

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<i>,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);


  }開發案例及設計:MrsFu123


  //根據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&lt;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)&gt;=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)&gt;=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&gt;=amountOutMin,'UniswapV2Router:INSUFFICIENT_OUTPUT_AMOUNT');


  IWETH(WETH).withdraw(amountOut);


  TransferHelper.safeTransferETH(to,amountOut);


  }


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69956839/viewspace-2937552/,如需轉載,請註明出處,否則將追究法律責任。

相關文章