nest3.0从架构解析到克隆四(NestOffer之Nest_3_MiningContract、Nest_3_OfferPrice)

我们之前介绍的是报价机NestOffer的核心部分Nest_3_OfferMain,我们在本节将继续介绍Nest_3_MiningContract与Nest_3_OfferPrice。

[返回总章](https://learnblockchain.cn/article/2125) 我们之前介绍的是报价机NestOffer的核心部分Nest_3_OfferMain,我们在本节将继续介绍Nest_3_MiningContract与Nest_3_OfferPrice。 1.Nest_3_OfferMain报价系统,调用挖矿合约Nest_3_MiningContract,调用Nest_3_OfferPrice报价系统。 2.Nest_3_MiningContract是报价机的辅助部分,主要是负责矿池存储和出矿逻辑。 3.Nest_3_OfferPrice则主要进行报价过程中的价格查询与调用。 我们将在下面进行更加详细的说明。 # Nest_3_MiningContract Nest_3_MiningContract较为简单,都是跟出块的产量有关。 ``` /** * @title Mining contract 挖矿合约 * @dev Mining pool + mining logic 矿池存储 + 出矿逻辑 */ contract Nest_3_MiningContract { using address_make_payable for address; using SafeMath for uint256; uint256 _blockAttenuation = 2400000; // Block decay time interval // 区块衰减间隔 uint256[10] _attenuationAmount; // Mining decay amount // 挖矿数量衰减 uint256 _afterMiningAmount = 40 ether; // Stable period mining amount // 平稳期出矿量 uint256 _firstBlockNum; // Starting mining block // 起始挖矿区块 uint256 _latestMining; // Latest offering block // 最新报价区块 Nest_3_VoteFactory _voteFactory; // Voting contract // 投票合约(这个需要先弄) ERC20 _nestContract; // NEST contract address // NEST 合约 address _offerFactoryAddress; // Offering contract address // 报价工厂合约地址 // Current block, current block mining amount //当前区块,当前块出矿量 event OreDrawingLog(uint256 nowBlock, uint256 blockAmount); /** * @dev Initialization method 初始化方法 * @param voteFactory voting contract address Current block, current block mining amount 做一个假的nest.v3.offerMain,然后就弄, */ constructor(address voteFactory) public { _voteFactory = Nest_3_VoteFactory(address(voteFactory)); _offerFactoryAddress = address(_voteFactory.checkAddress("nest.v3.offerMain")); _nestContract = ERC20(address(_voteFactory.checkAddress("nest"))); // Initiate mining parameters //初始化挖矿参数 _firstBlockNum = 6236588; _latestMining = block.number; uint256 blockAmount = 400 ether; for (uint256 i = 0; i < 10; i ++) { _attenuationAmount[i] = blockAmount; blockAmount = blockAmount.mul(8).div(10); } } /** * @dev Reset voting contract 重置投票合约 * @param voteFactory Voting contract address 投票合约地址 */ function changeMapping(address voteFactory) public onlyOwner { _voteFactory = Nest_3_VoteFactory(address(voteFactory)); _offerFactoryAddress = address(_voteFactory.checkAddress("nest.v3.offerMain")); _nestContract = ERC20(address(_voteFactory.checkAddress("nest"))); } /** * @dev Offering mining 报价出矿 * @return Current block mining amount 当前区块出矿量 */ function oreDrawing() public returns (uint256) { require(address(msg.sender) == _offerFactoryAddress, "No authority"); //这个说明,报价是由nest.v3.offerMain提出的 // Update mining amount list //更新出矿量列表 uint256 miningAmount = changeBlockAmountList(); //这个就是获得多少币的关键函数 // Transfer NEST if (_nestContract.balanceOf(address(this)) < miningAmount){ //这里balanceOf说的是这个智能合约地址里面有没有nest miningAmount = _nestContract.balanceOf(address(this)); } if (miningAmount > 0) { _nestContract.transfer(address(msg.sender), miningAmount); emit OreDrawingLog(block.number,miningAmount); } //如果里面的币够,就发送出去 return miningAmount; } /** * @dev Update mining amount list 更新出矿量列表 */ function changeBlockAmountList() private returns (uint256) { uint256 createBlock = _firstBlockNum;//6236588 uint256 recentlyUsedBlock = _latestMining;//初始化的时候,是以当时的block.number为时间点 uint256 attenuationPointNow = block.number.sub(createBlock).div(_blockAttenuation); //block.number-createBlock/_blockAttenuation,为衰减系数 uint256 miningAmount = 0; uint256 attenuation; if (attenuationPointNow > 9) { attenuation = _afterMiningAmount; } else { attenuation = _attenuationAmount[attenuationPointNow];//大概是400 } miningAmount = attenuation.mul(block.number.sub(recentlyUsedBlock));//400x(当前块数-初始化时的块数) _latestMining = block.number; return miningAmount; } /** * @dev Transfer all NEST 转移所有 NEST * @param target Transfer target address target 转移目标地址 */ function takeOutNest(address target) public onlyOwner { _nestContract.transfer(address(target),_nestContract.balanceOf(address(this))); } // Check block decay time interval //查看区块衰减间隔 function checkBlockAttenuation() public view returns(uint256) { return _blockAttenuation; } // Check latest offering block //查看最新报价区块 function checkLatestMining() public view returns(uint256) { return _latestMining; } // Check mining amount decay //查看挖矿数量衰减 function checkAttenuationAmount(uint256 num) public view returns(uint256) { return _attenuationAmount[num]; } // Check NEST balance //查看 NEST 余额 function checkNestBalance() public view returns(uint256) { return _nestContract.balanceOf(address(this)); } // Modify block decay time interval //修改区块衰减间隔 function changeBlockAttenuation(uint256 blockNum) public onlyOwner { require(blockNum > 0); _blockAttenuation = blockNum; } // Modify mining amount decay //修改挖矿数量衰减 function changeAttenuationAmount(uint256 firstAmount, uint256 top, uint256 bottom) public onlyOwner { uint256 blockAmount = firstAmount; for (uint256 i = 0; i < 10; i ++) { _attenuationAmount[i] = blockAmount; blockAmount = blockAmount.mul(top).div(bottom); } } // Administrator only modifier onlyOwner(){ require(_voteFactory.checkOwners(msg.sender), "No authority"); _; } } ``` # Nest_3_OfferPrice Nest_3_OfferPrice主要负责与价格相关的内容。 主要分定义部分,增加报价,和更新报价,之后剩下的内容都比较简单,就不说了。 ## 定义部分 ``` using SafeMath for uint256; using address_make_payable for address; using SafeERC20 for ERC20; Nest_3_VoteFactory _voteFactory; // Voting contract // 投票合约 ERC20 _nestToken; // NestToken Nest_NToken_TokenMapping _tokenMapping; // NToken mapping // NToken映射 Nest_3_OfferMain _offerMain; // Offering main contract // 报价工厂合约 Nest_3_Abonus _abonus; // Bonus pool // 分红池 address _nTokeOfferMain; // NToken offering main contract // NToken报价工厂合约 address _destructionAddress; // Destruction contract address // 销毁合约地址 address _nTokenAuction; // NToken auction contract address // NToken拍卖合约地址 struct PriceInfo { // Block price // 区块价格 uint256 ethAmount; // ETH 数量 // ETH amount uint256 erc20Amount; // ERC20 数量 // Erc20 amount uint256 frontBlock; // 上一个生效区块 // Last effective block address offerOwner; // 报价地址 // Offering address } struct TokenInfo { // token报价信息 // Token offer information mapping(uint256 => PriceInfo) priceInfoList; // 区块价格列表,区块号 => 区块价格 // Block price list, block number => block price uint256 latestOffer; // 最新生效区块 // Latest effective block uint256 priceCostLeast; // 价格 ETH 最少费用 // Minimum ETH cost for prices uint256 priceCostMost; // 价格 ETH 最多费用 // Maximum ETH cost for prices uint256 priceCostSingle; // 价格 ETH 单条数据费用 // ETH cost for single data uint256 priceCostUser; // 价格 ETH 费用用户比例 // User ratio of cost } uint256 destructionAmount = 10000 ether; // 调用价格销毁 NEST 数量 // Amount of NEST to destroy to call prices uint256 effectTime = 1 days; // 可以调用价格等待时间 // Waiting time to start calling prices mapping(address => TokenInfo) _tokenInfo; // token报价信息 // Token offer information mapping(address => bool) _blocklist; // 禁止名单 // Block list mapping(address => uint256) _addressEffect; // 调用价格地址生效时间 // Effective time of address to call prices mapping(address => bool) _offerMainMapping; // 报价合约映射 // Offering contract mapping // Real-time price token, ETH amount, erc20 amount // 实时价格 token, eth数量, erc20数量 event NowTokenPrice(address a, uint256 b, uint256 c); /** * @dev Initialization method 初始化方法 * @param voteFactory Voting contract address voteFactory 投票合约地址 */ constructor (address voteFactory) public { Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory)); _voteFactory = voteFactoryMap; _offerMain = Nest_3_OfferMain(address(voteFactoryMap.checkAddress("nest.v3.offerMain"))); _nTokeOfferMain = address(voteFactoryMap.checkAddress("nest.nToken.offerMain")); _abonus = Nest_3_Abonus(address(voteFactoryMap.checkAddress("nest.v3.abonus"))); _destructionAddress = address(voteFactoryMap.checkAddress("nest.v3.destruction")); _nestToken = ERC20(address(voteFactoryMap.checkAddress("nest"))); _tokenMapping = Nest_NToken_TokenMapping(address(voteFactoryMap.checkAddress("nest.nToken.tokenMapping"))); _nTokenAuction = address(voteFactoryMap.checkAddress("nest.nToken.tokenAuction")); _offerMainMapping[address(_offerMain)] = true; _offerMainMapping[address(_nTokeOfferMain)] = true; } ``` ## 增加报价 /** * @dev Modify voting contract 修改投票射合约 * @param voteFactory Voting contract address 投票合约地址 */ function changeMapping(address voteFactory) public onlyOwner { Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory)); _voteFactory = voteFactoryMap; _offerMain = Nest_3_OfferMain(address(voteFactoryMap.checkAddress("nest.v3.offerMain"))); _nTokeOfferMain = address(voteFactoryMap.checkAddress("nest.nToken.offerMain")); _abonus = Nest_3_Abonus(address(voteFactoryMap.checkAddress("nest.v3.abonus"))); _destructionAddress = address(voteFactoryMap.checkAddress("nest.v3.destruction")); _nestToken = ERC20(address(voteFactoryMap.checkAddress("nest"))); _tokenMapping = Nest_NToken_TokenMapping(address(voteFactoryMap.checkAddress("nest.nToken.tokenMapping"))); _nTokenAuction = address(voteFactoryMap.checkAddress("nest.nToken.tokenAuction")); _offerMainMapping[address(_offerMain)] = true; _offerMainMapping[address(_nTokeOfferMain)] = true; } /** * @dev Initialize token price charge parameters 初始化 token 价格收费参数 * @param tokenAddress Token address tokenAddress token地址 */ function addPriceCost(address tokenAddress) public { require(msg.sender == _nTokenAuction); TokenInfo storage tokenInfo = _tokenInfo[tokenAddress]; tokenInfo.priceCostLeast = 0.001 ether; tokenInfo.priceCostMost = 0.01 ether; tokenInfo.priceCostSingle = 0.0001 ether; tokenInfo.priceCostUser = 2; } /** * @dev Add price 增加价格 * @param ethAmount ETH amount eth数量 * @param tokenAmount Erc20 amount erc20数量 * @param endBlock Effective price block 生效价格区块 * @param tokenAddress Erc20 address erc20地址 * @param offerOwner Offering address 报价地址 */ function addPrice(uint256 ethAmount, uint256 tokenAmount, uint256 endBlock, address tokenAddress, address offerOwner) public onlyOfferMain{ // Add effective block price information // 增加生效区块价格信息 TokenInfo storage tokenInfo = _tokenInfo[tokenAddress]; PriceInfo storage priceInfo = tokenInfo.priceInfoList[endBlock]; priceInfo.ethAmount = priceInfo.ethAmount.add(ethAmount); priceInfo.erc20Amount = priceInfo.erc20Amount.add(tokenAmount); priceInfo.offerOwner = offerOwner; if (endBlock != tokenInfo.latestOffer) { // If different block offer // 不同区块报价 priceInfo.frontBlock = tokenInfo.latestOffer; tokenInfo.latestOffer = endBlock; } } /** * @dev Price modification in taker orders 吃单修改价格 * @param ethAmount ETH amount * @param tokenAmount Erc20 amount * @param tokenAddress Token address * @param endBlock Block of effective price 生效价格区块 */ function changePrice(uint256 ethAmount, uint256 tokenAmount, address tokenAddress, uint256 endBlock) public onlyOfferMain { TokenInfo storage tokenInfo = _tokenInfo[tokenAddress]; PriceInfo storage priceInfo = tokenInfo.priceInfoList[endBlock]; priceInfo.ethAmount = priceInfo.ethAmount.sub(ethAmount); priceInfo.erc20Amount = priceInfo.erc20Amount.sub(tokenAmount); } ## 更新报价 ``` /** * @dev Update and check the latest price 更新并查看最新价格 * @param tokenAddress Token address * @return ethAmount ETH amount * @return erc20Amount Erc20 amount * @return blockNum Price block */ function updateAndCheckPriceNow(address tokenAddress) public payable returns(uint256 ethAmount, uint256 erc20Amount, uint256 blockNum) { require(checkUseNestPrice(address(msg.sender))); TokenInfo storage tokenInfo = _tokenInfo[tokenAddress]; uint256 checkBlock = tokenInfo.latestOffer; while(checkBlock > 0 && (checkBlock >= block.number || tokenInfo.priceInfoList[checkBlock].ethAmount == 0)) { checkBlock = tokenInfo.priceInfoList[checkBlock].frontBlock; } require(checkBlock != 0); PriceInfo memory priceInfo = tokenInfo.priceInfoList[checkBlock]; address nToken = _tokenMapping.checkTokenMapping(tokenAddress); if (nToken == address(0x0)) { _abonus.switchToEth.value(tokenInfo.priceCostLeast.sub(tokenInfo.priceCostLeast.mul(tokenInfo.priceCostUser).div(10)))(address(_nestToken)); } else { _abonus.switchToEth.value(tokenInfo.priceCostLeast.sub(tokenInfo.priceCostLeast.mul(tokenInfo.priceCostUser).div(10)))(address(nToken)); } repayEth(priceInfo.offerOwner, tokenInfo.priceCostLeast.mul(tokenInfo.priceCostUser).div(10)); repayEth(address(msg.sender), msg.value.sub(tokenInfo.priceCostLeast)); emit NowTokenPrice(tokenAddress,priceInfo.ethAmount, priceInfo.erc20Amount); return (priceInfo.ethAmount,priceInfo.erc20Amount, checkBlock); } /** * @dev Update and check the latest price-internal use 更新并查看最新价格-内部使用 * @param tokenAddress Token address * @return ethAmount ETH amount * @return erc20Amount Erc20 amount */ function updateAndCheckPricePrivate(address tokenAddress) public view onlyOfferMain returns(uint256 ethAmount, uint256 erc20Amount) { TokenInfo storage tokenInfo = _tokenInfo[tokenAddress]; uint256 checkBlock = tokenInfo.latestOffer; while(checkBlock > 0 && (checkBlock >= block.number || tokenInfo.priceInfoList[checkBlock].ethAmount == 0)) { checkBlock = tokenInfo.priceInfoList[checkBlock].frontBlock; } if (checkBlock == 0) { return (0,0); } PriceInfo memory priceInfo = tokenInfo.priceInfoList[checkBlock]; return (priceInfo.ethAmount,priceInfo.erc20Amount); } /** * @dev Update and check the effective price list 更新并查看生效价格列表 * @param tokenAddress Token address * @param num Number of prices to check * @return uint256[] price list */ function updateAndCheckPriceList(address tokenAddress, uint256 num) public payable returns (uint256[] memory) { require(checkUseNestPrice(address(msg.sender))); TokenInfo storage tokenInfo = _tokenInfo[tokenAddress]; // Charge uint256 thisPay = tokenInfo.priceCostSingle.mul(num); if (thisPay < tokenInfo.priceCostLeast) { thisPay=tokenInfo.priceCostLeast; } else if (thisPay > tokenInfo.priceCostMost) { thisPay = tokenInfo.priceCostMost; } // Extract data uint256 length = num.mul(3); uint256 index = 0; uint256[] memory data = new uint256[](length); address latestOfferOwner = address(0x0); uint256 checkBlock = tokenInfo.latestOffer; while(index < length && checkBlock > 0){ if (checkBlock < block.number && tokenInfo.priceInfoList[checkBlock].ethAmount != 0) { // Add return data data[index++] = tokenInfo.priceInfoList[checkBlock].ethAmount; data[index++] = tokenInfo.priceInfoList[checkBlock].erc20Amount; data[index++] = checkBlock; if (latestOfferOwner == address(0x0)) { latestOfferOwner = tokenInfo.priceInfoList[checkBlock].offerOwner; } } checkBlock = tokenInfo.priceInfoList[checkBlock].frontBlock; } require(latestOfferOwner != address(0x0)); require(length == data.length); // Allocation address nToken = _tokenMapping.checkTokenMapping(tokenAddress); if (nToken == address(0x0)) { _abonus.switchToEth.value(thisPay.sub(thisPay.mul(tokenInfo.priceCostUser).div(10)))(address(_nestToken)); } else { _abonus.switchToEth.value(thisPay.sub(thisPay.mul(tokenInfo.priceCostUser).div(10)))(address(nToken)); } repayEth(latestOfferOwner, thisPay.mul(tokenInfo.priceCostUser).div(10)); repayEth(address(msg.sender), msg.value.sub(thisPay)); return data; } // Activate the price checking function // 激活使用价格合约 function activation() public { _nestToken.safeTransferFrom(address(msg.sender), _destructionAddress, destructionAmount); _addressEffect[address(msg.sender)] = now.add(effectTime); } ```

返回总章 我们之前介绍的是报价机NestOffer的核心部分Nest_3_OfferMain,我们在本节将继续介绍Nest_3_MiningContract与Nest_3_OfferPrice。 1.Nest_3_OfferMain报价系统,调用挖矿合约Nest_3_MiningContract,调用Nest_3_OfferPrice报价系统。 2.Nest_3_MiningContract是报价机的辅助部分,主要是负责矿池存储和出矿逻辑。 3.Nest_3_OfferPrice则主要进行报价过程中的价格查询与调用。 我们将在下面进行更加详细的说明。

Nest_3_MiningContract

Nest_3_MiningContract较为简单,都是跟出块的产量有关。

/**
 * @title Mining contract
 挖矿合约
 * @dev Mining pool + mining logic
 矿池存储 + 出矿逻辑
 */
contract Nest_3_MiningContract {

    using address_make_payable for address;
    using SafeMath for uint256;

    uint256 _blockAttenuation = 2400000;                 //  Block decay time interval
    //  区块衰减间隔
    uint256[10] _attenuationAmount;                      //  Mining decay amount
    //  挖矿数量衰减
    uint256 _afterMiningAmount = 40 ether;               //  Stable period mining amount
    //  平稳期出矿量
    uint256 _firstBlockNum;                              //  Starting mining block
    //  起始挖矿区块
    uint256 _latestMining;                               //  Latest offering block
    //  最新报价区块
    Nest_3_VoteFactory _voteFactory;                     //  Voting contract
    //  投票合约(这个需要先弄)
    ERC20 _nestContract;                                 //  NEST contract address
    //  NEST 合约
    address _offerFactoryAddress;                        //  Offering contract address
     //  报价工厂合约地址

    // Current block, current block mining amount
    //当前区块,当前块出矿量
    event OreDrawingLog(uint256 nowBlock, uint256 blockAmount);

    /**
    * @dev Initialization method
    初始化方法
    * @param voteFactory  voting contract address
    Current block, current block mining amount
    做一个假的nest.v3.offerMain,然后就弄,
    */
    constructor(address voteFactory) public {
        _voteFactory = Nest_3_VoteFactory(address(voteFactory));                  
        _offerFactoryAddress = address(_voteFactory.checkAddress("nest.v3.offerMain"));
        _nestContract = ERC20(address(_voteFactory.checkAddress("nest")));
        // Initiate mining parameters
        //初始化挖矿参数
        _firstBlockNum = 6236588;
        _latestMining = block.number;
        uint256 blockAmount = 400 ether;
        for (uint256 i = 0; i &lt; 10; i ++) {
            _attenuationAmount[i] = blockAmount;
            blockAmount = blockAmount.mul(8).div(10);
        }
    }

    /**
    * @dev Reset voting contract
    重置投票合约
    * @param voteFactory Voting contract address
    投票合约地址
    */
    function changeMapping(address voteFactory) public onlyOwner {
        _voteFactory = Nest_3_VoteFactory(address(voteFactory));                  
        _offerFactoryAddress = address(_voteFactory.checkAddress("nest.v3.offerMain"));
        _nestContract = ERC20(address(_voteFactory.checkAddress("nest")));
    }

    /**
    * @dev Offering mining
    报价出矿
    * @return Current block mining amount
    当前区块出矿量
    */
    function oreDrawing() public returns (uint256) {
        require(address(msg.sender) == _offerFactoryAddress, "No authority");
        //这个说明,报价是由nest.v3.offerMain提出的
        //  Update mining amount list
        //更新出矿量列表
        uint256 miningAmount = changeBlockAmountList();
        //这个就是获得多少币的关键函数
        //  Transfer NEST
        if (_nestContract.balanceOf(address(this)) &lt; miningAmount){
            //这里balanceOf说的是这个智能合约地址里面有没有nest
            miningAmount = _nestContract.balanceOf(address(this));
        }
        if (miningAmount > 0) {
            _nestContract.transfer(address(msg.sender), miningAmount);
            emit OreDrawingLog(block.number,miningAmount);
        }
        //如果里面的币够,就发送出去
        return miningAmount;
    }

    /**
    * @dev Update mining amount list
    更新出矿量列表
    */
    function changeBlockAmountList() private returns (uint256) {
        uint256 createBlock = _firstBlockNum;//6236588
        uint256 recentlyUsedBlock = _latestMining;//初始化的时候,是以当时的block.number为时间点
        uint256 attenuationPointNow = block.number.sub(createBlock).div(_blockAttenuation);
        //block.number-createBlock/_blockAttenuation,为衰减系数
        uint256 miningAmount = 0;
        uint256 attenuation;
        if (attenuationPointNow > 9) {
            attenuation = _afterMiningAmount;
        } else {
            attenuation = _attenuationAmount[attenuationPointNow];//大概是400
        }
        miningAmount = attenuation.mul(block.number.sub(recentlyUsedBlock));//400x(当前块数-初始化时的块数)
        _latestMining = block.number;
        return miningAmount;
    }

    /**
    * @dev Transfer all NEST
    转移所有 NEST
    * @param target Transfer target address
    target 转移目标地址
    */
    function takeOutNest(address target) public onlyOwner {
        _nestContract.transfer(address(target),_nestContract.balanceOf(address(this)));
    }

    // Check block decay time interval
    //查看区块衰减间隔
    function checkBlockAttenuation() public view returns(uint256) {
        return _blockAttenuation;
    }

    // Check latest offering block
    //查看最新报价区块
    function checkLatestMining() public view returns(uint256) {
        return _latestMining;
    }

    // Check mining amount decay
    //查看挖矿数量衰减
    function checkAttenuationAmount(uint256 num) public view returns(uint256) {
        return _attenuationAmount[num];
    }

    // Check NEST balance
    //查看 NEST 余额
    function checkNestBalance() public view returns(uint256) {
        return _nestContract.balanceOf(address(this));
    }

    // Modify block decay time interval
    //修改区块衰减间隔
    function changeBlockAttenuation(uint256 blockNum) public onlyOwner {
        require(blockNum > 0);
        _blockAttenuation = blockNum;
    }

    // Modify mining amount decay
    //修改挖矿数量衰减
    function changeAttenuationAmount(uint256 firstAmount, uint256 top, uint256 bottom) public onlyOwner {
        uint256 blockAmount = firstAmount;
        for (uint256 i = 0; i &lt; 10; i ++) {
            _attenuationAmount[i] = blockAmount;
            blockAmount = blockAmount.mul(top).div(bottom);
        }
    }

    // Administrator only
    modifier onlyOwner(){
        require(_voteFactory.checkOwners(msg.sender), "No authority");
        _;
    }
}

Nest_3_OfferPrice

Nest_3_OfferPrice主要负责与价格相关的内容。 主要分定义部分,增加报价,和更新报价,之后剩下的内容都比较简单,就不说了。

定义部分

    using SafeMath for uint256;
    using address_make_payable for address;
    using SafeERC20 for ERC20;

    Nest_3_VoteFactory _voteFactory;                                //  Voting contract
    //  投票合约
    ERC20 _nestToken;                                               //  NestToken
    Nest_NToken_TokenMapping _tokenMapping;                         //  NToken mapping
    //  NToken映射
    Nest_3_OfferMain _offerMain;                                    //  Offering main contract
    //  报价工厂合约
    Nest_3_Abonus _abonus;                                          //  Bonus pool
    //  分红池
    address _nTokeOfferMain;                                        //  NToken offering main contract
    //  NToken报价工厂合约
    address _destructionAddress;                                    //  Destruction contract address
    //  销毁合约地址
    address _nTokenAuction;                                         //  NToken auction contract address
    //  NToken拍卖合约地址
    struct PriceInfo {                                              //  Block price
//  区块价格     
        uint256 ethAmount;      //  ETH 数量                                    //  ETH amount
        uint256 erc20Amount;     //  ERC20 数量                                   //  Erc20 amount
        uint256 frontBlock;    //  上一个生效区块                                     //  Last effective block
        address offerOwner;     //  报价地址                                    //  Offering address
    }
    struct TokenInfo {           //  token报价信息                                   //  Token offer information
     mapping(uint256 => PriceInfo) priceInfoList;  //  区块价格列表,区块号 => 区块价格               //  Block price list, block number => block price
        uint256 latestOffer;               //  最新生效区块                         //  Latest effective block
        uint256 priceCostLeast;            //  价格 ETH 最少费用                          //  Minimum ETH cost for prices
        uint256 priceCostMost;               //  价格 ETH 最多费用                        //  Maximum ETH cost for prices
        uint256 priceCostSingle;             //  价格 ETH 单条数据费用                       //  ETH cost for single data
        uint256 priceCostUser;                //  价格 ETH 费用用户比例                      //  User ratio of cost 
    }
    uint256 destructionAmount = 10000 ether;   //  调用价格销毁 NEST 数量                     //  Amount of NEST to destroy to call prices
    uint256 effectTime = 1 days;                //  可以调用价格等待时间                    //  Waiting time to start calling prices
    mapping(address => TokenInfo) _tokenInfo;    //  token报价信息                    //  Token offer information
    mapping(address => bool) _blocklist;           //  禁止名单                 //  Block list
    mapping(address => uint256) _addressEffect;    //  调用价格地址生效时间                 //  Effective time of address to call prices 
    mapping(address => bool) _offerMainMapping;      //  报价合约映射               //  Offering contract mapping

    //  Real-time price  token, ETH amount, erc20 amount
    //  实时价格 token, eth数量, erc20数量
    event NowTokenPrice(address a, uint256 b, uint256 c);

    /**
    * @dev Initialization method
    初始化方法
    * @param voteFactory Voting contract address
    voteFactory 投票合约地址
    */
    constructor (address voteFactory) public {
        Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory));
        _voteFactory = voteFactoryMap;
        _offerMain = Nest_3_OfferMain(address(voteFactoryMap.checkAddress("nest.v3.offerMain")));
        _nTokeOfferMain = address(voteFactoryMap.checkAddress("nest.nToken.offerMain"));
        _abonus = Nest_3_Abonus(address(voteFactoryMap.checkAddress("nest.v3.abonus")));
        _destructionAddress = address(voteFactoryMap.checkAddress("nest.v3.destruction"));
        _nestToken = ERC20(address(voteFactoryMap.checkAddress("nest")));
        _tokenMapping = Nest_NToken_TokenMapping(address(voteFactoryMap.checkAddress("nest.nToken.tokenMapping")));
        _nTokenAuction = address(voteFactoryMap.checkAddress("nest.nToken.tokenAuction"));
        _offerMainMapping[address(_offerMain)] = true;
        _offerMainMapping[address(_nTokeOfferMain)] = true;
    }

