{"file_path":"VotingMachine.sol","creation_status":"success","source_code":"/*\r\nCopyright MOC Investments Corp. 2020. All rights reserved.\r\n \r\nYou acknowledge and agree that MOC Investments Corp. (“MOC”) (or MOC’s licensors) own all legal right, title and\r\ninterest in and to the work, software, application, source code, documentation and any other documents in this\r\nrepository (collectively, the “Program”), including any intellectual property rights which subsist in the\r\nProgram (whether those rights happen to be registered or not, and wherever in the world those rights may exist),\r\nwhether in source code or any other form.\r\n \r\nSubject to the limited license below, you may not (and you may not permit anyone else to) distribute, publish, copy,\r\nmodify, merge, combine with another program, create derivative works of, reverse engineer, decompile or otherwise\r\nattempt to extract the source code of, the Program or any part thereof, except that you may contribute to\r\nthis repository.\r\n \r\nYou are granted a non-exclusive, non-transferable, non-sublicensable license to distribute, publish, copy, modify,\r\nmerge, combine with another program or create derivative works of the Program (such resulting program, collectively,\r\nthe “Resulting Program”) solely for Non-Commercial Use as long as you:\r\n 1. give prominent notice (“Notice”) with each copy of the Resulting Program that the Program is used in the Resulting\r\n  Program and that the Program is the copyright of MOC Investments Corp.; and\r\n 2. subject the Resulting Program and any distribution, publication, copy, modification, merger therewith,\r\n  combination with another program or derivative works thereof to the same Notice requirement and Non-Commercial\r\n  Use restriction set forth herein.\r\n \r\n“Non-Commercial Use” means each use as described in clauses (1)-(3) below, as reasonably determined by MOC Investments\r\nCorp. in its sole discretion:\r\n 1. personal use for research, personal study, private entertainment, hobby projects or amateur pursuits, in each\r\n case without any anticipated commercial application;\r\n 2. use by any charitable organization, educational institution, public research organization, public safety or health\r\n organization, environmental protection organization or government institution; or\r\n 3. the number of monthly active users of the Resulting Program across all versions thereof and platforms globally\r\n do not exceed 10,000 at any time.\r\n \r\nYou will not use any trade mark, service mark, trade name, logo of MOC Investments Corp. or any other company or\r\norganization in a way that is likely or intended to cause confusion about the owner or authorized user of such marks,\r\nnames or logos.\r\n \r\nIf you have any questions, comments or interest in pursuing any other use cases, please reach out to us\r\nat moc.license@moneyonchain.com.\r\n\r\n*/\r\n\r\npragma solidity 0.6.12;\r\n\r\n\r\n/**\r\n * @dev Interface of the ERC20 standard as defined in the EIP.\r\n */\r\ninterface IERC20 {\r\n    /**\r\n     * @dev Returns the amount of tokens in existence.\r\n     */\r\n    function totalSupply() external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens owned by `account`.\r\n     */\r\n    function balanceOf(address account) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transfer(address recipient, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Returns the remaining number of tokens that `spender` will be\r\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\r\n     * zero by default.\r\n     *\r\n     * This value changes when {approve} or {transferFrom} are called.\r\n     */\r\n    function allowance(address owner, address spender) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\r\n     * that someone may use both the old and the new allowance by unfortunate\r\n     * transaction ordering. One possible solution to mitigate this race\r\n     * condition is to first reduce the spender's allowance to 0 and set the\r\n     * desired value afterwards:\r\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\r\n     *\r\n     * Emits an {Approval} event.\r\n     */\r\n    function approve(address spender, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\r\n     * allowance mechanism. `amount` is then deducted from the caller's\r\n     * allowance.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\r\n     * another (`to`).\r\n     *\r\n     * Note that `value` may be zero.\r\n     */\r\n    event Transfer(address indexed from, address indexed to, uint256 value);\r\n\r\n    /**\r\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\r\n     * a call to {approve}. `value` is the new allowance.\r\n     */\r\n    event Approval(address indexed owner, address indexed spender, uint256 value);\r\n}\r\n\r\n\r\n/**\r\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\r\n * checks.\r\n *\r\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\r\n * in bugs, because programmers usually assume that an overflow raises an\r\n * error, which is the standard behavior in high level programming languages.\r\n * `SafeMath` restores this intuition by reverting the transaction when an\r\n * operation overflows.\r\n *\r\n * Using this library instead of the unchecked operations eliminates an entire\r\n * class of bugs, so it's recommended to use it always.\r\n */\r\nlibrary SafeMath {\r\n    /**\r\n     * @dev Returns the addition of two unsigned integers, reverting on\r\n     * overflow.\r\n     *\r\n     * Counterpart to Solidity's `+` operator.\r\n     *\r\n     * Requirements:\r\n     * - Addition cannot overflow.\r\n     */\r\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        uint256 c = a + b;\r\n        require(c >= a, \"SafeMath: addition overflow\");\r\n\r\n        return c;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the subtraction of two unsigned integers, reverting on\r\n     * overflow (when the result is negative).\r\n     *\r\n     * Counterpart to Solidity's `-` operator.\r\n     *\r\n     * Requirements:\r\n     * - Subtraction cannot overflow.\r\n     */\r\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return sub(a, b, \"SafeMath: subtraction overflow\");\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\r\n     * overflow (when the result is negative).\r\n     *\r\n     * Counterpart to Solidity's `-` operator.\r\n     *\r\n     * Requirements:\r\n     * - Subtraction cannot overflow.\r\n     */\r\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\r\n        require(b <= a, errorMessage);\r\n        uint256 c = a - b;\r\n\r\n        return c;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the multiplication of two unsigned integers, reverting on\r\n     * overflow.\r\n     *\r\n     * Counterpart to Solidity's `*` operator.\r\n     *\r\n     * Requirements:\r\n     * - Multiplication cannot overflow.\r\n     */\r\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\r\n        // benefit is lost if 'b' is also tested.\r\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\r\n        if (a == 0) {\r\n            return 0;\r\n        }\r\n\r\n        uint256 c = a * b;\r\n        require(c / a == b, \"SafeMath: multiplication overflow\");\r\n\r\n        return c;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the integer division of two unsigned integers. Reverts on\r\n     * division by zero. The result is rounded towards zero.\r\n     *\r\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\r\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\r\n     * uses an invalid opcode to revert (consuming all remaining gas).\r\n     *\r\n     * Requirements:\r\n     * - The divisor cannot be zero.\r\n     */\r\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return div(a, b, \"SafeMath: division by zero\");\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\r\n     * division by zero. The result is rounded towards zero.\r\n     *\r\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\r\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\r\n     * uses an invalid opcode to revert (consuming all remaining gas).\r\n     *\r\n     * Requirements:\r\n     * - The divisor cannot be zero.\r\n     */\r\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\r\n        // Solidity only automatically asserts when dividing by 0\r\n        require(b > 0, errorMessage);\r\n        uint256 c = a / b;\r\n        // assert(a == b * c + a % b); // There is no case in which this doesn't hold\r\n\r\n        return c;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\r\n     * Reverts when dividing by zero.\r\n     *\r\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\r\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\r\n     * invalid opcode to revert (consuming all remaining gas).\r\n     *\r\n     * Requirements:\r\n     * - The divisor cannot be zero.\r\n     */\r\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return mod(a, b, \"SafeMath: modulo by zero\");\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\r\n     * Reverts with custom message when dividing by zero.\r\n     *\r\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\r\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\r\n     * invalid opcode to revert (consuming all remaining gas).\r\n     *\r\n     * Requirements:\r\n     * - The divisor cannot be zero.\r\n     */\r\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\r\n        require(b != 0, errorMessage);\r\n        return a % b;\r\n    }\r\n}\r\n\r\n\r\n\r\n\r\n/**\r\n * @title Initializable\r\n *\r\n * @dev Helper contract to support initializer functions. To use it, replace\r\n * the constructor with a function that has the `initializer` modifier.\r\n * WARNING: Unlike constructors, initializer functions must be manually\r\n * invoked. This applies both to deploying an Initializable contract, as well\r\n * as extending an Initializable contract via inheritance.\r\n * WARNING: When used with inheritance, manual care must be taken to not invoke\r\n * a parent initializer twice, or ensure that all initializers are idempotent,\r\n * because this is not dealt with automatically as with constructors.\r\n */\r\ncontract Initializable {\r\n\r\n  /**\r\n   * @dev Indicates that the contract has been initialized.\r\n   */\r\n  bool private initialized;\r\n\r\n  /**\r\n   * @dev Indicates that the contract is in the process of being initialized.\r\n   */\r\n  bool private initializing;\r\n\r\n  /**\r\n   * @dev Modifier to use in the initializer function of a contract.\r\n   */\r\n  modifier initializer() {\r\n    require(initializing || isConstructor() || !initialized, \"Contract instance has already been initialized\");\r\n\r\n    bool isTopLevelCall = !initializing;\r\n    if (isTopLevelCall) {\r\n      initializing = true;\r\n      initialized = true;\r\n    }\r\n\r\n    _;\r\n\r\n    if (isTopLevelCall) {\r\n      initializing = false;\r\n    }\r\n  }\r\n\r\n  /// @dev Returns true if and only if the function is running in the constructor\r\n  function isConstructor() private view returns (bool) {\r\n    // extcodesize checks the size of the code stored in an address, and\r\n    // address returns the current address. Since the code is still not\r\n    // deployed when running a constructor, any checks on its code size will\r\n    // yield zero, making it an effective way to detect if a contract is\r\n    // under construction or not.\r\n    address self = address(this);\r\n    uint256 cs;\r\n    assembly { cs := extcodesize(self) }\r\n    return cs == 0;\r\n  }\r\n\r\n  // Reserved storage space to allow for layout changes in the future.\r\n  uint256[50] private ______gap;\r\n}\r\n\r\n\r\n\r\n\r\n/*\r\n    Abstract contract meant to be reused.\r\n    An iterable unique map of address -> proposals.\r\n*/\r\nlibrary ProposalInfoLib {\r\n    using SafeMath for uint256;\r\n\r\n    struct ProposalData {\r\n        // The round in which this proposal was proposed\r\n        uint256 votingRound;\r\n        // Accumulated votes in MOCs\r\n        uint256 votes;\r\n        // Expiration time\r\n        uint256 expirationTimestamp;\r\n    }\r\n\r\n    struct ProposalInfoData {\r\n        address[] proposalList;\r\n        mapping(address => ProposalData) proposals;\r\n    }\r\n\r\n    /**\r\n      ProposalInfoData data initializations\r\n    */\r\n    function _init() internal pure returns (ProposalInfoData memory) {\r\n        address[] memory emptyList;\r\n        return ProposalInfoData(emptyList);\r\n    }\r\n\r\n    /**\r\n    Add to the set, increasing its size\r\n\r\n    @param _key the key of the mapping\r\n    @param _data the value to assign\r\n    */\r\n    function _push(\r\n        ProposalInfoData storage self,\r\n        address _key,\r\n        ProposalData memory _data\r\n    ) internal {\r\n        require(!_contains(self, _key), \"Duplicated key\");\r\n        require(_data.votingRound != 0, \"Invalid votingRound value\");\r\n        self.proposals[_key] = _data;\r\n        self.proposalList.push(_key);\r\n    }\r\n\r\n    /**\r\n    Replace an element by index. After an iteration the resulting index can be use to replace an element\r\n\r\n    @param _idx the index in the list for the old element\r\n    @param _newKey the new key of the mapping\r\n    @param _data the new value to assign\r\n    */\r\n    function _replace(\r\n        ProposalInfoData storage self,\r\n        uint256 _idx,\r\n        address _newKey,\r\n        ProposalData memory _data\r\n    ) internal {\r\n        require(_idx < _length(self), \"Index out of range_replace\");\r\n        require(_data.votingRound != 0, \"Invalid votingRound value\");\r\n        delete self.proposals[self.proposalList[_idx]];\r\n        require(!_contains(self, _newKey), \"Duplicated key\");\r\n        self.proposalList[_idx] = _newKey;\r\n        self.proposals[_newKey] = _data;\r\n    }\r\n\r\n    /**\r\n    Replace an element by index address\r\n\r\n    @param _oldKey the kef of the old element\r\n    @param _newKey the new key of the mapping\r\n    @param _data the new value to assign\r\n    */\r\n    function _replace(\r\n        ProposalInfoData storage self,\r\n        address _oldKey,\r\n        address _newKey,\r\n        ProposalData memory _data\r\n    ) internal {\r\n        _replace(self, _find(self, _oldKey), _newKey, _data);\r\n    }\r\n\r\n    /**\r\n    Gets an element by index (used during iteration).\r\n\r\n    @param _idx the index used to get the element\r\n    */\r\n    function _get(ProposalInfoData storage self, uint256 _idx)\r\n        internal\r\n        view\r\n        returns (address, ProposalData memory)\r\n    {\r\n        require(_idx < _length(self), \"Index out of range_get\");\r\n        return (self.proposalList[_idx], self.proposals[self.proposalList[_idx]]);\r\n    }\r\n\r\n    /**\r\n    Gets an element by address.\r\n\r\n    @param _key the key used to get the element\r\n    */\r\n    function _get(ProposalInfoData storage self, address _key)\r\n        internal\r\n        view\r\n        returns (ProposalData memory)\r\n    {\r\n        require(_contains(self, _key), \"Key not found\");\r\n        return self.proposals[_key];\r\n    }\r\n\r\n    /**\r\n    Set a value by address.\r\n\r\n    @param _key the key used to set the element value\r\n    @param _data the new value to set\r\n    */\r\n    function _set(\r\n        ProposalInfoData storage self,\r\n        address _key,\r\n        ProposalData memory _data\r\n    ) internal {\r\n        require(_contains(self, _key), \"Invalid key\");\r\n        require(_data.votingRound != 0, \"Invalid votingRound value\");\r\n        self.proposals[_key] = _data;\r\n    }\r\n\r\n    /**\r\n    Set a value by index.\r\n\r\n    @param _idx the index of element to change\r\n    @param _data the new value to set\r\n    */\r\n    function _set(\r\n        ProposalInfoData storage self,\r\n        uint256 _idx,\r\n        ProposalData memory _data\r\n    ) internal {\r\n        require(_idx < _length(self), \"Index out of range_set\");\r\n        _set(self, self.proposalList[_idx], _data);\r\n    }\r\n\r\n    /**\r\n    Get the quantity of elements\r\n\r\n    */\r\n    function _length(ProposalInfoData storage self) internal view returns (uint256) {\r\n        return self.proposalList.length;\r\n    }\r\n\r\n    /**\r\n    Check if the map contains a specific address.\r\n\r\n    @param _key the address to check\r\n    */\r\n    function _contains(ProposalInfoData storage self, address _key) internal view returns (bool) {\r\n        return _key != address(0) && self.proposals[_key].votingRound != 0;\r\n    }\r\n\r\n    /**\r\n    Remove from the list by index (reducing its size)\r\n\r\n    @param _idx the index of the element to remove\r\n    */\r\n    function _remove(ProposalInfoData storage self, uint256 _idx) internal {\r\n        require(_idx < _length(self), \"Index out of range _remove\");\r\n        delete self.proposals[self.proposalList[_idx]];\r\n        self.proposalList[_idx] = self.proposalList[self.proposalList.length - 1];\r\n        self.proposalList.pop();\r\n    }\r\n\r\n    /**\r\n      Remove from the list by address (reducing its size).\r\n      This method does a linear search of the element, use with care\r\n\r\n      @param _key the key used to search the element to remove\r\n    */\r\n    function _remove(ProposalInfoData storage self, address _key) internal {\r\n        _remove(self, _find(self, _key));\r\n    }\r\n\r\n    /**\r\n      This method does a linear search of some key, use with care\r\n\r\n      @param _key the key to that is searched\r\n    */\r\n    function _find(ProposalInfoData storage self, address _key) internal view returns (uint256) {\r\n        require(_contains(self, _key), \"Key not found\");\r\n        for (uint256 i = 0; i < _length(self); i++) {\r\n            if (self.proposalList[i] == _key) {\r\n                return i;\r\n            }\r\n        }\r\n        require(false, \"Missing key?\");\r\n        return 0;\r\n    }\r\n}\r\n\r\n\r\n/*\r\n    Abstract contract meant to be reused.\r\n*/\r\nlibrary PreVotingDataLib {\r\n    using SafeMath for uint256;\r\n    using ProposalInfoLib for ProposalInfoLib.ProposalInfoData;\r\n\r\n    struct PreVotingData {\r\n        // Proposal Information\r\n        ProposalInfoLib.ProposalInfoData proposalInfo;\r\n    }\r\n\r\n    /**\r\n    PreVotingList data initializations\r\n    */\r\n    function _init(PreVotingData storage self) internal {\r\n        self.proposalInfo = ProposalInfoLib._init();\r\n    }\r\n\r\n    /**\r\n    The proposal was never voted or is new in this round\r\n\r\n    @param _proposalAddr Address of the change contract that will be executed if this vote is successful\r\n    */\r\n    function _isEmptyProposal(\r\n        PreVotingData storage self,\r\n        uint256 _votingRound,\r\n        address _proposalAddr\r\n    ) internal view returns (bool) {\r\n        if (!self.proposalInfo._contains(_proposalAddr)) {\r\n            return true;\r\n        }\r\n        ProposalInfoLib.ProposalData memory proposal = self.proposalInfo._get(_proposalAddr);\r\n        return __isReusableProposal(_votingRound, proposal);\r\n    }\r\n\r\n    /**\r\n    Insert or update a proposal. If the list is full then replace the one with less stake.\r\n\r\n    @param _proposalAddr address of the change contract\r\n    @param _stake stake used\r\n    */\r\n    function _upsert(\r\n        PreVotingData storage self,\r\n        uint256 _votingRound,\r\n        uint256 _maxPreProposals,\r\n        uint256 _preVoteExpirationTimeDelta,\r\n        address _proposalAddr,\r\n        uint256 _stake\r\n    ) internal returns (bool) {\r\n        // Reuse a proposal.\r\n        if (self.proposalInfo._contains(_proposalAddr)) {\r\n            ProposalInfoLib.ProposalData memory proposal = self.proposalInfo._get(_proposalAddr);\r\n            if (!__isReusableProposal(_votingRound, proposal)) {\r\n                // Can't reuse an active proposal\r\n                return false;\r\n            }\r\n\r\n            self.proposalInfo._set(\r\n                _proposalAddr,\r\n                __newProposal(_votingRound, _preVoteExpirationTimeDelta, _stake)\r\n            );\r\n            return true;\r\n        }\r\n\r\n        // Completely new proposal, there is a place in the list\r\n        if (self.proposalInfo._length() < _maxPreProposals) {\r\n            self.proposalInfo._push(\r\n                _proposalAddr,\r\n                __newProposal(_votingRound, _preVoteExpirationTimeDelta, _stake)\r\n            );\r\n            return true;\r\n        }\r\n\r\n        // Completely new proposal but there is no place in the list, must check if there are proposals to remove.\r\n        (uint256 minIdx, uint256 minVal) = __findAPlace(self, _votingRound);\r\n        if (_stake > minVal) {\r\n            self.proposalInfo._replace(\r\n                minIdx,\r\n                _proposalAddr,\r\n                __newProposal(_votingRound, _preVoteExpirationTimeDelta, _stake)\r\n            );\r\n            return true;\r\n        }\r\n        return false;\r\n    }\r\n\r\n    /**\r\n     Add votes to a proposal\r\n\r\n     @param _proposalAddr address of the change contract\r\n     @param _stake stake used\r\n     */\r\n    function _addVotes(\r\n        PreVotingData storage self,\r\n        uint256 _votingRound,\r\n        address _proposalAddr,\r\n        uint256 _stake\r\n    ) internal returns (bool) {\r\n        if (!self.proposalInfo._contains(_proposalAddr)) {\r\n            return false;\r\n        }\r\n        ProposalInfoLib.ProposalData memory proposal = self.proposalInfo._get(_proposalAddr);\r\n        if (__isReusableProposal(_votingRound, proposal)) {\r\n            return false;\r\n        }\r\n        // We don't let them vote an expired proposal\r\n        if (__isExpired(proposal)) {\r\n            return false;\r\n        }\r\n        proposal.votes = _stake.add(proposal.votes);\r\n        self.proposalInfo._set(_proposalAddr, proposal);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n      Remove from the pre-voting list an expired proposal\r\n\r\n      @param _proposalAddr address of the change contract\r\n    */\r\n    function _remove(\r\n        PreVotingData storage self,\r\n        uint256 _votingRound,\r\n        address _proposalAddr\r\n    ) internal returns (bool) {\r\n        if (!self.proposalInfo._contains(_proposalAddr)) {\r\n            return false;\r\n        }\r\n        ProposalInfoLib.ProposalData memory proposal = self.proposalInfo._get(_proposalAddr);\r\n        if (!__isReusableProposal(_votingRound, proposal)) {\r\n            return false;\r\n        }\r\n        self.proposalInfo._remove(_proposalAddr);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n    Get a winner proposal.\r\n    Search the proposal with max pre-votes if it is expired then that proposal is the winner.\r\n    If two proposals has the same quantity of votes take the with older expiration time.\r\n    @param _preVoteMinPCToWin minimum percentage of vote needed to participate (moc votes/total moc in circulation).\r\n    @param _pctPrecision percentage precision.\r\n    @param _totalMOCSupply total supply of moc to calculate percentages.\r\n    */\r\n    function _getWinnerProposal(\r\n        PreVotingData storage self,\r\n        uint256 _votingRound,\r\n        uint256 _preVoteMinPCToWin,\r\n        uint256 _pctPrecision,\r\n        uint256 _totalMOCSupply\r\n    ) internal view returns (address candidateAddress, uint256 maxVal) {\r\n        address currentAddress;\r\n        ProposalInfoLib.ProposalData memory candidateProposal;\r\n        ProposalInfoLib.ProposalData memory currentProposal;\r\n        uint256 maxVotes = 0;\r\n\r\n        // Search the proposal (expired or not) with the max quantity of votes.\r\n        for (uint256 i = 0; i < self.proposalInfo._length(); i++) {\r\n            (currentAddress, currentProposal) = self.proposalInfo._get(i);\r\n\r\n            if (__isReusableProposal(_votingRound, currentProposal)) {\r\n                continue;\r\n            }\r\n\r\n            // Not enough votes to participate.\r\n            if (\r\n                currentProposal.votes.mul(_pctPrecision) < _totalMOCSupply.mul(_preVoteMinPCToWin)\r\n            ) {\r\n                continue;\r\n            }\r\n\r\n            if (\r\n                currentProposal.votes > maxVotes ||\r\n                (currentProposal.votes == maxVotes &&\r\n                    currentProposal.expirationTimestamp < candidateProposal.expirationTimestamp)\r\n            ) {\r\n                maxVotes = currentProposal.votes;\r\n                candidateAddress = currentAddress;\r\n                candidateProposal = currentProposal;\r\n            }\r\n        }\r\n\r\n        // if the candidate is expired we have a winner.\r\n        if (__isExpired(candidateProposal)) {\r\n            return (candidateAddress, candidateProposal.votes);\r\n        }\r\n        return (address(0), 0);\r\n    }\r\n\r\n    /**\r\n    Get the proposal count\r\n    */\r\n    function _getProposalCount(PreVotingData storage self) internal view returns (uint256) {\r\n        return self.proposalInfo._length();\r\n    }\r\n\r\n    /**\r\n    Get proposal address and information by index\r\n\r\n    @param _index Index of proposal to query. \r\n    */\r\n    function _getProposalByIndex(PreVotingData storage self, uint256 _index)\r\n        internal\r\n        view\r\n        returns (\r\n            address proposalAddress,\r\n            uint256 votingRound,\r\n            uint256 votes,\r\n            uint256 expirationTimeStamp\r\n        )\r\n    {\r\n        (address addr, ProposalInfoLib.ProposalData memory data) = self.proposalInfo._get(_index);\r\n        return (addr, data.votingRound, data.votes, data.expirationTimestamp);\r\n    }\r\n\r\n    /**\r\n    Check if a is valid.\r\n\r\n    @param _votes stake used\r\n    */\r\n    function __newProposal(\r\n        uint256 _votingRound,\r\n        uint256 _preVoteExpirationTimeDelta,\r\n        uint256 _votes\r\n    ) internal view returns (ProposalInfoLib.ProposalData memory) {\r\n        return\r\n            ProposalInfoLib.ProposalData({\r\n                votingRound: _votingRound,\r\n                votes: _votes, // solhint-disable-next-line not-rely-on-time\r\n                expirationTimestamp: block.timestamp + _preVoteExpirationTimeDelta\r\n            });\r\n    }\r\n\r\n    /**\r\n    Find a place in the list, at this point I'm sure that there is no winner proposal and that the list is\r\n    full (length > 1). We use the first  expired or reusable slot. If all the proposals are active then we\r\n    search for the one that has minimum votes.\r\n    */\r\n    function __findAPlace(PreVotingData storage self, uint256 _votingRound)\r\n        internal\r\n        view\r\n        returns (uint256 minIdx, uint256 minVal)\r\n    {\r\n        ProposalInfoLib.ProposalData memory proposal;\r\n        (, proposal) = self.proposalInfo._get(0);\r\n        if (__isReusableProposal(_votingRound, proposal) || __isExpired(proposal)) {\r\n            return (0, 0);\r\n        }\r\n\r\n        // The proposal in idx == 0 is not expired => is active.\r\n        (minIdx, minVal) = (0, proposal.votes);\r\n        for (uint256 i = 1; i < self.proposalInfo._length(); i++) {\r\n            (, proposal) = self.proposalInfo._get(i);\r\n            if (__isReusableProposal(_votingRound, proposal) || __isExpired(proposal)) {\r\n                return (i, 0);\r\n            }\r\n            // Not expired proposals, calculate the min and max\r\n            if (proposal.votes < minVal) {\r\n                (minIdx, minVal) = (i, proposal.votes);\r\n            }\r\n        }\r\n\r\n        // We only use an active proposal if there are no expired proposals or free slots.\r\n        return (minIdx, minVal);\r\n    }\r\n\r\n    function _isExpired(\r\n        PreVotingData storage self,\r\n        uint256 _votingRound,\r\n        address _proposalAddr\r\n    ) internal view returns (bool) {\r\n        if (!self.proposalInfo._contains(_proposalAddr)) {\r\n            return false;\r\n        }\r\n        ProposalInfoLib.ProposalData memory proposal = self.proposalInfo._get(_proposalAddr);\r\n        if (__isReusableProposal(_votingRound, proposal)) {\r\n            return false;\r\n        }\r\n        return __isExpired(proposal);\r\n    }\r\n\r\n    /**\r\n    The proposal was never voted or is new in this round\r\n\r\n    @param _proposal proposal data\r\n    */\r\n    function __isReusableProposal(\r\n        uint256 _votingRound,\r\n        ProposalInfoLib.ProposalData memory _proposal\r\n    ) internal pure returns (bool) {\r\n        return (_proposal.votingRound != _votingRound);\r\n    }\r\n\r\n    function __isExpired(ProposalInfoLib.ProposalData memory _proposal)\r\n        internal\r\n        view\r\n        returns (bool)\r\n    {\r\n        // solhint-disable-next-line not-rely-on-time\r\n        return (_proposal.expirationTimestamp < block.timestamp);\r\n    }\r\n}\r\n\r\n\r\n\r\n/*\r\n    Abstract contract meant to be reused.\r\n*/\r\nlibrary VotingDataLib {\r\n    using SafeMath for uint256;\r\n    using ProposalInfoLib for ProposalInfoLib.ProposalInfoData;\r\n\r\n    struct VotingData {\r\n        // Pre-voting winner proposal\r\n        address winnerProposal;\r\n        // Accumulated votes in MOCs\r\n        uint256 inFavorVotes;\r\n        // Accumulated votes in MOCs\r\n        uint256 againstVotes;\r\n        // voting process expiration time.\r\n        uint256 votingExpirationTime;\r\n    }\r\n\r\n    /**\r\n    Voting data initializations\r\n    */\r\n    function _init(VotingData storage self) internal {\r\n        self.winnerProposal = address(0);\r\n        self.inFavorVotes = 0;\r\n        self.againstVotes = 0;\r\n    }\r\n\r\n    /**\r\n     */\r\n    function _startVoting(\r\n        VotingData storage self,\r\n        uint256 _votingTimeDelta,\r\n        address _winnerProposal,\r\n        uint256 _inFavorVotes,\r\n        uint256 _againstVotes\r\n    ) internal {\r\n        self.winnerProposal = _winnerProposal;\r\n        self.inFavorVotes = _inFavorVotes;\r\n        self.againstVotes = _againstVotes;\r\n        // solhint-disable-next-line not-rely-on-time\r\n        self.votingExpirationTime = _votingTimeDelta + block.timestamp;\r\n    }\r\n\r\n    /**\r\n     */\r\n    function _addVotes(\r\n        VotingData storage self,\r\n        uint256 _stake,\r\n        bool _inFavorAgainst\r\n    ) internal {\r\n        if (_inFavorAgainst) {\r\n            self.inFavorVotes = self.inFavorVotes.add(_stake);\r\n        } else {\r\n            self.againstVotes = self.againstVotes.add(_stake);\r\n        }\r\n    }\r\n\r\n    /**\r\n     */\r\n    function _isVeto(\r\n        VotingData storage self,\r\n        uint256 _PCTPrecision,\r\n        uint256 _voteMinPctToVeto,\r\n        uint256 _totalMOC\r\n    ) internal view returns (bool) {\r\n        return (self.againstVotes.mul(_PCTPrecision) > _totalMOC.mul(_voteMinPctToVeto));\r\n    }\r\n\r\n    /**\r\n     */\r\n    function _isAccepted(\r\n        VotingData storage self,\r\n        uint256 _PCTPrecision,\r\n        uint256 _voteMinPctToVeto,\r\n        uint256 _voteMinPctForQuorum,\r\n        uint256 _voteMinPctToAccept,\r\n        uint256 _totalMOC\r\n    ) internal view returns (bool) {\r\n        uint256 inFavor = self.inFavorVotes.mul(_PCTPrecision);\r\n        // If the proposal is more than 70% of total mocs in circulation is accepted (can not be vetted anyway)\r\n        if ((inFavor >= _totalMOC.mul(_PCTPrecision.sub(_voteMinPctToVeto)))) {\r\n            return true;\r\n        }\r\n        // Still don't expired.\r\n        if (!_isExpired(self)) {\r\n            return false;\r\n        }\r\n        // Less than 20% of total mocs in circulation\r\n        if (inFavor < _totalMOC.mul(_voteMinPctForQuorum)) {\r\n            return false;\r\n        }\r\n        // After expiration in favor < 50% * (in favor + against)\r\n        if (inFavor < _voteMinPctToAccept.mul(self.againstVotes.add(self.inFavorVotes))) {\r\n            return false;\r\n        }\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     */\r\n    function _isExpired(VotingData storage self) internal view returns (bool) {\r\n        // solhint-disable-next-line not-rely-on-time\r\n        return (self.votingExpirationTime < block.timestamp);\r\n    }\r\n}\r\n\r\n\r\n\r\ninterface IRegistry {\r\n    // *** Getter Methods ***\r\n    function getDecimal(bytes32 _key) external view returns (int232 base, int16 exp);\r\n\r\n    function getUint(bytes32 _key) external view returns (uint248);\r\n\r\n    function getString(bytes32 _key) external view returns (string memory);\r\n\r\n    function getAddress(bytes32 _key) external view returns (address);\r\n\r\n    function getBytes(bytes32 _key) external view returns (bytes memory);\r\n\r\n    function getBool(bytes32 _key) external view returns (bool);\r\n\r\n    function getInt(bytes32 _key) external view returns (int248);\r\n\r\n    // *** Setter Methods ***\r\n    function setDecimal(\r\n        bytes32 _key,\r\n        int232 _base,\r\n        int16 _exp\r\n    ) external;\r\n\r\n    function setUint(bytes32 _key, uint248 _value) external;\r\n\r\n    function setString(bytes32 _key, string calldata _value) external;\r\n\r\n    function setAddress(bytes32 _key, address _value) external;\r\n\r\n    function setBytes(bytes32 _key, bytes calldata _value) external;\r\n\r\n    function setBool(bytes32 _key, bool _value) external;\r\n\r\n    function setInt(bytes32 _key, int248 _value) external;\r\n\r\n    // *** Delete Methods ***\r\n    function deleteDecimal(bytes32 _key) external;\r\n\r\n    function deleteUint(bytes32 _key) external;\r\n\r\n    function deleteString(bytes32 _key) external;\r\n\r\n    function deleteAddress(bytes32 _key) external;\r\n\r\n    function deleteBytes(bytes32 _key) external;\r\n\r\n    function deleteBool(bytes32 _key) external;\r\n\r\n    function deleteInt(bytes32 _key) external;\r\n\r\n    // Nov 2020 Upgrade\r\n    // *** Getter Methods ***\r\n    function getAddressArrayLength(bytes32 _key) external view returns (uint256);\r\n\r\n    function getAddressArrayElementAt(bytes32 _key, uint256 idx) external view returns (address);\r\n\r\n    function pushAddressArrayElement(bytes32 _key, address _addr) external;\r\n\r\n    function getAddressArray(bytes32 _key) external view returns (address[] memory);\r\n\r\n    function addressArrayContains(bytes32 _key, address value) external view returns (bool);\r\n\r\n    // *** Setters ***\r\n    function pushAddressArray(bytes32 _key, address[] memory data) external;\r\n\r\n    function clearAddressArray(bytes32 _key) external;\r\n\r\n    function removeAddressArrayElement(bytes32 _key, address value) external;\r\n}\r\n\r\n// Autogenerated by registryConstants.js\r\n// solhint-disable func-name-mixedcase\r\n\r\ncontract RegistryConstants {\r\n    // MOC_PROJECT_VERSION = keccak256(moc.project.version)\r\n    bytes32 public constant MOC_PROJECT_VERSION =\r\n        0xc1c87e0508bb8270ee6a6dbe630baa072e6e3d5968981666724b9333430e1c31;\r\n\r\n    // MOC_TOKEN = keccak256(moc.token)\r\n    bytes32 public constant MOC_TOKEN =\r\n        0x4bd5e7ff929fdd1ba62a33f76e0f40e97bb35e8bf126c0d9d91ce5c69a4bc521;\r\n\r\n    // MOC_DELAY_MACHINE = keccak256(moc.delay-machine)\r\n    bytes32 public constant MOC_DELAY_MACHINE =\r\n        0x66b60892ff6e7f0da16db27046f5960fdfd6bce5c3c8c21d56ccca3236a6281b;\r\n\r\n    // MOC_STAKING_MACHINE = keccak256(moc.staking-machine)\r\n    bytes32 public constant MOC_STAKING_MACHINE =\r\n        0x3c557531fea67120f21bc7711270a96f1b8cff3dfe3dd798a8a9f09ce9b77972;\r\n\r\n    // MOC_VESTING_MACHINE = keccak256(moc.vesting-machine)\r\n    bytes32 public constant MOC_VESTING_MACHINE =\r\n        0x7dfea4fb968e2599cdb7b3028c07d0188d0f92d1d00bd95c2805523c224649dd;\r\n\r\n    // MOC_VOTING_MACHINE = keccak256(moc.voting-machine)\r\n    bytes32 public constant MOC_VOTING_MACHINE =\r\n        0xc0ded27704f62d8726fdbd83648113d9fd8cf32c09f80523d2ba523e0bbd5ba4;\r\n\r\n    // MOC_UPGRADE_DELEGATOR = keccak256(moc.upgrade-delegator)\r\n    bytes32 public constant MOC_UPGRADE_DELEGATOR =\r\n        0x631bcbb9b033f9c8d13c32cf6e60827348d77b91b58c295e87745219242cca22;\r\n\r\n    // MOC_PRICE_PROVIDER_REGISTRY = keccak256(moc.price-provider-registy)\r\n    bytes32 public constant MOC_PRICE_PROVIDER_REGISTRY =\r\n        0xd4ed72d0bf9bae5e1e7ae31a372a37c8069168889284ec94be25b3f6707f5b4a;\r\n\r\n    // MOC_VOTING_MACHINE_MIN_STAKE = keccak256(moc.voting-machine.minStake)\r\n    bytes32 public constant MOC_VOTING_MACHINE_MIN_STAKE =\r\n        0x580be8e098dd1016787d59c2a534bf9df9ec679a29de4c8f92dc3807f7d7d54d;\r\n\r\n    // MOC_VOTING_MACHINE_PRE_VOTE_EXPIRATION_TIME_DELTA = keccak256(moc.voting-machine.preVoteExpirationTimeDelta)\r\n    bytes32 public constant MOC_VOTING_MACHINE_PRE_VOTE_EXPIRATION_TIME_DELTA =\r\n        0x62f5dbf0c17b0df83487409f747ad2eeca5fd54c140ca59b32cf39d6f6eaf916;\r\n\r\n    // MOC_VOTING_MACHINE_MAX_PRE_PROPOSALS = keccak256(moc.voting-machine.maxPreProposals)\r\n    bytes32 public constant MOC_VOTING_MACHINE_MAX_PRE_PROPOSALS =\r\n        0xc32b9cbc59039d297e670e7c196424308c90ba4a437fa7ccd008498c934e7dbf;\r\n\r\n    // MOC_VOTING_MACHINE_PRE_VOTE_MIN_PCT_TO_WIN = keccak256(moc.voting-machine.preVoteMinPCToWin)\r\n    bytes32 public constant MOC_VOTING_MACHINE_PRE_VOTE_MIN_PCT_TO_WIN =\r\n        0x0a1b21dfd7e4f3741529cf579e2731e847d81bbf13a82d0eba6910d7ac4c1c0a;\r\n\r\n    // MOC_VOTING_MACHINE_VOTE_MIN_PCT_TO_VETO = keccak256(moc.voting-machine.voteMinPctToVeto)\r\n    bytes32 public constant MOC_VOTING_MACHINE_VOTE_MIN_PCT_TO_VETO =\r\n        0xfb2d33acd65c36f68a15f8fe41cb8c0dd1eda164ffa87c6882e685ccb1c1adfb;\r\n\r\n    // MOC_VOTING_MACHINE_VOTE_MIN_PCT_FOR_QUORUM = keccak256(moc.voting-machine.voteMinPctForQuorum)\r\n    bytes32 public constant MOC_VOTING_MACHINE_VOTE_MIN_PCT_FOR_QUORUM =\r\n        0xde1ede48948567c43c504b761af8cd6af5363fafeceb1239b3083955d809714f;\r\n\r\n    // MOC_VOTING_MACHINE_VOTE_MIN_PCT_TO_ACCEPT = keccak256(moc.voting-machine.voteMinPctToAccept)\r\n    bytes32 public constant MOC_VOTING_MACHINE_VOTE_MIN_PCT_TO_ACCEPT =\r\n        0x99f83ee0c57b325f3deafb536d55596743ff112c6ac0d853d5f4f89b75dec045;\r\n\r\n    // MOC_VOTING_MACHINE_PCT_PRECISION = keccak256(moc.voting-machine.PCTPrecision)\r\n    bytes32 public constant MOC_VOTING_MACHINE_PCT_PRECISION =\r\n        0x73ee596441ef88c207a7a9147d62f59186b4991555e37b7ce9c801f9539d1050;\r\n\r\n    // MOC_VOTING_MACHINE_VOTING_TIME_DELTA = keccak256(moc.voting-machine.votingTimeDelta)\r\n    bytes32 public constant MOC_VOTING_MACHINE_VOTING_TIME_DELTA =\r\n        0xb43ee0a5ee6dcc7115ce824e4e353526ad6e479afa4daeb78451070de942de36;\r\n\r\n    // ORACLE_MANAGER_ADDR = keccak256(MOC_ORACLE\\1\\ORACLE_MANAGER_ADDR)\r\n    bytes32 public constant ORACLE_MANAGER_ADDR =\r\n        0x16986f74674f2ed21d50b6e74e6b12bb323ff4f72364542fd5de5104f3cc3ca9;\r\n\r\n    // SUPPORTERS_ADDR = keccak256(MOC_ORACLE\\1\\SUPPORTERS_ADDR)\r\n    bytes32 public constant SUPPORTERS_ADDR =\r\n        0xe4f979504d2a7a24557a15195eb83131e7c4a66d33900454705435aa5a6ee086;\r\n\r\n    // INFO_ADDR = keccak256(MOC_ORACLE\\1\\INFO_ADDR)\r\n    bytes32 public constant INFO_ADDR =\r\n        0xda9f12e01fc92de345bb741448d36ecb967052dd7aa1670439af833c9a3d78f1;\r\n\r\n    // ORACLE_PRICE_FETCH_RATE = keccak256(MOC_ORACLE\\1\\ORACLE_PRICE_FETCH_RATE)\r\n    bytes32 public constant ORACLE_PRICE_FETCH_RATE =\r\n        0x945f72e5d44fb0ce3b1de393d19415723b79f97ad801089d8470d1c20e15ffef;\r\n\r\n    // ORACLE_BLOCKCHAIN_INFO_INTERVAL = keccak256(MOC_ORACLE\\1\\ORACLE_BLOCKCHAIN_INFO_INTERVAL)\r\n    bytes32 public constant ORACLE_BLOCKCHAIN_INFO_INTERVAL =\r\n        0x11cfbdf601b80a575e4366f0234cc06de0c9f401fe250dd9dccfccefeedb6fc2;\r\n\r\n    // ORACLE_COIN_PAIR_LOOP_TASK_INTERVAL = keccak256(MOC_ORACLE\\1\\ORACLE_COIN_PAIR_LOOP_TASK_INTERVAL)\r\n    bytes32 public constant ORACLE_COIN_PAIR_LOOP_TASK_INTERVAL =\r\n        0x2f271dc1fa81985bda14a2d6d0d60b45191d2a2d97e636b192696a8796d654a7;\r\n\r\n    // ORACLE_MAIN_LOOP_TASK_INTERVAL = keccak256(MOC_ORACLE\\1\\ORACLE_MAIN_LOOP_TASK_INTERVAL)\r\n    bytes32 public constant ORACLE_MAIN_LOOP_TASK_INTERVAL =\r\n        0x275d8a46b817572476d2d55b41c7709dee307740bad676a9693805003a48d231;\r\n\r\n    // ORACLE_PRICE_REJECT_DELTA_PCT = keccak256(MOC_ORACLE\\1\\ORACLE_PRICE_REJECT_DELTA_PCT)\r\n    bytes32 public constant ORACLE_PRICE_REJECT_DELTA_PCT =\r\n        0x7a3ee46ca1bd3e19089870d8d6530b083a86da93aab52efccb32d5950e2709cf;\r\n\r\n    // ORACLE_CONFIGURATION_TASK_INTERVAL = keccak256(MOC_ORACLE\\1\\ORACLE_CONFIGURATION_TASK_INTERVAL)\r\n    bytes32 public constant ORACLE_CONFIGURATION_TASK_INTERVAL =\r\n        0xb027f2006a45346de89db4c5efc53f4e05e96532d27366aff00367a394d0abc4;\r\n\r\n    // ORACLE_GATHER_SIGNATURE_TIMEOUT = keccak256(MOC_ORACLE\\1\\ORACLE_GATHER_SIGNATURE_TIMEOUT)\r\n    bytes32 public constant ORACLE_GATHER_SIGNATURE_TIMEOUT =\r\n        0xf75b08b2b912abdbb87cc459ca0b4fdc019329386ec84ab68399b0c86fed5a95;\r\n\r\n    // ORACLE_MAIN_EXECUTOR_TASK_INTERVAL = keccak256(MOC_ORACLE\\1\\ORACLE_MAIN_EXECUTOR_TASK_INTERVAL)\r\n    bytes32 public constant ORACLE_MAIN_EXECUTOR_TASK_INTERVAL =\r\n        0xb324a91be1ac0d0c4888c835aee124ca1a7caf4b73ce10aa3504e2683865d7e5;\r\n\r\n    // SCHEDULER_POOL_DELAY = keccak256(MOC_ORACLE\\1\\SCHEDULER_POOL_DELAY)\r\n    bytes32 public constant SCHEDULER_POOL_DELAY =\r\n        0x6c2abc911c0fa4c73b90c7143a9f4429749be45ebfe7b81e69b86e7ca440d811;\r\n\r\n    // SCHEDULER_ROUND_DELAY = keccak256(MOC_ORACLE\\1\\SCHEDULER_ROUND_DELAY)\r\n    bytes32 public constant SCHEDULER_ROUND_DELAY =\r\n        0xa82bea7140872d1398fa0ab5075330ab0228f4c7e381b4b6502379ffc7cdcd9f;\r\n\r\n    // ORACLE_PRICE_DIGITS = keccak256(MOC_ORACLE\\1\\ORACLE_PRICE_DIGITS)\r\n    bytes32 public constant ORACLE_PRICE_DIGITS =\r\n        0x4cd7e3f12ee4a2db0a6ba16e03fbc31bba1048c149bbf4fc9f3c02021ec550b8;\r\n\r\n    // ORACLE_QUEUE_LEN = keccak256(MOC_ORACLE\\1\\ORACLE_QUEUE_LEN)\r\n    bytes32 public constant ORACLE_QUEUE_LEN =\r\n        0x7d32d87d65898c3cbc7e72c59d223bf61c7811e99dafafd24fb08e0a38f10914;\r\n\r\n    // MESSAGE_VERSION = keccak256(MOC_ORACLE\\1\\MESSAGE_VERSION)\r\n    bytes32 public constant MESSAGE_VERSION =\r\n        0xeafac1a2b4d4fdcc942cbdce334a88ec83387087978d039f1320d3639a0b59df;\r\n\r\n    // ORACLE_PRICE_DELTA_PCT = keccak256(MOC_ORACLE\\1\\ORACLE_PRICE_DELTA_PCT)\r\n    bytes32 public constant ORACLE_PRICE_DELTA_PCT =\r\n        0x41a2ac05b365409628009a8091d8dda06fe52fe2f1c792e651e5df7599a7a7de;\r\n\r\n    // ORACLE_PRICE_PUBLISH_BLOCKS = keccak256(MOC_ORACLE\\1\\ORACLE_PRICE_PUBLISH_BLOCKS)\r\n    bytes32 public constant ORACLE_PRICE_PUBLISH_BLOCKS =\r\n        0x51a2be29a473202678b6cf57b717ba5d7ff671f01fdbdbfcad4e1882601b8896;\r\n\r\n    // ORACLE_ENTERING_FALLBACKS_AMOUNTS = keccak256(MOC_ORACLE\\1\\ORACLE_ENTERING_FALLBACKS_AMOUNTS)\r\n    bytes32 public constant ORACLE_ENTERING_FALLBACKS_AMOUNTS =\r\n        0xf646c455329c7af0436f9e95c59c90ce0e11bb4e3a1deff805807798696adf88;\r\n\r\n    // ORACLE_TRIGGER_VALID_PUBLICATION_BLOCKS = keccak256(MOC_ORACLE\\1\\ORACLE_TRIGGER_VALID_PUBLICATION_BLOCKS)\r\n    bytes32 public constant ORACLE_TRIGGER_VALID_PUBLICATION_BLOCKS =\r\n        0xef9006fe6663199909dfaa4ab45e3f86d6454adb7773682f356824b6b3bc6b0e;\r\n\r\n    // ORACLE_MIN_ORACLES_PER_ROUND = keccak256(MOC_ORACLE\\1\\ORACLE_MIN_ORACLES_PER_ROUND)\r\n    bytes32 public constant ORACLE_MIN_ORACLES_PER_ROUND =\r\n        0xf5afc54dd2c3e35bfa15485ed117b621cf51f31f803d11be832ccde6c77a6b56;\r\n\r\n    // MOC_FLOW_BUFFERS = keccak256(MOC_FLOW\\1\\BUFFERS)\r\n    bytes32 public constant MOC_FLOW_BUFFERS =\r\n        0x4cb845794d5472a713e41e8e4ddc566dab8d695f1dc6c8edd43dad9d55112a22;\r\n\r\n    // MOC_FLOW_DRIPPERS = keccak256(MOC_FLOW\\1\\DRIPPERS)\r\n    bytes32 public constant MOC_FLOW_DRIPPERS =\r\n        0xdd6eacd9b2305faa48e6e500ef302cf28b8cd660dc843b355a6f5f26655eee73;\r\n\r\n    // MOC_FLOW_COINERS = keccak256(MOC_FLOW\\1\\COINERS)\r\n    bytes32 public constant MOC_FLOW_COINERS =\r\n        0x8970fe7a53b9c3dfce4f2afec48b5a6550afcb16ea2da8a10ec4b47a83a34a9d;\r\n\r\n    // MOC_FLOW_REVERSE_AUCTIONS = keccak256(MOC_FLOW\\1\\REVERSE_AUCTIONS)\r\n    bytes32 public constant MOC_FLOW_REVERSE_AUCTIONS =\r\n        0x0428ec087e0cce276a71d1caf1afe4da32a2d48b3ebe579040612b5bd262ff73;\r\n}\r\n\r\nlibrary RegistryConstantsLib {\r\n    function MOC_PROJECT_VERSION() internal pure returns (bytes32) {\r\n        // keccak256(moc.project.version)\r\n        return 0xc1c87e0508bb8270ee6a6dbe630baa072e6e3d5968981666724b9333430e1c31;\r\n    }\r\n\r\n    function MOC_TOKEN() internal pure returns (bytes32) {\r\n        // keccak256(moc.token)\r\n        return 0x4bd5e7ff929fdd1ba62a33f76e0f40e97bb35e8bf126c0d9d91ce5c69a4bc521;\r\n    }\r\n\r\n    function MOC_DELAY_MACHINE() internal pure returns (bytes32) {\r\n        // keccak256(moc.delay-machine)\r\n        return 0x66b60892ff6e7f0da16db27046f5960fdfd6bce5c3c8c21d56ccca3236a6281b;\r\n    }\r\n\r\n    function MOC_STAKING_MACHINE() internal pure returns (bytes32) {\r\n        // keccak256(moc.staking-machine)\r\n        return 0x3c557531fea67120f21bc7711270a96f1b8cff3dfe3dd798a8a9f09ce9b77972;\r\n    }\r\n\r\n    function MOC_VESTING_MACHINE() internal pure returns (bytes32) {\r\n        // keccak256(moc.vesting-machine)\r\n        return 0x7dfea4fb968e2599cdb7b3028c07d0188d0f92d1d00bd95c2805523c224649dd;\r\n    }\r\n\r\n    function MOC_VOTING_MACHINE() internal pure returns (bytes32) {\r\n        // keccak256(moc.voting-machine)\r\n        return 0xc0ded27704f62d8726fdbd83648113d9fd8cf32c09f80523d2ba523e0bbd5ba4;\r\n    }\r\n\r\n    function MOC_UPGRADE_DELEGATOR() internal pure returns (bytes32) {\r\n        // keccak256(moc.upgrade-delegator)\r\n        return 0x631bcbb9b033f9c8d13c32cf6e60827348d77b91b58c295e87745219242cca22;\r\n    }\r\n\r\n    function MOC_PRICE_PROVIDER_REGISTRY() internal pure returns (bytes32) {\r\n        // keccak256(moc.price-provider-registy)\r\n        return 0xd4ed72d0bf9bae5e1e7ae31a372a37c8069168889284ec94be25b3f6707f5b4a;\r\n    }\r\n\r\n    function MOC_VOTING_MACHINE_MIN_STAKE() internal pure returns (bytes32) {\r\n        // keccak256(moc.voting-machine.minStake)\r\n        return 0x580be8e098dd1016787d59c2a534bf9df9ec679a29de4c8f92dc3807f7d7d54d;\r\n    }\r\n\r\n    function MOC_VOTING_MACHINE_PRE_VOTE_EXPIRATION_TIME_DELTA() internal pure returns (bytes32) {\r\n        // keccak256(moc.voting-machine.preVoteExpirationTimeDelta)\r\n        return 0x62f5dbf0c17b0df83487409f747ad2eeca5fd54c140ca59b32cf39d6f6eaf916;\r\n    }\r\n\r\n    function MOC_VOTING_MACHINE_MAX_PRE_PROPOSALS() internal pure returns (bytes32) {\r\n        // keccak256(moc.voting-machine.maxPreProposals)\r\n        return 0xc32b9cbc59039d297e670e7c196424308c90ba4a437fa7ccd008498c934e7dbf;\r\n    }\r\n\r\n    function MOC_VOTING_MACHINE_PRE_VOTE_MIN_PCT_TO_WIN() internal pure returns (bytes32) {\r\n        // keccak256(moc.voting-machine.preVoteMinPCToWin)\r\n        return 0x0a1b21dfd7e4f3741529cf579e2731e847d81bbf13a82d0eba6910d7ac4c1c0a;\r\n    }\r\n\r\n    function MOC_VOTING_MACHINE_VOTE_MIN_PCT_TO_VETO() internal pure returns (bytes32) {\r\n        // keccak256(moc.voting-machine.voteMinPctToVeto)\r\n        return 0xfb2d33acd65c36f68a15f8fe41cb8c0dd1eda164ffa87c6882e685ccb1c1adfb;\r\n    }\r\n\r\n    function MOC_VOTING_MACHINE_VOTE_MIN_PCT_FOR_QUORUM() internal pure returns (bytes32) {\r\n        // keccak256(moc.voting-machine.voteMinPctForQuorum)\r\n        return 0xde1ede48948567c43c504b761af8cd6af5363fafeceb1239b3083955d809714f;\r\n    }\r\n\r\n    function MOC_VOTING_MACHINE_VOTE_MIN_PCT_TO_ACCEPT() internal pure returns (bytes32) {\r\n        // keccak256(moc.voting-machine.voteMinPctToAccept)\r\n        return 0x99f83ee0c57b325f3deafb536d55596743ff112c6ac0d853d5f4f89b75dec045;\r\n    }\r\n\r\n    function MOC_VOTING_MACHINE_PCT_PRECISION() internal pure returns (bytes32) {\r\n        // keccak256(moc.voting-machine.PCTPrecision)\r\n        return 0x73ee596441ef88c207a7a9147d62f59186b4991555e37b7ce9c801f9539d1050;\r\n    }\r\n\r\n    function MOC_VOTING_MACHINE_VOTING_TIME_DELTA() internal pure returns (bytes32) {\r\n        // keccak256(moc.voting-machine.votingTimeDelta)\r\n        return 0xb43ee0a5ee6dcc7115ce824e4e353526ad6e479afa4daeb78451070de942de36;\r\n    }\r\n\r\n    function ORACLE_MANAGER_ADDR() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_MANAGER_ADDR)\r\n        return 0x16986f74674f2ed21d50b6e74e6b12bb323ff4f72364542fd5de5104f3cc3ca9;\r\n    }\r\n\r\n    function SUPPORTERS_ADDR() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\SUPPORTERS_ADDR)\r\n        return 0xe4f979504d2a7a24557a15195eb83131e7c4a66d33900454705435aa5a6ee086;\r\n    }\r\n\r\n    function INFO_ADDR() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\INFO_ADDR)\r\n        return 0xda9f12e01fc92de345bb741448d36ecb967052dd7aa1670439af833c9a3d78f1;\r\n    }\r\n\r\n    function ORACLE_PRICE_FETCH_RATE() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_PRICE_FETCH_RATE)\r\n        return 0x945f72e5d44fb0ce3b1de393d19415723b79f97ad801089d8470d1c20e15ffef;\r\n    }\r\n\r\n    function ORACLE_BLOCKCHAIN_INFO_INTERVAL() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_BLOCKCHAIN_INFO_INTERVAL)\r\n        return 0x11cfbdf601b80a575e4366f0234cc06de0c9f401fe250dd9dccfccefeedb6fc2;\r\n    }\r\n\r\n    function ORACLE_COIN_PAIR_LOOP_TASK_INTERVAL() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_COIN_PAIR_LOOP_TASK_INTERVAL)\r\n        return 0x2f271dc1fa81985bda14a2d6d0d60b45191d2a2d97e636b192696a8796d654a7;\r\n    }\r\n\r\n    function ORACLE_MAIN_LOOP_TASK_INTERVAL() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_MAIN_LOOP_TASK_INTERVAL)\r\n        return 0x275d8a46b817572476d2d55b41c7709dee307740bad676a9693805003a48d231;\r\n    }\r\n\r\n    function ORACLE_PRICE_REJECT_DELTA_PCT() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_PRICE_REJECT_DELTA_PCT)\r\n        return 0x7a3ee46ca1bd3e19089870d8d6530b083a86da93aab52efccb32d5950e2709cf;\r\n    }\r\n\r\n    function ORACLE_CONFIGURATION_TASK_INTERVAL() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_CONFIGURATION_TASK_INTERVAL)\r\n        return 0xb027f2006a45346de89db4c5efc53f4e05e96532d27366aff00367a394d0abc4;\r\n    }\r\n\r\n    function ORACLE_GATHER_SIGNATURE_TIMEOUT() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_GATHER_SIGNATURE_TIMEOUT)\r\n        return 0xf75b08b2b912abdbb87cc459ca0b4fdc019329386ec84ab68399b0c86fed5a95;\r\n    }\r\n\r\n    function ORACLE_MAIN_EXECUTOR_TASK_INTERVAL() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_MAIN_EXECUTOR_TASK_INTERVAL)\r\n        return 0xb324a91be1ac0d0c4888c835aee124ca1a7caf4b73ce10aa3504e2683865d7e5;\r\n    }\r\n\r\n    function SCHEDULER_POOL_DELAY() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\SCHEDULER_POOL_DELAY)\r\n        return 0x6c2abc911c0fa4c73b90c7143a9f4429749be45ebfe7b81e69b86e7ca440d811;\r\n    }\r\n\r\n    function SCHEDULER_ROUND_DELAY() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\SCHEDULER_ROUND_DELAY)\r\n        return 0xa82bea7140872d1398fa0ab5075330ab0228f4c7e381b4b6502379ffc7cdcd9f;\r\n    }\r\n\r\n    function ORACLE_PRICE_DIGITS() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_PRICE_DIGITS)\r\n        return 0x4cd7e3f12ee4a2db0a6ba16e03fbc31bba1048c149bbf4fc9f3c02021ec550b8;\r\n    }\r\n\r\n    function ORACLE_QUEUE_LEN() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_QUEUE_LEN)\r\n        return 0x7d32d87d65898c3cbc7e72c59d223bf61c7811e99dafafd24fb08e0a38f10914;\r\n    }\r\n\r\n    function MESSAGE_VERSION() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\MESSAGE_VERSION)\r\n        return 0xeafac1a2b4d4fdcc942cbdce334a88ec83387087978d039f1320d3639a0b59df;\r\n    }\r\n\r\n    function ORACLE_PRICE_DELTA_PCT() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_PRICE_DELTA_PCT)\r\n        return 0x41a2ac05b365409628009a8091d8dda06fe52fe2f1c792e651e5df7599a7a7de;\r\n    }\r\n\r\n    function ORACLE_PRICE_PUBLISH_BLOCKS() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_PRICE_PUBLISH_BLOCKS)\r\n        return 0x51a2be29a473202678b6cf57b717ba5d7ff671f01fdbdbfcad4e1882601b8896;\r\n    }\r\n\r\n    function ORACLE_ENTERING_FALLBACKS_AMOUNTS() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_ENTERING_FALLBACKS_AMOUNTS)\r\n        return 0xf646c455329c7af0436f9e95c59c90ce0e11bb4e3a1deff805807798696adf88;\r\n    }\r\n\r\n    function ORACLE_TRIGGER_VALID_PUBLICATION_BLOCKS() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_TRIGGER_VALID_PUBLICATION_BLOCKS)\r\n        return 0xef9006fe6663199909dfaa4ab45e3f86d6454adb7773682f356824b6b3bc6b0e;\r\n    }\r\n\r\n    function ORACLE_MIN_ORACLES_PER_ROUND() internal pure returns (bytes32) {\r\n        // keccak256(MOC_ORACLE\\1\\ORACLE_MIN_ORACLES_PER_ROUND)\r\n        return 0xf5afc54dd2c3e35bfa15485ed117b621cf51f31f803d11be832ccde6c77a6b56;\r\n    }\r\n\r\n    function MOC_FLOW_BUFFERS() internal pure returns (bytes32) {\r\n        // keccak256(MOC_FLOW\\1\\BUFFERS)\r\n        return 0x4cb845794d5472a713e41e8e4ddc566dab8d695f1dc6c8edd43dad9d55112a22;\r\n    }\r\n\r\n    function MOC_FLOW_DRIPPERS() internal pure returns (bytes32) {\r\n        // keccak256(MOC_FLOW\\1\\DRIPPERS)\r\n        return 0xdd6eacd9b2305faa48e6e500ef302cf28b8cd660dc843b355a6f5f26655eee73;\r\n    }\r\n\r\n    function MOC_FLOW_COINERS() internal pure returns (bytes32) {\r\n        // keccak256(MOC_FLOW\\1\\COINERS)\r\n        return 0x8970fe7a53b9c3dfce4f2afec48b5a6550afcb16ea2da8a10ec4b47a83a34a9d;\r\n    }\r\n\r\n    function MOC_FLOW_REVERSE_AUCTIONS() internal pure returns (bytes32) {\r\n        // keccak256(MOC_FLOW\\1\\REVERSE_AUCTIONS)\r\n        return 0x0428ec087e0cce276a71d1caf1afe4da32a2d48b3ebe579040612b5bd262ff73;\r\n    }\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/// @title This contract provides an interface for feeding prices from oracles, and\r\n///        get the current price. One contract must be instanced per supported coin pair,\r\n///        and registered through OracleManager global contract.\r\n/// This contract has two lists:\r\n/// 1) A subscribed list (EnumerableSet.AddressSet) oracles owner addresses, this list has a max size (30).\r\n/// 2) A selected list, EnumerableSet.AddressSet of oracles owner addresses that are selected to participate in\r\n/// current publication round (10 entries max size).\r\n///\r\n/// Oracles are subscribed by adding them to the subscribed oracle list. When the list is full\r\n/// the oracle with less stake can be removed by a new oracle that is trying to\r\n/// subscribe (if its stake is greater than his).\r\n/// On each round switch the list of selected oracles is populated with the 10 Oracles with more stake. An oracle\r\n/// can unsubscribe itself from the subscribed list in the middle of the round, in this case, the oracle is still\r\n/// listed in the selected list until the round ends.\r\n/// If an oracle withdraw some stake then his participation in the round is put into consideration: If the\r\n/// oracle ends up having less stake than the next oracle in the subscribed list (but not in the selected list) then\r\n/// it is removed from the selected list and the point he accumulated during the round are lost (set to zero).\r\n\r\ninterface ICoinPairPrice {\r\n    // getOracleOwnerAddress: Given an Oracle address return the Oracle Owner address.\r\n    // Used during publication, the servers sign with the oracle address, but the list of selected oracles\r\n    // is by oracle owner address.\r\n    // getOracleOwnerStake: Get the stake stored in the supporters smart-contract\r\n    // prettier-ignore\r\n    struct CoinPairPriceCallbacks {\r\n        function (address) external view returns (address) getOracleOwnerAddress;\r\n        function (address) external view returns (uint256) getOracleOwnerStake;\r\n    }\r\n\r\n    /// @notice subscribe an oracle to this coin pair, allowing it to be selected in the next round.\r\n    /// If the subscribed list is full and the current oracle has more stake than one with minimum stake in the\r\n    /// subscribed list, then the one with minimum stake is replaced.\r\n    /// @param oracleOwnerAddr The address of the owner of the oracle to remove from system.\r\n    /// @dev This is designed to be called from OracleManager.\r\n    function subscribe(address oracleOwnerAddr) external;\r\n\r\n    /// @notice Unsubscribe an oracle from this coin pair. The oracle won't be selected in the next round.\r\n    /// After the round end, the oracle can withdraw stake without having the risk of loosing won points.\r\n    /// @param oracleOwnerAddr The address of the owner of the oracle to remove from system.\r\n    /// @dev This is designed to be called from OracleManager.\r\n    function unsubscribe(address oracleOwnerAddr) external;\r\n\r\n    /// @notice Returns true if an oracle is subscribed to this contract' coin pair\r\n    /// @param oracleOwnerAddr The address of the owner of the oracle to remove from system.\r\n    /// @dev This is designed to be called from OracleManager.\r\n    function isSubscribed(address oracleOwnerAddr) external view returns (bool);\r\n\r\n    /// @notice Publish a price. (The message contain oracleAddresses that must be converted to owner addresses).\r\n    /// @param _version Version number of message format (3)\r\n    /// @param _coinpair The coin pair to report (must match this contract)\r\n    /// @param _price Price to report.\r\n    /// @param _votedOracle The address of the oracle voted as a publisher by the network.\r\n    /// @param _blockNumber The block number acting as nonce to prevent replay attacks.\r\n    /// @param _sigV The array of V-component of Oracle signatures.\r\n    /// @param _sigR The array of R-component of Oracle signatures.\r\n    /// @param _sigS The array of S-component of Oracle signatures.\r\n    function publishPrice(\r\n        uint256 _version,\r\n        bytes32 _coinpair,\r\n        uint256 _price,\r\n        address _votedOracle,\r\n        uint256 _blockNumber,\r\n        uint8[] calldata _sigV,\r\n        bytes32[] calldata _sigR,\r\n        bytes32[] calldata _sigS\r\n    ) external;\r\n\r\n    /// @notice Publish a price without signature validation (when there is an emergecy!!!).\r\n    /// @param _price Price to report.\r\n    function emergencyPublish(uint256 _price) external;\r\n\r\n    /// @notice The oracle owner has withdrawn some stake.\r\n    /// Must check if the oracle is part of current round and if he lost his place with the\r\n    /// new stake value (the stake is global and is saved in the supporters contract).\r\n    /// @param oracleOwnerAddr the oracle owner that is trying to withdraw\r\n    function onWithdraw(address oracleOwnerAddr) external returns (uint256);\r\n\r\n    /// @notice Switch contract context to a new round. With the objective of\r\n    /// being a decentralized solution, this can be called by *anyone* if current\r\n    /// round lock period is expired.\r\n    /// This method search the subscribed list and choose the 10 with more stake.\r\n    function switchRound() external;\r\n\r\n    //////////////////////////////////////////////////////////////////////////////////// GETTERS\r\n\r\n    /// @notice Return the available reward fees\r\n    ///\r\n    function getAvailableRewardFees() external view returns (uint256);\r\n\r\n    //////////////////////////////////////////////////////////////////////////////////// GETTERS TO GET CURRENT PRICE\r\n    // MUST BE WHITELISTED\r\n    /// @notice Return the current price, compatible with old MOC Oracle\r\n    function peek() external view returns (bytes32, bool);\r\n\r\n    /// @notice Return the current price\r\n    function getPrice() external view returns (uint256);\r\n\r\n    ///////////////////////////////////////////////////////////////////////////////// GETTERS TO GET CURRENT PRICE END\r\n\r\n    /// @notice Return current round information\r\n    function getRoundInfo()\r\n        external\r\n        view\r\n        returns (\r\n            uint256 round,\r\n            uint256 startBlock,\r\n            uint256 lockPeriodTimestamp,\r\n            uint256 totalPoints,\r\n            address[] memory selectedOwners,\r\n            address[] memory selectedOracles\r\n        );\r\n\r\n    /// @notice Return round information for specific oracle\r\n    function getOracleRoundInfo(address addr)\r\n        external\r\n        view\r\n        returns (uint256 points, bool selectedInCurrentRound);\r\n\r\n    // The maximum count of oracles selected to participate each round\r\n    function maxOraclesPerRound() external view returns (uint256);\r\n\r\n    // The round lock period in secs\r\n    function roundLockPeriodSecs() external view returns (uint256);\r\n\r\n    function isOracleInCurrentRound(address oracleAddr) external view returns (bool);\r\n\r\n    /// @notice Returns the amount of oracles subscribed to this coin pair.\r\n    function getSubscribedOraclesLen() external view returns (uint256);\r\n\r\n    /// @notice Returns the oracle owner address that is subscribed to this coin pair\r\n    /// @param idx index to query.\r\n    function getSubscribedOracleAtIndex(uint256 idx) external view returns (address ownerAddr);\r\n\r\n    // Public variable\r\n    function getMaxSubscribedOraclesPerRound() external view returns (uint256);\r\n\r\n    // Public variable\r\n    function getCoinPair() external view returns (bytes32);\r\n\r\n    // Public variable\r\n    function getLastPublicationBlock() external view returns (uint256);\r\n\r\n    // Public variable\r\n    function getValidPricePeriodInBlocks() external view returns (uint256);\r\n\r\n    // Public variable\r\n    function getEmergencyPublishingPeriodInBlocks() external view returns (uint256);\r\n\r\n    // Public variable\r\n    function getOracleManager() external view returns (IOracleManager);\r\n\r\n    // Public variable\r\n    function getToken() external view returns (IERC20);\r\n\r\n    function getRegistry() external view returns (IRegistry);\r\n\r\n    // Public value from Registry:\r\n    //   The minimum count of oracles selected to participate each round\r\n    function getMinOraclesPerRound() external view returns (uint256);\r\n}\r\n\r\n\r\n/// This contract manages the Oracle and CoinPair registration info.\r\n/// The Oracle python server interacts with this contract:\r\n/// - Coin pair registration\r\n/// - Oracle registration to coin pairs\r\n/// - Access Oracle info (oracle address + url) indexed by oracle owner address\r\n/// - Get the oracle information (url + the specifics of some coin pair rounds) from an oracle address\r\n/// - Get the oracle address from the owner address.\r\ninterface IOracleManager {\r\n    // getOracleOwnerStake: Get the stake stored in the supporters smart-contract\r\n    // prettier-ignore\r\n    struct OracleManagerCallbacks {\r\n        function (address) external view returns (uint256) getOracleOwnerStake;\r\n    }\r\n\r\n    /// @notice Register a new coin pair contract (the contract must be created separately).\r\n    /// Once created the coin pairs cannot be removed.\r\n    /// @param coinPair The bytes32-encoded coinpair string (e.g. BTCUSD)\r\n    /// @param addr The contract address associated to the coin pair.\r\n    function registerCoinPair(bytes32 coinPair, address addr) external;\r\n\r\n    /// Register an oracle in the system must be called by the oracle owner.\r\n    /// @notice Registers the oracle and transfer the specified caller's MOC token stake.\r\n    /// @param oracleOwnerAddr The address of the owner of the oracle.\r\n    /// @param oracleAddr Address of the Oracle to register.\r\n    /// @param internetName Public Internet name of this Oracle.\r\n    function registerOracle(\r\n        address oracleOwnerAddr,\r\n        address oracleAddr,\r\n        string calldata internetName\r\n    ) external;\r\n\r\n    /// @notice Change the oracle \"internet\" name (URI), called by the owner.\r\n    /// @param oracleOwnerAddr The address of the owner of the oracle.\r\n    /// @param name The new name to set.\r\n    function setOracleName(address oracleOwnerAddr, string calldata name) external;\r\n\r\n    /// @notice Change the oracle address, called by the owner.\r\n    /// @param oracleOwnerAddr The address of the owner of the oracle.\r\n    /// @param oracleAddr new value for the address of the oracle\r\n    function setOracleAddress(address oracleOwnerAddr, address oracleAddr) external;\r\n\r\n    /// @notice Removes the oracle registration info. Must be called by the owner\r\n    /// The oracle must be previously unregistered from all coin pairs.\r\n    /// @param oracleOwnerAddr The address of the owner of the oracle to remove from system.\r\n    function removeOracle(address oracleOwnerAddr) external;\r\n\r\n    /// @notice Subscribe a registered oracle to participate in the next round of a registered coin-pair.\r\n    /// @param oracleOwnerAddr Address of oracle owner\r\n    function subscribeToCoinPair(address oracleOwnerAddr, bytes32 coinPair) external;\r\n\r\n    /// @notice Unsubscribe a registered oracle from participating in rounds of a registered coin-pair.\r\n    /// The oracle is flagged so it is not selected in the next round.\r\n    /// @param oracleOwnerAddr Address of oracle owner\r\n    function unSubscribeFromCoinPair(address oracleOwnerAddr, bytes32 coinPair) external;\r\n\r\n    /// @notice The oracle owner did a partial withdrawal of funds\r\n    /// 1. The oracle address is searched by the owner address.\r\n    /// 2. Each coin pair to which the oracle is subscribed is consulted to:\r\n    ///   - Check if the new amount is enough to stay in the current round.\r\n    ///       If not the oracle is replaced and lost his points.\r\n    ///   - Get the timestamp for the round end.\r\n    /// The return value is the maximum timestamp from all the coin pairs.\r\n    /// @param oracleOwnerAddr Address of oracle owner\r\n    /// @return the timestamp until which the funds must be locked.\r\n    function onWithdraw(address oracleOwnerAddr) external returns (uint256);\r\n\r\n    //////////////////////////////////////////////////////////////////////////////////// GETTERS USED BY COINPAIR\r\n    /// @notice Used by the coin pair to get the oracle address from the oracleOwnerAddress.\r\n    /// @param  oracleOwnerAddr the address of the owner of the oracle.\r\n    /// @return oracleAddr Address of oracle\r\n    function getOracleAddress(address oracleOwnerAddr) external view returns (address oracleAddr);\r\n\r\n    /// @notice Returns true if oracle is registered.\r\n    /// @param ownerAddr The address of the oracle's owner.\r\n    function isRegistered(address ownerAddr) external view returns (bool);\r\n\r\n    /// @notice Used by CoinPair\r\n    /// @param oracleAddr The oracle address not the owner address.\r\n    function getOracleOwner(address oracleAddr) external view returns (address);\r\n\r\n    /// @notice Returns the amount of owners registered.\r\n    function getRegisteredOraclesLen() external view returns (uint256);\r\n\r\n    /// @notice Returns the oracle name and address at index.\r\n    /// @param idx index to query.\r\n    function getRegisteredOracleAtIndex(uint256 idx)\r\n        external\r\n        view\r\n        returns (\r\n            address ownerAddr,\r\n            address oracleAddr,\r\n            string memory url\r\n        );\r\n\r\n    //////////////////////////////////////////////////////////////////////////////////// GETTERS USED BY COINPAIR END\r\n\r\n    //////////////////////////////////////////////////////////////////////////////////// GETTERS\r\n\r\n    // TODO: Check what is the minimum amount of getters the python server needs.\r\n\r\n    /// @notice Returns true if an oracle is subscribed to a coin pair\r\n    function isSubscribed(address oracleAddr, bytes32 coinPair) external view returns (bool);\r\n\r\n    /// @notice Return true if the oracle is registered on this coin-pair\r\n    /// @param oracleAddr addr The address of the Oracle check for.\r\n    function isOracleRegistered(address oracleAddr) external view returns (bool);\r\n\r\n    /// @notice Returns registration information for a registered Oracle.\r\n    /// @param oracleAddr addr The address of the Oracle to query for.\r\n    function getOracleRegistrationInfo(address oracleAddr)\r\n        external\r\n        view\r\n        returns (\r\n            string memory internetName,\r\n            uint256 stake,\r\n            address _owner\r\n        );\r\n\r\n    /// @notice Returns round information for a registered oracle in a specific coin-pair.\r\n    /// @param oracleAddr address of the oracle to query for.\r\n    /// @param coinpair The coin pair to lookup.\r\n    function getOracleRoundInfo(address oracleAddr, bytes32 coinpair)\r\n        external\r\n        view\r\n        returns (uint256 points, bool selectedInCurrentRound);\r\n\r\n    /// @notice Returns true if an oracle satisfies conditions to be removed from system.\r\n    /// @param oracleAddr the oracle address to lookup.\r\n    function canRemoveOracle(address oracleAddr) external view returns (bool);\r\n\r\n    /// @notice Get the stake in MOCs that an oracle has.\r\n    /// @param oracleAddr The address of the oracle.\r\n    function getStake(address oracleAddr) external view returns (uint256 balance);\r\n\r\n    //////////////////////////////////////////////////////////////////////////////////// GETTER TO LIST COIN PAIRS\r\n\r\n    /// @notice Returns the count of registered coin pairs.\r\n    /// Keep in mind that Deleted coin-pairs will contain zeroed addresses.\r\n    function getCoinPairCount() external view returns (uint256);\r\n\r\n    /// @notice Returns the coin pair at index.\r\n    /// @param i index to query.\r\n    function getCoinPairAtIndex(uint256 i) external view returns (bytes32);\r\n\r\n    /// @notice Return the contract address for a specified registered coin pair.\r\n    /// @param coinpair Coin-pair string to lookup (e.g: BTCUSD)\r\n    /// @return address Address of contract or zero if does not exist or was deleted.\r\n    function getContractAddress(bytes32 coinpair) external view returns (address);\r\n\r\n    /// @notice Searches a coinpair in coinPairList\r\n    /// @param coinPair The bytes32-encoded coinpair string (e.g. BTCUSD)\r\n    /// @param hint Optional hint to start traversing the coinPairList array, zero is to search all the array.\r\n    function getCoinPairIndex(bytes32 coinPair, uint256 hint) external view returns (uint256);\r\n\r\n    function getMaxStake(address[] calldata addresses) external view returns (address, uint256);\r\n\r\n    //////////////////////////////////////////////////////////////////////////////////// GETTER TO LIST COIN PAIRS END\r\n\r\n    // Public variable\r\n    function getStakingContract() external view returns (IStakingMachine);\r\n\r\n    // Public variable\r\n    function getMinCPSubscriptionStake() external view returns (uint256);\r\n}\r\n\r\n\r\n\r\ninterface IDelayMachine {\r\n    /// @notice Accept a deposit from an account.\r\n    /// @param mocs token quantity\r\n    /// @param expiration the expiration date for this deposit\r\n    /// @return id the transaction id\r\n    function deposit(\r\n        uint256 mocs,\r\n        address destination,\r\n        uint256 expiration\r\n    ) external returns (uint256 id);\r\n\r\n    /// @notice Cancel a transaction returning the funds to the source\r\n    /// @param id transaction id\r\n    function cancel(uint256 id) external;\r\n\r\n    /// @notice Withdraw stake, send it to the delay machine.\r\n    /// @param id transaction id\r\n    function withdraw(uint256 id) external;\r\n\r\n    /// @notice Returns the list of transaction for some account\r\n    /// @return ids transaction ids\r\n    /// @return amounts token quantity\r\n    /// @return expirations expiration dates\r\n    function getTransactions(address account)\r\n        external\r\n        view\r\n        returns (\r\n            uint256[] memory ids,\r\n            uint256[] memory amounts,\r\n            uint256[] memory expirations\r\n        );\r\n\r\n    /// @notice Returns the total balance in MOCs for an account\r\n    function getBalance(address account) external view returns (uint256);\r\n\r\n    // Public variable\r\n    function getToken() external view returns (IERC20);\r\n\r\n    // Public variable\r\n    function getLastId() external view returns (uint256);\r\n\r\n    // Public variable\r\n    function getSource() external view returns (address);\r\n}\r\n\r\n\r\ninterface IStakingMachine {\r\n    /// @notice Used by the voting machine to lock the current balance of MOCs.\r\n    /// @param mocHolder the moc holder whose mocs will be locked.\r\n    /// @param untilTimestamp timestamp until which the mocs will be locked.\r\n    function lockMocs(address mocHolder, uint256 untilTimestamp) external;\r\n\r\n    /// @notice Accept a deposit from an account.\r\n    /// Delegate to the Supporters smart contract.\r\n    /// @param mocs token quantity\r\n    /// @param destination the destination account of this deposit.\r\n    function deposit(uint256 mocs, address destination) external;\r\n\r\n    /// @notice Accept a deposit from an account.\r\n    /// @param mocs token quantity\r\n    /// @param destination the destination account of this deposit.\r\n    /// @param source the address that approved the transfer\r\n    function depositFrom(\r\n        uint256 mocs,\r\n        address destination,\r\n        address source\r\n    ) external;\r\n\r\n    /// @notice Withdraw stake, send it to the delay machine.\r\n    /// @param mocs token quantity\r\n    function withdraw(uint256 mocs) external;\r\n\r\n    /// @notice Reports the balance of MOCs for a specific user.\r\n    /// @param user user address\r\n    function getBalance(address user) external view returns (uint256);\r\n\r\n    /// @notice Reports the locked balance of MOCs for a specific user.\r\n    /// @param user user address\r\n    function getLockedBalance(address user) external view returns (uint256);\r\n\r\n    /// @notice Reports the balance of locked MOCs for a specific user.\r\n    /// Delegates to the Supporters smart contract.\r\n    /// @param user user address\r\n    /// @return amount the amount of mocs locked\r\n    /// @return untilTimestamp the timestamp that corresponds to the locking date.\r\n    function getLockingInfo(address user)\r\n        external\r\n        view\r\n        returns (uint256 amount, uint256 untilTimestamp);\r\n\r\n    // Public variable\r\n    function getSupporters() external view returns (address);\r\n\r\n    // Public variable\r\n    function getOracleManager() external view returns (IOracleManager);\r\n\r\n    // Public variable\r\n    function getMocToken() external view returns (IERC20);\r\n\r\n    // Public variable\r\n    function getDelayMachine() external view returns (IDelayMachine);\r\n\r\n    // Public variable\r\n    function getWithdrawLockTime() external view returns (uint256);\r\n}\r\n\r\ninterface IStakingMachineOracles {\r\n    /// @notice Register an oracle\r\n    /// @param oracleAddr address of the oracle (from which we publish prices)\r\n    /// @param url url used by the oracle server\r\n    function registerOracle(address oracleAddr, string calldata url) external;\r\n\r\n    /// @notice Change the oracle \"internet\" name (URI)\r\n    /// @param url The new url to set.\r\n    function setOracleName(string calldata url) external;\r\n\r\n    /// @notice Change the oracle address\r\n    /// @param oracleAddr The new oracle address\r\n    function setOracleAddress(address oracleAddr) external;\r\n\r\n    /// @notice Return true if the oracle is registered.\r\n    /// @param oracleAddr addr The address of the Oracle check for.\r\n    function isOracleRegistered(address oracleAddr) external view returns (bool);\r\n\r\n    /// @notice Returns true if an oracle satisfies conditions to be removed from system.\r\n    /// @param oracleAddr the oracle address to lookup.\r\n    function canRemoveOracle(address oracleAddr) external view returns (bool);\r\n\r\n    /// @notice Remove an oracle.\r\n    function removeOracle() external;\r\n\r\n    /// @notice Returns the count of registered coin pairs.\r\n    /// Keep in mind that Deleted coin-pairs will contain zeroed addresses.\r\n    function getCoinPairCount() external view returns (uint256);\r\n\r\n    /// @notice Returns the coin pair at index.\r\n    /// @param i index to query.\r\n    function getCoinPairAtIndex(uint256 i) external view returns (bytes32);\r\n\r\n    /// @notice Return the contract address for a specified registered coin pair.\r\n    /// @param coinpair Coin-pair string to lookup (e.g: BTCUSD)\r\n    /// @return address Address of contract or zero if does not exist or was deleted.\r\n    function getContractAddress(bytes32 coinpair) external view returns (address);\r\n\r\n    /// @notice Searches a coinpair in coinPairList\r\n    /// @param coinPair The bytes32-encoded coinpair string (e.g. BTCUSD)\r\n    /// @param hint Optional hint to start traversing the coinPairList array, zero is to search all the array.\r\n    function getCoinPairIndex(bytes32 coinPair, uint256 hint) external view returns (uint256);\r\n\r\n    /// @notice Subscribe an oracle to a coin pair.\r\n    /// @param coinPair coin pair to subscribe, for example BTCUSD\r\n    function subscribeToCoinPair(bytes32 coinPair) external;\r\n\r\n    /// @notice Unsubscribe an oracle from a coin pair.\r\n    /// @param coinPair coin pair to unsubscribe, for example BTCUSD\r\n    function unSubscribeFromCoinPair(bytes32 coinPair) external;\r\n\r\n    /// @notice Returns true if an oracle is subscribed to a coin pair\r\n    /// @param oracleAddr address of the oracle\r\n    /// @param coinPair coin pair to unsubscribe, for example BTCUSD\r\n    function isSubscribed(address oracleAddr, bytes32 coinPair) external view returns (bool);\r\n\r\n    /// @notice Returns the amount of owners registered.\r\n    /// Delegates to the Oracle Manager smart contract.\r\n    function getRegisteredOraclesLen() external view returns (uint256);\r\n\r\n    /// @notice Returns the oracle name and address at index.\r\n    /// Delegates to the Oracle Manager smart contract.\r\n    /// @param idx index to query.\r\n    function getRegisteredOracleAtIndex(uint256 idx)\r\n        external\r\n        view\r\n        returns (\r\n            address ownerAddr,\r\n            address oracleAddr,\r\n            string memory url\r\n        );\r\n}\r\n\r\n\r\ncontract RegistryValues is RegistryConstants {\r\n    function _totalSupply(IRegistry registry) internal view returns (uint256) {\r\n        return _getToken(registry).totalSupply();\r\n    }\r\n\r\n    function _lockStake(\r\n        IRegistry registry,\r\n        address mocHolder,\r\n        uint256 untilTimestamp\r\n    ) internal {\r\n        _getStakingMachine(registry).lockMocs(mocHolder, untilTimestamp);\r\n    }\r\n\r\n    function _getLockedStake(IRegistry registry, address user) internal view returns (uint256) {\r\n        return _getStakingMachine(registry).getLockedBalance(user);\r\n    }\r\n\r\n    function _getStake(IRegistry registry, address user) internal view returns (uint256) {\r\n        return _getStakingMachine(registry).getBalance(user);\r\n    }\r\n\r\n    function _getToken(IRegistry registry) internal view returns (IERC20) {\r\n        return IERC20(registry.getAddress(MOC_TOKEN));\r\n    }\r\n\r\n    function _getStakingMachine(IRegistry registry) internal view returns (IStakingMachine) {\r\n        return IStakingMachine(registry.getAddress(MOC_STAKING_MACHINE));\r\n    }\r\n\r\n    function _getMinStake(IRegistry registry) internal view returns (uint256) {\r\n        return registry.getUint(MOC_VOTING_MACHINE_MIN_STAKE);\r\n    }\r\n\r\n    function _getPreVoteExpirationTimeDelta(IRegistry registry) internal view returns (uint256) {\r\n        uint256 ret = registry.getUint(MOC_VOTING_MACHINE_PRE_VOTE_EXPIRATION_TIME_DELTA);\r\n        require(ret > 0, \"Invalid preVoteExpirationTimeDelta\");\r\n        return ret;\r\n    }\r\n\r\n    function _getMaxPreProposals(IRegistry registry) internal view returns (uint256) {\r\n        uint256 ret = registry.getUint(MOC_VOTING_MACHINE_MAX_PRE_PROPOSALS);\r\n        require(ret > 0, \"Invalid maxPreProposals\");\r\n        return ret;\r\n    }\r\n\r\n    function _getPreVoteMinPCToWin(IRegistry registry) internal view returns (uint256) {\r\n        uint256 ret = registry.getUint(MOC_VOTING_MACHINE_PRE_VOTE_MIN_PCT_TO_WIN);\r\n        require(ret > 0, \"Invalid preVoteMinPCToWin\");\r\n        return ret;\r\n    }\r\n\r\n    function _getVoteMinPctToVeto(IRegistry registry) internal view returns (uint256) {\r\n        uint256 ret = registry.getUint(MOC_VOTING_MACHINE_VOTE_MIN_PCT_TO_VETO);\r\n        require(ret > 0, \"Invalid voteMinPctToVeto\");\r\n        return ret;\r\n    }\r\n\r\n    function _getVoteMinPctForQuorum(IRegistry registry) internal view returns (uint256) {\r\n        uint256 ret = registry.getUint(MOC_VOTING_MACHINE_VOTE_MIN_PCT_FOR_QUORUM);\r\n        require(ret > 0, \"Invalid voteMinPctForQuorum\");\r\n        return ret;\r\n    }\r\n\r\n    function _getVoteMinPctToAccept(IRegistry registry) internal view returns (uint256) {\r\n        uint256 ret = registry.getUint(MOC_VOTING_MACHINE_VOTE_MIN_PCT_TO_ACCEPT);\r\n        require(ret > 0, \"Invalid voteMinPctToAccept\");\r\n        return ret;\r\n    }\r\n\r\n    function _getPCTPrecision(IRegistry registry) internal view returns (uint256) {\r\n        uint256 ret = registry.getUint(MOC_VOTING_MACHINE_PCT_PRECISION);\r\n        require(ret >= 100, \"Invalid pctPrecision\");\r\n        return ret;\r\n    }\r\n\r\n    function _getVotingTimeDelta(IRegistry registry) internal view returns (uint256) {\r\n        uint256 ret = registry.getUint(MOC_VOTING_MACHINE_VOTING_TIME_DELTA);\r\n        require(ret > 0, \"Invalid votingTimeDelta\");\r\n        return ret;\r\n    }\r\n}\r\n\r\n// prettier-ignore\r\n\r\n\r\n/**\r\n  @title ChangeContract\r\n  @notice This interface is the one used by the governance system.\r\n  @dev If you plan to do some changes to a system governed by this project you should write a contract\r\n  that does those changes, like a recipe. This contract MUST not have ANY kind of public or external function\r\n  that modifies the state of this ChangeContract, otherwise you could run into front-running issues when the governance\r\n  system is fully in place.\r\n */\r\ninterface ChangeContract {\r\n    /**\r\n      @notice Override this function with a recipe of the changes to be done when this ChangeContract\r\n      is executed\r\n     */\r\n    function execute() external;\r\n}\r\n\r\n\r\n/**\r\n  @title Governor\r\n  @notice Governor interface. This functions should be overwritten to\r\n  enable the comunnication with the rest of the system\r\n  */\r\ninterface IGovernor {\r\n    /**\r\n      @notice Function to be called to make the changes in changeContract\r\n      @dev This function should be protected somehow to only execute changes that\r\n      benefit the system. This decision process is independent of this architechture\r\n      therefore is independent of this interface too\r\n      @param changeContract Address of the contract that will execute the changes\r\n     */\r\n    function executeChange(ChangeContract changeContract) external;\r\n\r\n    /**\r\n      @notice Function to be called to make the changes in changeContract\r\n      @param _changer Address of the contract that will execute the changes\r\n     */\r\n    function isAuthorizedChanger(address _changer) external view returns (bool);\r\n}\r\n\r\n// prettier-ignore\r\n\r\n\r\n/**\r\n  @title Governed\r\n  @notice Base contract to be inherited by governed contracts\r\n  @dev This contract is not usable on its own since it does not have any _productive useful_ behaviour\r\n  The only purpose of this contract is to define some useful modifiers and functions to be used on the\r\n  governance aspect of the child contract\r\n  */\r\ncontract Governed {\r\n    /**\r\n      @notice The address of the contract which governs this one\r\n     */\r\n    IGovernor public governor;\r\n\r\n    string private constant NOT_AUTHORIZED_CHANGER = \"not_authorized_changer\";\r\n\r\n    /**\r\n      @notice Modifier that protects the function\r\n      @dev You should use this modifier in any function that should be called through\r\n      the governance system\r\n     */\r\n    modifier onlyAuthorizedChanger() {\r\n        require(governor.isAuthorizedChanger(msg.sender), NOT_AUTHORIZED_CHANGER);\r\n        _;\r\n    }\r\n\r\n    /**\r\n      @notice Initialize the contract with the basic settings\r\n      @dev This initialize replaces the constructor but it is not called automatically.\r\n      It is necessary because of the upgradeability of the contracts\r\n      @param _governor Governor address\r\n     */\r\n    function _initialize(IGovernor _governor) internal {\r\n        governor = _governor;\r\n    }\r\n\r\n    /**\r\n      @notice Change the contract's governor. Should be called through the old governance system\r\n      @param newIGovernor New governor address\r\n     */\r\n    function changeIGovernor(IGovernor newIGovernor) external onlyAuthorizedChanger {\r\n        governor = newIGovernor;\r\n    }\r\n\r\n    /**\r\n      @notice This method is used by a change contract to access the storage freely even without a setter.\r\n      @param data the serialized function arguments\r\n     */\r\n    function delegateCallToChanger(bytes calldata data)\r\n        external\r\n        onlyAuthorizedChanger\r\n        returns (bytes memory)\r\n    {\r\n        address changerContrat = msg.sender;\r\n        (bool success, bytes memory result) = changerContrat.delegatecall(\r\n            abi.encodeWithSignature(\"impersonate(bytes)\", data)\r\n        );\r\n        require(success, \"Error in delegate call\");\r\n        return result;\r\n    }\r\n\r\n    // Leave a gap betweeen inherited contracts variables in order to be\r\n    // able to add more variables in them later\r\n    uint256[50] private upgradeGap;\r\n}\r\n\r\n// prettier-ignore\r\n\r\ncontract VotingMachineStorage is Initializable, Governed, RegistryValues {\r\n    using SafeMath for uint256;\r\n    using PreVotingDataLib for PreVotingDataLib.PreVotingData;\r\n    using VotingDataLib for VotingDataLib.VotingData;\r\n\r\n    // Iterable list of proposals used during preVoting\r\n    enum VotingState {PreVoting, Voting, Accepted}\r\n\r\n    // Governor used to execute change contracts\r\n    IGovernor public controlledGovernor;\r\n\r\n    // Library configuration.\r\n    IRegistry public registry;\r\n\r\n    // Current voting round\r\n    // TODO: With uint8 is enough, can be packed with something else?\r\n    uint256 internal votingRound;\r\n\r\n    struct Vote {\r\n        address addr;\r\n        uint8 round;\r\n    }\r\n\r\n    // Votes\r\n    mapping(address => Vote) public votes;\r\n\r\n    // The contract state\r\n    VotingState internal votingState;\r\n    PreVotingDataLib.PreVotingData internal preVotingData;\r\n    VotingDataLib.VotingData internal votingData;\r\n\r\n    // Empty internal constructor, to prevent people from mistakenly deploying\r\n    // an instance of this contract, which should be used via inheritance.\r\n    // solhint-disable-next-line no-empty-blocks\r\n    constructor() internal {}\r\n\r\n    // Reserved storage space to allow for layout changes in the future.\r\n    uint256[50] private ______gap;\r\n}\r\n\r\n// prettier-ignore\r\n// prettier-ignore\r\n\r\ninterface IVotingMachine {\r\n    /**\r\n        get current contract state\r\n        */\r\n    function getState() external view returns (uint256);\r\n\r\n    /**\r\n        return the current voting round\r\n        */\r\n    function getVotingRound() external view returns (uint256);\r\n\r\n    /**\r\n    Pre Vote a proposal\r\n\r\n    @param _proposal Address of the change contract that will be executed if this vote is successful\r\n    */\r\n    function preVote(address _proposal) external;\r\n\r\n    /**\r\n    Vote a proposal\r\n\r\n    @param _inFavorAgainst Type of vote\r\n    */\r\n    function vote(bool _inFavorAgainst) external;\r\n\r\n    /**\r\n    There is a veto Condition\r\n\r\n    */\r\n    function vetoCondition() external;\r\n\r\n    /**\r\n    Veto\r\n    */\r\n    function veto() external;\r\n\r\n    function readyToPreVoteStep() external view returns (bool);\r\n\r\n    /**\r\n    preVoteStep\r\n    */\r\n    function preVoteStep() external;\r\n\r\n    function readyToVoteStep() external view returns (bool);\r\n\r\n    /**\r\n    voteStep\r\n    */\r\n    function voteStep() external;\r\n\r\n    /**\r\n    vetoStep\r\n    */\r\n    function vetoStep() external;\r\n\r\n    /**\r\n    acceptedStep\r\n    */\r\n    function acceptedStep() external;\r\n\r\n    /**\r\n    Get the pre-voting registered proposal count.\r\n    */\r\n    function getProposalCount() external view returns (uint256);\r\n\r\n    /**\r\n    Get pre-voting proposal address and information by index\r\n\r\n    @param _index Index of proposal to query.\r\n    */\r\n    function getProposalByIndex(uint256 _index)\r\n        external\r\n        view\r\n        returns (\r\n            address proposalAddress,\r\n            uint256 proposalVotingRound,\r\n            uint256 proposalVotes,\r\n            uint256 proposalExpirationTimeStamp\r\n        );\r\n\r\n    /**\r\n    Get voting data\r\n    */\r\n    function getVotingData()\r\n        external\r\n        view\r\n        returns (\r\n            address winnerProposal,\r\n            uint256 inFavorVotes,\r\n            uint256 againstVotes,\r\n            uint256 votingExpirationTime\r\n        );\r\n\r\n    /**\r\n        Get user vote\r\n    */\r\n    function getUserVote(address user)\r\n        external\r\n        view\r\n        returns (address voteAddress, uint256 voteRound);\r\n\r\n    /**\r\n    will the call to unregister be successfull?\r\n\r\n    @param _proposal Address of the change contract that will be executed if this vote is successful\r\n    */\r\n    function canUnregister(address _proposal) external view returns (bool);\r\n\r\n    /**\r\n    Unregister a proposal, free the assets it uses.\r\n\r\n    @param _proposal Address of the change contract that will be executed if this vote is successful\r\n    */\r\n    function unregister(address _proposal) external;\r\n}\r\n\r\n// prettier-ignore\r\n\r\ncontract VotingMachine is VotingMachineStorage, IVotingMachine {\r\n    using SafeMath for uint256;\r\n\r\n    // Emitted by VotingLib\r\n    // event Vote(uint256 earnings, uint256 start, uint256 end);\r\n    event VoteEvent(\r\n        address indexed user,\r\n        address indexed subaccount,\r\n        address indexed destination,\r\n        uint256 amount,\r\n        uint256 mocs\r\n    );\r\n\r\n    modifier atState(VotingState _state) {\r\n        require(votingState == _state, \"Invalid state\");\r\n        _;\r\n    }\r\n\r\n    /**\r\n     @notice Contract creation\r\n\r\n     @param _governor The address of the contract which governs this one\r\n     @param _controlledGovernor The address of the governor that executes the change contracts\r\n    */\r\n    function initialize(\r\n        IGovernor _governor,\r\n        IGovernor _controlledGovernor,\r\n        IRegistry _registry\r\n    ) external initializer {\r\n        Governed._initialize(_governor);\r\n        votingState = VotingState.PreVoting;\r\n        registry = _registry;\r\n\r\n        votingRound = 1;\r\n        controlledGovernor = _controlledGovernor;\r\n        preVotingData._init();\r\n        votingData._init();\r\n    }\r\n\r\n    /**\r\n    get current contract state\r\n\r\n    */\r\n    function getState() external view override returns (uint256) {\r\n        return uint256(votingState);\r\n    }\r\n\r\n    /**\r\n        return the current voting round\r\n        */\r\n    function getVotingRound() external view override returns (uint256) {\r\n        return votingRound;\r\n    }\r\n\r\n    /**\r\n    Pre Vote\r\n\r\n    @param _changeContractAddress Address of the change contract that will be executed if this vote is successful\r\n    */\r\n    function preVote(address _changeContractAddress)\r\n    external\r\n    override\r\n    atState(VotingState.PreVoting)\r\n    {\r\n        require(_changeContractAddress != address(0), \"address must be != 0\");\r\n        (address winnerProposal,) = _getWinnerProposal();\r\n        require(winnerProposal == address(0), \"There is a winner proposal\");\r\n\r\n        require(!preVotingData._isExpired(votingRound, _changeContractAddress), \"Proposal expired\");\r\n\r\n        uint256 stake = _getStake(registry, msg.sender);\r\n        Vote memory _vote = votes[msg.sender];\r\n        if (_alreadyVoted(_vote) && !preVotingData._isExpired(votingRound, _vote.addr)) {\r\n            // This is necessary to avoid storing the voting history.\r\n            require(_vote.addr == _changeContractAddress, \"Must vote the same proposal\");\r\n            uint256 locked = _getLockedStake(registry, msg.sender);\r\n            require(stake > locked, \"Not enough stake\");\r\n            stake = stake - locked;\r\n        }\r\n        // solhint-disable-next-line not-rely-on-time\r\n        _lockStake(registry, msg.sender, (block.timestamp).add(_getVotingTimeDelta(registry)));\r\n        votes[msg.sender] = Vote(_changeContractAddress, uint8(votingRound));\r\n\r\n        if (preVotingData._isEmptyProposal(votingRound, _changeContractAddress)) {\r\n            require(stake > _getMinStake(registry), \"Not enough stake\");\r\n            require(\r\n                preVotingData._upsert(\r\n                    votingRound,\r\n                    _getMaxPreProposals(registry),\r\n                    _getPreVoteExpirationTimeDelta(registry),\r\n                    _changeContractAddress,\r\n                    stake\r\n                ),\r\n                \"Not enough to add a proposal\"\r\n            );\r\n        } else {\r\n            require(\r\n                preVotingData._addVotes(votingRound, _changeContractAddress, stake),\r\n                \"Proposal expired\"\r\n            );\r\n        }\r\n    }\r\n\r\n    /**\r\n    Vote a proposal\r\n\r\n    @param _inFavorAgainst Type of vote\r\n    */\r\n    function vote(bool _inFavorAgainst) external override atState(VotingState.Voting) {\r\n        uint256 stake = _getStake(registry, msg.sender);\r\n        Vote memory _vote = votes[msg.sender];\r\n\r\n        // Those that voted something different than the winner proposal can use they whole stake\r\n        if (_alreadyVoted(_vote) && _vote.addr == votingData.winnerProposal) {\r\n            uint256 locked = _getLockedStake(registry, msg.sender);\r\n            require(stake > locked, \"Not enough stake\");\r\n            stake = stake - locked;\r\n        }\r\n        _lockStake(registry, msg.sender, (block.timestamp).add(_getVotingTimeDelta(registry)));\r\n        votes[msg.sender] = Vote(votingData.winnerProposal, uint8(votingRound));\r\n        votingData._addVotes(stake, _inFavorAgainst);\r\n    }\r\n\r\n    /**\r\n        Return vote info.\r\n    */\r\n    function getVoteInfo()\r\n    external\r\n    view\r\n    returns (\r\n        address winnerProposal,\r\n        uint256 inFavorVotes,\r\n        uint256 againstVotes\r\n    )\r\n    {\r\n        if (votingState != VotingState.Voting) {\r\n            return (address(0), 0, 0);\r\n        }\r\n        return (votingData.winnerProposal, votingData.inFavorVotes, votingData.againstVotes);\r\n    }\r\n\r\n    /**\r\n    Vote Condition\r\n    */\r\n    function vetoCondition() external override {}\r\n\r\n    /**\r\n    Veto\r\n    */\r\n    function veto() external override {}\r\n\r\n    function readyToPreVoteStep() external view override returns (bool) {\r\n        (address winnerProposal,) = _getWinnerProposal();\r\n        return (winnerProposal != address(0));\r\n    }\r\n\r\n    /**\r\n    preVoteStep\r\n    */\r\n    function preVoteStep() external override atState(VotingState.PreVoting) {\r\n        (address winnerProposal, uint256 votesInFavor) = _getWinnerProposal();\r\n        require(winnerProposal != address(0), \"No winner proposal\");\r\n\r\n        votingState = VotingState.Voting;\r\n        // Expires all the pre-voting proposals.\r\n        votingData._startVoting(_getVotingTimeDelta(registry), winnerProposal, votesInFavor, 0);\r\n    }\r\n\r\n    function readyToVoteStep() external view override returns (bool) {\r\n        return (_isVeto() || _isAccepted() || votingData._isExpired());\r\n    }\r\n\r\n    /**\r\n    voteStep\r\n    */\r\n    function voteStep() external override atState(VotingState.Voting) {\r\n        if (_isVeto()) {\r\n            votingState = VotingState.PreVoting;\r\n            votingRound = votingRound + 1;\r\n        } else if (_isAccepted()) {\r\n            votingState = VotingState.Accepted;\r\n            votingRound = votingRound + 1;\r\n        } else if (votingData._isExpired()) {\r\n            votingState = VotingState.PreVoting;\r\n            votingRound = votingRound + 1;\r\n        }\r\n    }\r\n\r\n    /**\r\n    vetoStep\r\n    */\r\n    function vetoStep() external override {}\r\n\r\n    /**\r\n    acceptedStep\r\n    */\r\n    function acceptedStep() external override atState(VotingState.Accepted) {\r\n        {\r\n            // Try-catch and in any case change state to PreVoting.\r\n            try controlledGovernor.executeChange(ChangeContract(votingData.winnerProposal)) {\r\n                votingState = VotingState.PreVoting;\r\n            } catch (bytes memory) {\r\n                votingState = VotingState.PreVoting;\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n    will the call to unregister be successfull?\r\n\r\n    @param _changeContractAddress Address of the change contract that will be executed if this vote is successful\r\n    */\r\n    function canUnregister(address _changeContractAddress) external view override returns (bool) {\r\n        return (_changeContractAddress != address(0) &&\r\n        preVotingData._isEmptyProposal(votingRound, _changeContractAddress));\r\n    }\r\n\r\n    /**\r\n    Unregister a proposal, free the assets it uses.\r\n\r\n    @param _changeContractAddress Address of the change contract that will be executed if this vote is successful\r\n    */\r\n    function unregister(address _changeContractAddress) external override {\r\n        require(_changeContractAddress != address(0), \"address must be != 0\");\r\n        require(preVotingData._remove(votingRound, _changeContractAddress), \"Can't remove\");\r\n    }\r\n\r\n    /**\r\n    get the maximum total expiration time of a voting process.\r\n    \r\n    function __totalExpirationTime() internal view returns (uint256) {\r\n        return _getPreVoteExpirationTimeDelta(registry) + _getVotingTimeDelta(registry);\r\n    }*/\r\n\r\n    /**\r\n    The used still didn't vote in this round\r\n    */\r\n    function _alreadyVoted(Vote memory _vote) internal view returns (bool) {\r\n        return (_vote.round == votingRound);\r\n    }\r\n\r\n    function _isAccepted() internal view returns (bool) {\r\n        return\r\n        votingData._isAccepted(\r\n            _getPCTPrecision(registry),\r\n            _getVoteMinPctToVeto(registry),\r\n            _getVoteMinPctForQuorum(registry),\r\n            _getVoteMinPctToAccept(registry),\r\n            _totalSupply(registry)\r\n        );\r\n    }\r\n\r\n    function _isVeto() internal view returns (bool) {\r\n        return\r\n        votingData._isVeto(\r\n            _getPCTPrecision(registry),\r\n            _getVoteMinPctToVeto(registry),\r\n            _totalSupply(registry)\r\n        );\r\n    }\r\n\r\n    function _getWinnerProposal() internal view returns (address candidate, uint256 maxVal) {\r\n        return\r\n        preVotingData._getWinnerProposal(\r\n            votingRound,\r\n            _getPreVoteMinPCToWin(registry),\r\n            _getPCTPrecision(registry),\r\n            _totalSupply(registry)\r\n        );\r\n    }\r\n\r\n    /**\r\n    Get the pre-voting registered proposal count.\r\n    */\r\n    function getProposalCount() external view override returns (uint256) {\r\n        return preVotingData._getProposalCount();\r\n    }\r\n\r\n    /**\r\n    Get pre-voting proposal address and information by index\r\n\r\n    @param _index Index of proposal to query. \r\n    */\r\n    function getProposalByIndex(uint256 _index)\r\n    external\r\n    view\r\n    override\r\n    returns (\r\n        address proposalAddress,\r\n        uint256 votingRound,\r\n        uint256 votes,\r\n        uint256 expirationTimeStamp\r\n    )\r\n    {\r\n        return preVotingData._getProposalByIndex(_index);\r\n    }\r\n\r\n    /**\r\n    Get voting data\r\n    */\r\n    function getVotingData()\r\n    external\r\n    view\r\n    override\r\n    returns (\r\n        address winnerProposal,\r\n        uint256 inFavorVotes,\r\n        uint256 againstVotes,\r\n        uint256 votingExpirationTime\r\n    )\r\n    {\r\n        return (\r\n        votingData.winnerProposal,\r\n        votingData.inFavorVotes,\r\n        votingData.againstVotes,\r\n        votingData.votingExpirationTime\r\n        );\r\n    }\r\n\r\n    /**\r\n        Get user vote\r\n    */\r\n    function getUserVote(address user)\r\n    external\r\n    view\r\n    override\r\n    returns (address voteAddress, uint256 voteRound)\r\n    {\r\n        Vote memory _vote = votes[user];\r\n        return (_vote.addr, _vote.round);\r\n    }\r\n}\r\n\r\n","deployed_bytecode":"0x608060405234801561001057600080fd5b50600436106103fb5760003560e01c806397492d7511610215578063d274eaff11610125578063e62c6a69116100b8578063ef9b78c611610087578063ef9b78c6146106b8578063f13eb2d5146108c1578063f63420ac146108c9578063fa8ab4c1146108d1578063faf620bc146108d9576103fb565b8063e62c6a69146108a9578063e873e208146108b1578063ea0e0661146108b9578063ec0e8bda146106b8576103fb565b8063d8bff5a5116100f4578063d8bff5a514610769578063dc8990e1146107b4578063e1a9941914610899578063e362cb7c146108a1576103fb565b8063d274eaff14610708578063d3f055d714610710578063d4923d4e14610718578063d51673fb14610761576103fb565b8063b6e08330116101a8578063bcff0e1211610177578063bcff0e12146106b0578063bef3a4df146106b8578063c08cc02d146106c0578063c0c53b8b146106c8578063d0360cdb14610700576103fb565b8063b6e0833014610672578063b74ab6fc14610698578063b90163d1146106a0578063ba6fc287146106a8576103fb565b8063a6c456f1116101e4578063a6c456f114610652578063b01f02bf1461065a578063b3699ded14610662578063b5b831e21461066a576103fb565b806397492d75146106325780639b09d9c91461063a5780639d81ac8414610642578063a68d751e1461064a576103fb565b80633f827a5a116103105780635fe22793116102a35780638a365e59116102725780638a365e591461060a5780638bc7b6f2146106125780638da1b81d1461061a578063915e4e101461062257806394ff8ee61461062a576103fb565b80635fe22793146105ea5780636eec5a4a146105f25780637b103999146105fa5780637c197e2114610602576103fb565b80634b9f5c98116102df5780634b9f5c98146105b35780634eb836f5146105d2578063541f51fd146105da578063586dec23146105e2576103fb565b80633f827a5a14610575578063484cae4e1461057d5780634a78f3ce146105855780634b903654146105ab576103fb565b806325dff9d1116103935780632dae20f3116103625780632dae20f3146104ea5780632ec2c246146104f257806337d1d3891461051857806339e94f13146105655780633bdc39501461056d576103fb565b806325dff9d1146104a257806326400693146104d257806328f134a4146104da578063296e9cc4146104e2576103fb565b806310da5e4b116103cf57806310da5e4b1461044e5780631865c57d146104885780631f17a49e14610490578063213fe5c01461049a576103fb565b80623db248146104005780630358faeb1461041a5780630c340a24146104225780630fc67cec14610446575b600080fd5b6104086108e1565b60408051918252519081900360200190f35b610408610905565b61042a610929565b604080516001600160a01b039092168252519081900360200190f35b610408610938565b6104746004803603602081101561046457600080fd5b50356001600160a01b031661095c565b604080519115158252519081900360200190f35b610408610987565b6104986109a0565b005b610408610a6d565b6104aa610a91565b604080516001600160a01b039094168452602084019290925282820152519081900360600190f35b610408610ada565b610408610afe565b610408610b22565b610498610b46565b6104986004803603602081101561050857600080fd5b50356001600160a01b0316610c4f565b6105356004803603602081101561052e57600080fd5b5035610cf1565b604080516001600160a01b0390951685526020850193909352838301919091526060830152519081900360800190f35b610408610d10565b610408610d34565b610408610d58565b610408610d7c565b6104986004803603602081101561059b57600080fd5b50356001600160a01b0316610da0565b610408611245565b610498600480360360208110156105c957600080fd5b50351515611269565b610408611442565b610408611466565b61040861148a565b6104086114ae565b6104086114d2565b61042a6114f6565b610408611505565b610408611529565b61040861152f565b610408611553565b610408611577565b61040861159b565b6104086115bf565b6104086115e3565b610408611607565b61040861162b565b61040861164f565b610408611673565b610408611697565b6105356116bb565b6104986004803603602081101561068857600080fd5b50356001600160a01b03166116d9565b610408611829565b61040861184d565b610408611871565b61042a611895565b6104986118a4565b6104086118a6565b610498600480360360608110156106de57600080fd5b506001600160a01b0381358116916020810135821691604090910135166118b2565b6104086119b2565b6104086119d6565b6104086119fa565b61073e6004803603602081101561072e57600080fd5b50356001600160a01b0316611a1e565b604080516001600160a01b03909316835260208301919091528051918290030190f35b610408611a6c565b61078f6004803603602081101561077f57600080fd5b50356001600160a01b0316611a90565b604080516001600160a01b03909316835260ff90911660208301528051918290030190f35b610824600480360360208110156107ca57600080fd5b8101906020810181356401000000008111156107e557600080fd5b8201836020820111156107f757600080fd5b8035906020019184600183028401116401000000008311171561081957600080fd5b509092509050611ab7565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561085e578181015183820152602001610846565b50505050905090810190601f16801561088b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610474611d0b565b610474611d28565b610408611d50565b610408611d74565b610408611d98565b610408611dbc565b610498611de0565b610408611ecd565b610408611ef1565b7fc1c87e0508bb8270ee6a6dbe630baa072e6e3d5968981666724b9333430e1c3181565b7fda9f12e01fc92de345bb741448d36ecb967052dd7aa1670439af833c9a3d78f181565b6033546001600160a01b031681565b7f275d8a46b817572476d2d55b41c7709dee307740bad676a9693805003a48d23181565b60006001600160a01b03821615801590610981575060685461098190606b9084611f15565b92915050565b606a5460009060ff16600281111561099b57fe5b905090565b600180606a5460ff1660028111156109b457fe5b146109f6576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c696420737461746560981b604482015290519081900360640190fd5b6109fe611f56565b15610a2657606a80546000919060ff19166001835b0217905550606880546001019055610a6a565b610a2e611fa6565b15610a4757606a80546002919060ff1916600183610a13565b610a51606d612022565b15610a6a57606a805460ff191690556068805460010190555b50565b7fb43ee0a5ee6dcc7115ce824e4e353526ad6e479afa4daeb78451070de942de3681565b600080806001606a5460ff166002811115610aa857fe5b14610abb57506000915081905080610ad5565b5050606d54606e54606f546001600160a01b039092169250905b909192565b7fc32b9cbc59039d297e670e7c196424308c90ba4a437fa7ccd008498c934e7dbf81565b7f4cd7e3f12ee4a2db0a6ba16e03fbc31bba1048c149bbf4fc9f3c02021ec550b881565b7f2f271dc1fa81985bda14a2d6d0d60b45191d2a2d97e636b192696a8796d654a781565b600280606a5460ff166002811115610b5a57fe5b14610b9c576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c696420737461746560981b604482015290519081900360640190fd5b606654606d546040805163463bbf4160e11b81526001600160a01b03928316600482015290519190921691638c777e8291602480830192600092919082900301818387803b158015610bed57600080fd5b505af1925050508015610bfe575060015b610c42573d808015610c2c576040519150601f19603f3d011682016040523d82523d6000602084013e610c31565b606091505b5050606a805460ff19169055610a6a565b50606a805460ff19169055565b6001600160a01b038116610ca1576040805162461bcd60e51b8152602060048201526014602482015273061646472657373206d75737420626520213d20360641b604482015290519081900360640190fd5b606854610cb190606b908361202b565b610a6a576040805162461bcd60e51b815260206004820152600c60248201526b43616e27742072656d6f766560a01b604482015290519081900360640190fd5b6000808080610d01606b86612084565b93509350935093509193509193565b7f7dfea4fb968e2599cdb7b3028c07d0188d0f92d1d00bd95c2805523c224649dd81565b7f7a3ee46ca1bd3e19089870d8d6530b083a86da93aab52efccb32d5950e2709cf81565b7feafac1a2b4d4fdcc942cbdce334a88ec83387087978d039f1320d3639a0b59df81565b7fb324a91be1ac0d0c4888c835aee124ca1a7caf4b73ce10aa3504e2683865d7e581565b600080606a5460ff166002811115610db457fe5b14610df6576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c696420737461746560981b604482015290519081900360640190fd5b6001600160a01b038216610e48576040805162461bcd60e51b8152602060048201526014602482015273061646472657373206d75737420626520213d20360641b604482015290519081900360640190fd5b6000610e526120be565b5090506001600160a01b03811615610eb1576040805162461bcd60e51b815260206004820152601a60248201527f546865726520697320612077696e6e65722070726f706f73616c000000000000604482015290519081900360640190fd5b606854610ec190606b908561211d565b15610f06576040805162461bcd60e51b815260206004820152601060248201526f141c9bdc1bdcd85b08195e1c1a5c995960821b604482015290519081900360640190fd5b606754600090610f1f906001600160a01b03163361216b565b9050610f29613a00565b50336000908152606960209081526040918290208251808401909352546001600160a01b0381168352600160a01b900460ff1690820152610f69816121f5565b8015610f8357506068548151610f8191606b9161211d565b155b1561105957846001600160a01b031681600001516001600160a01b031614610ff2576040805162461bcd60e51b815260206004820152601b60248201527f4d75737420766f7465207468652073616d652070726f706f73616c0000000000604482015290519081900360640190fd5b60675460009061100b906001600160a01b031633612206565b9050808311611054576040805162461bcd60e51b815260206004820152601060248201526f4e6f7420656e6f756768207374616b6560801b604482015290519081900360640190fd5b909103905b606754611082906001600160a01b03163361107d6110768361225d565b4290612350565b6123aa565b6040805180820182526001600160a01b0387811682526068805460ff90811660208086019182523360009081526069909152959095209351845495516001600160a01b031990961693169290921760ff60a01b1916600160a01b9490921693909302179055546110f590606b9087611f15565b156111e95760675461110f906001600160a01b0316612426565b8211611155576040805162461bcd60e51b815260206004820152601060248201526f4e6f7420656e6f756768207374616b6560801b604482015290519081900360640190fd5b6068546067546111939190611172906001600160a01b03166124ca565b606754611187906001600160a01b03166125bd565b606b929190898761269a565b6111e4576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f75676820746f2061646420612070726f706f73616c00000000604482015290519081900360640190fd5b61123e565b6068546111fa90606b908785612775565b61123e576040805162461bcd60e51b815260206004820152601060248201526f141c9bdc1bdcd85b08195e1c1a5c995960821b604482015290519081900360640190fd5b5050505050565b7ff646c455329c7af0436f9e95c59c90ce0e11bb4e3a1deff805807798696adf8881565b600180606a5460ff16600281111561127d57fe5b146112bf576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c696420737461746560981b604482015290519081900360640190fd5b6067546000906112d8906001600160a01b03163361216b565b90506112e2613a00565b50336000908152606960209081526040918290208251808401909352546001600160a01b0381168352600160a01b900460ff1690820152611322816121f5565b801561133d5750606d5481516001600160a01b039081169116145b156113a95760675460009061135b906001600160a01b031633612206565b90508083116113a4576040805162461bcd60e51b815260206004820152601060248201526f4e6f7420656e6f756768207374616b6560801b604482015290519081900360640190fd5b909103905b6067546113c6906001600160a01b03163361107d6110768361225d565b604080518082018252606d80546001600160a01b03908116835260685460ff90811660208086019182523360009081526069909152959095209351845495516001600160a01b031990961692169190911760ff60a01b1916600160a01b949091169390930292909217905561143c908386612800565b50505050565b7f16986f74674f2ed21d50b6e74e6b12bb323ff4f72364542fd5de5104f3cc3ca981565b7ff5afc54dd2c3e35bfa15485ed117b621cf51f31f803d11be832ccde6c77a6b5681565b7fc0ded27704f62d8726fdbd83648113d9fd8cf32c09f80523d2ba523e0bbd5ba481565b7f0428ec087e0cce276a71d1caf1afe4da32a2d48b3ebe579040612b5bd262ff7381565b7fdd6eacd9b2305faa48e6e500ef302cf28b8cd660dc843b355a6f5f26655eee7381565b6067546001600160a01b031681565b7f51a2be29a473202678b6cf57b717ba5d7ff671f01fdbdbfcad4e1882601b889681565b60685490565b7fb027f2006a45346de89db4c5efc53f4e05e96532d27366aff00367a394d0abc481565b7f7d32d87d65898c3cbc7e72c59d223bf61c7811e99dafafd24fb08e0a38f1091481565b7f41a2ac05b365409628009a8091d8dda06fe52fe2f1c792e651e5df7599a7a7de81565b7ff75b08b2b912abdbb87cc459ca0b4fdc019329386ec84ab68399b0c86fed5a9581565b7fd4ed72d0bf9bae5e1e7ae31a372a37c8069168889284ec94be25b3f6707f5b4a81565b7f66b60892ff6e7f0da16db27046f5960fdfd6bce5c3c8c21d56ccca3236a6281b81565b7fa82bea7140872d1398fa0ab5075330ab0228f4c7e381b4b6502379ffc7cdcd9f81565b7f4bd5e7ff929fdd1ba62a33f76e0f40e97bb35e8bf126c0d9d91ce5c69a4bc52181565b7f11cfbdf601b80a575e4366f0234cc06de0c9f401fe250dd9dccfccefeedb6fc281565b7f3c557531fea67120f21bc7711270a96f1b8cff3dfe3dd798a8a9f09ce9b7797281565b7f631bcbb9b033f9c8d13c32cf6e60827348d77b91b58c295e87745219242cca2281565b606d54606e54606f546070546001600160a01b039093169290919293565b6033546040805163d994d6d560e01b815233600482015290516001600160a01b039092169163d994d6d591602480820192602092909190829003018186803b15801561172457600080fd5b505afa158015611738573d6000803e3d6000fd5b505050506040513d602081101561174e57600080fd5b50516040805180820190915260168152753737ba2fb0baba3437b934bd32b22fb1b430b733b2b960511b6020820152906118065760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156117cb5781810151838201526020016117b3565b50505050905090810190601f1680156117f85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50603380546001600160a01b0319166001600160a01b0392909216919091179055565b7fde1ede48948567c43c504b761af8cd6af5363fafeceb1239b3083955d809714f81565b7f73ee596441ef88c207a7a9147d62f59186b4991555e37b7ce9c801f9539d105081565b7f0a1b21dfd7e4f3741529cf579e2731e847d81bbf13a82d0eba6910d7ac4c1c0a81565b6066546001600160a01b031681565b565b600061099b606b612838565b600054610100900460ff16806118cb57506118cb612843565b806118d9575060005460ff16155b6119145760405162461bcd60e51b815260040180806020018281038252602e815260200180613b13602e913960400191505060405180910390fd5b600054610100900460ff1615801561193f576000805460ff1961ff0019909116610100171660011790555b61194884612849565b606a805460ff19169055606780546001600160a01b038481166001600160a01b03199283161790925560016068556066805492861692909116919091179055611991606b61286b565b61199b606d612888565b801561143c576000805461ff001916905550505050565b7f8970fe7a53b9c3dfce4f2afec48b5a6550afcb16ea2da8a10ec4b47a83a34a9d81565b7f945f72e5d44fb0ce3b1de393d19415723b79f97ad801089d8470d1c20e15ffef81565b7ffb2d33acd65c36f68a15f8fe41cb8c0dd1eda164ffa87c6882e685ccb1c1adfb81565b600080611a29613a00565b5050506001600160a01b03908116600090815260696020908152604091829020825180840190935254928316808352600160a01b90930460ff1691018190529091565b7f62f5dbf0c17b0df83487409f747ad2eeca5fd54c140ca59b32cf39d6f6eaf91681565b6069602052600090815260409020546001600160a01b03811690600160a01b900460ff1682565b6033546040805163d994d6d560e01b815233600482015290516060926001600160a01b03169163d994d6d5916024808301926020929190829003018186803b158015611b0257600080fd5b505afa158015611b16573d6000803e3d6000fd5b505050506040513d6020811015611b2c57600080fd5b50516040805180820190915260168152753737ba2fb0baba3437b934bd32b22fb1b430b733b2b960511b602082015290611ba75760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156117cb5781810151838201526020016117b3565b50600033905060006060826001600160a01b031686866040516024018080602001828103825284848281815260200192508082843760008382015260408051601f909201601f1990811690940182810390940182529283526020810180516001600160e01b03166350b113e560e11b17815292518151919750955085945091925081905083835b60208310611c4d5780518252601f199092019160209182019101611c2e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114611cad576040519150601f19603f3d011682016040523d82523d6000602084013e611cb2565b606091505b509150915081611d02576040805162461bcd60e51b8152602060048201526016602482015275115c9c9bdc881a5b8819195b1959d85d194818d85b1b60521b604482015290519081900360640190fd5b95945050505050565b600080611d166120be565b506001600160a01b0316151591505090565b6000611d32611f56565b80611d405750611d40611fa6565b8061099b575061099b606d612022565b7f4cb845794d5472a713e41e8e4ddc566dab8d695f1dc6c8edd43dad9d55112a2281565b7fef9006fe6663199909dfaa4ab45e3f86d6454adb7773682f356824b6b3bc6b0e81565b7fe4f979504d2a7a24557a15195eb83131e7c4a66d33900454705435aa5a6ee08681565b7f99f83ee0c57b325f3deafb536d55596743ff112c6ac0d853d5f4f89b75dec04581565b600080606a5460ff166002811115611df457fe5b14611e36576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c696420737461746560981b604482015290519081900360640190fd5b600080611e416120be565b90925090506001600160a01b038216611e96576040805162461bcd60e51b8152602060048201526012602482015271139bc81dda5b9b995c881c1c9bdc1bdcd85b60721b604482015290519081900360640190fd5b606a805460ff19166001179055606754611ec890611ebc906001600160a01b031661225d565b606d90848460006128a7565b505050565b7f6c2abc911c0fa4c73b90c7143a9f4429749be45ebfe7b81e69b86e7ca440d81181565b7f580be8e098dd1016787d59c2a534bf9df9ec679a29de4c8f92dc3807f7d7d54d81565b6000611f2184836128d9565b611f2d57506001611f4f565b611f35613a17565b611f3f8584612910565b9050611f4b84826129a4565b9150505b9392505050565b60675460009061099b90611f72906001600160a01b03166129aa565b606754611f87906001600160a01b0316612a98565b606754611f9c906001600160a01b0316612b8b565b606d929190612c00565b60675460009061099b90611fc2906001600160a01b03166129aa565b606754611fd7906001600160a01b0316612a98565b606754611fec906001600160a01b0316612c25565b606754612001906001600160a01b0316612d18565b606754612016906001600160a01b0316612b8b565b606d9493929190612e0b565b60030154421190565b600061203784836128d9565b61204357506000611f4f565b61204b613a17565b6120558584612910565b905061206184826129a4565b61206f576000915050611f4f565b6120798584612ec1565b506001949350505050565b6000806000806000612094613a17565b61209e8888612ed8565b80516020820151604090920151929b909a50909850909650945050505050565b606854606754600091829161211591906120e0906001600160a01b0316612fc4565b6067546120f5906001600160a01b03166129aa565b60675461210a906001600160a01b0316612b8b565b606b939291906130b7565b915091509091565b600061212984836128d9565b61213557506000611f4f565b61213d613a17565b6121478584612910565b905061215384826129a4565b15612162576000915050611f4f565b611f4b8161319d565b6000612176836131a6565b6001600160a01b031663f8b2cb4f836040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156121c257600080fd5b505afa1580156121d6573d6000803e3d6000fd5b505050506040513d60208110156121ec57600080fd5b50519392505050565b606854602082015160ff1614919050565b6000612211836131a6565b6001600160a01b031663c4086893836040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156121c257600080fd5b600080826001600160a01b031663bd02d0f57fb43ee0a5ee6dcc7115ce824e4e353526ad6e479afa4daeb78451070de942de3660001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156122c757600080fd5b505afa1580156122db573d6000803e3d6000fd5b505050506040513d60208110156122f157600080fd5b50516001600160f81b0316905080610981576040805162461bcd60e51b815260206004820152601760248201527f496e76616c696420766f74696e6754696d6544656c7461000000000000000000604482015290519081900360640190fd5b600082820183811015611f4f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6123b3836131a6565b6001600160a01b031663d602ac6883836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561240957600080fd5b505af115801561241d573d6000803e3d6000fd5b50505050505050565b6000816001600160a01b031663bd02d0f57f580be8e098dd1016787d59c2a534bf9df9ec679a29de4c8f92dc3807f7d7d54d60001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561248f57600080fd5b505afa1580156124a3573d6000803e3d6000fd5b505050506040513d60208110156124b957600080fd5b50516001600160f81b031692915050565b600080826001600160a01b031663bd02d0f57fc32b9cbc59039d297e670e7c196424308c90ba4a437fa7ccd008498c934e7dbf60001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561253457600080fd5b505afa158015612548573d6000803e3d6000fd5b505050506040513d602081101561255e57600080fd5b50516001600160f81b0316905080610981576040805162461bcd60e51b815260206004820152601760248201527f496e76616c6964206d617850726550726f706f73616c73000000000000000000604482015290519081900360640190fd5b600080826001600160a01b031663bd02d0f57f62f5dbf0c17b0df83487409f747ad2eeca5fd54c140ca59b32cf39d6f6eaf91660001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561262757600080fd5b505afa15801561263b573d6000803e3d6000fd5b505050506040513d602081101561265157600080fd5b50516001600160f81b03169050806109815760405162461bcd60e51b8152600401808060200182810382526022815260200180613af16022913960400191505060405180910390fd5b60006126a687846128d9565b156126f8576126b3613a17565b6126bd8885612910565b90506126c987826129a4565b6126d757600091505061276b565b6126ee846126e689888761320f565b8a9190613238565b600191505061276b565b8461270288613309565b10156127275761271f8361271788878661320f565b89919061330d565b50600161276b565b6000806127348989613404565b91509150808411156127645761275982866127508b8a8961320f565b8c9291906134c9565b60019250505061276b565b6000925050505b9695505050505050565b600061278185846128d9565b61278d575060006127f8565b612795613a17565b61279f8685612910565b90506127ab85826129a4565b156127ba5760009150506127f8565b6127c38161319d565b156127d25760009150506127f8565b60208101516127e2908490612350565b60208201526127f2868583613238565b60019150505b949350505050565b801561281f5760018301546128159083612350565b6001840155611ec8565b600283015461282e9083612350565b6002840155505050565b600061098182613309565b303b1590565b603380546001600160a01b0319166001600160a01b0392909216919091179055565b612873613672565b80518051839161143c91839160200190613a38565b80546001600160a01b0319168155600060018201819055600290910155565b84546001600160a01b0319166001600160a01b0393909316929092178455600184015560028301554201600390910155565b60006001600160a01b03821615801590611f4f5750506001600160a01b031660009081526001919091016020526040902054151590565b612918613a17565b61292283836128d9565b612963576040805162461bcd60e51b815260206004820152600d60248201526c12d95e481b9bdd08199bdd5b99609a1b604482015290519081900360640190fd5b506001600160a01b03166000908152600191820160209081526040918290208251606081018452815481529381015491840191909152600201549082015290565b51141590565b600080826001600160a01b031663bd02d0f57f73ee596441ef88c207a7a9147d62f59186b4991555e37b7ce9c801f9539d105060001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612a1457600080fd5b505afa158015612a28573d6000803e3d6000fd5b505050506040513d6020811015612a3e57600080fd5b50516001600160f81b031690506064811015610981576040805162461bcd60e51b815260206004820152601460248201527324b73b30b634b2103831ba283932b1b4b9b4b7b760611b604482015290519081900360640190fd5b600080826001600160a01b031663bd02d0f57ffb2d33acd65c36f68a15f8fe41cb8c0dd1eda164ffa87c6882e685ccb1c1adfb60001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612b0257600080fd5b505afa158015612b16573d6000803e3d6000fd5b505050506040513d6020811015612b2c57600080fd5b50516001600160f81b0316905080610981576040805162461bcd60e51b815260206004820152601860248201527f496e76616c696420766f74654d696e506374546f5665746f0000000000000000604482015290519081900360640190fd5b6000612b968261368d565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612bce57600080fd5b505afa158015612be2573d6000803e3d6000fd5b505050506040513d6020811015612bf857600080fd5b505192915050565b6000612c0c82846136f6565b6002860154612c1b90866136f6565b1195945050505050565b600080826001600160a01b031663bd02d0f57fde1ede48948567c43c504b761af8cd6af5363fafeceb1239b3083955d809714f60001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612c8f57600080fd5b505afa158015612ca3573d6000803e3d6000fd5b505050506040513d6020811015612cb957600080fd5b50516001600160f81b0316905080610981576040805162461bcd60e51b815260206004820152601b60248201527f496e76616c696420766f74654d696e506374466f7251756f72756d0000000000604482015290519081900360640190fd5b600080826001600160a01b031663bd02d0f57f99f83ee0c57b325f3deafb536d55596743ff112c6ac0d853d5f4f89b75dec04560001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612d8257600080fd5b505afa158015612d96573d6000803e3d6000fd5b505050506040513d6020811015612dac57600080fd5b50516001600160f81b0316905080610981576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420766f74654d696e506374546f416363657074000000000000604482015290519081900360640190fd5b600080612e258789600101546136f690919063ffffffff16565b9050612e3b612e34888861374f565b84906136f6565b8110612e4b57600191505061276b565b612e5488612022565b612e6257600091505061276b565b612e6c83866136f6565b811015612e7d57600091505061276b565b612ea2612e9b89600101548a6002015461235090919063ffffffff16565b85906136f6565b811015612eb357600091505061276b565b506001979650505050505050565b612ed482612ecf8484613791565b613871565b5050565b6000612ee2613a17565b612eeb84613309565b8310612f37576040805162461bcd60e51b8152602060048201526016602482015275125b99195e081bdd5d081bd9881c985b99d957d9d95d60521b604482015290519081900360640190fd5b836000018381548110612f4657fe5b600091825260208220015485546001600160a01b03909116916001870191879087908110612f7057fe5b60009182526020808320909101546001600160a01b031683528281019390935260409182019020815160608101835281548152600182015493810193909352600201549082015290925090505b9250929050565b600080826001600160a01b031663bd02d0f57f0a1b21dfd7e4f3741529cf579e2731e847d81bbf13a82d0eba6910d7ac4c1c0a60001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561302e57600080fd5b505afa158015613042573d6000803e3d6000fd5b505050506040513d602081101561305857600080fd5b50516001600160f81b0316905080610981576040805162461bcd60e51b815260206004820152601960248201527f496e76616c696420707265566f74654d696e5043546f57696e00000000000000604482015290519081900360640190fd5b60008060006130c4613a17565b6130cc613a17565b6000805b6130d98c613309565b811015613169576130ea8c82612ed8565b90955092506130f98b846129a4565b1561310357613161565b61310d888b6136f6565b602084015161311c908b6136f6565b101561312757613161565b818360200151118061314e575081836020015114801561314e575083604001518360400151105b1561316157826020015191508496508293505b6001016130d0565b506131738361319d565b156131875750506020015191506131939050565b60008095509550505050505b9550959350505050565b60400151421190565b6000816001600160a01b03166321f8a7217f3c557531fea67120f21bc7711270a96f1b8cff3dfe3dd798a8a9f09ce9b7797260001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612bce57600080fd5b613217613a17565b50604080516060810182529384526020840191909152429091019082015290565b61324283836128d9565b613281576040805162461bcd60e51b815260206004820152600b60248201526a496e76616c6964206b657960a81b604482015290519081900360640190fd5b80516132d0576040805162461bcd60e51b8152602060048201526019602482015278496e76616c696420766f74696e67526f756e642076616c756560381b604482015290519081900360640190fd5b6001600160a01b039091166000908152600192830160209081526040918290208351815590830151938101939093550151600290910155565b5490565b61331783836128d9565b1561335a576040805162461bcd60e51b815260206004820152600e60248201526d4475706c696361746564206b657960901b604482015290519081900360640190fd5b80516133a9576040805162461bcd60e51b8152602060048201526019602482015278496e76616c696420766f74696e67526f756e642076616c756560381b604482015290519081900360640190fd5b6001600160a01b039091166000818152600180850160209081526040808420865181558287015181850155950151600290950194909455845490810185559381529190912090910180546001600160a01b0319169091179055565b60008061340f613a17565b61341a856000612ed8565b9150613428905084826129a4565b8061343757506134378161319d565b15613449576000809250925050612fbd565b602081015160009350915060015b61346086613309565b8110156134c0576134718682612ed8565b925061347f905085836129a4565b8061348e575061348e8261319d565b156134a057925060009150612fbd9050565b82826020015110156134b85760208201519093509150825b600101613457565b50509250929050565b6134d284613309565b8310613525576040805162461bcd60e51b815260206004820152601a60248201527f496e646578206f7574206f662072616e67655f7265706c616365000000000000604482015290519081900360640190fd5b8051613574576040805162461bcd60e51b8152602060048201526019602482015278496e76616c696420766f74696e67526f756e642076616c756560381b604482015290519081900360640190fd5b83600101600085600001858154811061358957fe5b60009182526020808320909101546001600160a01b03168352820192909252604001812081815560018101829055600201556135c584836128d9565b15613608576040805162461bcd60e51b815260206004820152600e60248201526d4475706c696361746564206b657960901b604482015290519081900360640190fd5b8184600001848154811061361857fe5b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055939091168152600194850183526040908190208251815592820151948301949094559092015160029092019190915550565b61367a613a9d565b5060408051602081019091526060815290565b6000816001600160a01b03166321f8a7217f4bd5e7ff929fdd1ba62a33f76e0f40e97bb35e8bf126c0d9d91ce5c69a4bc52160001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612bce57600080fd5b60008261370557506000610981565b8282028284828161371257fe5b0414611f4f5760405162461bcd60e51b8152600401808060200182810382526021815260200180613ad06021913960400191505060405180910390fd5b6000611f4f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506139a6565b600061379d83836128d9565b6137de576040805162461bcd60e51b815260206004820152600d60248201526c12d95e481b9bdd08199bdd5b99609a1b604482015290519081900360640190fd5b60005b6137ea84613309565b81101561383457826001600160a01b031684600001828154811061380a57fe5b6000918252602090912001546001600160a01b0316141561382c579050610981565b6001016137e1565b506040805162461bcd60e51b815260206004820152600c60248201526b4d697373696e67206b65793f60a01b604482015290519081900360640190fd5b61387a82613309565b81106138cd576040805162461bcd60e51b815260206004820152601a60248201527f496e646578206f7574206f662072616e6765205f72656d6f7665000000000000604482015290519081900360640190fd5b8160010160008360000183815481106138e257fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181018290556002015581548290600019810190811061392657fe5b60009182526020909120015482546001600160a01b039091169083908390811061394c57fe5b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055815482908061398057fe5b600082815260209020810160001990810180546001600160a01b03191690550190555050565b600081848411156139f85760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156117cb5781810151838201526020016117b3565b505050900390565b604080518082019091526000808252602082015290565b60405180606001604052806000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a8d579160200282015b82811115613a8d57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613a58565b50613a99929150613ab0565b5090565b6040518060200160405280606081525090565b5b80821115613a995780546001600160a01b0319168155600101613ab156fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77496e76616c696420707265566f746545787069726174696f6e54696d6544656c7461436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a2646970667358221220b506dac616b893b23a1bf317dfd8224b96b00c5906e9e5ed4df8b40d88af85c764736f6c634300060c0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"istanbul","optimizer":{"enabled":true,"runs":200}},"optimization_runs":200,"sourcify_repo_url":null,"decoded_constructor_args":null,"compiler_version":"0.6.12+commit.27d51765","is_verified_via_verifier_alliance":true,"verified_at":"2021-05-14T15:53:40.129327Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x608060405234801561001057600080fd5b50613b76806100206000396000f3fe608060405234801561001057600080fd5b50600436106103fb5760003560e01c806397492d7511610215578063d274eaff11610125578063e62c6a69116100b8578063ef9b78c611610087578063ef9b78c6146106b8578063f13eb2d5146108c1578063f63420ac146108c9578063fa8ab4c1146108d1578063faf620bc146108d9576103fb565b8063e62c6a69146108a9578063e873e208146108b1578063ea0e0661146108b9578063ec0e8bda146106b8576103fb565b8063d8bff5a5116100f4578063d8bff5a514610769578063dc8990e1146107b4578063e1a9941914610899578063e362cb7c146108a1576103fb565b8063d274eaff14610708578063d3f055d714610710578063d4923d4e14610718578063d51673fb14610761576103fb565b8063b6e08330116101a8578063bcff0e1211610177578063bcff0e12146106b0578063bef3a4df146106b8578063c08cc02d146106c0578063c0c53b8b146106c8578063d0360cdb14610700576103fb565b8063b6e0833014610672578063b74ab6fc14610698578063b90163d1146106a0578063ba6fc287146106a8576103fb565b8063a6c456f1116101e4578063a6c456f114610652578063b01f02bf1461065a578063b3699ded14610662578063b5b831e21461066a576103fb565b806397492d75146106325780639b09d9c91461063a5780639d81ac8414610642578063a68d751e1461064a576103fb565b80633f827a5a116103105780635fe22793116102a35780638a365e59116102725780638a365e591461060a5780638bc7b6f2146106125780638da1b81d1461061a578063915e4e101461062257806394ff8ee61461062a576103fb565b80635fe22793146105ea5780636eec5a4a146105f25780637b103999146105fa5780637c197e2114610602576103fb565b80634b9f5c98116102df5780634b9f5c98146105b35780634eb836f5146105d2578063541f51fd146105da578063586dec23146105e2576103fb565b80633f827a5a14610575578063484cae4e1461057d5780634a78f3ce146105855780634b903654146105ab576103fb565b806325dff9d1116103935780632dae20f3116103625780632dae20f3146104ea5780632ec2c246146104f257806337d1d3891461051857806339e94f13146105655780633bdc39501461056d576103fb565b806325dff9d1146104a257806326400693146104d257806328f134a4146104da578063296e9cc4146104e2576103fb565b806310da5e4b116103cf57806310da5e4b1461044e5780631865c57d146104885780631f17a49e14610490578063213fe5c01461049a576103fb565b80623db248146104005780630358faeb1461041a5780630c340a24146104225780630fc67cec14610446575b600080fd5b6104086108e1565b60408051918252519081900360200190f35b610408610905565b61042a610929565b604080516001600160a01b039092168252519081900360200190f35b610408610938565b6104746004803603602081101561046457600080fd5b50356001600160a01b031661095c565b604080519115158252519081900360200190f35b610408610987565b6104986109a0565b005b610408610a6d565b6104aa610a91565b604080516001600160a01b039094168452602084019290925282820152519081900360600190f35b610408610ada565b610408610afe565b610408610b22565b610498610b46565b6104986004803603602081101561050857600080fd5b50356001600160a01b0316610c4f565b6105356004803603602081101561052e57600080fd5b5035610cf1565b604080516001600160a01b0390951685526020850193909352838301919091526060830152519081900360800190f35b610408610d10565b610408610d34565b610408610d58565b610408610d7c565b6104986004803603602081101561059b57600080fd5b50356001600160a01b0316610da0565b610408611245565b610498600480360360208110156105c957600080fd5b50351515611269565b610408611442565b610408611466565b61040861148a565b6104086114ae565b6104086114d2565b61042a6114f6565b610408611505565b610408611529565b61040861152f565b610408611553565b610408611577565b61040861159b565b6104086115bf565b6104086115e3565b610408611607565b61040861162b565b61040861164f565b610408611673565b610408611697565b6105356116bb565b6104986004803603602081101561068857600080fd5b50356001600160a01b03166116d9565b610408611829565b61040861184d565b610408611871565b61042a611895565b6104986118a4565b6104086118a6565b610498600480360360608110156106de57600080fd5b506001600160a01b0381358116916020810135821691604090910135166118b2565b6104086119b2565b6104086119d6565b6104086119fa565b61073e6004803603602081101561072e57600080fd5b50356001600160a01b0316611a1e565b604080516001600160a01b03909316835260208301919091528051918290030190f35b610408611a6c565b61078f6004803603602081101561077f57600080fd5b50356001600160a01b0316611a90565b604080516001600160a01b03909316835260ff90911660208301528051918290030190f35b610824600480360360208110156107ca57600080fd5b8101906020810181356401000000008111156107e557600080fd5b8201836020820111156107f757600080fd5b8035906020019184600183028401116401000000008311171561081957600080fd5b509092509050611ab7565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561085e578181015183820152602001610846565b50505050905090810190601f16801561088b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610474611d0b565b610474611d28565b610408611d50565b610408611d74565b610408611d98565b610408611dbc565b610498611de0565b610408611ecd565b610408611ef1565b7fc1c87e0508bb8270ee6a6dbe630baa072e6e3d5968981666724b9333430e1c3181565b7fda9f12e01fc92de345bb741448d36ecb967052dd7aa1670439af833c9a3d78f181565b6033546001600160a01b031681565b7f275d8a46b817572476d2d55b41c7709dee307740bad676a9693805003a48d23181565b60006001600160a01b03821615801590610981575060685461098190606b9084611f15565b92915050565b606a5460009060ff16600281111561099b57fe5b905090565b600180606a5460ff1660028111156109b457fe5b146109f6576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c696420737461746560981b604482015290519081900360640190fd5b6109fe611f56565b15610a2657606a80546000919060ff19166001835b0217905550606880546001019055610a6a565b610a2e611fa6565b15610a4757606a80546002919060ff1916600183610a13565b610a51606d612022565b15610a6a57606a805460ff191690556068805460010190555b50565b7fb43ee0a5ee6dcc7115ce824e4e353526ad6e479afa4daeb78451070de942de3681565b600080806001606a5460ff166002811115610aa857fe5b14610abb57506000915081905080610ad5565b5050606d54606e54606f546001600160a01b039092169250905b909192565b7fc32b9cbc59039d297e670e7c196424308c90ba4a437fa7ccd008498c934e7dbf81565b7f4cd7e3f12ee4a2db0a6ba16e03fbc31bba1048c149bbf4fc9f3c02021ec550b881565b7f2f271dc1fa81985bda14a2d6d0d60b45191d2a2d97e636b192696a8796d654a781565b600280606a5460ff166002811115610b5a57fe5b14610b9c576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c696420737461746560981b604482015290519081900360640190fd5b606654606d546040805163463bbf4160e11b81526001600160a01b03928316600482015290519190921691638c777e8291602480830192600092919082900301818387803b158015610bed57600080fd5b505af1925050508015610bfe575060015b610c42573d808015610c2c576040519150601f19603f3d011682016040523d82523d6000602084013e610c31565b606091505b5050606a805460ff19169055610a6a565b50606a805460ff19169055565b6001600160a01b038116610ca1576040805162461bcd60e51b8152602060048201526014602482015273061646472657373206d75737420626520213d20360641b604482015290519081900360640190fd5b606854610cb190606b908361202b565b610a6a576040805162461bcd60e51b815260206004820152600c60248201526b43616e27742072656d6f766560a01b604482015290519081900360640190fd5b6000808080610d01606b86612084565b93509350935093509193509193565b7f7dfea4fb968e2599cdb7b3028c07d0188d0f92d1d00bd95c2805523c224649dd81565b7f7a3ee46ca1bd3e19089870d8d6530b083a86da93aab52efccb32d5950e2709cf81565b7feafac1a2b4d4fdcc942cbdce334a88ec83387087978d039f1320d3639a0b59df81565b7fb324a91be1ac0d0c4888c835aee124ca1a7caf4b73ce10aa3504e2683865d7e581565b600080606a5460ff166002811115610db457fe5b14610df6576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c696420737461746560981b604482015290519081900360640190fd5b6001600160a01b038216610e48576040805162461bcd60e51b8152602060048201526014602482015273061646472657373206d75737420626520213d20360641b604482015290519081900360640190fd5b6000610e526120be565b5090506001600160a01b03811615610eb1576040805162461bcd60e51b815260206004820152601a60248201527f546865726520697320612077696e6e65722070726f706f73616c000000000000604482015290519081900360640190fd5b606854610ec190606b908561211d565b15610f06576040805162461bcd60e51b815260206004820152601060248201526f141c9bdc1bdcd85b08195e1c1a5c995960821b604482015290519081900360640190fd5b606754600090610f1f906001600160a01b03163361216b565b9050610f29613a00565b50336000908152606960209081526040918290208251808401909352546001600160a01b0381168352600160a01b900460ff1690820152610f69816121f5565b8015610f8357506068548151610f8191606b9161211d565b155b1561105957846001600160a01b031681600001516001600160a01b031614610ff2576040805162461bcd60e51b815260206004820152601b60248201527f4d75737420766f7465207468652073616d652070726f706f73616c0000000000604482015290519081900360640190fd5b60675460009061100b906001600160a01b031633612206565b9050808311611054576040805162461bcd60e51b815260206004820152601060248201526f4e6f7420656e6f756768207374616b6560801b604482015290519081900360640190fd5b909103905b606754611082906001600160a01b03163361107d6110768361225d565b4290612350565b6123aa565b6040805180820182526001600160a01b0387811682526068805460ff90811660208086019182523360009081526069909152959095209351845495516001600160a01b031990961693169290921760ff60a01b1916600160a01b9490921693909302179055546110f590606b9087611f15565b156111e95760675461110f906001600160a01b0316612426565b8211611155576040805162461bcd60e51b815260206004820152601060248201526f4e6f7420656e6f756768207374616b6560801b604482015290519081900360640190fd5b6068546067546111939190611172906001600160a01b03166124ca565b606754611187906001600160a01b03166125bd565b606b929190898761269a565b6111e4576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f75676820746f2061646420612070726f706f73616c00000000604482015290519081900360640190fd5b61123e565b6068546111fa90606b908785612775565b61123e576040805162461bcd60e51b815260206004820152601060248201526f141c9bdc1bdcd85b08195e1c1a5c995960821b604482015290519081900360640190fd5b5050505050565b7ff646c455329c7af0436f9e95c59c90ce0e11bb4e3a1deff805807798696adf8881565b600180606a5460ff16600281111561127d57fe5b146112bf576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c696420737461746560981b604482015290519081900360640190fd5b6067546000906112d8906001600160a01b03163361216b565b90506112e2613a00565b50336000908152606960209081526040918290208251808401909352546001600160a01b0381168352600160a01b900460ff1690820152611322816121f5565b801561133d5750606d5481516001600160a01b039081169116145b156113a95760675460009061135b906001600160a01b031633612206565b90508083116113a4576040805162461bcd60e51b815260206004820152601060248201526f4e6f7420656e6f756768207374616b6560801b604482015290519081900360640190fd5b909103905b6067546113c6906001600160a01b03163361107d6110768361225d565b604080518082018252606d80546001600160a01b03908116835260685460ff90811660208086019182523360009081526069909152959095209351845495516001600160a01b031990961692169190911760ff60a01b1916600160a01b949091169390930292909217905561143c908386612800565b50505050565b7f16986f74674f2ed21d50b6e74e6b12bb323ff4f72364542fd5de5104f3cc3ca981565b7ff5afc54dd2c3e35bfa15485ed117b621cf51f31f803d11be832ccde6c77a6b5681565b7fc0ded27704f62d8726fdbd83648113d9fd8cf32c09f80523d2ba523e0bbd5ba481565b7f0428ec087e0cce276a71d1caf1afe4da32a2d48b3ebe579040612b5bd262ff7381565b7fdd6eacd9b2305faa48e6e500ef302cf28b8cd660dc843b355a6f5f26655eee7381565b6067546001600160a01b031681565b7f51a2be29a473202678b6cf57b717ba5d7ff671f01fdbdbfcad4e1882601b889681565b60685490565b7fb027f2006a45346de89db4c5efc53f4e05e96532d27366aff00367a394d0abc481565b7f7d32d87d65898c3cbc7e72c59d223bf61c7811e99dafafd24fb08e0a38f1091481565b7f41a2ac05b365409628009a8091d8dda06fe52fe2f1c792e651e5df7599a7a7de81565b7ff75b08b2b912abdbb87cc459ca0b4fdc019329386ec84ab68399b0c86fed5a9581565b7fd4ed72d0bf9bae5e1e7ae31a372a37c8069168889284ec94be25b3f6707f5b4a81565b7f66b60892ff6e7f0da16db27046f5960fdfd6bce5c3c8c21d56ccca3236a6281b81565b7fa82bea7140872d1398fa0ab5075330ab0228f4c7e381b4b6502379ffc7cdcd9f81565b7f4bd5e7ff929fdd1ba62a33f76e0f40e97bb35e8bf126c0d9d91ce5c69a4bc52181565b7f11cfbdf601b80a575e4366f0234cc06de0c9f401fe250dd9dccfccefeedb6fc281565b7f3c557531fea67120f21bc7711270a96f1b8cff3dfe3dd798a8a9f09ce9b7797281565b7f631bcbb9b033f9c8d13c32cf6e60827348d77b91b58c295e87745219242cca2281565b606d54606e54606f546070546001600160a01b039093169290919293565b6033546040805163d994d6d560e01b815233600482015290516001600160a01b039092169163d994d6d591602480820192602092909190829003018186803b15801561172457600080fd5b505afa158015611738573d6000803e3d6000fd5b505050506040513d602081101561174e57600080fd5b50516040805180820190915260168152753737ba2fb0baba3437b934bd32b22fb1b430b733b2b960511b6020820152906118065760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156117cb5781810151838201526020016117b3565b50505050905090810190601f1680156117f85780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50603380546001600160a01b0319166001600160a01b0392909216919091179055565b7fde1ede48948567c43c504b761af8cd6af5363fafeceb1239b3083955d809714f81565b7f73ee596441ef88c207a7a9147d62f59186b4991555e37b7ce9c801f9539d105081565b7f0a1b21dfd7e4f3741529cf579e2731e847d81bbf13a82d0eba6910d7ac4c1c0a81565b6066546001600160a01b031681565b565b600061099b606b612838565b600054610100900460ff16806118cb57506118cb612843565b806118d9575060005460ff16155b6119145760405162461bcd60e51b815260040180806020018281038252602e815260200180613b13602e913960400191505060405180910390fd5b600054610100900460ff1615801561193f576000805460ff1961ff0019909116610100171660011790555b61194884612849565b606a805460ff19169055606780546001600160a01b038481166001600160a01b03199283161790925560016068556066805492861692909116919091179055611991606b61286b565b61199b606d612888565b801561143c576000805461ff001916905550505050565b7f8970fe7a53b9c3dfce4f2afec48b5a6550afcb16ea2da8a10ec4b47a83a34a9d81565b7f945f72e5d44fb0ce3b1de393d19415723b79f97ad801089d8470d1c20e15ffef81565b7ffb2d33acd65c36f68a15f8fe41cb8c0dd1eda164ffa87c6882e685ccb1c1adfb81565b600080611a29613a00565b5050506001600160a01b03908116600090815260696020908152604091829020825180840190935254928316808352600160a01b90930460ff1691018190529091565b7f62f5dbf0c17b0df83487409f747ad2eeca5fd54c140ca59b32cf39d6f6eaf91681565b6069602052600090815260409020546001600160a01b03811690600160a01b900460ff1682565b6033546040805163d994d6d560e01b815233600482015290516060926001600160a01b03169163d994d6d5916024808301926020929190829003018186803b158015611b0257600080fd5b505afa158015611b16573d6000803e3d6000fd5b505050506040513d6020811015611b2c57600080fd5b50516040805180820190915260168152753737ba2fb0baba3437b934bd32b22fb1b430b733b2b960511b602082015290611ba75760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156117cb5781810151838201526020016117b3565b50600033905060006060826001600160a01b031686866040516024018080602001828103825284848281815260200192508082843760008382015260408051601f909201601f1990811690940182810390940182529283526020810180516001600160e01b03166350b113e560e11b17815292518151919750955085945091925081905083835b60208310611c4d5780518252601f199092019160209182019101611c2e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114611cad576040519150601f19603f3d011682016040523d82523d6000602084013e611cb2565b606091505b509150915081611d02576040805162461bcd60e51b8152602060048201526016602482015275115c9c9bdc881a5b8819195b1959d85d194818d85b1b60521b604482015290519081900360640190fd5b95945050505050565b600080611d166120be565b506001600160a01b0316151591505090565b6000611d32611f56565b80611d405750611d40611fa6565b8061099b575061099b606d612022565b7f4cb845794d5472a713e41e8e4ddc566dab8d695f1dc6c8edd43dad9d55112a2281565b7fef9006fe6663199909dfaa4ab45e3f86d6454adb7773682f356824b6b3bc6b0e81565b7fe4f979504d2a7a24557a15195eb83131e7c4a66d33900454705435aa5a6ee08681565b7f99f83ee0c57b325f3deafb536d55596743ff112c6ac0d853d5f4f89b75dec04581565b600080606a5460ff166002811115611df457fe5b14611e36576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c696420737461746560981b604482015290519081900360640190fd5b600080611e416120be565b90925090506001600160a01b038216611e96576040805162461bcd60e51b8152602060048201526012602482015271139bc81dda5b9b995c881c1c9bdc1bdcd85b60721b604482015290519081900360640190fd5b606a805460ff19166001179055606754611ec890611ebc906001600160a01b031661225d565b606d90848460006128a7565b505050565b7f6c2abc911c0fa4c73b90c7143a9f4429749be45ebfe7b81e69b86e7ca440d81181565b7f580be8e098dd1016787d59c2a534bf9df9ec679a29de4c8f92dc3807f7d7d54d81565b6000611f2184836128d9565b611f2d57506001611f4f565b611f35613a17565b611f3f8584612910565b9050611f4b84826129a4565b9150505b9392505050565b60675460009061099b90611f72906001600160a01b03166129aa565b606754611f87906001600160a01b0316612a98565b606754611f9c906001600160a01b0316612b8b565b606d929190612c00565b60675460009061099b90611fc2906001600160a01b03166129aa565b606754611fd7906001600160a01b0316612a98565b606754611fec906001600160a01b0316612c25565b606754612001906001600160a01b0316612d18565b606754612016906001600160a01b0316612b8b565b606d9493929190612e0b565b60030154421190565b600061203784836128d9565b61204357506000611f4f565b61204b613a17565b6120558584612910565b905061206184826129a4565b61206f576000915050611f4f565b6120798584612ec1565b506001949350505050565b6000806000806000612094613a17565b61209e8888612ed8565b80516020820151604090920151929b909a50909850909650945050505050565b606854606754600091829161211591906120e0906001600160a01b0316612fc4565b6067546120f5906001600160a01b03166129aa565b60675461210a906001600160a01b0316612b8b565b606b939291906130b7565b915091509091565b600061212984836128d9565b61213557506000611f4f565b61213d613a17565b6121478584612910565b905061215384826129a4565b15612162576000915050611f4f565b611f4b8161319d565b6000612176836131a6565b6001600160a01b031663f8b2cb4f836040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156121c257600080fd5b505afa1580156121d6573d6000803e3d6000fd5b505050506040513d60208110156121ec57600080fd5b50519392505050565b606854602082015160ff1614919050565b6000612211836131a6565b6001600160a01b031663c4086893836040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156121c257600080fd5b600080826001600160a01b031663bd02d0f57fb43ee0a5ee6dcc7115ce824e4e353526ad6e479afa4daeb78451070de942de3660001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156122c757600080fd5b505afa1580156122db573d6000803e3d6000fd5b505050506040513d60208110156122f157600080fd5b50516001600160f81b0316905080610981576040805162461bcd60e51b815260206004820152601760248201527f496e76616c696420766f74696e6754696d6544656c7461000000000000000000604482015290519081900360640190fd5b600082820183811015611f4f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6123b3836131a6565b6001600160a01b031663d602ac6883836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561240957600080fd5b505af115801561241d573d6000803e3d6000fd5b50505050505050565b6000816001600160a01b031663bd02d0f57f580be8e098dd1016787d59c2a534bf9df9ec679a29de4c8f92dc3807f7d7d54d60001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561248f57600080fd5b505afa1580156124a3573d6000803e3d6000fd5b505050506040513d60208110156124b957600080fd5b50516001600160f81b031692915050565b600080826001600160a01b031663bd02d0f57fc32b9cbc59039d297e670e7c196424308c90ba4a437fa7ccd008498c934e7dbf60001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561253457600080fd5b505afa158015612548573d6000803e3d6000fd5b505050506040513d602081101561255e57600080fd5b50516001600160f81b0316905080610981576040805162461bcd60e51b815260206004820152601760248201527f496e76616c6964206d617850726550726f706f73616c73000000000000000000604482015290519081900360640190fd5b600080826001600160a01b031663bd02d0f57f62f5dbf0c17b0df83487409f747ad2eeca5fd54c140ca59b32cf39d6f6eaf91660001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561262757600080fd5b505afa15801561263b573d6000803e3d6000fd5b505050506040513d602081101561265157600080fd5b50516001600160f81b03169050806109815760405162461bcd60e51b8152600401808060200182810382526022815260200180613af16022913960400191505060405180910390fd5b60006126a687846128d9565b156126f8576126b3613a17565b6126bd8885612910565b90506126c987826129a4565b6126d757600091505061276b565b6126ee846126e689888761320f565b8a9190613238565b600191505061276b565b8461270288613309565b10156127275761271f8361271788878661320f565b89919061330d565b50600161276b565b6000806127348989613404565b91509150808411156127645761275982866127508b8a8961320f565b8c9291906134c9565b60019250505061276b565b6000925050505b9695505050505050565b600061278185846128d9565b61278d575060006127f8565b612795613a17565b61279f8685612910565b90506127ab85826129a4565b156127ba5760009150506127f8565b6127c38161319d565b156127d25760009150506127f8565b60208101516127e2908490612350565b60208201526127f2868583613238565b60019150505b949350505050565b801561281f5760018301546128159083612350565b6001840155611ec8565b600283015461282e9083612350565b6002840155505050565b600061098182613309565b303b1590565b603380546001600160a01b0319166001600160a01b0392909216919091179055565b612873613672565b80518051839161143c91839160200190613a38565b80546001600160a01b0319168155600060018201819055600290910155565b84546001600160a01b0319166001600160a01b0393909316929092178455600184015560028301554201600390910155565b60006001600160a01b03821615801590611f4f5750506001600160a01b031660009081526001919091016020526040902054151590565b612918613a17565b61292283836128d9565b612963576040805162461bcd60e51b815260206004820152600d60248201526c12d95e481b9bdd08199bdd5b99609a1b604482015290519081900360640190fd5b506001600160a01b03166000908152600191820160209081526040918290208251606081018452815481529381015491840191909152600201549082015290565b51141590565b600080826001600160a01b031663bd02d0f57f73ee596441ef88c207a7a9147d62f59186b4991555e37b7ce9c801f9539d105060001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612a1457600080fd5b505afa158015612a28573d6000803e3d6000fd5b505050506040513d6020811015612a3e57600080fd5b50516001600160f81b031690506064811015610981576040805162461bcd60e51b815260206004820152601460248201527324b73b30b634b2103831ba283932b1b4b9b4b7b760611b604482015290519081900360640190fd5b600080826001600160a01b031663bd02d0f57ffb2d33acd65c36f68a15f8fe41cb8c0dd1eda164ffa87c6882e685ccb1c1adfb60001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612b0257600080fd5b505afa158015612b16573d6000803e3d6000fd5b505050506040513d6020811015612b2c57600080fd5b50516001600160f81b0316905080610981576040805162461bcd60e51b815260206004820152601860248201527f496e76616c696420766f74654d696e506374546f5665746f0000000000000000604482015290519081900360640190fd5b6000612b968261368d565b6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612bce57600080fd5b505afa158015612be2573d6000803e3d6000fd5b505050506040513d6020811015612bf857600080fd5b505192915050565b6000612c0c82846136f6565b6002860154612c1b90866136f6565b1195945050505050565b600080826001600160a01b031663bd02d0f57fde1ede48948567c43c504b761af8cd6af5363fafeceb1239b3083955d809714f60001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612c8f57600080fd5b505afa158015612ca3573d6000803e3d6000fd5b505050506040513d6020811015612cb957600080fd5b50516001600160f81b0316905080610981576040805162461bcd60e51b815260206004820152601b60248201527f496e76616c696420766f74654d696e506374466f7251756f72756d0000000000604482015290519081900360640190fd5b600080826001600160a01b031663bd02d0f57f99f83ee0c57b325f3deafb536d55596743ff112c6ac0d853d5f4f89b75dec04560001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612d8257600080fd5b505afa158015612d96573d6000803e3d6000fd5b505050506040513d6020811015612dac57600080fd5b50516001600160f81b0316905080610981576040805162461bcd60e51b815260206004820152601a60248201527f496e76616c696420766f74654d696e506374546f416363657074000000000000604482015290519081900360640190fd5b600080612e258789600101546136f690919063ffffffff16565b9050612e3b612e34888861374f565b84906136f6565b8110612e4b57600191505061276b565b612e5488612022565b612e6257600091505061276b565b612e6c83866136f6565b811015612e7d57600091505061276b565b612ea2612e9b89600101548a6002015461235090919063ffffffff16565b85906136f6565b811015612eb357600091505061276b565b506001979650505050505050565b612ed482612ecf8484613791565b613871565b5050565b6000612ee2613a17565b612eeb84613309565b8310612f37576040805162461bcd60e51b8152602060048201526016602482015275125b99195e081bdd5d081bd9881c985b99d957d9d95d60521b604482015290519081900360640190fd5b836000018381548110612f4657fe5b600091825260208220015485546001600160a01b03909116916001870191879087908110612f7057fe5b60009182526020808320909101546001600160a01b031683528281019390935260409182019020815160608101835281548152600182015493810193909352600201549082015290925090505b9250929050565b600080826001600160a01b031663bd02d0f57f0a1b21dfd7e4f3741529cf579e2731e847d81bbf13a82d0eba6910d7ac4c1c0a60001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561302e57600080fd5b505afa158015613042573d6000803e3d6000fd5b505050506040513d602081101561305857600080fd5b50516001600160f81b0316905080610981576040805162461bcd60e51b815260206004820152601960248201527f496e76616c696420707265566f74654d696e5043546f57696e00000000000000604482015290519081900360640190fd5b60008060006130c4613a17565b6130cc613a17565b6000805b6130d98c613309565b811015613169576130ea8c82612ed8565b90955092506130f98b846129a4565b1561310357613161565b61310d888b6136f6565b602084015161311c908b6136f6565b101561312757613161565b818360200151118061314e575081836020015114801561314e575083604001518360400151105b1561316157826020015191508496508293505b6001016130d0565b506131738361319d565b156131875750506020015191506131939050565b60008095509550505050505b9550959350505050565b60400151421190565b6000816001600160a01b03166321f8a7217f3c557531fea67120f21bc7711270a96f1b8cff3dfe3dd798a8a9f09ce9b7797260001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612bce57600080fd5b613217613a17565b50604080516060810182529384526020840191909152429091019082015290565b61324283836128d9565b613281576040805162461bcd60e51b815260206004820152600b60248201526a496e76616c6964206b657960a81b604482015290519081900360640190fd5b80516132d0576040805162461bcd60e51b8152602060048201526019602482015278496e76616c696420766f74696e67526f756e642076616c756560381b604482015290519081900360640190fd5b6001600160a01b039091166000908152600192830160209081526040918290208351815590830151938101939093550151600290910155565b5490565b61331783836128d9565b1561335a576040805162461bcd60e51b815260206004820152600e60248201526d4475706c696361746564206b657960901b604482015290519081900360640190fd5b80516133a9576040805162461bcd60e51b8152602060048201526019602482015278496e76616c696420766f74696e67526f756e642076616c756560381b604482015290519081900360640190fd5b6001600160a01b039091166000818152600180850160209081526040808420865181558287015181850155950151600290950194909455845490810185559381529190912090910180546001600160a01b0319169091179055565b60008061340f613a17565b61341a856000612ed8565b9150613428905084826129a4565b8061343757506134378161319d565b15613449576000809250925050612fbd565b602081015160009350915060015b61346086613309565b8110156134c0576134718682612ed8565b925061347f905085836129a4565b8061348e575061348e8261319d565b156134a057925060009150612fbd9050565b82826020015110156134b85760208201519093509150825b600101613457565b50509250929050565b6134d284613309565b8310613525576040805162461bcd60e51b815260206004820152601a60248201527f496e646578206f7574206f662072616e67655f7265706c616365000000000000604482015290519081900360640190fd5b8051613574576040805162461bcd60e51b8152602060048201526019602482015278496e76616c696420766f74696e67526f756e642076616c756560381b604482015290519081900360640190fd5b83600101600085600001858154811061358957fe5b60009182526020808320909101546001600160a01b03168352820192909252604001812081815560018101829055600201556135c584836128d9565b15613608576040805162461bcd60e51b815260206004820152600e60248201526d4475706c696361746564206b657960901b604482015290519081900360640190fd5b8184600001848154811061361857fe5b600091825260208083209190910180546001600160a01b0319166001600160a01b03948516179055939091168152600194850183526040908190208251815592820151948301949094559092015160029092019190915550565b61367a613a9d565b5060408051602081019091526060815290565b6000816001600160a01b03166321f8a7217f4bd5e7ff929fdd1ba62a33f76e0f40e97bb35e8bf126c0d9d91ce5c69a4bc52160001b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612bce57600080fd5b60008261370557506000610981565b8282028284828161371257fe5b0414611f4f5760405162461bcd60e51b8152600401808060200182810382526021815260200180613ad06021913960400191505060405180910390fd5b6000611f4f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506139a6565b600061379d83836128d9565b6137de576040805162461bcd60e51b815260206004820152600d60248201526c12d95e481b9bdd08199bdd5b99609a1b604482015290519081900360640190fd5b60005b6137ea84613309565b81101561383457826001600160a01b031684600001828154811061380a57fe5b6000918252602090912001546001600160a01b0316141561382c579050610981565b6001016137e1565b506040805162461bcd60e51b815260206004820152600c60248201526b4d697373696e67206b65793f60a01b604482015290519081900360640190fd5b61387a82613309565b81106138cd576040805162461bcd60e51b815260206004820152601a60248201527f496e646578206f7574206f662072616e6765205f72656d6f7665000000000000604482015290519081900360640190fd5b8160010160008360000183815481106138e257fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181018290556002015581548290600019810190811061392657fe5b60009182526020909120015482546001600160a01b039091169083908390811061394c57fe5b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055815482908061398057fe5b600082815260209020810160001990810180546001600160a01b03191690550190555050565b600081848411156139f85760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156117cb5781810151838201526020016117b3565b505050900390565b604080518082019091526000808252602082015290565b60405180606001604052806000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a8d579160200282015b82811115613a8d57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613a58565b50613a99929150613ab0565b5090565b6040518060200160405280606081525090565b5b80821115613a995780546001600160a01b0319168155600101613ab156fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77496e76616c696420707265566f746545787069726174696f6e54696d6544656c7461436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a2646970667358221220b506dac616b893b23a1bf317dfd8224b96b00c5906e9e5ed4df8b40d88af85c764736f6c634300060c0033","name":"VotingMachine","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"istanbul","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[],"certified":false,"conflicting_implementations":null,"abi":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"subaccount","type":"address"},{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mocs","type":"uint256"}],"name":"VoteEvent","type":"event"},{"inputs":[],"name":"INFO_ADDR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MESSAGE_VERSION","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_DELAY_MACHINE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_FLOW_BUFFERS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_FLOW_COINERS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_FLOW_DRIPPERS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_FLOW_REVERSE_AUCTIONS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_PRICE_PROVIDER_REGISTRY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_PROJECT_VERSION","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_STAKING_MACHINE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_TOKEN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_UPGRADE_DELEGATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_VESTING_MACHINE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_VOTING_MACHINE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_VOTING_MACHINE_MAX_PRE_PROPOSALS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_VOTING_MACHINE_MIN_STAKE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_VOTING_MACHINE_PCT_PRECISION","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_VOTING_MACHINE_PRE_VOTE_EXPIRATION_TIME_DELTA","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_VOTING_MACHINE_PRE_VOTE_MIN_PCT_TO_WIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_VOTING_MACHINE_VOTE_MIN_PCT_FOR_QUORUM","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_VOTING_MACHINE_VOTE_MIN_PCT_TO_ACCEPT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_VOTING_MACHINE_VOTE_MIN_PCT_TO_VETO","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MOC_VOTING_MACHINE_VOTING_TIME_DELTA","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_BLOCKCHAIN_INFO_INTERVAL","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_COIN_PAIR_LOOP_TASK_INTERVAL","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_CONFIGURATION_TASK_INTERVAL","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_ENTERING_FALLBACKS_AMOUNTS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_GATHER_SIGNATURE_TIMEOUT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_MAIN_EXECUTOR_TASK_INTERVAL","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_MAIN_LOOP_TASK_INTERVAL","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_MANAGER_ADDR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_MIN_ORACLES_PER_ROUND","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_PRICE_DELTA_PCT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_PRICE_DIGITS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_PRICE_FETCH_RATE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_PRICE_PUBLISH_BLOCKS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_PRICE_REJECT_DELTA_PCT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_QUEUE_LEN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_TRIGGER_VALID_PUBLICATION_BLOCKS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SCHEDULER_POOL_DELAY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SCHEDULER_ROUND_DELAY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUPPORTERS_ADDR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptedStep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_changeContractAddress","type":"address"}],"name":"canUnregister","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IGovernor","name":"newIGovernor","type":"address"}],"name":"changeIGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"controlledGovernor","outputs":[{"internalType":"contract IGovernor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"delegateCallToChanger","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getProposalByIndex","outputs":[{"internalType":"address","name":"proposalAddress","type":"address"},{"internalType":"uint256","name":"votingRound","type":"uint256"},{"internalType":"uint256","name":"votes","type":"uint256"},{"internalType":"uint256","name":"expirationTimeStamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProposalCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserVote","outputs":[{"internalType":"address","name":"voteAddress","type":"address"},{"internalType":"uint256","name":"voteRound","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVoteInfo","outputs":[{"internalType":"address","name":"winnerProposal","type":"address"},{"internalType":"uint256","name":"inFavorVotes","type":"uint256"},{"internalType":"uint256","name":"againstVotes","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVotingData","outputs":[{"internalType":"address","name":"winnerProposal","type":"address"},{"internalType":"uint256","name":"inFavorVotes","type":"uint256"},{"internalType":"uint256","name":"againstVotes","type":"uint256"},{"internalType":"uint256","name":"votingExpirationTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVotingRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"contract IGovernor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IGovernor","name":"_governor","type":"address"},{"internalType":"contract IGovernor","name":"_controlledGovernor","type":"address"},{"internalType":"contract IRegistry","name":"_registry","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_changeContractAddress","type":"address"}],"name":"preVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"preVoteStep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"readyToPreVoteStep","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"readyToVoteStep","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_changeContractAddress","type":"address"}],"name":"unregister","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"veto","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vetoCondition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vetoStep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_inFavorAgainst","type":"bool"}],"name":"vote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"voteStep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"votes","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint8","name":"round","type":"uint8"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":null}