ETH Price: $2,412.88 (+7.35%)

Transaction Decoder

Block:
11703816 at Jan-22-2021 06:56:23 AM +UTC
Transaction Fee:
0.004157131076707609 ETH $10.03
Gas Used:
56,947 Gas / 73.000001347 Gwei

Emitted Events:

148 Nest_NToken.Transfer( from=Nest_3_TokenSave, to=[Sender] 0x8282568fc223156c945fc549893a3bc84a1f3bf2, value=4040000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x03904F4B...a46c99102
(NEST Protocol: Token Verification)
0x8282568f...84A1F3bf2
0.242787355141840592 Eth
Nonce: 194
0.238630224065132983 Eth
Nonce: 195
0.004157131076707609
(BeePool)
347.52168538936895233 Eth347.525842520445659939 Eth0.004157131076707609
0xE4EcBca3...ddb26b49d

Execution Trace

Nest_3_TokenAbonus.takeOut( amount=4040000000000000000000, token=0xE4EcBca33c5e29d34263400912157d4ddb26b49d )
  • Nest_3_TokenSave.checkAmount( sender=0x8282568fC223156c945fC549893A3bC84A1F3bf2, token=0xE4EcBca33c5e29d34263400912157d4ddb26b49d ) => ( 4040000000000000000000 )
  • Nest_3_TokenSave.takeOut( num=4040000000000000000000, token=0xE4EcBca33c5e29d34263400912157d4ddb26b49d, target=0x8282568fC223156c945fC549893A3bC84A1F3bf2 )
    • Nest_3_VoteFactory.checkAddress( name=nest.v3.tokenAbonus ) => ( contractAddress=0x19E1d193A448bD13097EFC2aea867468726e67c5 )
    • Nest_NToken.transfer( to=0x8282568fC223156c945fC549893A3bC84A1F3bf2, value=4040000000000000000000 ) => ( True )
      File 1 of 4: Nest_3_TokenAbonus
      pragma solidity 0.6.0;
      
      /**
       * @title Dividend logic
       * @dev Some operations about dividend,logic and asset separation
       */
      contract Nest_3_TokenAbonus {
          using address_make_payable for address;
          using SafeMath for uint256;
          
          ERC20 _nestContract;
          Nest_3_TokenSave _tokenSave;                                                                //  Lock-up contract
          Nest_3_Abonus _abonusContract;                                                              //  ETH bonus pool
          Nest_3_VoteFactory _voteFactory;                                                            //  Voting contract
          Nest_3_Leveling _nestLeveling;                                                              //  Leveling contract
          address _destructionAddress;                                                                //  Destroy contract address
          
          uint256 _timeLimit = 168 hours;                                                             //  Bonus period
          uint256 _nextTime = 1596168000;                                                             //  Next bonus time
          uint256 _getAbonusTimeLimit = 60 hours;                                                     //  During of triggering calculation of bonus
          uint256 _times = 0;                                                                         //  Bonus ledger
          uint256 _expectedIncrement = 3;                                                             //  Expected bonus increment ratio
          uint256 _expectedSpanForNest = 100000000 ether;                                             //  NEST expected bonus increment threshold
          uint256 _expectedSpanForNToken = 1000000 ether;                                             //  NToken expected bonus increment threshold
          uint256 _expectedMinimum = 100 ether;                                                       //  Expected minimum bonus
          uint256 _savingLevelOne = 10;                                                               //  Saving threshold level 1
          uint256 _savingLevelTwo = 20;                                                               //  Saving threshold level 2 
          uint256 _savingLevelTwoSub = 100 ether;                                                     //  Function parameters of savings threshold level 2  
          uint256 _savingLevelThree = 30;                                                             //  Function parameters of savings threshold level 3
          uint256 _savingLevelThreeSub = 600 ether;                                                   //  Function parameters of savings threshold level 3
          
          mapping(address => uint256) _abonusMapping;                                                 //  Bonus pool snapshot - token address (NEST or NToken) => number of ETH in the bonus pool 
          mapping(address => uint256) _tokenAllValueMapping;                                          //  Number of tokens (circulation) - token address (NEST or NToken) ) => total circulation 
          mapping(address => mapping(uint256 => uint256)) _tokenAllValueHistory;                      //  NEST or NToken circulation snapshot - token address (NEST or NToken) => number of periods => total circulation 
          mapping(address => mapping(uint256 => mapping(address => uint256))) _tokenSelfHistory;      //  Personal lockup - NEST or NToken snapshot token address (NEST or NToken) => period => user address => total circulation
          mapping(address => mapping(uint256 => bool)) _snapshot;                                     //  Whether snapshot - token address (NEST or NToken) => number of periods => whether to take a snapshot
          mapping(uint256 => mapping(address => mapping(address => bool))) _getMapping;               //  Receiving records - period => token address (NEST or NToken) => user address => whether received
          
          //  Log token address, amount
          event GetTokenLog(address tokenAddress, uint256 tokenAmount);
          
         /**
          * @dev Initialization method
          * @param voteFactory Voting contract address
          */
          constructor (address voteFactory) public {
              Nest_3_VoteFactory voteFactoryMap = Nest_3_VoteFactory(address(voteFactory));
              _voteFactory = voteFactoryMap; 
              _nestContract = ERC20(address(voteFactoryMap.checkAddress("nest")));
              _tokenSave = Nest_3_TokenSave(address(voteFactoryMap.checkAddress("nest.v3.tokenSave")));
              address payable addr = address(voteFactoryMap.checkAddress("nest.v3.abonus")).make_payable();
              _abonusContract = Nest_3_Abonus(addr);
              address payable levelingAddr = address(voteFactoryMap.checkAddress("nest.v3.leveling")).make_payable();
              _nestLeveling = Nest_3_Leveling(levelingAddr);
              _destructionAddress = address(voteFactoryMap.checkAddress("nest.v3.destruction"));
          }
          
          /**
          * @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; 
              _nestContract = ERC20(address(voteFactoryMap.checkAddress("nest")));
              _tokenSave = Nest_3_TokenSave(address(voteFactoryMap.checkAddress("nest.v3.tokenSave")));
              address payable addr = address(voteFactoryMap.checkAddress("nest.v3.abonus")).make_payable();
              _abonusContract = Nest_3_Abonus(addr);
              address payable levelingAddr = address(voteFactoryMap.checkAddress("nest.v3.leveling")).make_payable();
              _nestLeveling = Nest_3_Leveling(levelingAddr);
              _destructionAddress = address(voteFactoryMap.checkAddress("nest.v3.destruction"));
          }
          
          /**
          * @dev Deposit 
          * @param amount Deposited amount
          * @param token Locked token address
          */
          function depositIn(uint256 amount, address token) public {
              uint256 nowTime = now;
              uint256 nextTime = _nextTime;
              uint256 timeLimit = _timeLimit;
              if (nowTime < nextTime) {
                  //  Bonus triggered
                  require(!(nowTime >= nextTime.sub(timeLimit) && nowTime <= nextTime.sub(timeLimit).add(_getAbonusTimeLimit)));
              } else {
                  //  Bonus not triggered
                  uint256 times = (nowTime.sub(_nextTime)).div(_timeLimit);
                  //  Calculate the time when bonus should be started
                  uint256 startTime = _nextTime.add((times).mul(_timeLimit));  
                  //  Calculate the time when bonus should be stopped
                  uint256 endTime = startTime.add(_getAbonusTimeLimit);                                                                    
                  require(!(nowTime >= startTime && nowTime <= endTime));
              }
              _tokenSave.depositIn(amount, token, address(msg.sender));                 
          }
          
          /**
          * @dev Withdrawing
          * @param amount Withdrawing amount
          * @param token Token address
          */
          function takeOut(uint256 amount, address token) public {
              require(amount > 0, "Parameter needs to be greater than 0");                                                                
              require(amount <= _tokenSave.checkAmount(address(msg.sender), token), "Insufficient storage balance");
              if (token == address(_nestContract)) {
                  require(!_voteFactory.checkVoteNow(address(tx.origin)), "Voting");
              }
              _tokenSave.takeOut(amount, token, address(msg.sender));                                                             
          }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
          
          /**
          * @dev Receiving
          * @param token Receiving token address
          */
          function getAbonus(address token) public {
              uint256 tokenAmount = _tokenSave.checkAmount(address(msg.sender), token);
              require(tokenAmount > 0, "Insufficient storage balance");
              reloadTime();
              reloadToken(token);                                                                                                      
              uint256 nowTime = now;
              require(nowTime >= _nextTime.sub(_timeLimit) && nowTime <= _nextTime.sub(_timeLimit).add(_getAbonusTimeLimit), "Not time to draw");
              require(!_getMapping[_times.sub(1)][token][address(msg.sender)], "Have received");                                     
              _tokenSelfHistory[token][_times.sub(1)][address(msg.sender)] = tokenAmount;                                         
              require(_tokenAllValueMapping[token] > 0, "Total flux error");
              uint256 selfNum = tokenAmount.mul(_abonusMapping[token]).div(_tokenAllValueMapping[token]);
              require(selfNum > 0, "No limit available");
              _getMapping[_times.sub(1)][token][address(msg.sender)] = true;
              _abonusContract.getETH(selfNum, token,address(msg.sender)); 
              emit GetTokenLog(token, selfNum);
          }
          
          /**
          * @dev Update bonus time and stage ledger
          */
          function reloadTime() private {
              uint256 nowTime = now;
              //  The current time must exceed the bonus time
              if (nowTime >= _nextTime) {                                                                                                 
                  uint256 time = (nowTime.sub(_nextTime)).div(_timeLimit);
                  uint256 startTime = _nextTime.add((time).mul(_timeLimit));                                                              
                  uint256 endTime = startTime.add(_getAbonusTimeLimit);                                                                   
                  if (nowTime >= startTime && nowTime <= endTime) {
                      _nextTime = getNextTime();                                                                                      
                      _times = _times.add(1);                                                                                       
                  }
              }
          }
          
          /**
          * @dev Snapshot of the amount of tokens
          * @param token Receiving token address
          */
          function reloadToken(address token) private {
              if (!_snapshot[token][_times.sub(1)]) {
                  levelingResult(token);                                                                                          
                  _abonusMapping[token] = _abonusContract.getETHNum(token); 
                  _tokenAllValueMapping[token] = allValue(token);
                  _tokenAllValueHistory[token][_times.sub(1)] = allValue(token);
                  _snapshot[token][_times.sub(1)] = true;
              }
          }
          
          /**
          * @dev Leveling settlement
          * @param token Receiving token address
          */
          function levelingResult(address token) private {
              uint256 steps;
              if (token == address(_nestContract)) {
                  steps = allValue(token).div(_expectedSpanForNest);
              } else {
                  steps = allValue(token).div(_expectedSpanForNToken);
              }
              uint256 minimumAbonus = _expectedMinimum;
              for (uint256 i = 0; i < steps; i++) {
                  minimumAbonus = minimumAbonus.add(minimumAbonus.mul(_expectedIncrement).div(100));
              }
              uint256 thisAbonus = _abonusContract.getETHNum(token);
              if (thisAbonus > minimumAbonus) {
                  uint256 levelAmount = 0;
                  if (thisAbonus > 5000 ether) {
                      levelAmount = thisAbonus.mul(_savingLevelThree).div(100).sub(_savingLevelThreeSub);
                  } else if (thisAbonus > 1000 ether) {
                      levelAmount = thisAbonus.mul(_savingLevelTwo).div(100).sub(_savingLevelTwoSub);
                  } else {
                      levelAmount = thisAbonus.mul(_savingLevelOne).div(100);
                  }
                  if (thisAbonus.sub(levelAmount) < minimumAbonus) {
                      _abonusContract.getETH(thisAbonus.sub(minimumAbonus), token, address(this));
                      _nestLeveling.switchToEth.value(thisAbonus.sub(minimumAbonus))(token);
                  } else {
                      _abonusContract.getETH(levelAmount, token, address(this));
                      _nestLeveling.switchToEth.value(levelAmount)(token);
                  }
              } else {
                  uint256 ethValue = _nestLeveling.tranEth(minimumAbonus.sub(thisAbonus), token, address(this));
                  _abonusContract.switchToEth.value(ethValue)(token);
              }
          }
          
           // Next bonus time, current bonus deadline, ETH number, NEST number, NEST participating in bonus, bonus to receive, approved amount, balance, whether bonus can be paid 
          function getInfo(address token) public view returns (uint256 nextTime, uint256 getAbonusTime, uint256 ethNum, uint256 tokenValue, uint256 myJoinToken, uint256 getEth, uint256 allowNum, uint256 leftNum, bool allowAbonus)  {
              uint256 nowTime = now;
              if (nowTime >= _nextTime.sub(_timeLimit) && nowTime <= _nextTime.sub(_timeLimit).add(_getAbonusTimeLimit) && _times > 0 && _snapshot[token][_times.sub(1)]) {
                  //  Bonus have been triggered, and during the time of this bonus, display snapshot data 
                  allowAbonus = _getMapping[_times.sub(1)][token][address(msg.sender)];
                  ethNum = _abonusMapping[token];
                  tokenValue = _tokenAllValueMapping[token];
              } else {
                  //  Display real-time data 
                  ethNum = _abonusContract.getETHNum(token);
                  tokenValue = allValue(token);
                  allowAbonus = _getMapping[_times][token][address(msg.sender)];
              }
              myJoinToken = _tokenSave.checkAmount(address(msg.sender), token);
              if (allowAbonus == true) {
                  getEth = 0; 
              } else {
                  getEth = myJoinToken.mul(ethNum).div(tokenValue);
              }
              nextTime = getNextTime();
              getAbonusTime = nextTime.sub(_timeLimit).add(_getAbonusTimeLimit);
              allowNum = ERC20(token).allowance(address(msg.sender), address(_tokenSave));
              leftNum = ERC20(token).balanceOf(address(msg.sender));
          }
          
          /**
          * @dev View next bonus time 
          * @return Next bonus time 
          */
          function getNextTime() public view returns (uint256) {
              uint256 nowTime = now;
              if (_nextTime > nowTime) { 
                  return _nextTime; 
              } else {
                  uint256 time = (nowTime.sub(_nextTime)).div(_timeLimit);
                  return _nextTime.add(_timeLimit.mul(time.add(1)));
              }
          }
          
          /**
          * @dev View total circulation 
          * @return Total circulation
          */
          function allValue(address token) public view returns (uint256) {
              if (token == address(_nestContract)) {
                  uint256 all = 10000000000 ether;
                  uint256 leftNum = all.sub(_nestContract.balanceOf(address(_voteFactory.checkAddress("nest.v3.miningSave")))).sub(_nestContract.balanceOf(address(_destructionAddress)));
                  return leftNum;
              } else {
                  return ERC20(token).totalSupply();
              }
          }
          
          /**
          * @dev View bonus period
          * @return Bonus period
          */
          function checkTimeLimit() public view returns (uint256) {
              return _timeLimit;
          }
          
          /**
          * @dev View duration of triggering calculation of bonus
          * @return Bonus period
          */
          function checkGetAbonusTimeLimit() public view returns (uint256) {
              return _getAbonusTimeLimit;
          }
          
          /**
          * @dev View current lowest expected bonus
          * @return Current lowest expected bonus
          */
          function checkMinimumAbonus(address token) public view returns (uint256) {
              uint256 miningAmount;
              if (token == address(_nestContract)) {
                  miningAmount = allValue(token).div(_expectedSpanForNest);
              } else {
                  miningAmount = allValue(token).div(_expectedSpanForNToken);
              }
              uint256 minimumAbonus = _expectedMinimum;
              for (uint256 i = 0; i < miningAmount; i++) {
                  minimumAbonus = minimumAbonus.add(minimumAbonus.mul(_expectedIncrement).div(100));
              }
              return minimumAbonus;
          }
          
          /**
          * @dev Check whether the bonus token is snapshoted
          * @param token Token address
          * @return Whether snapshoted
          */
          function checkSnapshot(address token) public view returns (bool) {
              return _snapshot[token][_times.sub(1)];
          }
          
          /**
          * @dev Check the expected bonus incremental ratio
          * @return Expected bonus increment ratio
          */
          function checkeExpectedIncrement() public view returns (uint256) {
              return _expectedIncrement;
          }
          
          /**
          * @dev View expected minimum bonus
          * @return Expected minimum bonus
          */
          function checkExpectedMinimum() public view returns (uint256) {
              return _expectedMinimum;
          }
          
          /**
          * @dev View savings threshold
          * @return Save threshold
          */
          function checkSavingLevelOne() public view returns (uint256) {
              return _savingLevelOne;
          }
          function checkSavingLevelTwo() public view returns (uint256) {
              return _savingLevelTwo;
          }
          function checkSavingLevelThree() public view returns (uint256) {
              return _savingLevelThree;
          }
          
          /**
          * @dev View NEST liquidity snapshot
          * @param token Locked token address
          * @param times Bonus snapshot period
          */
          function checkTokenAllValueHistory(address token, uint256 times) public view returns (uint256) {
              return _tokenAllValueHistory[token][times];
          }
          
          /**
          * @dev View personal lock-up NEST snapshot
          * @param times Bonus snapshot period
          * @param user User address
          * @return The number of personal locked NEST snapshots
          */
          function checkTokenSelfHistory(address token, uint256 times, address user) public view returns (uint256) {
              return _tokenSelfHistory[token][times][user];
          }
          
          // View the period number of bonus
          function checkTimes() public view returns (uint256) {
              return _times;
          }
          
          // NEST expected bonus increment threshold
          function checkExpectedSpanForNest() public view returns (uint256) {
              return _expectedSpanForNest;
          }
          
          // NToken expected bonus increment threshold
          function checkExpectedSpanForNToken() public view returns (uint256) {
              return _expectedSpanForNToken;
          }
          
          // View the function parameters of savings threshold level 3
          function checkSavingLevelTwoSub() public view returns (uint256) {
              return _savingLevelTwoSub;
          }
          
          // View the function parameters of savings threshold level 3
          function checkSavingLevelThreeSub() public view returns (uint256) {
              return _savingLevelThreeSub;
          }
          
          /**
          * @dev Update bonus period
          * @param hour Bonus period (hours)
          */
          function changeTimeLimit(uint256 hour) public onlyOwner {
              require(hour > 0, "Parameter needs to be greater than 0");
              _timeLimit = hour.mul(1 hours);
          }
          
          /**
          * @dev Update collection period
          * @param hour Collection period (hours)
          */
          function changeGetAbonusTimeLimit(uint256 hour) public onlyOwner {
              require(hour > 0, "Parameter needs to be greater than 0");
              _getAbonusTimeLimit = hour;
          }
          
          /**
          * @dev Update expected bonus increment ratio
          * @param num Expected bonus increment ratio
          */
          function changeExpectedIncrement(uint256 num) public onlyOwner {
              require(num > 0, "Parameter needs to be greater than 0");
              _expectedIncrement = num;
          }
          
          /**
          * @dev Update expected minimum bonus
          * @param num Expected minimum bonus
          */
          function changeExpectedMinimum(uint256 num) public onlyOwner {
              require(num > 0, "Parameter needs to be greater than 0");
              _expectedMinimum = num;
          }
          
          /**
          * @dev  Update saving threshold
          * @param threshold Saving threshold
          */
          function changeSavingLevelOne(uint256 threshold) public onlyOwner {
              _savingLevelOne = threshold;
          }
          function changeSavingLevelTwo(uint256 threshold) public onlyOwner {
              _savingLevelTwo = threshold;
          }
          function changeSavingLevelThree(uint256 threshold) public onlyOwner {
              _savingLevelThree = threshold;
          }
          
          /**
          * @dev Update the function parameters of savings threshold level 2
          */
          function changeSavingLevelTwoSub(uint256 num) public onlyOwner {
              _savingLevelTwoSub = num;
          }
          
          /**
          * @dev Update the function parameters of savings threshold level 3
          */
          function changeSavingLevelThreeSub(uint256 num) public onlyOwner {
              _savingLevelThreeSub = num;
          }
          
          /**
          * @dev Update NEST expected bonus incremental threshold
          * @param num Threshold
          */
          function changeExpectedSpanForNest(uint256 num) public onlyOwner {
              _expectedSpanForNest = num;
          }
          
          /**
          * @dev Update NToken expected bonus incremental threshold
          * @param num Threshold
          */
          function changeExpectedSpanForNToken(uint256 num) public onlyOwner {
              _expectedSpanForNToken = num;
          }
          
          receive() external payable {
              
          }
          
          // Administrator only
          modifier onlyOwner(){
              require(_voteFactory.checkOwners(address(msg.sender)), "No authority");
              _;
          }
      }
      
      // NEST and NToken lock-up contracts
      interface Nest_3_TokenSave {
          function depositIn(uint256 num, address token, address target) external;
          function checkAmount(address sender, address token) external view returns(uint256);
          function takeOut(uint256 num, address token, address target) external;
      }
      
      // ETH bonus pool
      interface Nest_3_Abonus {
          function getETH(uint256 num, address token, address target) external;
          function getETHNum(address token) external view returns (uint256);
          function switchToEth(address token) external payable;
      }
      
      // Leveling contract
      interface Nest_3_Leveling {
          function tranEth(uint256 amount, address token, address target) external returns (uint256);
          function switchToEth(address token) external payable;
      }
      
      // Voting factory contract
      interface Nest_3_VoteFactory {
          // Check if there is a vote currently participating
          function checkVoteNow(address user) external view returns(bool);
          // Check address
      	function checkAddress(string calldata name) external view returns (address contractAddress);
      	// Check whether the administrator
      	function checkOwners(address man) external view returns (bool);
      }
      
      // ERC20 contract
      interface ERC20 {
          function totalSupply() external view returns (uint256);
          function balanceOf(address account) external view returns (uint256);
          function transfer(address recipient, uint256 amount) external returns (bool);
          function allowance(address owner, address spender) external view returns (uint256);
          function approve(address spender, uint256 amount) external returns (bool);
          function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
          event Transfer(address indexed from, address indexed to, uint256 value);
          event Approval(address indexed owner, address indexed spender, uint256 value);
      }
      
      library SafeMath {
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
              uint256 c = a + b;
              require(c >= a, "SafeMath: addition overflow");
      
              return c;
          }
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
              return sub(a, b, "SafeMath: subtraction overflow");
          }
          function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b <= a, errorMessage);
              uint256 c = a - b;
      
              return c;
          }
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
              if (a == 0) {
                  return 0;
              }
              uint256 c = a * b;
              require(c / a == b, "SafeMath: multiplication overflow");
      
              return c;
          }
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              return div(a, b, "SafeMath: division by zero");
          }
          function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              uint256 c = a / b;
              return c;
          }
          function mod(uint256 a, uint256 b) internal pure returns (uint256) {
              return mod(a, b, "SafeMath: modulo by zero");
          }
          function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b != 0, errorMessage);
              return a % b;
          }
      }
      
      library address_make_payable {
         function make_payable(address x) internal pure returns (address payable) {
            return address(uint160(x));
         }
      }

      File 2 of 4: Nest_3_TokenSave
      pragma solidity 0.6.0;
      
      /**
       * @title NEST and NToken lock-up contract
       * @dev NEST and NToken deposit and withdrawal
       */
      contract Nest_3_TokenSave {
          using SafeMath for uint256;
          
          Nest_3_VoteFactory _voteFactory;                                 //  Voting contract
          mapping(address => mapping(address => uint256))  _baseMapping;   //  Ledger token=>user=>amount
          
          /**
          * @dev initialization method
          * @param voteFactory Voting contract address
          */
          constructor(address voteFactory) public {
              _voteFactory = Nest_3_VoteFactory(voteFactory); 
          }
          
          /**
          * @dev Reset voting contract
          * @param voteFactory Voting contract address
          */
          function changeMapping(address voteFactory) public onlyOwner {
              _voteFactory = Nest_3_VoteFactory(voteFactory); 
          }
          
          /**
          * @dev Withdrawing
          * @param num Withdrawing amount
          * @param token Lock-up token address
          * @param target Transfer target
          */
          function takeOut(uint256 num, address token, address target) public onlyContract {
              require(num <= _baseMapping[token][address(target)], "Insufficient storage balance");
              _baseMapping[token][address(target)] = _baseMapping[token][address(target)].sub(num);
              ERC20(token).transfer(address(target), num);
          }
          
          /**
          * @dev Depositing
          * @param num Depositing amount
          * @param token Lock-up token address
          * @param target Depositing target
          */
          function depositIn(uint256 num, address token, address target) public onlyContract {
              require(ERC20(token).transferFrom(address(target),address(this),num), "Authorization transfer failed");  
              _baseMapping[token][address(target)] = _baseMapping[token][address(target)].add(num);
          }
          
          /**
          * @dev Check the amount
          * @param sender Check address
          * @param token Lock-up token address
          * @return uint256 Check address corresponding lock-up limit 
          */
          function checkAmount(address sender, address token) public view returns(uint256) {
              return _baseMapping[token][address(sender)];
          }
          
          // Administrators only
          modifier onlyOwner(){
              require(_voteFactory.checkOwners(address(msg.sender)), "No authority");
              _;
          }
          
          // Only for bonus logic contract
          modifier onlyContract(){
              require(_voteFactory.checkAddress("nest.v3.tokenAbonus") == address(msg.sender), "No authority");
              _;
          }
      }
      
      // ERC20 contract
      interface ERC20 {
          function totalSupply() external view returns (uint256);
          function balanceOf(address account) external view returns (uint256);
          function transfer(address recipient, uint256 amount) external returns (bool);
          function allowance(address owner, address spender) external view returns (uint256);
          function approve(address spender, uint256 amount) external returns (bool);
          function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
          event Transfer(address indexed from, address indexed to, uint256 value);
          event Approval(address indexed owner, address indexed spender, uint256 value);
      }
      
      // Voting factory
      interface Nest_3_VoteFactory {
          // Check address
      	function checkAddress(string calldata name) external view returns (address contractAddress);
      	// Check whether the administrator
      	function checkOwners(address man) external view returns (bool);
      }
      
      library SafeMath {
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
              uint256 c = a + b;
              require(c >= a, "SafeMath: addition overflow");
      
              return c;
          }
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
              return sub(a, b, "SafeMath: subtraction overflow");
          }
          function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b <= a, errorMessage);
              uint256 c = a - b;
      
              return c;
          }
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
              if (a == 0) {
                  return 0;
              }
              uint256 c = a * b;
              require(c / a == b, "SafeMath: multiplication overflow");
      
              return c;
          }
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              return div(a, b, "SafeMath: division by zero");
          }
          function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              uint256 c = a / b;
              return c;
          }
          function mod(uint256 a, uint256 b) internal pure returns (uint256) {
              return mod(a, b, "SafeMath: modulo by zero");
          }
          function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b != 0, errorMessage);
              return a % b;
          }
      }

      File 3 of 4: Nest_NToken
      pragma solidity 0.6.0;
      
      library SafeMath {
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
              uint256 c = a + b;
              require(c >= a, "SafeMath: addition overflow");
      
              return c;
          }
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
              return sub(a, b, "SafeMath: subtraction overflow");
          }
          function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b <= a, errorMessage);
              uint256 c = a - b;
      
              return c;
          }
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
              if (a == 0) {
                  return 0;
              }
              uint256 c = a * b;
              require(c / a == b, "SafeMath: multiplication overflow");
      
              return c;
          }
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              return div(a, b, "SafeMath: division by zero");
          }
          function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              uint256 c = a / b;
              return c;
          }
          function mod(uint256 a, uint256 b) internal pure returns (uint256) {
              return mod(a, b, "SafeMath: modulo by zero");
          }
          function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b != 0, errorMessage);
              return a % b;
          }
      }
      
      //  voting contract 
      interface Nest_3_VoteFactory {
          //  Check address 
      	function checkAddress(string calldata name) external view returns (address contractAddress);
      	//  check whether the administrator 
      	function checkOwners(address man) external view returns (bool);
      }
      
      /**
       * @title NToken contract 
       * @dev Include standard erc20 method, mining method, and mining data 
       */
      interface IERC20 {
          function totalSupply() external view returns (uint256);
          function balanceOf(address who) external view returns (uint256);
          function allowance(address owner, address spender) external view returns (uint256);
          function transfer(address to, uint256 value) external returns (bool);
          function approve(address spender, uint256 value) external returns (bool);
          function transferFrom(address from, address to, uint256 value) external returns (bool);
          event Transfer(address indexed from, address indexed to, uint256 value);
          event Approval(address indexed owner, address indexed spender, uint256 value);
      }
      
      contract Nest_NToken is IERC20 {
          using SafeMath for uint256;
          
          mapping (address => uint256) private _balances;                                 //  Balance ledger 
          mapping (address => mapping (address => uint256)) private _allowed;             //  Approval ledger 
          uint256 private _totalSupply = 0 ether;                                         //  Total supply 
          string public name;                                                             //  Token name 
          string public symbol;                                                           //  Token symbol 
          uint8 public decimals = 18;                                                     //  Precision
          uint256 public _createBlock;                                                    //  Create block number
          uint256 public _recentlyUsedBlock;                                              //  Recently used block number
          Nest_3_VoteFactory _voteFactory;                                                //  Voting factory contract
          address _bidder;                                                                //  Owner
          
          /**
          * @dev Initialization method
          * @param _name Token name
          * @param _symbol Token symbol
          * @param voteFactory Voting factory contract address
          * @param bidder Successful bidder address
          */
          constructor (string memory _name, string memory _symbol, address voteFactory, address bidder) public {
          	name = _name;                                                               
          	symbol = _symbol;
          	_createBlock = block.number;
          	_recentlyUsedBlock = block.number;
          	_voteFactory = Nest_3_VoteFactory(address(voteFactory));
          	_bidder = bidder;
          }
          
          /**
          * @dev Reset voting contract method
          * @param voteFactory Voting contract address
          */
          function changeMapping (address voteFactory) public onlyOwner {
          	_voteFactory = Nest_3_VoteFactory(address(voteFactory));
          }
          
          /**
          * @dev Additional issuance
          * @param value Additional issuance amount
          */
          function increaseTotal(uint256 value) public {
              address offerMain = address(_voteFactory.checkAddress("nest.nToken.offerMain"));
              require(address(msg.sender) == offerMain, "No authority");
              _balances[offerMain] = _balances[offerMain].add(value);
              _totalSupply = _totalSupply.add(value);
              _recentlyUsedBlock = block.number;
          }
      
          /**
          * @dev Check the total amount of tokens
          * @return Total supply
          */
          function totalSupply() override public view returns (uint256) {
              return _totalSupply;
          }
      
          /**
          * @dev Check address balance
          * @param owner Address to be checked
          * @return Return the balance of the corresponding address
          */
          function balanceOf(address owner) override public view returns (uint256) {
              return _balances[owner];
          }
          
          /**
          * @dev Check block information
          * @return createBlock Initial block number
          * @return recentlyUsedBlock Recently mined and issued block
          */
          function checkBlockInfo() public view returns(uint256 createBlock, uint256 recentlyUsedBlock) {
              return (_createBlock, _recentlyUsedBlock);
          }
      
          /**
           * @dev Check owner's approved allowance to the spender
           * @param owner Approving address
           * @param spender Approved address
           * @return Approved amount
           */
          function allowance(address owner, address spender) override public view returns (uint256) {
              return _allowed[owner][spender];
          }
      
          /**
          * @dev Transfer method
          * @param to Transfer target
          * @param value Transfer amount
          * @return Whether the transfer is successful
          */
          function transfer(address to, uint256 value) override public returns (bool) {
              _transfer(msg.sender, to, value);
              return true;
          }
      
          /**
           * @dev Approval method
           * @param spender Approval target
           * @param value Approval amount
           * @return Whether the approval is successful
           */
          function approve(address spender, uint256 value) override public returns (bool) {
              require(spender != address(0));
      
              _allowed[msg.sender][spender] = value;
              emit Approval(msg.sender, spender, value);
              return true;
          }
      
          /**
           * @dev Transfer tokens when approved
           * @param from Transfer-out account address
           * @param to Transfer-in account address
           * @param value Transfer amount
           * @return Whether approved transfer is successful
           */
          function transferFrom(address from, address to, uint256 value) override public returns (bool) {
              _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
              _transfer(from, to, value);
              emit Approval(from, msg.sender, _allowed[from][msg.sender]);
              return true;
          }
      
          /**
           * @dev Increase the allowance
           * @param spender Approval target
           * @param addedValue Amount to increase
           * @return whether increase is successful
           */
          function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
              require(spender != address(0));
      
              _allowed[msg.sender][spender] = _allowed[msg.sender][spender].add(addedValue);
              emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
              return true;
          }
      
          /**
           * @dev Decrease the allowance
           * @param spender Approval target
           * @param subtractedValue Amount to decrease
           * @return Whether decrease is successful
           */
          function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
              require(spender != address(0));
      
              _allowed[msg.sender][spender] = _allowed[msg.sender][spender].sub(subtractedValue);
              emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
              return true;
          }
      
          /**
          * @dev Transfer method
          * @param to Transfer target
          * @param value Transfer amount
          */
          function _transfer(address from, address to, uint256 value) internal {
              _balances[from] = _balances[from].sub(value);
              _balances[to] = _balances[to].add(value);
              emit Transfer(from, to, value);
          }
          
          /**
          * @dev Check the creator
          * @return Creator address
          */
          function checkBidder() public view returns(address) {
              return _bidder;
          }
          
          /**
          * @dev Transfer creator
          * @param bidder New creator address
          */
          function changeBidder(address bidder) public {
              require(address(msg.sender) == _bidder);
              _bidder = bidder; 
          }
          
          // Administrator only
          modifier onlyOwner(){
              require(_voteFactory.checkOwners(msg.sender));
              _;
          }
      }

      File 4 of 4: Nest_3_VoteFactory
      pragma solidity 0.6.0;
      
      /**
       * @title Voting factory + mapping
       * @dev Vote creating method
       */
      contract Nest_3_VoteFactory {
          using SafeMath for uint256;
          
          uint256 _limitTime = 7 days;                                    //  Vote duration
          uint256 _NNLimitTime = 1 days;                                  //  NestNode raising time
          uint256 _circulationProportion = 51;                            //  Proportion of votes to pass
          uint256 _NNUsedCreate = 10;                                     //  The minimum number of NNs to create a voting contract
          uint256 _NNCreateLimit = 100;                                   //  The minimum number of NNs needed to start voting
          uint256 _emergencyTime = 0;                                     //  The emergency state start time
          uint256 _emergencyTimeLimit = 3 days;                           //  The emergency state duration
          uint256 _emergencyNNAmount = 1000;                              //  The number of NNs required to switch the emergency state
          ERC20 _NNToken;                                                 //  NestNode Token
          ERC20 _nestToken;                                               //  NestToken
          mapping(string => address) _contractAddress;                    //  Voting contract mapping
          mapping(address => bool) _modifyAuthority;                      //  Modify permissions
          mapping(address => address) _myVote;                            //  Personal voting address
          mapping(address => uint256) _emergencyPerson;                   //  Emergency state personal voting number
          mapping(address => bool) _contractData;                         //  Voting contract data
          bool _stateOfEmergency = false;                                 //  Emergency state
          address _destructionAddress;                                    //  Destroy contract address
      
          event ContractAddress(address contractAddress);
          
          /**
          * @dev Initialization method
          */
          constructor () public {
              _modifyAuthority[address(msg.sender)] = true;
          }
          
          /**
          * @dev Reset contract
          */
          function changeMapping() public onlyOwner {
              _NNToken = ERC20(checkAddress("nestNode"));
              _destructionAddress = address(checkAddress("nest.v3.destruction"));
              _nestToken = ERC20(address(checkAddress("nest")));
          }
          
          /**
          * @dev Create voting contract
          * @param implementContract The executable contract address for voting
          * @param nestNodeAmount Number of NNs to pledge
          */
          function createVote(address implementContract, uint256 nestNodeAmount) public {
              require(address(tx.origin) == address(msg.sender), "It can't be a contract");
              require(nestNodeAmount >= _NNUsedCreate);
              Nest_3_VoteContract newContract = new Nest_3_VoteContract(implementContract, _stateOfEmergency, nestNodeAmount);
              require(_NNToken.transferFrom(address(tx.origin), address(newContract), nestNodeAmount), "Authorization transfer failed");
              _contractData[address(newContract)] = true;
              emit ContractAddress(address(newContract));
          }
          
          /**
          * @dev Use NEST to vote
          * @param contractAddress Vote contract address
          */
          function nestVote(address contractAddress) public {
              require(address(msg.sender) == address(tx.origin), "It can't be a contract");
              require(_contractData[contractAddress], "It's not a voting contract");
              require(!checkVoteNow(address(msg.sender)));
              Nest_3_VoteContract newContract = Nest_3_VoteContract(contractAddress);
              newContract.nestVote();
              _myVote[address(tx.origin)] = contractAddress;
          }
          
          /**
          * @dev Vote using NestNode Token
          * @param contractAddress Vote contract address
          * @param NNAmount Amount of NNs to pledge
          */
          function nestNodeVote(address contractAddress, uint256 NNAmount) public {
              require(address(msg.sender) == address(tx.origin), "It can't be a contract");
              require(_contractData[contractAddress], "It's not a voting contract");
              Nest_3_VoteContract newContract = Nest_3_VoteContract(contractAddress);
              require(_NNToken.transferFrom(address(tx.origin), address(newContract), NNAmount), "Authorization transfer failed");
              newContract.nestNodeVote(NNAmount);
          }
          
          /**
          * @dev Excecute contract
          * @param contractAddress Vote contract address
          */
          function startChange(address contractAddress) public {
              require(address(msg.sender) == address(tx.origin), "It can't be a contract");
              require(_contractData[contractAddress], "It's not a voting contract");
              Nest_3_VoteContract newContract = Nest_3_VoteContract(contractAddress);
              require(_stateOfEmergency == newContract.checkStateOfEmergency());
              addSuperManPrivate(address(newContract));
              newContract.startChange();
              deleteSuperManPrivate(address(newContract));
          }
          
          /**
          * @dev Switch emergency state-transfer in NestNode Token
          * @param amount Amount of NNs to transfer
          */
          function sendNestNodeForStateOfEmergency(uint256 amount) public {
              require(_NNToken.transferFrom(address(tx.origin), address(this), amount));
              _emergencyPerson[address(tx.origin)] = _emergencyPerson[address(tx.origin)].add(amount);
          }
          
          /**
          * @dev Switch emergency state-transfer out NestNode Token
          */
          function turnOutNestNodeForStateOfEmergency() public {
              require(_emergencyPerson[address(tx.origin)] > 0);
              require(_NNToken.transfer(address(tx.origin), _emergencyPerson[address(tx.origin)]));
              _emergencyPerson[address(tx.origin)] = 0;
              uint256 nestAmount = _nestToken.balanceOf(address(this));
              require(_nestToken.transfer(address(_destructionAddress), nestAmount));
          }
          
          /**
          * @dev Modify emergency state
          */
          function changeStateOfEmergency() public {
              if (_stateOfEmergency) {
                  require(now > _emergencyTime.add(_emergencyTimeLimit));
                  _stateOfEmergency = false;
                  _emergencyTime = 0;
              } else {
                  require(_emergencyPerson[address(msg.sender)] > 0);
                  require(_NNToken.balanceOf(address(this)) >= _emergencyNNAmount);
                  _stateOfEmergency = true;
                  _emergencyTime = now;
              }
          }
          
          /**
          * @dev Check whether participating in the voting
          * @param user Address to check
          * @return bool Whether voting
          */
          function checkVoteNow(address user) public view returns (bool) {
              if (_myVote[user] == address(0x0)) {
                  return false;
              } else {
                  Nest_3_VoteContract vote = Nest_3_VoteContract(_myVote[user]);
                  if (vote.checkContractEffective() || vote.checkPersonalAmount(user) == 0) {
                      return false;
                  }
                  return true;
              }
          }
          
          /**
          * @dev Check my voting
          * @param user Address to check
          * @return address Address recently participated in the voting contract address
          */
          function checkMyVote(address user) public view returns (address) {
              return _myVote[user];
          }
          
          //  Check the voting time
          function checkLimitTime() public view returns (uint256) {
              return _limitTime;
          }
          
          //  Check the NestNode raising time
          function checkNNLimitTime() public view returns (uint256) {
              return _NNLimitTime;
          }
          
          //  Check the voting proportion to pass
          function checkCirculationProportion() public view returns (uint256) {
              return _circulationProportion;
          }
          
          //  Check the minimum number of NNs to create a voting contract
          function checkNNUsedCreate() public view returns (uint256) {
              return _NNUsedCreate;
          }
          
          //  Check the minimum number of NNs raised to start a vote
          function checkNNCreateLimit() public view returns (uint256) {
              return _NNCreateLimit;
          }
          
          //  Check whether in emergency state
          function checkStateOfEmergency() public view returns (bool) {
              return _stateOfEmergency;
          }
          
          //  Check the start time of the emergency state
          function checkEmergencyTime() public view returns (uint256) {
              return _emergencyTime;
          }
          
          //  Check the duration of the emergency state
          function checkEmergencyTimeLimit() public view returns (uint256) {
              return _emergencyTimeLimit;
          }
          
          //  Check the amount of personal pledged NNs
          function checkEmergencyPerson(address user) public view returns (uint256) {
              return _emergencyPerson[user];
          }
          
          //  Check the number of NNs required for the emergency
          function checkEmergencyNNAmount() public view returns (uint256) {
              return _emergencyNNAmount;
          }
          
          //  Verify voting contract data
          function checkContractData(address contractAddress) public view returns (bool) {
              return _contractData[contractAddress];
          }
          
          //  Modify voting time
          function changeLimitTime(uint256 num) public onlyOwner {
              require(num > 0, "Parameter needs to be greater than 0");
              _limitTime = num;
          }
          
          //  Modify the NestNode raising time
          function changeNNLimitTime(uint256 num) public onlyOwner {
              require(num > 0, "Parameter needs to be greater than 0");
              _NNLimitTime = num;
          }
          
          //  Modify the voting proportion
          function changeCirculationProportion(uint256 num) public onlyOwner {
              require(num > 0, "Parameter needs to be greater than 0");
              _circulationProportion = num;
          }
          
          //  Modify the minimum number of NNs to create a voting contract
          function changeNNUsedCreate(uint256 num) public onlyOwner {
              _NNUsedCreate = num;
          }
          
          //  Modify the minimum number of NNs to raised to start a voting
          function checkNNCreateLimit(uint256 num) public onlyOwner {
              _NNCreateLimit = num;
          }
          
          //  Modify the emergency state duration
          function changeEmergencyTimeLimit(uint256 num) public onlyOwner {
              require(num > 0);
              _emergencyTimeLimit = num.mul(1 days);
          }
          
          //  Modify the number of NNs required for emergency state
          function changeEmergencyNNAmount(uint256 num) public onlyOwner {
              require(num > 0);
              _emergencyNNAmount = num;
          }
          
          //  Check address
          function checkAddress(string memory name) public view returns (address contractAddress) {
              return _contractAddress[name];
          }
          
          //  Add contract mapping address
          function addContractAddress(string memory name, address contractAddress) public onlyOwner {
              _contractAddress[name] = contractAddress;
          }
          
          //  Add administrator address 
          function addSuperMan(address superMan) public onlyOwner {
              _modifyAuthority[superMan] = true;
          }
          function addSuperManPrivate(address superMan) private {
              _modifyAuthority[superMan] = true;
          }
          
          //  Delete administrator address
          function deleteSuperMan(address superMan) public onlyOwner {
              _modifyAuthority[superMan] = false;
          }
          function deleteSuperManPrivate(address superMan) private {
              _modifyAuthority[superMan] = false;
          }
          
          //  Delete voting contract data
          function deleteContractData(address contractAddress) public onlyOwner {
              _contractData[contractAddress] = false;
          }
          
          //  Check whether the administrator
          function checkOwners(address man) public view returns (bool) {
              return _modifyAuthority[man];
          }
          
          //  Administrator only
          modifier onlyOwner() {
              require(checkOwners(msg.sender), "No authority");
              _;
          }
      }
      
      /**
       * @title Voting contract
       */
      contract Nest_3_VoteContract {
          using SafeMath for uint256;
          
          Nest_3_Implement _implementContract;                //  Executable contract
          Nest_3_TokenSave _tokenSave;                        //  Lock-up contract
          Nest_3_VoteFactory _voteFactory;                    //  Voting factory contract
          Nest_3_TokenAbonus _tokenAbonus;                    //  Bonus logic contract
          ERC20 _nestToken;                                   //  NestToken
          ERC20 _NNToken;                                     //  NestNode Token
          address _miningSave;                                //  Mining pool contract
          address _implementAddress;                          //  Executable contract address
          address _destructionAddress;                        //  Destruction contract address
          uint256 _createTime;                                //  Creation time
          uint256 _endTime;                                   //  End time
          uint256 _totalAmount;                               //  Total votes
          uint256 _circulation;                               //  Passed votes
          uint256 _destroyedNest;                             //  Destroyed NEST
          uint256 _NNLimitTime;                               //  NestNode raising time
          uint256 _NNCreateLimit;                             //  Minimum number of NNs to create votes
          uint256 _abonusTimes;                               //  Period number of used snapshot in emergency state
          uint256 _allNNAmount;                               //  Total number of NNs
          bool _effective = false;                            //  Whether vote is effective
          bool _nestVote = false;                             //  Whether NEST vote can be performed
          bool _isChange = false;                             //  Whether NEST vote is executed
          bool _stateOfEmergency;                             //  Whether the contract is in emergency state
          mapping(address => uint256) _personalAmount;        //  Number of personal votes
          mapping(address => uint256) _personalNNAmount;      //  Number of NN personal votes
          
          /**
          * @dev Initialization method
          * @param contractAddress Executable contract address
          * @param stateOfEmergency Whether in emergency state
          * @param NNAmount Amount of NNs
          */
          constructor (address contractAddress, bool stateOfEmergency, uint256 NNAmount) public {
              Nest_3_VoteFactory voteFactory = Nest_3_VoteFactory(address(msg.sender));
              _voteFactory = voteFactory;
              _nestToken = ERC20(voteFactory.checkAddress("nest"));
              _NNToken = ERC20(voteFactory.checkAddress("nestNode"));
              _implementContract = Nest_3_Implement(address(contractAddress));
              _implementAddress = address(contractAddress);
              _destructionAddress = address(voteFactory.checkAddress("nest.v3.destruction"));
              _personalNNAmount[address(tx.origin)] = NNAmount;
              _allNNAmount = NNAmount;
              _createTime = now;                                    
              _endTime = _createTime.add(voteFactory.checkLimitTime());
              _NNLimitTime = voteFactory.checkNNLimitTime();
              _NNCreateLimit = voteFactory.checkNNCreateLimit();
              _stateOfEmergency = stateOfEmergency;
              if (stateOfEmergency) {
                  //  If in emergency state, read the last two periods of bonus lock-up and total circulation data
                  _tokenAbonus = Nest_3_TokenAbonus(voteFactory.checkAddress("nest.v3.tokenAbonus"));
                  _abonusTimes = _tokenAbonus.checkTimes().sub(2);
                  require(_abonusTimes > 0);
                  _circulation = _tokenAbonus.checkTokenAllValueHistory(address(_nestToken),_abonusTimes).mul(voteFactory.checkCirculationProportion()).div(100);
              } else {
                  _miningSave = address(voteFactory.checkAddress("nest.v3.miningSave"));
                  _tokenSave = Nest_3_TokenSave(voteFactory.checkAddress("nest.v3.tokenSave"));
                  _circulation = (uint256(10000000000 ether).sub(_nestToken.balanceOf(address(_miningSave))).sub(_nestToken.balanceOf(address(_destructionAddress)))).mul(voteFactory.checkCirculationProportion()).div(100);
              }
              if (_allNNAmount >= _NNCreateLimit) {
                  _nestVote = true;
              }
          }
          
          /**
          * @dev NEST voting
          */
          function nestVote() public onlyFactory {
              require(now <= _endTime, "Voting time exceeded");
              require(!_effective, "Vote in force");
              require(_nestVote);
              require(_personalAmount[address(tx.origin)] == 0, "Have voted");
              uint256 amount;
              if (_stateOfEmergency) {
                  //  If in emergency state, read the last two periods of bonus lock-up and total circulation data
                  amount = _tokenAbonus.checkTokenSelfHistory(address(_nestToken),_abonusTimes, address(tx.origin));
              } else {
                  amount = _tokenSave.checkAmount(address(tx.origin), address(_nestToken));
              }
              _personalAmount[address(tx.origin)] = amount;
              _totalAmount = _totalAmount.add(amount);
              ifEffective();
          }
          
          /**
          * @dev NEST voting cancellation
          */
          function nestVoteCancel() public {
              require(address(msg.sender) == address(tx.origin), "It can't be a contract");
              require(now <= _endTime, "Voting time exceeded");
              require(!_effective, "Vote in force");
              require(_personalAmount[address(tx.origin)] > 0, "No vote");                     
              _totalAmount = _totalAmount.sub(_personalAmount[address(tx.origin)]);
              _personalAmount[address(tx.origin)] = 0;
          }
          
          /**
          * @dev  NestNode voting
          * @param NNAmount Amount of NNs
          */
          function nestNodeVote(uint256 NNAmount) public onlyFactory {
              require(now <= _createTime.add(_NNLimitTime), "Voting time exceeded");
              require(!_nestVote);
              _personalNNAmount[address(tx.origin)] = _personalNNAmount[address(tx.origin)].add(NNAmount);
              _allNNAmount = _allNNAmount.add(NNAmount);
              if (_allNNAmount >= _NNCreateLimit) {
                  _nestVote = true;
              }
          }
          
          /**
          * @dev Withdrawing lock-up NNs
          */
          function turnOutNestNode() public {
              if (_nestVote) {
                  //  Normal NEST voting
                  if (!_stateOfEmergency || !_effective) {
                      //  Non-emergency state
                      require(now > _endTime, "Vote unenforceable");
                  }
              } else {
                  //  NN voting
                  require(now > _createTime.add(_NNLimitTime));
              }
              require(_personalNNAmount[address(tx.origin)] > 0);
              //  Reverting back the NNs
              require(_NNToken.transfer(address(tx.origin), _personalNNAmount[address(tx.origin)]));
              _personalNNAmount[address(tx.origin)] = 0;
              //  Destroying NEST Tokens 
              uint256 nestAmount = _nestToken.balanceOf(address(this));
              _destroyedNest = _destroyedNest.add(nestAmount);
              require(_nestToken.transfer(address(_destructionAddress), nestAmount));
          }
          
          /**
          * @dev Execute the contract
          */
          function startChange() public onlyFactory {
              require(!_isChange);
              _isChange = true;
              if (_stateOfEmergency) {
                  require(_effective, "Vote unenforceable");
              } else {
                  require(_effective && now > _endTime, "Vote unenforceable");
              }
              //  Add the executable contract to the administrator list
              _voteFactory.addSuperMan(address(_implementContract));
              //  Execute
              _implementContract.doit();
              //  Delete the authorization
              _voteFactory.deleteSuperMan(address(_implementContract));
          }
          
          /**
          * @dev check whether the vote is effective
          */
          function ifEffective() private {
              if (_totalAmount >= _circulation) {
                  _effective = true;
              }
          }
          
          /**
          * @dev Check whether the vote is over
          */
          function checkContractEffective() public view returns (bool) {
              if (_effective || now > _endTime) {
                  return true;
              } 
              return false;
          }
          
          //  Check the executable implement contract address
          function checkImplementAddress() public view returns (address) {
              return _implementAddress;
          }
          
          //  Check the voting start time
          function checkCreateTime() public view returns (uint256) {
              return _createTime;
          }
          
          //  Check the voting end time
          function checkEndTime() public view returns (uint256) {
              return _endTime;
          }
          
          //  Check the current total number of votes
          function checkTotalAmount() public view returns (uint256) {
              return _totalAmount;
          }
          
          //  Check the number of votes to pass
          function checkCirculation() public view returns (uint256) {
              return _circulation;
          }
          
          //  Check the number of personal votes
          function checkPersonalAmount(address user) public view returns (uint256) {
              return _personalAmount[user];
          }
          
          //  Check the destroyed NEST
          function checkDestroyedNest() public view returns (uint256) {
              return _destroyedNest;
          }
          
          //  Check whether the contract is effective
          function checkEffective() public view returns (bool) {
              return _effective;
          }
          
          //  Check whether in emergency state
          function checkStateOfEmergency() public view returns (bool) {
              return _stateOfEmergency;
          }
          
          //  Check NestNode raising time
          function checkNNLimitTime() public view returns (uint256) {
              return _NNLimitTime;
          }
          
          //  Check the minimum number of NNs to create a vote
          function checkNNCreateLimit() public view returns (uint256) {
              return _NNCreateLimit;
          }
          
          //  Check the period number of snapshot used in the emergency state
          function checkAbonusTimes() public view returns (uint256) {
              return _abonusTimes;
          }
          
          //  Check number of personal votes
          function checkPersonalNNAmount(address user) public view returns (uint256) {
              return _personalNNAmount[address(user)];
          }
          
          //  Check the total number of NNs
          function checkAllNNAmount() public view returns (uint256) {
              return _allNNAmount;
          }
          
          //  Check whether NEST voting is available
          function checkNestVote() public view returns (bool) {
              return _nestVote;
          }
          
          //  Check whether it has been excecuted
          function checkIsChange() public view returns (bool) {
              return _isChange;
          }
          
          //  Vote Factory contract only
          modifier onlyFactory() {
              require(address(_voteFactory) == address(msg.sender), "No authority");
              _;
          }
      }
      
      //  Executable contract
      interface Nest_3_Implement {
          //  Execute
          function doit() external;
      }
      
      //  NEST lock-up contract
      interface Nest_3_TokenSave {
          //  Check lock-up amount
          function checkAmount(address sender, address token) external view returns (uint256);
      }
      
      //  Bonus logic contract
      interface Nest_3_TokenAbonus {
          //  Check NEST circulation snapshot
          function checkTokenAllValueHistory(address token, uint256 times) external view returns (uint256);
          //  Check NEST user balance snapshot
          function checkTokenSelfHistory(address token, uint256 times, address user) external view returns (uint256);
          //  Check bonus ledger period
          function checkTimes() external view returns (uint256);
      }
      
      //  Erc20 contract
      interface ERC20 {
          function totalSupply() external view returns (uint256);
          function balanceOf(address account) external view returns (uint256);
          function transfer(address recipient, uint256 amount) external returns (bool);
          function allowance(address owner, address spender) external view returns (uint256);
          function approve(address spender, uint256 amount) external returns (bool);
          function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
          event Transfer(address indexed from, address indexed to, uint256 value);
          event Approval(address indexed owner, address indexed spender, uint256 value);
      }
      
      library SafeMath {
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
              uint256 c = a + b;
              require(c >= a, "SafeMath: addition overflow");
      
              return c;
          }
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
              return sub(a, b, "SafeMath: subtraction overflow");
          }
          function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b <= a, errorMessage);
              uint256 c = a - b;
      
              return c;
          }
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
              if (a == 0) {
                  return 0;
              }
              uint256 c = a * b;
              require(c / a == b, "SafeMath: multiplication overflow");
      
              return c;
          }
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              return div(a, b, "SafeMath: division by zero");
          }
          function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              uint256 c = a / b;
              return c;
          }
          function mod(uint256 a, uint256 b) internal pure returns (uint256) {
              return mod(a, b, "SafeMath: modulo by zero");
          }
          function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b != 0, errorMessage);
              return a % b;
          }
      }