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 }