增加报价

/**
* @dev Modify voting contract
修改投票射合约
* @param voteFactory Voting contract address
投票合约地址
*/
function changeMapping(address voteFactory) public onlyOwner {
    Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory));
    _voteFactory = voteFactoryMap;                                   
    _offerMain = Nest_3_OfferMain(address(voteFactoryMap.checkAddress("nest.v3.offerMain")));
    _nTokeOfferMain = address(voteFactoryMap.checkAddress("nest.nToken.offerMain"));
    _abonus = Nest_3_Abonus(address(voteFactoryMap.checkAddress("nest.v3.abonus")));
    _destructionAddress = address(voteFactoryMap.checkAddress("nest.v3.destruction"));
    _nestToken = ERC20(address(voteFactoryMap.checkAddress("nest")));
    _tokenMapping = Nest_NToken_TokenMapping(address(voteFactoryMap.checkAddress("nest.nToken.tokenMapping")));
    _nTokenAuction = address(voteFactoryMap.checkAddress("nest.nToken.tokenAuction"));
    _offerMainMapping[address(_offerMain)] = true;
    _offerMainMapping[address(_nTokeOfferMain)] = true;
}

/**
* @dev Initialize token price charge parameters
初始化 token 价格收费参数
* @param tokenAddress Token address
tokenAddress token地址
*/
function addPriceCost(address tokenAddress) public {
    require(msg.sender == _nTokenAuction);
    TokenInfo storage tokenInfo = _tokenInfo[tokenAddress];
    tokenInfo.priceCostLeast = 0.001 ether;
    tokenInfo.priceCostMost = 0.01 ether;
    tokenInfo.priceCostSingle = 0.0001 ether;
    tokenInfo.priceCostUser = 2;
}

