阿凡達泰山眾籌商城開發(系統)丨阿凡達泰山眾籌系統開發(開發穩定版)
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<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);
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69956839/viewspace-2937552/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 阿凡達泰山眾籌開發系統丨阿凡達泰山眾籌系統開發(詳情版)丨阿凡達泰山眾籌原始碼開發原始碼
- Avatar阿凡達泰山眾籌商城開發上線版丨Avatar阿凡達泰山眾籌商城系統開發(開發原始碼)原始碼
- 阿凡達泰山眾籌開發(功能)丨阿凡達泰山眾籌系統開發(成熟方案及案例)
- 阿凡達泰山眾籌開發原理丨阿凡達泰山眾籌系統開發(方案及詳細)
- 阿凡達(泰山眾籌)開發案例版丨阿凡達(泰山眾籌)系統開發(規則及原始碼)原始碼
- 泰山眾籌(阿凡達)系統開發成熟及方案丨泰山眾籌阿凡達開發原始碼功能原始碼
- Avatar阿凡達泰山眾籌開發案例版丨Avatar阿凡達泰山眾籌系統開發(開發邏輯及方案)
- 什麼是阿凡達泰山眾籌系統開發丨阿凡達泰山眾籌系統開發(dapp開發技術)APP
- 泰山眾籌阿凡達(avatar)開發詳細丨泰山眾籌阿凡達(avatar)系統開發(開發及原始碼)原始碼
- 泰山眾籌(阿凡達4.0)系統開發流程及分析丨泰山眾籌(阿凡達4.0)開發原始碼功能原始碼
- 泰山眾籌(阿凡達)開發邏輯丨泰山眾籌(阿凡達)系統開發成熟案例及原始碼分析原始碼
- 泰山眾籌阿凡達avatar開發功能丨泰山眾籌阿凡達avatar系統開發流程及原始碼分析原始碼
- 阿凡達泰山眾籌系統開發Avata模式模式
- 泰山眾籌4.0阿凡達開發原理丨泰山眾籌4.0阿凡達系統開發詳細技術及原始碼分析原始碼
- 阿凡達泰山眾籌開發正式版丨阿凡達泰山眾籌系統開發流程及原始碼(web3.0技術開發)原始碼Web
- sun4.0泰山眾籌系統開發(模式案例)|阿凡達泰山眾籌sun開發方案模式
- Avatar阿凡達泰山眾籌開發|眾籌系統DAPP開發技術APP
- 泰山眾籌阿凡達系統開發模式邏輯模式
- 泰山眾籌商城開發、泰山眾籌DAPP系統開發、泰山眾籌原始碼部署開發APP原始碼
- 關於泰山眾籌4.0/阿凡達眾籌系統/技術開發
- 深入分析:Avatar阿凡達泰山眾籌系統開發
- 阿凡達Avata泰山眾籌系統開發技術搭建
- 泰山眾籌系統丨及泰山眾籌系統開發原始碼部署(技術開發流程)泰山眾籌原始碼
- 泰山眾籌商城系統開發(實現方案)丨泰山眾籌商城開發原始碼及功能原始碼
- Avatar阿凡達泰山眾籌系統開發(模式)|Avatar阿凡達需求方案部署模式
- 阿凡達(Avatar)泰山眾籌商城系統開發技術詳細及案例
- 阿凡達Sun4眾籌開發系統搭建|泰山眾籌模式系統原始碼部署模式原始碼
- 泰山眾籌APP開發,泰山眾籌商城開發,泰山眾籌是什麼模式?APP模式
- 泰山眾籌系統Dapp開發/泰山眾籌原始碼/泰山眾籌矩陣開發方案APP原始碼矩陣
- 深入瞭解阿凡達泰山眾籌商城系統開發詳情版及原始碼功能原始碼
- 區塊鏈泰山眾籌商城開發原始碼版丨區塊鏈泰山眾籌系統開發(方案及功能)區塊鏈原始碼
- 泰山眾籌4.0商城開發詳情丨泰山眾籌4.0商城系統開發實現技術案例及原始碼原始碼
- Avatar阿凡達(泰山眾籌)系統開發技術詳情及方案原始碼原始碼
- 關於sun4.0泰山眾籌阿凡達模式系統開發技術方案模式
- Sun(泰山眾籌)系統開發|眾籌DAPP開發搭建技術APP
- AVATAR阿凡達合約系統?區塊鏈阿凡達泰山眾籌專案邏輯系統開發功能及原始碼區塊鏈原始碼
- 泰山眾籌系統開發實現融資需求
- 深入分析阿凡達Avatar泰山眾籌系統開發詳細方案及案例原始碼原始碼