交易所开发逻辑丨交易所系统开发(开发项目)丨交易所源码详解
智能合约函数通过ABI(Application Binary Interface,应用二进制接口)和外部业务系统交互,ABI往往通过JSON文件表示,ABI文件是智能合约编译后的产物。
区块链存储的智能合约都是二进制格式的,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,并传递哪些参数,通过对ABI中的JSON数据解析就可以得出这些信息。
这里将ABI和API进行对比:API是程序间交互的接口,接口包含程序提供外界存取所需的函数、参数等内容;ABI也是程序间交互的接口,但程序是被编译后的二进制字节码,传递的是二进制格式的信息,ABI用于描述如何编解码程序间传递的二进制信息。
//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));
}