/**
* @dev Add price
增加价格
* @param ethAmount ETH amount
eth数量
* @param tokenAmount Erc20 amount
erc20数量
* @param endBlock Effective price block
生效价格区块
* @param tokenAddress Erc20 address
erc20地址
* @param offerOwner Offering address
报价地址
*/
function addPrice(uint256 ethAmount, uint256 tokenAmount, uint256 endBlock, address tokenAddress, address offerOwner) public onlyOfferMain{
    // Add effective block price information
    // 增加生效区块价格信息
    TokenInfo storage tokenInfo = _tokenInfo[tokenAddress];
    PriceInfo storage priceInfo = tokenInfo.priceInfoList[endBlock];
    priceInfo.ethAmount = priceInfo.ethAmount.add(ethAmount);
    priceInfo.erc20Amount = priceInfo.erc20Amount.add(tokenAmount);
    priceInfo.offerOwner = offerOwner;
    if (endBlock != tokenInfo.latestOffer) {
        // If different block offer
        // 不同区块报价
        priceInfo.frontBlock = tokenInfo.latestOffer;
        tokenInfo.latestOffer = endBlock;
    }
}

/**
* @dev Price modification in taker orders
吃单修改价格
* @param ethAmount ETH amount
* @param tokenAmount Erc20 amount
* @param tokenAddress Token address 
* @param endBlock Block of effective price
生效价格区块 
*/
function changePrice(uint256 ethAmount, uint256 tokenAmount, address tokenAddress, uint256 endBlock) public onlyOfferMain {
    TokenInfo storage tokenInfo = _tokenInfo[tokenAddress];
    PriceInfo storage priceInfo = tokenInfo.priceInfoList[endBlock];
    priceInfo.ethAmount = priceInfo.ethAmount.sub(ethAmount);
    priceInfo.erc20Amount = priceInfo.erc20Amount.sub(tokenAmount);
}

