交易所開發(fā)邏輯丨交易所系統(tǒng)開發(fā)(開發(fā)項目)丨交易所源碼詳解
智能合約函數(shù)通過ABI(Application Binary Interface,應(yīng)用二進(jìn)制接口)和外部業(yè)務(wù)系統(tǒng)交互,ABI往往通過JSON文件表示,ABI文件是智能合約編譯后的產(chǎn)物。
區(qū)塊鏈存儲的智能合約都是二進(jìn)制格式的,When the virtual machine executes these binary files,there needs to be a suitable way to pass on which smart contract function is called by the external system,并傳遞哪些參數(shù),通過對ABI中的JSON數(shù)據(jù)解析就可以得出這些信息。
這里將ABI和API進(jìn)行對比:API是程序間交互的接口,接口包含程序提供外界存取所需的函數(shù)、參數(shù)等內(nèi)容;ABI也是程序間交互的接口,但程序是被編譯后的二進(jìn)制字節(jié)碼,傳遞的是二進(jìn)制格式的信息,ABI用于描述如何編解碼程序間傳遞的二進(jìn)制信息。
//this low-level function should be called from a contract which performs important safety checks
function mint(address to)external lock returns(uint liquidity){
(uint112 _reserve0,uint112 _reserve1,)=getReserves();//gas savings
uint balance0=IERC20(token0).balanceOf(address(this));
uint balance1=IERC20(token1).balanceOf(address(this));
uint amount0=balance0.sub(_reserve0);
uint amount1=balance1.sub(_reserve1);
bool feeOn=_mintFee(_reserve0,_reserve1);
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);
}
require(liquidity>0,'UniswapV2:INSUFFICIENT_LIQUIDITY_MINTED');
_mint(to,liquidity);
_update(balance0,balance1,_reserve0,_reserve1);
if(feeOn)kLast=uint(reserve0).mul(reserve1);//reserve0 and reserve1 are up-to-date
emit Mint(msg.sender,amount0,amount1);
}
//this low-level function should be called from a contract which performs important safety checks
function burn(address to)external lock returns(uint amount0,uint amount1){
(uint112 _reserve0,uint112 _reserve1,)=getReserves();//gas savings
address _token0=token0;//gas savings
address _token1=token1;//gas savings
uint balance0=IERC20(_token0).balanceOf(address(this));
uint balance1=IERC20(_token1).balanceOf(address(this));
uint liquidity=balanceOf[address(this)];
bool feeOn=_mintFee(_reserve0,_reserve1);
uint _totalSupply=totalSupply;//gas savings,must be defined here since totalSupply can update in _mintFee
amount0=liquidity.mul(balance0)/_totalSupply;//using balances ensures pro-rata distribution
amount1=liquidity.mul(balance1)/_totalSupply;//using balances ensures pro-rata distribution
require(amount0>0&&amount1>0,'UniswapV2:INSUFFICIENT_LIQUIDITY_BURNED');
_burn(address(this),liquidity);
_safeTransfer(_token0,to,amount0);
_safeTransfer(_token1,to,amount1);
balance0=IERC20(_token0).balanceOf(address(this));
balance1=IERC20(_token1).balanceOf(address(this));
_update(balance0,balance1,_reserve0,_reserve1);
if(feeOn)kLast=uint(reserve0).mul(reserve1);//reserve0 and reserve1 are up-to-date
emit Burn(msg.sender,amount0,amount1,to);
}
//this low-level function should be called from a contract which performs important safety checks
function swap(uint amount0Out,uint amount1Out,address to,bytes calldata data)external lock{
require(amount0Out>0||amount1Out>0,'UniswapV2:INSUFFICIENT_OUTPUT_AMOUNT');
(uint112 _reserve0,uint112 _reserve1,)=getReserves();//gas savings
require(amount0Out<_reserve0&&amount1Out<_reserve1,'UniswapV2:INSUFFICIENT_LIQUIDITY');
uint balance0;
uint balance1;
{//scope for _token{0,1},avoids stack too deep errors
address _token0=token0;
address _token1=token1;
require(to!=_token0&&to!=_token1,'UniswapV2:INVALID_TO');
if(amount0Out>0)_safeTransfer(_token0,to,amount0Out);//optimistically transfer tokens
if(amount1Out>0)_safeTransfer(_token1,to,amount1Out);//optimistically transfer tokens
if(data.length>0)IUniswapV2Callee(to).uniswapV2Call(msg.sender,amount0Out,amount1Out,data);
balance0=IERC20(_token0).balanceOf(address(this));
balance1=IERC20(_token1).balanceOf(address(this));
}