區塊鏈積分商城開發運營版丨區塊鏈積分商城系統開發(案例及詳細)
“新零售”的核心要義在於推動線上與線下的一體化程式,其關鍵在於使線上的網際網路力量和線下的實體店終端形成真正意義上的合力,從而完成電商平臺和實體零售店面在商業維度上的最佳化升級。同時,促成價格消費時代向價值消費時代的全面轉型。
pragma solidity=0.5.16;
import'./interfaces/IUniswapV2Pair.sol';
import'./UniswapV2ERC20.sol';
import'./libraries/Math.sol';
import'./libraries/UQ112x112.sol';
import'./interfaces/IERC20.sol';
import'./interfaces/IUniswapV2Factory.sol';
import'./interfaces/IUniswapV2Callee.sol';
contract UniswapV2Pair is IUniswapV2Pair,UniswapV2ERC20{
using SafeMath for uint;
using UQ112x112 for uint224;
//最低流動性
uint public constant MINIMUM_LIQUIDITY=10**3;
//獲取transfer方法的bytecode前四個位元組
bytes4 private constant SELECTOR=bytes4(keccak256(bytes('transfer(address,uint256)')));
address public factory;
address public token0;
address public token1;
uint112 private reserve0;//uses single storage slot,accessible via getReserves==使用單個儲存槽,可透過getReserves訪問
uint112 private reserve1;//uses single storage slot,accessible via getReserves
uint32 private blockTimestampLast;//uses single storage slot,accessible via getReserves
uint public price0CumulativeLast;//最後價格累計的0價格?
uint public price1CumulativeLast;
//緊接最近一次流動性事件之後
uint public kLast;//reserve0*reserve1,as of immediately after the most recent liquidity event
uint private unlocked=1;
//防止遞迴迭代出現問題,所以要上鎖
//一個鎖,使用該modifier的函式在unlocked==1時才可以進入,
//第一個呼叫者進入後,會將unlocked置為0,此使第二個呼叫者無法再進入
//執行完_部分的程式碼後,才會再將unlocked置1,重新將鎖開啟
modifier lock(){
require(unlocked==1,'UniswapV2:LOCKED');
unlocked=0;
_;
unlocked=1;
}
//獲取儲備:返回:_reserve0,_reserve1,_blockTimestampLast
//用於獲取兩個token在池子中的數量和最後更新的時間
function getReserves()public view returns(uint112 _reserve0,uint112 _reserve1,uint32 _blockTimestampLast){
_reserve0=reserve0;
_reserve1=reserve1;
//時間戳
_blockTimestampLast=blockTimestampLast;
}
//轉賬,安全校驗
function _safeTransfer(address token,address to,uint value)private{
//呼叫transfer方法,把地址token中的value個coin轉賬給to
(bool success,bytes memory data)=token.call(abi.encodeWithSelector(SELECTOR,to,value));
//檢查返回值,必須成功否則報錯
require(success&&(data.length==0||abi.decode(data,(bool))),'UniswapV2:TRANSFER_FAILED');
}
event Mint(address indexed sender,uint amount0,uint amount1);
event Burn(address indexed sender,uint amount0,uint amount1,address indexed to);
event Swap(address indexed sender,uint amount0In,uint amount1In,uint amount0Out,uint amount1Out,address indexed to);
event Sync(uint112 reserve0,uint112 reserve1);
//部署此合約時將msg.sender設定為factory,後續初始化時會用到這個值
constructor()public{
factory=msg.sender;
}
//called once by the factory at time of deployment
//在UniswapV2Factory.sol的createPair中呼叫過
function initialize(address _token0,address _token1)external{
require(msg.sender==factory,'UniswapV2:FORBIDDEN');//sufficient check
token0=_token0;
token1=_token1;
}
//update reserves and,on the first call per block,price accumulators
//更新儲備,並在每個區塊的第一次呼叫時更新價格累加器
/**
更新變數:
blockTimestampLast
reserve0
reserve1
price0CumulativeLast
price1CumulativeLast
*/
//這個函式是用來更新價格oracle的,計算累計價格
function _update(uint balance0,uint balance1,uint112 _reserve0,uint112 _reserve1)private{
//溢位校驗
require(balance0<=uint112(-1)&&balance1<=uint112(-1),'UniswapV2:OVERFLOW');
uint32 blockTimestamp=uint32(block.timestamp%2**32);
uint32 timeElapsed=blockTimestamp-blockTimestampLast;//overflow is desired
//計算時間加權的累計價格,256位中,前112位用來存整數,後112位用來存小數,多的32位用來存溢位的值
if(timeElapsed>0&&_reserve0!=0&&_reserve1!=0){
//*never overflows,and+overflow is desired
price0CumulativeLast+=uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0))*timeElapsed;
price1CumulativeLast+=uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1))*timeElapsed;
}
//更新reserve值
reserve0=uint112(balance0);
reserve1=uint112(balance1);
blockTimestampLast=blockTimestamp;
emit Sync(reserve0,reserve1);
}
//if fee is on,mint liquidity equivalent to 1/6th of the growth in sqrt(k)
//如果收費,增發流動性相當於sqrt(k)增長的1/6
function _mintFee(uint112 _reserve0,uint112 _reserve1)private returns(bool feeOn){
//獲取接收手續費的地址
address feeTo=IUniswapV2Factory(factory).feeTo();
//手續費接收者不為0地址
feeOn=feeTo!=address(0);
uint _kLast=kLast;//gas savings
//手續費接收者不為0地址
if(feeOn){
if(_kLast!=0){
uint rootK=Math.sqrt(uint(_reserve0).mul(_reserve1));
uint rootKLast=Math.sqrt(_kLast);
if(rootK>rootKLast){
uint numerator=totalSupply.mul(rootK.sub(rootKLast));
uint denominator=rootK.mul(5).add(rootKLast);
uint liquidity=numerator/denominator;
if(liquidity>0)_mint(feeTo,liquidity);
}
}
}
//手續費接收者為0,並且kLast不為0
else if(_kLast!=0){
kLast=0;
}
}
//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
//合約裡兩種token的當前的balance
uint balance0=IERC20(token0).balanceOf(address(this));
uint balance1=IERC20(token1).balanceOf(address(this));
//獲得當前balance和上一次快取的餘額的差值
//因為balance是動態變化的,reserve是靜態變化的
uint amount0=balance0.sub(_reserve0);
uint amount1=balance1.sub(_reserve1);
//計算手續費
bool feeOn=_mintFee(_reserve0,_reserve1);
//gas節省,必須在此處定義,因為totalSupply可以在_mintFee中更新
//totalSupply是pair的憑證
uint _totalSupply=totalSupply;//gas savings,must be defined here since totalSupply can update in _mintFee
if(_totalSupply==0){
//第一次鑄幣,也就是第一次注入流動性,值為根號k減去MINIMUM_LIQUIDITY,防止資料溢位
liquidity=Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
//把MINIMUM_LIQUIDITY賦給地址0,永久鎖住
_mint(address(0),MINIMUM_LIQUIDITY);//permanently lock the first MINIMUM_LIQUIDITY tokens
}else{
//計算增量的token佔總池子的比例,作為新鑄幣的數量
//木桶法則,按最少的來,按當前投入的佔池子總的比例增發
liquidity=Math.min(amount0.mul(_totalSupply)/_reserve0,amount1.mul(_totalSupply)/_reserve1);
}
require(liquidity>0,'UniswapV2:INSUFFICIENT_LIQUIDITY_MINTED');
//鑄幣,修改to的token數量及totalsupply
//給to地址發憑證,同時pair合約的totalSupply增發同等的憑證
_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/1
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);
//_token0/1給to轉amount0/1
_safeTransfer(_token0,to,amount0);
_safeTransfer(_token1,to,amount1);
//獲取轉賬後的balance
balance0=IERC20(_token0).balanceOf(address(this));
balance1=IERC20(_token1).balanceOf(address(this));
//更新reserve0,reserve1和時間戳
_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
//交易函式
//可以是token0-->token1,
//也可以是token1-->token0
//但引數中:amount0Out和amount1Out中有一個值是0
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));
}
uint amount0In=balance0>_reserve0-amount0Out?balance0-(_reserve0-amount0Out):0;
uint amount1In=balance1>_reserve1-amount1Out?balance1-(_reserve1-amount1Out):0;
require(amount0In>0||amount1In>0,'UniswapV2:INSUFFICIENT_INPUT_AMOUNT');
{//scope for reserve{0,1}Adjusted,avoids stack too deep errors
//防止資料溢位校驗
uint balance0Adjusted=balance0.mul(1000).sub(amount0In.mul(3));
uint balance1Adjusted=balance1.mul(1000).sub(amount1In.mul(3));
require(balance0Adjusted.mul(balance1Adjusted)>=uint(_reserve0).mul(_reserve1).mul(1000**2),'UniswapV2:K');
}
//更新
_update(balance0,balance1,_reserve0,_reserve1);
emit Swap(msg.sender,amount0In,amount1In,amount0Out,amount1Out,to);
}
//force balances to match reserves
//強制balance以匹配儲備
function skim(address to)external lock{
address _token0=token0;//gas savings
address _token1=token1;//gas savings
_safeTransfer(_token0,to,IERC20(_token0).balanceOf(address(this)).sub(reserve0));
_safeTransfer(_token1,to,IERC20(_token1).balanceOf(address(this)).sub(reserve1));
}
//force reserves to match balances
//強制儲備以匹配balance
function sync()external lock{
_update(IERC20(token0).balanceOf(address(this)),IERC20(token1).balanceOf(address(this)),reserve0,reserve1);
}
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69956839/viewspace-2937012/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 區塊鏈商城開發正式版丨區塊鏈商城系統開發技術原理丨區塊鏈商城原始碼平臺區塊鏈原始碼
- DAPP區塊鏈商城開發(多語言)丨DAPP區塊鏈商城系統開發(海外版)及案例原始碼APP區塊鏈原始碼
- 區塊鏈商城dapp系統開發技術詳情丨區塊鏈商城dapp開發原始碼案例部署區塊鏈APP原始碼
- 區塊鏈商城系統開發區塊鏈
- 區塊鏈積分聯盟模式系統如何開發?(區塊鏈積分聯盟模式系統開發原始碼demo)區塊鏈模式原始碼
- 區塊鏈多商戶商城開發上線版丨區塊鏈多商戶商城系統開發(專案及方案)區塊鏈
- 區塊鏈交易所開發運營版丨區塊鏈交易所繫統開發(詳細案例)及邏輯方案丨原始碼區塊鏈原始碼
- 區塊鏈泰山眾籌商城開發原始碼版丨區塊鏈泰山眾籌系統開發(方案及功能)區塊鏈原始碼
- 區塊鏈開發公司如何應用?聊區塊鏈+積分聯盟區塊鏈
- 區塊鏈眾籌商城系統開發實現技術方案丨區塊鏈眾籌商城開發原始碼部署區塊鏈原始碼
- 區塊鏈遊戲系統開發(Gamefi鏈遊開發案例)丨Gamefi鏈遊系統開發詳細及原始碼區塊鏈遊戲GAM原始碼
- 區塊鏈數字藏品開發原理丨區塊鏈數字藏品系統開發(技術詳細)及原始碼案例區塊鏈原始碼
- 區塊鏈交易所繫統開發(海外版)丨區塊鏈交易所繫統開發(開發案例及原始碼)區塊鏈原始碼
- 泰山&眾籌互助區塊鏈商城dapp系統開發功能詳情區塊鏈APP
- 區塊鏈多鏈錢包開發詳情版丨區塊鏈多鏈錢包系統開發實現技術方案及邏輯區塊鏈
- 鏈遊開發功能版/NFT鏈遊系統開發運營版/區塊鏈遊戲系統開發/成熟技術/原始碼案例區塊鏈遊戲原始碼
- 區塊鏈商城系統介紹區塊鏈
- 區塊鏈商城系統開發規則說明(邏輯及原始碼)區塊鏈原始碼
- 區塊鏈錢包系統開發:區塊鏈支付平臺系統開發區塊鏈
- 區塊鏈投票系統開發方案,區塊鏈投票系統開發原始碼區塊鏈原始碼
- Thinkphp開發的積分商城系統原始碼詳情開發示例PHP原始碼
- 上海區塊鏈系統開發/區塊鏈交易所繫統開發區塊鏈
- 區塊鏈眾籌互助商城dapp系統開發合約技術詳情區塊鏈APP
- 區塊鏈拼團挖礦商城dapp系統開發詳情(模式定製)區塊鏈APP模式
- NFT區塊鏈遊戲系統開發技術方案丨NFT區塊鏈遊戲系統開發原始碼詳解區塊鏈遊戲原始碼
- 廈門區塊鏈公鏈系統開發及DAPP開發區塊鏈APP
- 區塊鏈社交即時通訊系統開發方案,區塊鏈系統開發區塊鏈
- 拼團眾籌商城開發運營版丨拼團眾籌商城系統開發(詳情及案例原始碼)原始碼
- 區塊鏈數字版權,區塊鏈數字藏品交易系統開發區塊鏈
- 區塊鏈落地應用開發,區塊鏈幣幣撮合交易系統開發區塊鏈
- 區塊鏈公鏈系統開發與發展區塊鏈
- 關於/區塊鏈系統開發|(成熟技術)/區塊鏈系統開發介紹方案區塊鏈
- DAPP商城開發詳細丨DAPP商城系統開發(方案及規則)丨DAPP商城原始碼部署APP原始碼
- 區塊鏈錢包支付系統:區塊鏈支付平臺開發區塊鏈
- 區塊鏈聊天通訊直播系統開發app,區塊鏈應用開發方案區塊鏈APP
- 區塊鏈商品溯源平臺開發,區塊鏈公共服務系統開發方案區塊鏈
- BSC幣安鏈盲盒區塊鏈遊戲開發詳情丨BSC幣安鏈盲盒區塊鏈遊戲系統開發技術原理及分析區塊鏈遊戲開發
- 關於區塊鏈DAPP系統開發詳細功能邏輯區塊鏈APP