阿凡達Avatar泰山眾籌系統(tǒng)開發(fā)(開發(fā)規(guī)則)丨泰山眾籌阿凡達Avatar系統(tǒng)開發(fā)詳情方案
Specifically,new retail is consumer-centered,based on the digitalization of people,goods and services,supply chain and other links,connecting various consumption scenarios through data flow,including smart phones,mobile terminals,computers,physical stores,and new ways that can be realized in the future,and using digital technology to realize the comprehensive integration of physical and virtual retail supply chain,transaction delivery chain,and service chain,It provides consumers with a seamless consumption experience covering all channels,and is an efficient and inclusive pan-retail business characterized by logistics distribution replacing physical delivery.
//****SWAP****
//requires the initial amount to have already been sent to the first pair
//交易方法
//需要先將amounts[0]的金額已經(jīng)轉(zhuǎn)到第一個pair地址(即path[0]+path[1]組成的pair)!
function _swap(uint[]memory amounts,address[]memory path,address _to)internal virtual{
for(uint i;i<path.length-1;i++){//遍歷整個path
//得到進/出token地址
(address input,address output)=(path<i>,path[i+1]);
//排序得到token0
(address token0,)=UniswapV2Library.sortTokens(input,output);
//獲取到output幣種的輸出量!
uint amountOut=amounts[i+1];案例開發(fā)及I35功能7O98源碼O7I8
//根據(jù)token0,input得到amount0需要out,還是amount1是out,;注意其中之一一定是0,即入token的金額,不需要pair轉(zhuǎn)出
(uint amount0Out,uint amount1Out)=input==token0?(uint(0),amountOut):(amountOut,uint(0));
//如果i小于path長度-2,就表示還需要繼續(xù)交易,所以to是下一個交易對,如果一樣就表示path結(jié)束了,to就是參數(shù)中的_to
address to=i<path.length-2?UniswapV2Library.pairFor(factory,output,path[i+2]):_to;
//調(diào)用pair的swap方法,其中一個out是0,另一個是要轉(zhuǎn)出的金額,內(nèi)部是轉(zhuǎn)出輸出量,并校驗交易是否正確,更新儲備量
IUniswapV2Pair(UniswapV2Library.pairFor(factory,input,output)).swap(
amount0Out,amount1Out,to,new bytes(0)
);需求及模式介紹:MrsFu123
}
}
//輸入精確的token,換取另一個token(輸出量不確定)
function swapExactTokensForTokens(
uint amountIn,//輸入金額
uint amountOutMin,//最小輸出金額
address[]calldata path,//交易路徑
address to,
uint deadline
)external virtual override ensure(deadline)returns(uint[]memory amounts){
//通過getAmountsOut獲取整個path完整路徑的輸入/出量,下標(biāo)0是用戶實際輸入額,最后一個位置是實際輸出額
amounts=UniswapV2Library.getAmountsOut(factory,amountIn,path);
//需要滿足計算得來最終輸出量大于等于最小輸出金額
require(amounts[amounts.length-1]>=amountOutMin,'UniswapV2Router:INSUFFICIENT_OUTPUT_AMOUNT');
//先將amounts[0]入金額轉(zhuǎn)入第一個pair!!
TransferHelper.safeTransferFrom(
path[0],msg.sender,UniswapV2Library.pairFor(factory,path[0],path[1]),amounts[0]
);
//調(diào)用內(nèi)部_swap方法
_swap(amounts,path,to);
}
//輸入不確定數(shù)量A,換取精確輸出的B(例:精確輸出1個token,正常100u可以換1個token,由于發(fā)交易后其他人先交易過,導(dǎo)致價格變了,可能95或者105可以買1個token,95肯定交易通過,如果amountInMax是102,該交易就無法成交,回退)
function swapTokensForExactTokens(
uint amountOut,//精確的輸出額
uint amountInMax,//最大允許的輸入量
address[]calldata path,
address to,
uint deadline
)external virtual override ensure(deadline)returns(uint[]memory amounts){
//根據(jù)getAmountsIn計算出輸入輸出量
amounts=UniswapV2Library.getAmountsIn(factory,amountOut,path);
//需要第一個輸入量小于等于計算來的實際輸入量
require(amounts[0]<=amountInMax,'UniswapV2Router:EXCESSIVE_INPUT_AMOUNT');
//將計算得來的金額amounts[0]轉(zhuǎn)入第一個pair
TransferHelper.safeTransferFrom(
path[0],msg.sender,UniswapV2Library.pairFor(factory,path[0],path[1]),amounts[0]
);
//調(diào)用內(nèi)部_swap方法
_swap(amounts,path,to);
}
//輸入精確的eth換取不定量的token,對應(yīng)swapExactTokensForTokens,不過輸入的是eth,換成weth就一樣了
function swapExactETHForTokens(uint amountOutMin,address[]calldata path,address to,uint deadline)
external
virtual
override
payable
ensure(deadline)
returns(uint[]memory amounts)
{
//要求path[0]是weth地址
require(path[0]==WETH,'UniswapV2Router:INVALID_PATH');
//通過getAmountsOut,輸入額是msg.value
amounts=UniswapV2Library.getAmountsOut(factory,msg.value,path);
//需要滿足計算得來最終輸出量大于等于最小輸出金額
require(amounts[amounts.length-1]>=amountOutMin,'UniswapV2Router:INSUFFICIENT_OUTPUT_AMOUNT');
//pair中只會存weth,沒有eth
IWETH(WETH).deposit{value:amounts[0]}();//兌換成weth
//將weth轉(zhuǎn)入到第一個pair
assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory,path[0],path[1]),amounts[0]));
//調(diào)用內(nèi)部_swap方法
_swap(amounts,path,to);
}
//輸入不定量的A,換取精確的輸出ETH,對應(yīng)swapTokensForExactTokens,只是內(nèi)部將weth轉(zhuǎn)成eth再給用戶
function swapTokensForExactETH(uint amountOut,uint amountInMax,address[]calldata path,address to,uint deadline)
external
virtual
override
ensure(deadline)
returns(uint[]memory amounts)
{
//path最后一個輸出地址是weth
require(path[path.length-1]==WETH,'UniswapV2Router:INVALID_PATH');
//
amounts=UniswapV2Library.getAmountsIn(factory,amountOut,path);
//需要第一個輸入量小于等于計算來的實際輸入量
require(amounts[0]<=amountInMax,'UniswapV2Router:EXCESSIVE_INPUT_AMOUNT');
//將計算得來的金額amounts[0]轉(zhuǎn)入第一個pair
TransferHelper.safeTransferFrom(
path[0],msg.sender,UniswapV2Library.pairFor(factory,path[0],path[1]),amounts[0]
);
//調(diào)用內(nèi)部_swap方法,注意第三個參數(shù)改成了當(dāng)前路由地址!
_swap(amounts,path,address(this));
//交換成功后,將weth轉(zhuǎn)換成eth,再轉(zhuǎn)給to
IWETH(WETH).withdraw(amounts[amounts.length-1]);
TransferHelper.safeTransferETH(to,amounts[amounts.length-1]);
}
//輸入精確的A換取不定量的eth swapExactTokensForTokens只是輸出是eth
function swapExactTokensForETH(uint amountIn,uint amountOutMin,address[]calldata path,address to,uint deadline)
external
virtual
override
ensure(deadline)
returns(uint[]memory amounts)
{
//path最后一個輸出地址是weth
require(path[path.length-1]==WETH,'UniswapV2Router:INVALID_PATH');
//
amounts=UniswapV2Library.getAmountsOut(factory,amountIn,path);
//注意輸出要大于最小輸出
require(amounts[amounts.length-1]>=amountOutMin,'UniswapV2Router:INSUFFICIENT_OUTPUT_AMOUNT');
//
TransferHelper.safeTransferFrom(
path[0],msg.sender,UniswapV2Library.pairFor(factory,path[0],path[1]),amounts[0]
);
//調(diào)用內(nèi)部_swap方法,注意第三個參數(shù)改成了當(dāng)前路由地址!
_swap(amounts,path,address(this));
//交換成功后,將weth轉(zhuǎn)換成eth,再轉(zhuǎn)給to
IWETH(WETH).withdraw(amounts[amounts.length-1]);
TransferHelper.safeTransferETH(to,amounts[amounts.length-1]);
}
//輸入不定量的ETH換取精確的token輸出,對應(yīng)swapTokensForExactTokens,只是輸入的是eth
function swapETHForExactTokens(uint amountOut,address[]calldata path,address to,uint deadline)
external
virtual
override
payable
ensure(deadline)
returns(uint[]memory amounts)
{
require(path[0]==WETH,'UniswapV2Router:INVALID_PATH');
amounts=UniswapV2Library.getAmountsIn(factory,amountOut,path);
//注意,實際輸入需要小于msg.value,即eth輸入量
require(amounts[0]<=msg.value,'UniswapV2Router:EXCESSIVE_INPUT_AMOUNT');
IWETH(WETH).deposit{value:amounts[0]}();
assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory,path[0],path[1]),amounts[0]));
_swap(amounts,path,to);
//refund dust eth,if any
//如果實際不需要那么多eth,將剩余返還用戶
if(msg.value>amounts[0])TransferHelper.safeTransferETH(msg.sender,msg.value-amounts[0]);
}