更新报价

    /**
    * @dev Update and check the latest price
    更新并查看最新价格
    * @param tokenAddress Token address
    * @return ethAmount ETH amount
    * @return erc20Amount Erc20 amount
    * @return blockNum Price block
    */
    function updateAndCheckPriceNow(address tokenAddress) public payable returns(uint256 ethAmount, uint256 erc20Amount, uint256 blockNum) {
        require(checkUseNestPrice(address(msg.sender)));
        TokenInfo storage tokenInfo = _tokenInfo[tokenAddress];
        uint256 checkBlock = tokenInfo.latestOffer;
        while(checkBlock > 0 && (checkBlock >= block.number || tokenInfo.priceInfoList[checkBlock].ethAmount == 0)) {
            checkBlock = tokenInfo.priceInfoList[checkBlock].frontBlock;
        }
        require(checkBlock != 0);
        PriceInfo memory priceInfo = tokenInfo.priceInfoList[checkBlock];
        address nToken = _tokenMapping.checkTokenMapping(tokenAddress);
        if (nToken == address(0x0)) {
            _abonus.switchToEth.value(tokenInfo.priceCostLeast.sub(tokenInfo.priceCostLeast.mul(tokenInfo.priceCostUser).div(10)))(address(_nestToken));
        } else {
            _abonus.switchToEth.value(tokenInfo.priceCostLeast.sub(tokenInfo.priceCostLeast.mul(tokenInfo.priceCostUser).div(10)))(address(nToken));
        }
        repayEth(priceInfo.offerOwner, tokenInfo.priceCostLeast.mul(tokenInfo.priceCostUser).div(10));
        repayEth(address(msg.sender), msg.value.sub(tokenInfo.priceCostLeast));
        emit NowTokenPrice(tokenAddress,priceInfo.ethAmount, priceInfo.erc20Amount);
        return (priceInfo.ethAmount,priceInfo.erc20Amount, checkBlock);
    }

    /**
    * @dev Update and check the latest price-internal use
    更新并查看最新价格-内部使用
    * @param tokenAddress Token address
    * @return ethAmount ETH amount
    * @return erc20Amount Erc20 amount
    */
    function updateAndCheckPricePrivate(address tokenAddress) public view onlyOfferMain returns(uint256 ethAmount, uint256 erc20Amount) {
        TokenInfo storage tokenInfo = _tokenInfo[tokenAddress];
        uint256 checkBlock = tokenInfo.latestOffer;
        while(checkBlock > 0 && (checkBlock >= block.number || tokenInfo.priceInfoList[checkBlock].ethAmount == 0)) {
            checkBlock = tokenInfo.priceInfoList[checkBlock].frontBlock;
        }
        if (checkBlock == 0) {
            return (0,0);
        }
        PriceInfo memory priceInfo = tokenInfo.priceInfoList[checkBlock];
        return (priceInfo.ethAmount,priceInfo.erc20Amount);
    }

    /**
    * @dev Update and check the effective price list
    更新并查看生效价格列表
    * @param tokenAddress Token address
    * @param num Number of prices to check
    * @return uint256[] price list
    */
    function updateAndCheckPriceList(address tokenAddress, uint256 num) public payable returns (uint256[] memory) {
        require(checkUseNestPrice(address(msg.sender)));
        TokenInfo storage tokenInfo = _tokenInfo[tokenAddress];
        // Charge
        uint256 thisPay = tokenInfo.priceCostSingle.mul(num);
        if (thisPay &lt; tokenInfo.priceCostLeast) {
            thisPay=tokenInfo.priceCostLeast;
        } else if (thisPay > tokenInfo.priceCostMost) {
            thisPay = tokenInfo.priceCostMost;
        }

        // Extract data
        uint256 length = num.mul(3);
        uint256 index = 0;
        uint256[] memory data = new uint256[](length);
        address latestOfferOwner = address(0x0);
        uint256 checkBlock = tokenInfo.latestOffer;
        while(index &lt; length && checkBlock > 0){
            if (checkBlock &lt; block.number && tokenInfo.priceInfoList[checkBlock].ethAmount != 0) {
                // Add return data
                data[index++] = tokenInfo.priceInfoList[checkBlock].ethAmount;
                data[index++] = tokenInfo.priceInfoList[checkBlock].erc20Amount;
                data[index++] = checkBlock;
                if (latestOfferOwner == address(0x0)) {
                    latestOfferOwner = tokenInfo.priceInfoList[checkBlock].offerOwner;
                }
            }
            checkBlock = tokenInfo.priceInfoList[checkBlock].frontBlock;
        }
        require(latestOfferOwner != address(0x0));
        require(length == data.length);
        // Allocation
        address nToken = _tokenMapping.checkTokenMapping(tokenAddress);
        if (nToken == address(0x0)) {
            _abonus.switchToEth.value(thisPay.sub(thisPay.mul(tokenInfo.priceCostUser).div(10)))(address(_nestToken));
        } else {
            _abonus.switchToEth.value(thisPay.sub(thisPay.mul(tokenInfo.priceCostUser).div(10)))(address(nToken));
        }
        repayEth(latestOfferOwner, thisPay.mul(tokenInfo.priceCostUser).div(10));
        repayEth(address(msg.sender), msg.value.sub(thisPay));
        return data;
    }

    // Activate the price checking function
    // 激活使用价格合约
    function activation() public {
        _nestToken.safeTransferFrom(address(msg.sender), _destructionAddress, destructionAmount);
        _addressEffect[address(msg.sender)] = now.add(effectTime);
    }

区块链技术网。

  • 发表于 2021-02-02 09:41
  • 阅读 ( 521 )
  • 学分 ( 1 )
  • 分类:NEST

评论