github.com/klaytn/klaytn@v1.12.1/contracts/bridge/BridgeOperator.sol (about) 1 // Copyright 2019 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The klaytn library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 pragma solidity 0.5.6; 18 19 import "../externals/openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; 20 import "../externals/openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol"; 21 import "../externals/openzeppelin-solidity/contracts/math/SafeMath.sol"; 22 import "../externals/openzeppelin-solidity/contracts/ownership/Ownable.sol"; 23 24 25 contract BridgeOperator is Ownable { 26 struct VotesData { 27 address[] voters; // voter list for deleting voted map 28 mapping(address => bytes32) voted; // <operator, sha3(type, args, nonce)> 29 30 bytes32[] voteKeys; // voteKey list for deleting voteCounts map 31 mapping(bytes32 => uint8) voteCounts; // <sha3(type, args, nonce), uint8> 32 } 33 34 mapping(uint8 => mapping (uint64 => VotesData)) private votes; // <voteType, <nonce, VotesData> 35 mapping(uint64 => bool) public closedValueTransferVotes; // <nonce, bool> 36 37 uint64 public constant MAX_OPERATOR = 12; 38 mapping(address => bool) public operators; 39 address[] public operatorList; 40 41 mapping(uint8 => uint8) public operatorThresholds; // <vote type, uint8> 42 uint64 public configurationNonce; 43 44 enum VoteType { 45 ValueTransfer, 46 Configuration, 47 Max 48 } 49 50 constructor() internal { 51 for (uint8 i = 0; i < uint8(VoteType.Max); i++) { 52 operatorThresholds[uint8(i)] = 1; 53 } 54 55 operators[msg.sender] = true; 56 operatorList.push(msg.sender); 57 } 58 59 modifier onlyOperators() 60 { 61 require(operators[msg.sender], "msg.sender is not an operator"); 62 _; 63 } 64 65 function getOperatorList() external view returns(address[] memory) { 66 return operatorList; 67 } 68 69 // _voteCommon handles common functionality for voting. 70 function _voteCommon(VoteType _voteType, uint64 _nonce, bytes32 _voteKey) 71 private 72 returns(bool) 73 { 74 VotesData storage vote = votes[uint8(_voteType)][_nonce]; 75 76 bytes32 oldVoteKeyOfVoter = vote.voted[msg.sender]; 77 if (oldVoteKeyOfVoter == bytes32(0)) { 78 vote.voters.push(msg.sender); 79 } else { 80 vote.voteCounts[oldVoteKeyOfVoter]--; 81 } 82 83 vote.voted[msg.sender] = _voteKey; 84 85 if (vote.voteCounts[_voteKey] == 0) { 86 vote.voteKeys.push(_voteKey); 87 } 88 vote.voteCounts[_voteKey]++; 89 90 if (vote.voteCounts[_voteKey] >= operatorThresholds[uint8(_voteType)]) { 91 _removeVoteData(_voteType, _nonce); 92 return true; 93 } 94 return false; 95 } 96 97 // _removeVoteData removes a vote data according to voteType and nonce. 98 function _removeVoteData(VoteType _voteType, uint64 _nonce) 99 internal 100 { 101 VotesData storage vote = votes[uint8(_voteType)][_nonce]; 102 103 for (uint8 i = 0; i < vote.voters.length; i++) { 104 delete vote.voted[vote.voters[i]]; 105 } 106 107 for (uint8 i = 0; i < vote.voteKeys.length; i++) { 108 delete vote.voteCounts[vote.voteKeys[i]]; 109 } 110 111 delete votes[uint8(_voteType)][_nonce]; 112 } 113 114 // _voteValueTransfer votes value transfer transaction with the operator. 115 function _voteValueTransfer(uint64 _requestNonce) 116 internal 117 returns(bool) 118 { 119 require(!closedValueTransferVotes[_requestNonce], "closed vote"); 120 121 bytes32 voteKey = keccak256(msg.data); 122 if (_voteCommon(VoteType.ValueTransfer, _requestNonce, voteKey)) { 123 closedValueTransferVotes[_requestNonce] = true; 124 return true; 125 } 126 127 return false; 128 } 129 130 // _voteConfiguration votes contract configuration transaction with the operator. 131 function _voteConfiguration(uint64 _requestNonce) 132 internal 133 returns(bool) 134 { 135 require(configurationNonce == _requestNonce, "nonce mismatch"); 136 137 bytes32 voteKey = keccak256(msg.data); 138 if (_voteCommon(VoteType.Configuration, _requestNonce, voteKey)) { 139 configurationNonce++; 140 return true; 141 } 142 143 return false; 144 } 145 146 // registerOperator registers a new operator. 147 function registerOperator(address _operator) 148 external 149 onlyOwner 150 { 151 require(operatorList.length < MAX_OPERATOR, "max operator limit"); 152 require(!operators[_operator], "exist operator"); 153 operators[_operator] = true; 154 operatorList.push(_operator); 155 } 156 157 // deregisterOperator deregisters the operator. 158 function deregisterOperator(address _operator) 159 external 160 onlyOwner 161 { 162 require(operators[_operator]); 163 delete operators[_operator]; 164 165 for (uint i = 0; i < operatorList.length; i++) { 166 if (operatorList[i] == _operator) { 167 operatorList[i] = operatorList[operatorList.length-1]; 168 operatorList.length--; 169 break; 170 } 171 } 172 } 173 174 // setOperatorThreshold sets the operator threshold. 175 function setOperatorThreshold(VoteType _voteType, uint8 _threshold) 176 external 177 onlyOwner 178 { 179 require(_threshold > 0, "zero threshold"); 180 require(operatorList.length >= _threshold, "bigger than num of operators"); 181 operatorThresholds[uint8(_voteType)] = _threshold; 182 } 183 }