github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/contracts/chief/src/poc_s0.5.sol (about)

     1  pragma solidity >=0.5.0 <0.6.0;
     2  
     3  contract POC_1_0_0 {
     4  
     5      struct minerInfo {
     6          address owner;//该矿工的owner地址
     7          uint256 amount;//抵押金额
     8          uint256 stop_block;//暂停出块时的区块号
     9      }
    10  
    11      //矿工地址对应的状态信息
    12      mapping(address=>minerInfo) minerMap;
    13  
    14      //正常出块矿工地址列表
    15      address[] normalList;
    16  
    17      //normalList下标索引
    18      mapping (address => uint256) normalListIndex;
    19  
    20      //停止出块矿工地址列表
    21      address[] stopList;
    22  
    23      //stopList下标索引
    24      mapping (address => uint256) stopListIndex;
    25  
    26      //黑名单列表
    27      address[] blackList;
    28  
    29      //blackList下标索引
    30      mapping (address => uint256) blackListIndex;
    31  
    32      //锁定名单列表
    33      address[] lockList;
    34  
    35      //lockList下标索引
    36      mapping (address => uint) lockListIndex;
    37  
    38  
    39      //合约owner地址
    40      address[] owner;
    41  
    42      //初始最小存放金额
    43      uint256 public initMinDeposit;
    44  
    45      //启动挖矿块号
    46      uint256 public initBlockNumber;
    47  
    48      //存款减半间隔区块数
    49      uint256 public depositHalveLimitNumber;
    50  
    51      //提现最小等待区块数
    52      uint256 public withdrawWaitNumber;
    53  
    54      //新的合约owner生效区块数
    55      uint256 public newOwnerEffectiveNumber;
    56  
    57  
    58      //存款
    59      event Deposit(address indexed miner, address indexed owner, uint256 amount);
    60  
    61      //暂停出块
    62      event Stop(address indexed miner);
    63  
    64      //启动出块
    65      event Start(address indexed miner);
    66  
    67      //提现
    68      event Withdraw(address indexed miner, address indexed owner, uint256 amount);
    69  
    70      modifier onlyOwner() {
    71  
    72          uint256 len = owner.length;
    73          address currentOwner;
    74  
    75          //最新owner
    76          currentOwner = owner[len - 1];
    77  
    78          //检查最新owner是否未生效
    79          if (len > 1 && block.number < newOwnerEffectiveNumber){
    80              currentOwner = owner[len - 2];//使用上一个owner
    81          }
    82  
    83          require(msg.sender == currentOwner);
    84          _;
    85      }
    86  
    87      constructor(address _addr, uint256 _amount, uint256 _waitNumber, uint256 _limitNumber) public {
    88  
    89          initMinDeposit = _amount;
    90          owner.push(_addr);
    91          withdrawWaitNumber = _waitNumber;
    92          depositHalveLimitNumber = _limitNumber;
    93          initBlockNumber = block.number;
    94      }
    95  
    96  
    97      //每经过 depositHalveLimitNumber 区块数以后,质押金额即可减半,减半三次后不再减半
    98      function minDepositAmount() public view returns(uint256) {
    99  
   100          // 减半次数
   101          uint256 num = (block.number - initBlockNumber) / depositHalveLimitNumber;
   102  
   103          if (num > 3){
   104              num = 3;
   105          }
   106          return initMinDeposit / (2 ** (num));
   107      }
   108  
   109  
   110      //存款进入出块人列表
   111      function deposit(bytes32 _r, bytes32 _s, uint8 _v) public payable {
   112  
   113          //满足最小存款金额
   114          require (msg.value >= minDepositAmount());
   115  
   116          //交易发起人是否得到矿工授权
   117          bytes32 h = keccak256(abi.encodePacked(msg.sender));
   118  
   119          //获取矿工地址
   120          address minerAddress = ecrecover(h,_v,_r,_s);
   121  
   122          require (minerAddress != address(uint160(0)));
   123  
   124          //只能质押一次
   125          require (minerMap[minerAddress].amount == 0);
   126  
   127          //记录出块信息
   128          minerMap[minerAddress] = minerInfo(msg.sender, msg.value, 0);
   129  
   130          //添加到正常出块列表
   131          normalList.push(minerAddress);
   132  
   133          //添加索引
   134          normalListIndex[minerAddress] = normalList.length - 1;
   135  
   136          //添加事件日志
   137          emit Deposit(minerAddress, msg.sender, msg.value);
   138      }
   139  
   140  
   141      //暂停出块 准备提现
   142      function stop(address minerAddress) public {
   143  
   144          //是否是地址owner
   145          require (minerMap[minerAddress].owner == msg.sender);
   146  
   147          require(addStop(minerAddress) == 1);
   148      }
   149  
   150  
   151      //结束暂停出块 恢复出块
   152      function start(address minerAddress) public {
   153  
   154          //是否是地址owner
   155          require (minerMap[minerAddress].owner == msg.sender);
   156  
   157          require(addStart(minerAddress) == 1);
   158      }
   159  
   160  
   161  
   162      //owner设置暂停出块
   163      function ownerStop(address minerAddress) public onlyOwner returns(int8) {
   164  
   165          return addStop(minerAddress);
   166      }
   167  
   168  
   169      //添加暂停出块入口 -1 不存在此地址 0 此地址已经在暂停列表 1 设置成功
   170      function addStop(address minerAddress) private returns(int8) {
   171  
   172          //是否存在此地址
   173          if (minerMap[minerAddress].amount == 0){
   174              return -1;
   175          }
   176  
   177          //是否已经在暂停出块
   178          if (minerMap[minerAddress].stop_block != 0){
   179              return 0;
   180          }
   181  
   182          //修改状态
   183          minerMap[minerAddress].stop_block = block.number;
   184  
   185          //获取位置下标
   186          uint256 index = normalListIndex[minerAddress];
   187  
   188          //使用最后一个地址覆盖
   189          normalList[index] = normalList[normalList.length - 1];
   190  
   191          normalList.length -= 1;
   192  
   193          //更新normalList索引
   194          delete normalListIndex[minerAddress];
   195          if (index < normalList.length){
   196              normalListIndex[normalList[index]] = index;
   197          }
   198  
   199          //加入暂停出块列表
   200          stopList.push(minerAddress);
   201  
   202          //更新stopList索引
   203          stopListIndex[minerAddress] = stopList.length - 1;
   204  
   205          //添加事件日志
   206          emit Stop(minerAddress);
   207  
   208          return 1;
   209      }
   210  
   211  
   212      //添加启动出块入口 -1 不存在此地址 0 此地址已经在出块列表或不被允许启动 1 设置成功
   213      function addStart(address minerAddress) private returns(int8) {
   214  
   215          //是否存在此地址
   216          if (minerMap[minerAddress].amount == 0){
   217              return -1;
   218          }
   219  
   220          //是否在黑名单或者锁定状态
   221          if (blackAndLockStatus(minerAddress) > 0){
   222              return 0;
   223          }
   224  
   225          //是否已经在正常出块
   226          if (minerMap[minerAddress].stop_block == 0){
   227              return 0;
   228          }
   229  
   230          //修改状态
   231          minerMap[minerAddress].stop_block = 0;
   232  
   233          //获取位置下标
   234          uint256 index = stopListIndex[minerAddress];
   235  
   236          //使用最后一个地址覆盖
   237          stopList[index] = stopList[stopList.length - 1];
   238          stopList.length -= 1;
   239  
   240          //更新stopList索引
   241          delete stopListIndex[minerAddress];
   242          if (index < stopList.length){
   243              stopListIndex[stopList[index]] = index;
   244          }
   245  
   246          //加入出块列表
   247          normalList.push(minerAddress);
   248  
   249          //更新normalList索引
   250          normalListIndex[minerAddress] = normalList.length - 1;
   251  
   252          //添加事件日志
   253          emit Start(minerAddress);
   254  
   255          return 1;
   256      }
   257  
   258  
   259      //获取黑名单和锁定状态
   260      function blackAndLockStatus(address minerAddress) public view returns(int8) {
   261  
   262          int8 value = 0;
   263  
   264          //是否在黑名单内
   265          if (blackList.length > 0 && blackList[blackListIndex[minerAddress]] == minerAddress){
   266              value += 1;
   267          }
   268  
   269          //是否在锁定名单内
   270          if (lockList.length > 0 && lockList[lockListIndex[minerAddress]] == minerAddress){
   271              value += 2;
   272          }
   273  
   274          return value;
   275      }
   276  
   277  
   278      //owner 新增地址到黑名单列表
   279      function ownerPushBlackList(address minerAddress) public onlyOwner {
   280  
   281          //是否已经在黑名单列表
   282          if (blackList.length > 0 && blackList[blackListIndex[minerAddress]] == minerAddress){
   283              return;
   284          }
   285  
   286          //加入黑名单列表
   287          blackList.push(minerAddress);
   288  
   289          //更新黑名单列表索引
   290          blackListIndex[minerAddress] = blackList.length - 1;
   291      }
   292  
   293  
   294      //owner 从黑名单列表剔除一个地址 -1 不存在此地址 1 设置成功
   295      function ownerPopBlackList(address minerAddress) public onlyOwner returns(int8){
   296  
   297          //获取位置下标
   298          uint256 index = blackListIndex[minerAddress];
   299  
   300          //是否存在此地址
   301          if (blackList.length < 1 || blackList[index] != minerAddress){
   302              return -1;
   303          }
   304  
   305          //使用最后一个地址覆盖
   306          blackList[index] = blackList[blackList.length - 1];
   307          blackList.length -= 1;
   308  
   309          //更新blackList索引
   310          delete blackListIndex[minerAddress];
   311          if (index < blackList.length){
   312              blackListIndex[blackList[index]] = index;
   313          }
   314  
   315          return 1;
   316      }
   317  
   318  
   319      //owner 清空黑名单列表
   320      function ownerEmptyBlackList() public onlyOwner {
   321  
   322          //清空索引
   323          for(uint256 i = 0; i < blackList.length; i++){
   324              delete blackListIndex[blackList[i]];
   325          }
   326  
   327          //删除数据
   328          blackList.length = 0;
   329  
   330      }
   331  
   332  
   333      //owner 新增地址到锁定列表
   334      function ownerPushLockList(address minerAddress) public onlyOwner {
   335  
   336          //是否已经在锁定列表
   337          if (lockList.length > 0 && lockList[lockListIndex[minerAddress]] == minerAddress){
   338              return;
   339          }
   340  
   341          //加入锁定列表
   342          lockList.push(minerAddress);
   343  
   344          //更新锁定列表索引
   345          lockListIndex[minerAddress] = lockList.length - 1;
   346  
   347      }
   348  
   349  
   350      //owner 从锁定列表中删除一个地址 -1 不存在此地址 1 设置成功
   351      function ownerPopLockList(address minerAddress) public onlyOwner returns(int8){
   352  
   353          //获取位置下标
   354          uint256 index = lockListIndex[minerAddress];
   355  
   356          //是否存在此地址
   357          if (lockList.length < 1 || lockList[index] != minerAddress){
   358              return -1;
   359          }
   360  
   361          //使用最后一个覆盖
   362          lockList[index] = lockList[lockList.length - 1];
   363          lockList.length -= 1;
   364  
   365          //更新locklist索引
   366          delete lockListIndex[minerAddress];
   367          if (index < lockList.length){
   368              lockListIndex[lockList[index]] = index;
   369          }
   370  
   371          return 1;
   372  
   373      }
   374  
   375  
   376      //owner 设置启动挖矿块号
   377      function ownerSetInitBlockNumber (uint256 _number) onlyOwner public {
   378          initBlockNumber = _number;
   379      }
   380  
   381  
   382  
   383      //修改owner
   384      function changeOwner(address _newOwner, uint256 _number) onlyOwner public {
   385  
   386          //覆盖未生效的owner
   387          if (block.number < newOwnerEffectiveNumber){
   388              owner[owner.length - 1] = _newOwner;
   389          } else {
   390              owner.push(_newOwner);
   391          }
   392          newOwnerEffectiveNumber = _number;
   393      }
   394  
   395  
   396      //质押资金提现
   397      function withdraw(address minerAddress) public {
   398  
   399          //是否是地址owner
   400          require (minerMap[minerAddress].owner == msg.sender);
   401  
   402          //是否处于暂停状态
   403          require (minerMap[minerAddress].stop_block > 0);
   404  
   405          //暂停等待期是否完成
   406          require (block.number - minerMap[minerAddress].stop_block > withdrawWaitNumber);
   407  
   408          //是否在黑名单或者锁定状态
   409          require (blackAndLockStatus(minerAddress) == 0);
   410  
   411          uint256 amount = minerMap[minerAddress].amount;
   412  
   413          //删除记录
   414          delete minerMap[minerAddress];
   415  
   416          //获取位置下标
   417          uint256 index = stopListIndex[minerAddress];
   418  
   419          //使用最后一个地址覆盖
   420          stopList[index] = stopList[stopList.length - 1];
   421          stopList.length -= 1;
   422  
   423          //更新stopList索引
   424          delete stopListIndex[minerAddress];
   425          if (index < stopList.length){
   426              stopListIndex[stopList[index]] = index;
   427          }
   428  
   429          //添加事件日志
   430          emit Withdraw(minerAddress, msg.sender, amount);
   431  
   432          //资金返回
   433          msg.sender.transfer(amount);
   434      }
   435  
   436  
   437      //提出大于最小质押金额的资金
   438      function withdrawSurplus(address minerAddress) public {
   439          //是否是地址owner
   440          require (minerMap[minerAddress].owner == msg.sender);
   441  
   442          uint256 amount = minerMap[minerAddress].amount - minDepositAmount();
   443  
   444          require (amount > 0);
   445  
   446          minerMap[minerAddress].amount = minerMap[minerAddress].amount - amount;
   447  
   448          //添加事件日志
   449          emit Withdraw(minerAddress, msg.sender, amount);
   450  
   451          //资金返回
   452          msg.sender.transfer(amount);
   453      }
   454  
   455  
   456  
   457      // 获取矿工信息,当amount 或 minerOwner为空时 表示不存在记录,number为暂停块号,大于0则已经处于暂停状态
   458      function minerStatus(address _addr) public view returns(uint256, uint256, address) {
   459  
   460          uint256 amount = minerMap[_addr].amount;
   461          uint256 number = minerMap[_addr].stop_block;
   462          address minerOwner = minerMap[_addr].owner;
   463  
   464          return (amount, number, minerOwner);
   465      }
   466  
   467  
   468      //获取所有暂停出块地址
   469      function getStopList() public view returns(address[] memory) {
   470          return stopList;
   471      }
   472  
   473  
   474      //获取所有正常出块地址
   475      function getNormalList() public view returns(address[] memory) {
   476          return normalList;
   477      }
   478  
   479  
   480      //获取所有黑名单地址
   481      function getBlackList () public view returns(address[] memory) {
   482          return blackList;
   483      }
   484  
   485  
   486      //获取所有锁定名单地址
   487      function getLockList () public view returns(address[] memory) {
   488          return lockList;
   489      }
   490  
   491  
   492      //获取所有owner地址
   493      function getOwnerList() public view returns(address[] memory) {
   494          return owner;
   495      }
   496  
   497  
   498      //获取所有信息
   499      function getAll() public view returns(
   500          address[] memory,
   501          uint256[] memory,
   502          uint256[] memory,
   503          address[] memory,
   504          uint256[] memory
   505      ){
   506          uint256 slen = stopList.length;
   507          uint256 nlen = normalList.length;
   508          uint256 len = slen + nlen;
   509  
   510          //地址列表
   511          address[] memory minerList;
   512          minerList = new address[](len);
   513  
   514          //质押资金列表
   515          uint256[] memory amountList;
   516          amountList = new uint256[](len);
   517  
   518          //暂停区块号列表
   519          uint256[] memory blockList;
   520          blockList = new uint256[](len);
   521  
   522          //owner列表
   523          address[] memory ownerList;
   524          ownerList = new address[](len);
   525  
   526          //黑名单状态
   527          uint256[] memory blackStatusList;
   528          blackStatusList = new uint256[](len);
   529  
   530          for (uint256 i = 0; i < slen; i++){
   531              minerList[i]  = stopList[i];
   532              amountList[i] = minerMap[stopList[i]].amount;
   533              blockList[i]  = minerMap[stopList[i]].stop_block;
   534              ownerList[i]  = minerMap[stopList[i]].owner;
   535              if (blackList.length > 0 && blackList[blackListIndex[stopList[i]]] == stopList[i]){
   536                  blackStatusList[i] = 1;
   537              } else {
   538                  blackStatusList[i] = 0;
   539              }
   540          }
   541  
   542          for (uint256 j = 0; j < nlen; j++ ){
   543              minerList[slen + j]  = normalList[j];
   544              amountList[slen + j] = minerMap[normalList[j]].amount;
   545              blockList[slen + j]  = minerMap[normalList[j]].stop_block;
   546              ownerList[slen + j]  = minerMap[normalList[j]].owner;
   547              if (blackList.length > 0 && blackList[blackListIndex[normalList[j]]] == normalList[j]){
   548                  blackStatusList[slen + j] = 1;
   549              } else {
   550                  blackStatusList[slen + j] = 0;
   551              }
   552          }
   553          return (minerList, amountList, blockList, ownerList, blackStatusList);
   554      }
   555  }