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  }