MATIC Price: $1.00 (-1.16%)
Gas: 94 GWei
 

Overview

MATIC Balance

Polygon PoS Chain LogoPolygon PoS Chain LogoPolygon PoS Chain Logo0 MATIC

MATIC Value

$0.00

Sponsored

Transaction Hash
Method
Block
From
To
Value
0x60806040219363892021-11-29 12:26:34851 days ago1638188794IN
 Create: DisputeManager
0 MATIC0.1616010630

Parent Txn Hash Block From To Value
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DisputeManager

Compiler Version
v0.5.8+commit.23d335f2

Optimization Enabled:
Yes with 500 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at polygonscan.com on 2021-11-29
*/

// Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/lib/token/ERC20.sol
// Adapted to use pragma ^0.5.8 and satisfy our linter rules

pragma solidity ^0.5.8;


/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
contract ERC20 {
    function totalSupply() public view returns (uint256);

    function balanceOf(address _who) public view returns (uint256);

    function allowance(address _owner, address _spender) public view returns (uint256);

    function transfer(address _to, uint256 _value) public returns (bool);

    function approve(address _spender, uint256 _value) public returns (bool);

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool);

    event Transfer(
        address indexed from,
        address indexed to,
        uint256 value
    );

    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}

// File: contracts/lib/os/SafeERC20.sol

// Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/SafeERC20.sol
// Adapted to use pragma ^0.5.8 and satisfy our linter rules

pragma solidity ^0.5.8;



library SafeERC20 {
    // Before 0.5, solidity has a mismatch between `address.transfer()` and `token.transfer()`:
    // https://github.com/ethereum/solidity/issues/3544
    bytes4 private constant TRANSFER_SELECTOR = 0xa9059cbb;

    /**
    * @dev Same as a standards-compliant ERC20.transfer() that never reverts (returns false).
    *      Note that this makes an external call to the token.
    */
    function safeTransfer(ERC20 _token, address _to, uint256 _amount) internal returns (bool) {
        bytes memory transferCallData = abi.encodeWithSelector(
            TRANSFER_SELECTOR,
            _to,
            _amount
        );
        return invokeAndCheckSuccess(address(_token), transferCallData);
    }

    /**
    * @dev Same as a standards-compliant ERC20.transferFrom() that never reverts (returns false).
    *      Note that this makes an external call to the token.
    */
    function safeTransferFrom(ERC20 _token, address _from, address _to, uint256 _amount) internal returns (bool) {
        bytes memory transferFromCallData = abi.encodeWithSelector(
            _token.transferFrom.selector,
            _from,
            _to,
            _amount
        );
        return invokeAndCheckSuccess(address(_token), transferFromCallData);
    }

    /**
    * @dev Same as a standards-compliant ERC20.approve() that never reverts (returns false).
    *      Note that this makes an external call to the token.
    */
    function safeApprove(ERC20 _token, address _spender, uint256 _amount) internal returns (bool) {
        bytes memory approveCallData = abi.encodeWithSelector(
            _token.approve.selector,
            _spender,
            _amount
        );
        return invokeAndCheckSuccess(address(_token), approveCallData);
    }

    function invokeAndCheckSuccess(address _addr, bytes memory _calldata) private returns (bool) {
        bool ret;
        assembly {
            let ptr := mload(0x40)    // free memory pointer

            let success := call(
                gas,                  // forward all gas
                _addr,                // address
                0,                    // no value
                add(_calldata, 0x20), // calldata start
                mload(_calldata),     // calldata length
                ptr,                  // write output over free memory
                0x20                  // uint256 return
            )

            if gt(success, 0) {
            // Check number of bytes returned from last function call
                switch returndatasize

                // No bytes returned: assume success
                case 0 {
                    ret := 1
                }

                // 32 bytes returned: check if non-zero
                case 0x20 {
                // Only return success if returned data was true
                // Already have output in ptr
                    ret := eq(mload(ptr), 1)
                }

                // Not sure what was returned: don't mark as success
                default { }
            }
        }
        return ret;
    }
}

// File: contracts/lib/os/SafeMath.sol

// Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/lib/math/SafeMath.sol
// Adapted to use pragma ^0.5.8 and satisfy our linter rules

pragma solidity >=0.4.24 <0.6.0;


/**
 * @title SafeMath
 * @dev Math operations with safety checks that revert on error
 */
library SafeMath {
    string private constant ERROR_ADD_OVERFLOW = "MATH_ADD_OVERFLOW";
    string private constant ERROR_SUB_UNDERFLOW = "MATH_SUB_UNDERFLOW";
    string private constant ERROR_MUL_OVERFLOW = "MATH_MUL_OVERFLOW";
    string private constant ERROR_DIV_ZERO = "MATH_DIV_ZERO";

    /**
    * @dev Multiplies two numbers, reverts on overflow.
    */
    function mul(uint256 _a, uint256 _b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (_a == 0) {
            return 0;
        }

        uint256 c = _a * _b;
        require(c / _a == _b, ERROR_MUL_OVERFLOW);

        return c;
    }

    /**
    * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
    */
    function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
        require(_b > 0, ERROR_DIV_ZERO); // Solidity only automatically asserts when dividing by 0
        uint256 c = _a / _b;
        // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold

        return c;
    }

    /**
    * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
    */
    function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
        require(_b <= _a, ERROR_SUB_UNDERFLOW);
        uint256 c = _a - _b;

        return c;
    }

    /**
    * @dev Adds two numbers, reverts on overflow.
    */
    function add(uint256 _a, uint256 _b) internal pure returns (uint256) {
        uint256 c = _a + _b;
        require(c >= _a, ERROR_ADD_OVERFLOW);

        return c;
    }

    /**
    * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
    * reverts when dividing by zero.
    */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, ERROR_DIV_ZERO);
        return a % b;
    }
}

// File: contracts/lib/os/SafeMath64.sol

// Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/lib/math/SafeMath64.sol
// Adapted to use pragma ^0.5.8 and satisfy our linter rules

pragma solidity ^0.5.8;


/**
 * @title SafeMath64
 * @dev Math operations for uint64 with safety checks that revert on error
 */
library SafeMath64 {
    string private constant ERROR_ADD_OVERFLOW = "MATH64_ADD_OVERFLOW";
    string private constant ERROR_SUB_UNDERFLOW = "MATH64_SUB_UNDERFLOW";
    string private constant ERROR_MUL_OVERFLOW = "MATH64_MUL_OVERFLOW";
    string private constant ERROR_DIV_ZERO = "MATH64_DIV_ZERO";

    /**
    * @dev Multiplies two numbers, reverts on overflow.
    */
    function mul(uint64 _a, uint64 _b) internal pure returns (uint64) {
        uint256 c = uint256(_a) * uint256(_b);
        require(c < 0x010000000000000000, ERROR_MUL_OVERFLOW); // 2**64 (less gas this way)

        return uint64(c);
    }

    /**
    * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
    */
    function div(uint64 _a, uint64 _b) internal pure returns (uint64) {
        require(_b > 0, ERROR_DIV_ZERO); // Solidity only automatically asserts when dividing by 0
        uint64 c = _a / _b;
        // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold

        return c;
    }

    /**
    * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
    */
    function sub(uint64 _a, uint64 _b) internal pure returns (uint64) {
        require(_b <= _a, ERROR_SUB_UNDERFLOW);
        uint64 c = _a - _b;

        return c;
    }

    /**
    * @dev Adds two numbers, reverts on overflow.
    */
    function add(uint64 _a, uint64 _b) internal pure returns (uint64) {
        uint64 c = _a + _b;
        require(c >= _a, ERROR_ADD_OVERFLOW);

        return c;
    }

    /**
    * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
    * reverts when dividing by zero.
    */
    function mod(uint64 a, uint64 b) internal pure returns (uint64) {
        require(b != 0, ERROR_DIV_ZERO);
        return a % b;
    }
}

// File: contracts/lib/os/Uint256Helpers.sol

// Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/Uint256Helpers.sol
// Adapted to use pragma ^0.5.8 and satisfy our linter rules

pragma solidity ^0.5.8;


library Uint256Helpers {
    uint256 private constant MAX_UINT8 = uint8(-1);
    uint256 private constant MAX_UINT64 = uint64(-1);

    string private constant ERROR_UINT8_NUMBER_TOO_BIG = "UINT8_NUMBER_TOO_BIG";
    string private constant ERROR_UINT64_NUMBER_TOO_BIG = "UINT64_NUMBER_TOO_BIG";

    function toUint8(uint256 a) internal pure returns (uint8) {
        require(a <= MAX_UINT8, ERROR_UINT8_NUMBER_TOO_BIG);
        return uint8(a);
    }

    function toUint64(uint256 a) internal pure returns (uint64) {
        require(a <= MAX_UINT64, ERROR_UINT64_NUMBER_TOO_BIG);
        return uint64(a);
    }
}

// File: contracts/arbitration/IArbitrator.sol

pragma solidity ^0.5.8;



interface IArbitrator {
    /**
    * @dev Create a dispute over the Arbitrable sender with a number of possible rulings
    * @param _possibleRulings Number of possible rulings allowed for the dispute
    * @param _metadata Optional metadata that can be used to provide additional information on the dispute to be created
    * @return Dispute identification number
    */
    function createDispute(uint256 _possibleRulings, bytes calldata _metadata) external returns (uint256);

    /**
    * @dev Submit evidence for a dispute
    * @param _disputeId Id of the dispute in the Protocol
    * @param _submitter Address of the account submitting the evidence
    * @param _evidence Data submitted for the evidence related to the dispute
    */
    function submitEvidence(uint256 _disputeId, address _submitter, bytes calldata _evidence) external;

    /**
    * @dev Close the evidence period of a dispute
    * @param _disputeId Identification number of the dispute to close its evidence submitting period
    */
    function closeEvidencePeriod(uint256 _disputeId) external;

    /**
    * @notice Rule dispute #`_disputeId` if ready
    * @param _disputeId Identification number of the dispute to be ruled
    * @return subject Arbitrable instance associated to the dispute
    * @return ruling Ruling number computed for the given dispute
    */
    function rule(uint256 _disputeId) external returns (address subject, uint256 ruling);

    /**
    * @dev Tell the dispute fees information to create a dispute
    * @return recipient Address where the corresponding dispute fees must be transferred to
    * @return feeToken ERC20 token used for the fees
    * @return feeAmount Total amount of fees that must be allowed to the recipient
    */
    function getDisputeFees() external view returns (address recipient, ERC20 feeToken, uint256 feeAmount);
}

// File: contracts/arbitration/IArbitrable.sol

pragma solidity ^0.5.8;



contract IArbitrable {
    /**
    * @dev Emitted when an IArbitrable instance's dispute is ruled by an IArbitrator
    * @param arbitrator IArbitrator instance ruling the dispute
    * @param disputeId Identification number of the dispute being ruled by the arbitrator
    * @param ruling Ruling given by the arbitrator
    */
    event Ruled(IArbitrator indexed arbitrator, uint256 indexed disputeId, uint256 ruling);
}

// File: contracts/disputes/IDisputeManager.sol

pragma solidity ^0.5.8;




interface IDisputeManager {
    enum DisputeState {
        PreDraft,
        Adjudicating,
        Ruled
    }

    enum AdjudicationState {
        Invalid,
        Committing,
        Revealing,
        Appealing,
        ConfirmingAppeal,
        Ended
    }

    /**
    * @dev Create a dispute to be drafted in a future term
    * @param _subject Arbitrable instance creating the dispute
    * @param _possibleRulings Number of possible rulings allowed for the drafted jurors to vote on the dispute
    * @param _metadata Optional metadata that can be used to provide additional information on the dispute to be created
    * @return Dispute identification number
    */
    function createDispute(IArbitrable _subject, uint8 _possibleRulings, bytes calldata _metadata) external returns (uint256);

    /**
    * @dev Submit evidence for a dispute
    * @param _subject Arbitrable instance submitting the dispute
    * @param _disputeId Identification number of the dispute receiving new evidence
    * @param _submitter Address of the account submitting the evidence
    * @param _evidence Data submitted for the evidence of the dispute
    */
    function submitEvidence(IArbitrable _subject, uint256 _disputeId, address _submitter, bytes calldata _evidence) external;

    /**
    * @dev Close the evidence period of a dispute
    * @param _subject IArbitrable instance requesting to close the evidence submission period
    * @param _disputeId Identification number of the dispute to close its evidence submitting period
    */
    function closeEvidencePeriod(IArbitrable _subject, uint256 _disputeId) external;

    /**
    * @dev Draft jurors for the next round of a dispute
    * @param _disputeId Identification number of the dispute to be drafted
    */
    function draft(uint256 _disputeId) external;

    /**
    * @dev Appeal round of a dispute in favor of a certain ruling
    * @param _disputeId Identification number of the dispute being appealed
    * @param _roundId Identification number of the dispute round being appealed
    * @param _ruling Ruling appealing a dispute round in favor of
    */
    function createAppeal(uint256 _disputeId, uint256 _roundId, uint8 _ruling) external;

    /**
    * @dev Confirm appeal for a round of a dispute in favor of a ruling
    * @param _disputeId Identification number of the dispute confirming an appeal of
    * @param _roundId Identification number of the dispute round confirming an appeal of
    * @param _ruling Ruling being confirmed against a dispute round appeal
    */
    function confirmAppeal(uint256 _disputeId, uint256 _roundId, uint8 _ruling) external;

    /**
    * @dev Compute the final ruling for a dispute
    * @param _disputeId Identification number of the dispute to compute its final ruling
    * @return subject Arbitrable instance associated to the dispute
    * @return finalRuling Final ruling decided for the given dispute
    */
    function computeRuling(uint256 _disputeId) external returns (IArbitrable subject, uint8 finalRuling);

    /**
    * @dev Settle penalties for a round of a dispute
    * @param _disputeId Identification number of the dispute to settle penalties for
    * @param _roundId Identification number of the dispute round to settle penalties for
    * @param _jurorsToSettle Maximum number of jurors to be slashed in this call
    */
    function settlePenalties(uint256 _disputeId, uint256 _roundId, uint256 _jurorsToSettle) external;

    /**
    * @dev Claim rewards for a round of a dispute for juror
    * @dev For regular rounds, it will only reward winning jurors
    * @param _disputeId Identification number of the dispute to settle rewards for
    * @param _roundId Identification number of the dispute round to settle rewards for
    * @param _juror Address of the juror to settle their rewards
    */
    function settleReward(uint256 _disputeId, uint256 _roundId, address _juror) external;

    /**
    * @dev Settle appeal deposits for a round of a dispute
    * @param _disputeId Identification number of the dispute to settle appeal deposits for
    * @param _roundId Identification number of the dispute round to settle appeal deposits for
    */
    function settleAppealDeposit(uint256 _disputeId, uint256 _roundId) external;

    /**
    * @dev Tell the amount of token fees required to create a dispute
    * @return feeToken ERC20 token used for the fees
    * @return feeAmount Total amount of fees to be paid for a dispute at the given term
    */
    function getDisputeFees() external view returns (ERC20 feeToken, uint256 feeAmount);

    /**
    * @dev Tell information of a certain dispute
    * @param _disputeId Identification number of the dispute being queried
    * @return subject Arbitrable subject being disputed
    * @return possibleRulings Number of possible rulings allowed for the drafted jurors to vote on the dispute
    * @return state Current state of the dispute being queried: pre-draft, adjudicating, or ruled
    * @return finalRuling The winning ruling in case the dispute is finished
    * @return lastRoundId Identification number of the last round created for the dispute
    * @return createTermId Identification number of the term when the dispute was created
    */
    function getDispute(uint256 _disputeId) external view
        returns (IArbitrable subject, uint8 possibleRulings, DisputeState state, uint8 finalRuling, uint256 lastRoundId, uint64 createTermId);

    /**
    * @dev Tell information of a certain adjudication round
    * @param _disputeId Identification number of the dispute being queried
    * @param _roundId Identification number of the round being queried
    * @return draftTerm Term from which the requested round can be drafted
    * @return delayedTerms Number of terms the given round was delayed based on its requested draft term id
    * @return jurorsNumber Number of jurors requested for the round
    * @return selectedJurors Number of jurors already selected for the requested round
    * @return settledPenalties Whether or not penalties have been settled for the requested round
    * @return collectedTokens Amount of juror tokens that were collected from slashed jurors for the requested round
    * @return coherentJurors Number of jurors that voted in favor of the final ruling in the requested round
    * @return state Adjudication state of the requested round
    */
    function getRound(uint256 _disputeId, uint256 _roundId) external view
        returns (
            uint64 draftTerm,
            uint64 delayedTerms,
            uint64 jurorsNumber,
            uint64 selectedJurors,
            uint256 jurorFees,
            bool settledPenalties,
            uint256 collectedTokens,
            uint64 coherentJurors,
            AdjudicationState state
        );

    /**
    * @dev Tell appeal-related information of a certain adjudication round
    * @param _disputeId Identification number of the dispute being queried
    * @param _roundId Identification number of the round being queried
    * @return maker Address of the account appealing the given round
    * @return appealedRuling Ruling confirmed by the appealer of the given round
    * @return taker Address of the account confirming the appeal of the given round
    * @return opposedRuling Ruling confirmed by the appeal taker of the given round
    */
    function getAppeal(uint256 _disputeId, uint256 _roundId) external view
        returns (address maker, uint64 appealedRuling, address taker, uint64 opposedRuling);

    /**
    * @dev Tell information related to the next round due to an appeal of a certain round given.
    * @param _disputeId Identification number of the dispute being queried
    * @param _roundId Identification number of the round requesting the appeal details of
    * @return nextRoundStartTerm Term ID from which the next round will start
    * @return nextRoundJurorsNumber Jurors number for the next round
    * @return newDisputeState New state for the dispute associated to the given round after the appeal
    * @return feeToken ERC20 token used for the next round fees
    * @return jurorFees Total amount of fees to be distributed between the winning jurors of the next round
    * @return totalFees Total amount of fees for a regular round at the given term
    * @return appealDeposit Amount to be deposit of fees for a regular round at the given term
    * @return confirmAppealDeposit Total amount of fees for a regular round at the given term
    */
    function getNextRoundDetails(uint256 _disputeId, uint256 _roundId) external view
        returns (
            uint64 nextRoundStartTerm,
            uint64 nextRoundJurorsNumber,
            DisputeState newDisputeState,
            ERC20 feeToken,
            uint256 totalFees,
            uint256 jurorFees,
            uint256 appealDeposit,
            uint256 confirmAppealDeposit
        );

    /**
    * @dev Tell juror-related information of a certain adjudication round
    * @param _disputeId Identification number of the dispute being queried
    * @param _roundId Identification number of the round being queried
    * @param _juror Address of the juror being queried
    * @return weight Juror weight drafted for the requested round
    * @return rewarded Whether or not the given juror was rewarded based on the requested round
    */
    function getJuror(uint256 _disputeId, uint256 _roundId, address _juror) external view returns (uint64 weight, bool rewarded);
}

// File: contracts/lib/PctHelpers.sol

pragma solidity ^0.5.8;



library PctHelpers {
    using SafeMath for uint256;

    uint256 internal constant PCT_BASE = 10000; // ‱ (1 / 10,000)
    uint256 internal constant PCT_BASE_HIGH_PRECISION = 1e18; // 100%

    function isValid(uint16 _pct) internal pure returns (bool) {
        return _pct <= PCT_BASE;
    }

    function isValidHighPrecision(uint256 _pct) internal pure returns (bool) {
        return _pct <= PCT_BASE_HIGH_PRECISION;
    }

    function pct(uint256 self, uint16 _pct) internal pure returns (uint256) {
        return self.mul(uint256(_pct)) / PCT_BASE;
    }

    function pct256(uint256 self, uint256 _pct) internal pure returns (uint256) {
        return self.mul(_pct) / PCT_BASE;
    }

    function pctHighPrecision(uint256 self, uint256 _pct) internal pure returns (uint256) {
        return self.mul(_pct) / PCT_BASE_HIGH_PRECISION;
    }

    function pctIncrease(uint256 self, uint16 _pct) internal pure returns (uint256) {
        // No need for SafeMath: for addition note that `PCT_BASE` is lower than (2^256 - 2^16)
        return self.mul(PCT_BASE + uint256(_pct)) / PCT_BASE;
    }
}

// File: contracts/voting/ICRVotingOwner.sol

pragma solidity ^0.5.8;


interface ICRVotingOwner {
    /**
    * @dev Ensure votes can be committed for a vote instance, revert otherwise
    * @param _voteId ID of the vote instance to request the weight of a voter for
    */
    function ensureCanCommit(uint256 _voteId) external;

    /**
    * @dev Ensure a certain voter can commit votes for a vote instance, revert otherwise
    * @param _voteId ID of the vote instance to request the weight of a voter for
    * @param _voter Address of the voter querying the weight of
    */
    function ensureCanCommit(uint256 _voteId, address _voter) external;

    /**
    * @dev Ensure a certain voter can reveal votes for vote instance, revert otherwise
    * @param _voteId ID of the vote instance to request the weight of a voter for
    * @param _voter Address of the voter querying the weight of
    * @return Weight of the requested juror for the requested vote instance
    */
    function ensureCanReveal(uint256 _voteId, address _voter) external returns (uint64);
}

// File: contracts/voting/ICRVoting.sol

pragma solidity ^0.5.8;



interface ICRVoting {
    /**
    * @dev Create a new vote instance
    * @dev This function can only be called by the CRVoting owner
    * @param _voteId ID of the new vote instance to be created
    * @param _possibleOutcomes Number of possible outcomes for the new vote instance to be created
    */
    function create(uint256 _voteId, uint8 _possibleOutcomes) external;

    /**
    * @dev Get the winning outcome of a vote instance
    * @param _voteId ID of the vote instance querying the winning outcome of
    * @return Winning outcome of the given vote instance or refused in case it's missing
    */
    function getWinningOutcome(uint256 _voteId) external view returns (uint8);

    /**
    * @dev Get the tally of an outcome for a certain vote instance
    * @param _voteId ID of the vote instance querying the tally of
    * @param _outcome Outcome querying the tally of
    * @return Tally of the outcome being queried for the given vote instance
    */
    function getOutcomeTally(uint256 _voteId, uint8 _outcome) external view returns (uint256);

    /**
    * @dev Tell whether an outcome is valid for a given vote instance or not
    * @param _voteId ID of the vote instance to check the outcome of
    * @param _outcome Outcome to check if valid or not
    * @return True if the given outcome is valid for the requested vote instance, false otherwise
    */
    function isValidOutcome(uint256 _voteId, uint8 _outcome) external view returns (bool);

    /**
    * @dev Get the outcome voted by a voter for a certain vote instance
    * @param _voteId ID of the vote instance querying the outcome of
    * @param _voter Address of the voter querying the outcome of
    * @return Outcome of the voter for the given vote instance
    */
    function getVoterOutcome(uint256 _voteId, address _voter) external view returns (uint8);

    /**
    * @dev Tell whether a voter voted in favor of a certain outcome in a vote instance or not
    * @param _voteId ID of the vote instance to query if a voter voted in favor of a certain outcome
    * @param _outcome Outcome to query if the given voter voted in favor of
    * @param _voter Address of the voter to query if voted in favor of the given outcome
    * @return True if the given voter voted in favor of the given outcome, false otherwise
    */
    function hasVotedInFavorOf(uint256 _voteId, uint8 _outcome, address _voter) external view returns (bool);

    /**
    * @dev Filter a list of voters based on whether they voted in favor of a certain outcome in a vote instance or not
    * @param _voteId ID of the vote instance to be checked
    * @param _outcome Outcome to filter the list of voters of
    * @param _voters List of addresses of the voters to be filtered
    * @return List of results to tell whether a voter voted in favor of the given outcome or not
    */
    function getVotersInFavorOf(uint256 _voteId, uint8 _outcome, address[] calldata _voters) external view returns (bool[] memory);
}

// File: contracts/treasury/ITreasury.sol

pragma solidity ^0.5.8;



interface ITreasury {
    /**
    * @dev Assign a certain amount of tokens to an account
    * @param _token ERC20 token to be assigned
    * @param _to Address of the recipient that will be assigned the tokens to
    * @param _amount Amount of tokens to be assigned to the recipient
    */
    function assign(ERC20 _token, address _to, uint256 _amount) external;

    /**
    * @dev Withdraw a certain amount of tokens
    * @param _token ERC20 token to be withdrawn
    * @param _to Address of the recipient that will receive the tokens
    * @param _amount Amount of tokens to be withdrawn from the sender
    */
    function withdraw(ERC20 _token, address _to, uint256 _amount) external;
}

// File: contracts/registry/IJurorsRegistry.sol

pragma solidity ^0.5.8;



interface IJurorsRegistry {

    /**
    * @dev Assign a requested amount of juror tokens to a juror
    * @param _juror Juror to add an amount of tokens to
    * @param _amount Amount of tokens to be added to the available balance of a juror
    */
    function assignTokens(address _juror, uint256 _amount) external;

    /**
    * @dev Burn a requested amount of juror tokens
    * @param _amount Amount of tokens to be burned
    */
    function burnTokens(uint256 _amount) external;

    /**
    * @dev Draft a set of jurors based on given requirements for a term id
    * @param _params Array containing draft requirements:
    *        0. bytes32 Term randomness
    *        1. uint256 Dispute id
    *        2. uint64  Current term id
    *        3. uint256 Number of seats already filled
    *        4. uint256 Number of seats left to be filled
    *        5. uint64  Number of jurors required for the draft
    *        6. uint16  Permyriad of the minimum active balance to be locked for the draft
    *
    * @return jurors List of jurors selected for the draft
    * @return length Size of the list of the draft result
    */
    function draft(uint256[7] calldata _params) external returns (address[] memory jurors, uint256 length);

    /**
    * @dev Slash a set of jurors based on their votes compared to the winning ruling
    * @param _termId Current term id
    * @param _jurors List of juror addresses to be slashed
    * @param _lockedAmounts List of amounts locked for each corresponding juror that will be either slashed or returned
    * @param _rewardedJurors List of booleans to tell whether a juror's active balance has to be slashed or not
    * @return Total amount of slashed tokens
    */
    function slashOrUnlock(uint64 _termId, address[] calldata _jurors, uint256[] calldata _lockedAmounts, bool[] calldata _rewardedJurors)
        external
        returns (uint256 collectedTokens);

    /**
    * @dev Try to collect a certain amount of tokens from a juror for the next term
    * @param _juror Juror to collect the tokens from
    * @param _amount Amount of tokens to be collected from the given juror and for the requested term id
    * @param _termId Current term id
    * @return True if the juror has enough unlocked tokens to be collected for the requested term, false otherwise
    */
    function collectTokens(address _juror, uint256 _amount, uint64 _termId) external returns (bool);

    /**
    * @dev Lock a juror's withdrawals until a certain term ID
    * @param _juror Address of the juror to be locked
    * @param _termId Term ID until which the juror's withdrawals will be locked
    */
    function lockWithdrawals(address _juror, uint64 _termId) external;

    /**
    * @dev Tell the active balance of a juror for a given term id
    * @param _juror Address of the juror querying the active balance of
    * @param _termId Term ID querying the active balance for
    * @return Amount of active tokens for juror in the requested past term id
    */
    function activeBalanceOfAt(address _juror, uint64 _termId) external view returns (uint256);

    /**
    * @dev Tell the total amount of active juror tokens at the given term id
    * @param _termId Term ID querying the total active balance for
    * @return Total amount of active juror tokens at the given term id
    */
    function totalActiveBalanceAt(uint64 _termId) external view returns (uint256);
}

// File: contracts/lib/os/IsContract.sol

// Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/IsContract.sol
// Adapted to use pragma ^0.5.8 and satisfy our linter rules

pragma solidity ^0.5.8;


contract IsContract {
    /*
    * NOTE: this should NEVER be used for authentication
    * (see pitfalls: https://github.com/fergarrui/ethereum-security/tree/master/contracts/extcodesize).
    *
    * This is only intended to be used as a sanity check that an address is actually a contract,
    * RATHER THAN an address not being a contract.
    */
    function isContract(address _target) internal view returns (bool) {
        if (_target == address(0)) {
            return false;
        }

        uint256 size;
        assembly { size := extcodesize(_target) }
        return size > 0;
    }
}

// File: contracts/lib/os/TimeHelpers.sol

// Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/TimeHelpers.sol
// Adapted to use pragma ^0.5.8 and satisfy our linter rules

pragma solidity ^0.5.8;



contract TimeHelpers {
    using Uint256Helpers for uint256;

    /**
    * @dev Returns the current block number.
    *      Using a function rather than `block.number` allows us to easily mock the block number in
    *      tests.
    */
    function getBlockNumber() internal view returns (uint256) {
        return block.number;
    }

    /**
    * @dev Returns the current block number, converted to uint64.
    *      Using a function rather than `block.number` allows us to easily mock the block number in
    *      tests.
    */
    function getBlockNumber64() internal view returns (uint64) {
        return getBlockNumber().toUint64();
    }

    /**
    * @dev Returns the current timestamp.
    *      Using a function rather than `block.timestamp` allows us to easily mock it in
    *      tests.
    */
    function getTimestamp() internal view returns (uint256) {
        return block.timestamp; // solium-disable-line security/no-block-members
    }

    /**
    * @dev Returns the current timestamp, converted to uint64.
    *      Using a function rather than `block.timestamp` allows us to easily mock it in
    *      tests.
    */
    function getTimestamp64() internal view returns (uint64) {
        return getTimestamp().toUint64();
    }
}

// File: contracts/court/clock/IClock.sol

pragma solidity ^0.5.8;


interface IClock {
    /**
    * @dev Ensure that the current term of the clock is up-to-date
    * @return Identification number of the current term
    */
    function ensureCurrentTerm() external returns (uint64);

    /**
    * @dev Transition up to a certain number of terms to leave the clock up-to-date
    * @param _maxRequestedTransitions Max number of term transitions allowed by the sender
    * @return Identification number of the term ID after executing the heartbeat transitions
    */
    function heartbeat(uint64 _maxRequestedTransitions) external returns (uint64);

    /**
    * @dev Ensure that a certain term has its randomness set
    * @return Randomness of the current term
    */
    function ensureCurrentTermRandomness() external returns (bytes32);

    /**
    * @dev Tell the last ensured term identification number
    * @return Identification number of the last ensured term
    */
    function getLastEnsuredTermId() external view returns (uint64);

    /**
    * @dev Tell the current term identification number. Note that there may be pending term transitions.
    * @return Identification number of the current term
    */
    function getCurrentTermId() external view returns (uint64);

    /**
    * @dev Tell the number of terms the clock should transition to be up-to-date
    * @return Number of terms the clock should transition to be up-to-date
    */
    function getNeededTermTransitions() external view returns (uint64);

    /**
    * @dev Tell the information related to a term based on its ID
    * @param _termId ID of the term being queried
    * @return startTime Term start time
    * @return randomnessBN Block number used for randomness in the requested term
    * @return randomness Randomness computed for the requested term
    * @return celesteTokenTotalSupply Total supply of the Celeste token
    */
    function getTerm(uint64 _termId) external view returns (uint64 startTime, uint64 randomnessBN, bytes32 randomness, uint256 celesteTokenTotalSupply);

    /**
    * @dev Tell the randomness of a term even if it wasn't computed yet
    * @param _termId Identification number of the term being queried
    * @return Randomness of the requested term
    */
    function getTermRandomness(uint64 _termId) external view returns (bytes32);

    /**
    * @dev Tell the total supply of the celeste token at a specific term
    * @param _termId Identification number of the term being queried
    * @return Total supply of celeste token
    */
    function getTermTokenTotalSupply(uint64 _termId) external view returns (uint256);
}

// File: contracts/court/clock/CourtClock.sol

pragma solidity ^0.5.8;






contract CourtClock is IClock, TimeHelpers {
    using SafeMath64 for uint64;

    string private constant ERROR_TERM_DOES_NOT_EXIST = "CLK_TERM_DOES_NOT_EXIST";
    string private constant ERROR_TERM_DURATION_TOO_LONG = "CLK_TERM_DURATION_TOO_LONG";
    string private constant ERROR_TERM_RANDOMNESS_NOT_YET = "CLK_TERM_RANDOMNESS_NOT_YET";
    string private constant ERROR_TERM_RANDOMNESS_UNAVAILABLE = "CLK_TERM_RANDOMNESS_UNAVAILABLE";
    string private constant ERROR_BAD_FIRST_TERM_START_TIME = "CLK_BAD_FIRST_TERM_START_TIME";
    string private constant ERROR_TOO_MANY_TRANSITIONS = "CLK_TOO_MANY_TRANSITIONS";
    string private constant ERROR_INVALID_TRANSITION_TERMS = "CLK_INVALID_TRANSITION_TERMS";
    string private constant ERROR_CANNOT_DELAY_STARTED_COURT = "CLK_CANNOT_DELAY_STARTED_COURT";
    string private constant ERROR_CANNOT_DELAY_PAST_START_TIME = "CLK_CANNOT_DELAY_PAST_START_TIME";

    // Maximum number of term transitions a callee may have to assume in order to call certain functions that require the Court being up-to-date
    uint64 internal constant MAX_AUTO_TERM_TRANSITIONS_ALLOWED = 1;

    // Max duration in seconds that a term can last
    uint64 internal constant MAX_TERM_DURATION = 365 days;

    // Max time until first term starts since contract is deployed
    uint64 internal constant MAX_FIRST_TERM_DELAY_PERIOD = 2 * MAX_TERM_DURATION;

    struct Term {
        uint64 startTime;              // Timestamp when the term started
        uint64 randomnessBN;           // Block number for entropy
        bytes32 randomness;            // Entropy from randomnessBN block hash
        uint256 celesteTokenTotalSupply;
    }

    // Duration in seconds for each term of the Court
    uint64 private termDuration;

    // Last ensured term id
    uint64 private termId;

    // List of Court terms indexed by id
    mapping (uint64 => Term) private terms;

    event Heartbeat(uint64 previousTermId, uint64 currentTermId);
    event StartTimeDelayed(uint64 previousStartTime, uint64 currentStartTime);

    /**
    * @dev Ensure a certain term has already been processed
    * @param _termId Identification number of the term to be checked
    */
    modifier termExists(uint64 _termId) {
        require(_termId <= termId, ERROR_TERM_DOES_NOT_EXIST);
        _;
    }

    /**
    * @dev Constructor function
    * @param _termParams Array containing:
    *        0. _termDuration Duration in seconds per term
    *        1. _firstTermStartTime Timestamp in seconds when the court will open (to give time for juror on-boarding)
    */
    constructor(uint64[2] memory _termParams, ERC20 _celesteToken) public {
        uint64 _termDuration = _termParams[0];
        uint64 _firstTermStartTime = _termParams[1];

        require(_termDuration < MAX_TERM_DURATION, ERROR_TERM_DURATION_TOO_LONG);
        require(_firstTermStartTime >= getTimestamp64() + _termDuration, ERROR_BAD_FIRST_TERM_START_TIME);
        require(_firstTermStartTime <= getTimestamp64() + MAX_FIRST_TERM_DELAY_PERIOD, ERROR_BAD_FIRST_TERM_START_TIME);

        termDuration = _termDuration;

        // No need for SafeMath: we already checked values above
        terms[0].startTime = _firstTermStartTime - _termDuration;
        terms[0].celesteTokenTotalSupply = _celesteToken.totalSupply();
    }

    /**
    * @notice Ensure that the current term of the Court is up-to-date. If the Court is outdated by more than `MAX_AUTO_TERM_TRANSITIONS_ALLOWED`
    *         terms, the heartbeat function must be called manually instead.
    * @return Identification number of the current term
    */
    function ensureCurrentTerm() external returns (uint64) {
        return _ensureCurrentTerm();
    }

    /**
    * @notice Transition up to `_maxRequestedTransitions` terms
    * @param _maxRequestedTransitions Max number of term transitions allowed by the sender
    * @return Identification number of the term ID after executing the heartbeat transitions
    */
    function heartbeat(uint64 _maxRequestedTransitions) external returns (uint64) {
        return _heartbeat(_maxRequestedTransitions);
    }

    /**
    * @notice Ensure that a certain term has its randomness set. As we allow to draft disputes requested for previous terms, if there
    *      were mined more than 256 blocks for the current term, the blockhash of its randomness BN is no longer available, given
    *      round will be able to be drafted in the following term.
    * @return Randomness of the current term
    */
    function ensureCurrentTermRandomness() external returns (bytes32) {
        // If the randomness for the given term was already computed, return
        uint64 currentTermId = termId;
        Term storage term = terms[currentTermId];
        bytes32 termRandomness = term.randomness;
        if (termRandomness != bytes32(0)) {
            return termRandomness;
        }

        // Compute term randomness
        bytes32 newRandomness = _computeTermRandomness(currentTermId);
        require(newRandomness != bytes32(0), ERROR_TERM_RANDOMNESS_UNAVAILABLE);
        term.randomness = newRandomness;
        return newRandomness;
    }

    /**
    * @dev Tell the term duration of the Court
    * @return Duration in seconds of the Court term
    */
    function getTermDuration() external view returns (uint64) {
        return termDuration;
    }

    /**
    * @dev Tell the last ensured term identification number
    * @return Identification number of the last ensured term
    */
    function getLastEnsuredTermId() external view returns (uint64) {
        return _lastEnsuredTermId();
    }

    /**
    * @dev Tell the current term identification number. Note that there may be pending term transitions.
    * @return Identification number of the current term
    */
    function getCurrentTermId() external view returns (uint64) {
        return _currentTermId();
    }

    /**
    * @dev Tell the number of terms the Court should transition to be up-to-date
    * @return Number of terms the Court should transition to be up-to-date
    */
    function getNeededTermTransitions() external view returns (uint64) {
        return _neededTermTransitions();
    }

    /**
    * @dev Tell the information related to a term based on its ID. Note that if the term has not been reached, the
    *      information returned won't be computed yet. This function allows querying future terms that were not computed yet.
    * @param _termId ID of the term being queried
    * @return startTime Term start time
    * @return randomnessBN Block number used for randomness in the requested term
    * @return randomness Randomness computed for the requested term
    * @return celesteTokenTotalSupply Total supply of the Celeste token
    */
    function getTerm(uint64 _termId) external view returns (uint64 startTime, uint64 randomnessBN, bytes32 randomness, uint256 celesteTokenTotalSupply) {
        Term storage term = terms[_termId];
        return (term.startTime, term.randomnessBN, term.randomness, term.celesteTokenTotalSupply);
    }

    /**
    * @dev Tell the randomness of a term even if it wasn't computed yet
    * @param _termId Identification number of the term being queried
    * @return Randomness of the requested term
    */
    function getTermRandomness(uint64 _termId) external view termExists(_termId) returns (bytes32) {
        return _computeTermRandomness(_termId);
    }

    /**
    * @dev Tell the total supply of the celeste token at a specific term
    * @param _termId Identification number of the term being queried
    * @return Total supply of celeste token
    */
    function getTermTokenTotalSupply(uint64 _termId) external view termExists(_termId) returns (uint256) {
        return terms[_termId].celesteTokenTotalSupply;
    }

    /**
    * @dev Internal function to ensure that the current term of the Court is up-to-date. If the Court is outdated by more than
    *      `MAX_AUTO_TERM_TRANSITIONS_ALLOWED` terms, the heartbeat function must be called manually.
    * @return Identification number of the resultant term ID after executing the corresponding transitions
    */
    function _ensureCurrentTerm() internal returns (uint64) {
        // Check the required number of transitions does not exceeds the max allowed number to be processed automatically
        uint64 requiredTransitions = _neededTermTransitions();
        require(requiredTransitions <= MAX_AUTO_TERM_TRANSITIONS_ALLOWED, ERROR_TOO_MANY_TRANSITIONS);

        // If there are no transitions pending, return the last ensured term id
        if (uint256(requiredTransitions) == 0) {
            return termId;
        }

        // Process transition if there is at least one pending
        return _heartbeat(requiredTransitions);
    }

    /**
    * @dev Internal function to transition the Court terms up to a requested number of terms
    * @param _maxRequestedTransitions Max number of term transitions allowed by the sender
    * @return Identification number of the resultant term ID after executing the requested transitions
    */
    function _heartbeat(uint64 _maxRequestedTransitions) internal returns (uint64) {
        // Transition the minimum number of terms between the amount requested and the amount actually needed
        uint64 neededTransitions = _neededTermTransitions();
        uint256 transitions = uint256(_maxRequestedTransitions < neededTransitions ? _maxRequestedTransitions : neededTransitions);
        require(transitions > 0, ERROR_INVALID_TRANSITION_TERMS);

        uint64 blockNumber = getBlockNumber64();
        uint64 previousTermId = termId;
        uint64 currentTermId = previousTermId;
        for (uint256 transition = 1; transition <= transitions; transition++) {
            // Term IDs are incremented by one based on the number of time periods since the Court started. Since time is represented in uint64,
            // even if we chose the minimum duration possible for a term (1 second), we can ensure terms will never reach 2^64 since time is
            // already assumed to fit in uint64.
            Term storage previousTerm = terms[currentTermId++];
            Term storage currentTerm = terms[currentTermId];
            (ERC20 feeToken,,,,,, uint256[4] memory jurorsParams) = _getConfig(currentTermId);
            _onTermTransitioned(currentTermId);

            // Set the start time of the new term. Note that we are using a constant term duration value to guarantee
            // equally long terms, regardless of heartbeats.
            currentTerm.startTime = previousTerm.startTime.add(termDuration);

            // In order to draft a random number of jurors in a term, we use a randomness factor for each term based on a
            // block number that is set once the term has started. Note that this information could not be known beforehand.
            currentTerm.randomnessBN = blockNumber + 1;

            // We check if the feeTokenTotalSupply is set, which means this networks feeToken doesn't have an accurate
            // totalSupply so we will use the hardcoded value
            currentTerm.celesteTokenTotalSupply = jurorsParams[3] > 0 ? jurorsParams[3] : feeToken.totalSupply();
        }

        termId = currentTermId;
        emit Heartbeat(previousTermId, currentTermId);
        return currentTermId;
    }

    /**
    * @dev Internal function to delay the first term start time only if it wasn't reached yet
    * @param _newFirstTermStartTime New timestamp in seconds when the court will open
    */
    function _delayStartTime(uint64 _newFirstTermStartTime) internal {
        require(_currentTermId() == 0, ERROR_CANNOT_DELAY_STARTED_COURT);

        Term storage term = terms[0];
        uint64 currentFirstTermStartTime = term.startTime.add(termDuration);
        require(_newFirstTermStartTime > currentFirstTermStartTime, ERROR_CANNOT_DELAY_PAST_START_TIME);

        // No need for SafeMath: we already checked above that `_newFirstTermStartTime` > `currentFirstTermStartTime` >= `termDuration`
        term.startTime = _newFirstTermStartTime - termDuration;
        emit StartTimeDelayed(currentFirstTermStartTime, _newFirstTermStartTime);
    }

    /**
    * @dev Internal function to notify when a term has been transitioned. This function must be overridden to provide custom behavior.
    * @param _termId Identification number of the new current term that has been transitioned
    */
    function _onTermTransitioned(uint64 _termId) internal;

    /**
    * @dev Internal function to tell the last ensured term identification number
    * @return Identification number of the last ensured term
    */
    function _lastEnsuredTermId() internal view returns (uint64) {
        return termId;
    }

    /**
    * @dev Internal function to tell the current term identification number. Note that there may be pending term transitions.
    * @return Identification number of the current term
    */
    function _currentTermId() internal view returns (uint64) {
        return termId.add(_neededTermTransitions());
    }

    /**
    * @dev Internal function to tell the number of terms the Court should transition to be up-to-date
    * @return Number of terms the Court should transition to be up-to-date
    */
    function _neededTermTransitions() internal view returns (uint64) {
        // Note that the Court is always initialized providing a start time for the first-term in the future. If that's the case,
        // no term transitions are required.
        uint64 currentTermStartTime = terms[termId].startTime;
        if (getTimestamp64() < currentTermStartTime) {
            return uint64(0);
        }

        // No need for SafeMath: we already know that the start time of the current term is in the past
        return (getTimestamp64() - currentTermStartTime) / termDuration;
    }

    /**
    * @dev Internal function to compute the randomness that will be used to draft jurors for the given term. This
    *      function assumes the given term exists. To determine the randomness factor for a term we use the hash of a
    *      block number that is set once the term has started to ensure it cannot be known beforehand. Note that the
    *      hash function being used only works for the 256 most recent block numbers.
    * @param _termId Identification number of the term being queried
    * @return Randomness computed for the given term
    */
    function _computeTermRandomness(uint64 _termId) internal view returns (bytes32) {
        Term storage term = terms[_termId];
        require(getBlockNumber64() > term.randomnessBN, ERROR_TERM_RANDOMNESS_NOT_YET);
        return blockhash(term.randomnessBN);
    }

    /**
    * @dev Tell the full Court configuration parameters at a certain term
    * @param _termId Identification number of the term querying the Court config of
    * @return token Address of the token used to pay for fees
    * @return fees Array containing:
    *         0. jurorFee Amount of fee tokens that is paid per juror per dispute
    *         1. draftFee Amount of fee tokens per juror to cover the drafting cost
    *         2. settleFee Amount of fee tokens per juror to cover round settlement cost
    * @return maxRulingOptions Max number of selectable outcomes for each dispute
    * @return roundParams Array containing durations of phases of a dispute and other params for rounds:
    *         0. evidenceTerms Max submitting evidence period duration in terms
    *         1. commitTerms Commit period duration in terms
    *         2. revealTerms Reveal period duration in terms
    *         3. appealTerms Appeal period duration in terms
    *         4. appealConfirmationTerms Appeal confirmation period duration in terms
    *         5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *         6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *         7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *         8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @return pcts Array containing:
    *         0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
    *         1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000)
    * @return appealCollateralParams Array containing params for appeal collateral:
    *         0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling
    *         1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal
    * @return jurorsParams Array containing params for juror registry:
    *         0. minActiveBalance Minimum amount of juror tokens that can be activated
    *         1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake
    *         2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake
    *         3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do

    */
    function _getConfig(uint64 _termId) internal view returns (
        ERC20 feeToken,
        uint256[3] memory fees,
        uint8 maxRulingOptions,
        uint64[9] memory roundParams,
        uint16[2] memory pcts,
        uint256[2] memory appealCollateralParams,
        uint256[4] memory jurorsParams
    );
}

// File: contracts/court/config/IConfig.sol

pragma solidity ^0.5.8;



interface IConfig {

    /**
    * @dev Tell the full Court configuration parameters at a certain term
    * @param _termId Identification number of the term querying the Court config of
    * @return token Address of the token used to pay for fees
    * @return fees Array containing:
    *         0. jurorFee Amount of fee tokens that is paid per juror per dispute
    *         1. draftFee Amount of fee tokens per juror to cover the drafting cost
    *         2. settleFee Amount of fee tokens per juror to cover round settlement cost
    * @return maxRulingOptions Max number of selectable outcomes for each dispute
    * @return roundParams Array containing durations of phases of a dispute and other params for rounds:
    *         0. evidenceTerms Max submitting evidence period duration in terms
    *         1. commitTerms Commit period duration in terms
    *         2. revealTerms Reveal period duration in terms
    *         3. appealTerms Appeal period duration in terms
    *         4. appealConfirmationTerms Appeal confirmation period duration in terms
    *         5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *         6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *         7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *         8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @return pcts Array containing:
    *         0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
    *         1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000)
    * @return appealCollateralParams Array containing params for appeal collateral:
    *         0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling
    *         1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal
    * @return jurorsParams Array containing params for juror registry:
    *         0. minActiveBalance Minimum amount of juror tokens that can be activated
    *         1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake
    *         2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake
    *         3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do
    */
    function getConfig(uint64 _termId) external view
        returns (
            ERC20 feeToken,
            uint256[3] memory fees,
            uint8 maxRulingOptions,
            uint64[9] memory roundParams,
            uint16[2] memory pcts,
            uint256[2] memory appealCollateralParams,
            uint256[4] memory jurorsParams
        );

    /**
    * @dev Tell the draft config at a certain term
    * @param _termId Identification number of the term querying the draft config of
    * @return feeToken Address of the token used to pay for fees
    * @return draftFee Amount of fee tokens per juror to cover the drafting cost
    * @return penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
    */
    function getDraftConfig(uint64 _termId) external view returns (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct);

    /**
    * @dev Tell the min active balance config at a certain term
    * @param _termId Term querying the min active balance config of
    * @return Minimum amount of tokens jurors have to activate to participate in the Court
    */
    function getMinActiveBalance(uint64 _termId) external view returns (uint256);

    /**
    * @dev Tell whether a certain holder accepts automatic withdrawals of tokens or not
    * @return True if the given holder accepts automatic withdrawals of their tokens, false otherwise
    */
    function areWithdrawalsAllowedFor(address _holder) external view returns (bool);
}

// File: contracts/court/config/CourtConfigData.sol

pragma solidity ^0.5.8;



contract CourtConfigData {

    struct Config {
        FeesConfig fees;                        // Full fees-related config
        DisputesConfig disputes;                // Full disputes-related config
        JurorsConfig jurors;                    // Full juror-related config
    }

    struct FeesConfig {
        ERC20 token;                            // ERC20 token to be used for the fees of the Court
        uint16 finalRoundReduction;             // Permyriad of fees reduction applied for final appeal round (‱ - 1/10,000)
        uint256 jurorFee;                       // Amount of tokens paid to draft a juror to adjudicate a dispute
        uint256 draftFee;                       // Amount of tokens paid per round to cover the costs of drafting jurors
        uint256 settleFee;                      // Amount of tokens paid per round to cover the costs of slashing jurors
    }

    struct DisputesConfig {
        uint8 maxRulingOptions;                 // Max number of ruling options selectable by jurors for a dispute
        uint64 evidenceTerms;                   // Max submitting evidence period duration in terms
        uint64 commitTerms;                     // Committing period duration in terms
        uint64 revealTerms;                     // Revealing period duration in terms
        uint64 appealTerms;                     // Appealing period duration in terms
        uint64 appealConfirmTerms;              // Confirmation appeal period duration in terms
        uint16 penaltyPct;                      // Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
        uint64 firstRoundJurorsNumber;          // Number of jurors drafted on first round
        uint64 appealStepFactor;                // Factor in which the jurors number is increased on each appeal
        uint64 finalRoundLockTerms;             // Period a coherent juror in the final round will remain locked
        uint256 maxRegularAppealRounds;         // Before the final appeal
        uint256 appealCollateralFactor;         // Permyriad multiple of dispute fees required to appeal a preliminary ruling (‱ - 1/10,000)
        uint256 appealConfirmCollateralFactor;  // Permyriad multiple of dispute fees required to confirm appeal (‱ - 1/10,000)
    }

    struct JurorsConfig {
        uint256 minActiveBalance;               // Minimum amount of tokens jurors have to activate to participate in the Court
        uint256 minMaxPctTotalSupply;           // Minimum max percent of the total supply a juror can activate, applied for total supply active stake
        uint256 maxMaxPctTotalSupply;           // Maximum max percent of the total supply a juror can activate, applied for 0 active stake
        uint256 feeTokenTotalSupply;            // Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do
    }

    struct DraftConfig {
        ERC20 feeToken;                         // ERC20 token to be used for the fees of the Court
        uint16 penaltyPct;                      // Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
        uint256 draftFee;                       // Amount of tokens paid per round to cover the costs of drafting jurors
    }
}

// File: contracts/court/config/CourtConfig.sol

pragma solidity ^0.5.8;







contract CourtConfig is IConfig, CourtConfigData {
    using SafeMath64 for uint64;
    using PctHelpers for uint256;

    string private constant ERROR_TOO_OLD_TERM = "CONF_TOO_OLD_TERM";
    string private constant ERROR_RULING_OPTIONS_LESS_THAN_MIN = "CONF_RULING_OPTIONS_LESS_THAN_MIN";
    string private constant ERROR_RULING_OPTIONS_MORE_THAN_MAX = "CONF_RULING_OPTIONS_MORE_THAN_MAX";
    string private constant ERROR_INVALID_PENALTY_PCT = "CONF_INVALID_PENALTY_PCT";
    string private constant ERROR_INVALID_FINAL_ROUND_REDUCTION_PCT = "CONF_INVALID_FINAL_ROUND_RED_PCT";
    string private constant ERROR_INVALID_MAX_APPEAL_ROUNDS = "CONF_INVALID_MAX_APPEAL_ROUNDS";
    string private constant ERROR_LARGE_ROUND_PHASE_DURATION = "CONF_LARGE_ROUND_PHASE_DURATION";
    string private constant ERROR_BAD_INITIAL_JURORS_NUMBER = "CONF_BAD_INITIAL_JURORS_NUMBER";
    string private constant ERROR_BAD_APPEAL_STEP_FACTOR = "CONF_BAD_APPEAL_STEP_FACTOR";
    string private constant ERROR_ZERO_COLLATERAL_FACTOR = "CONF_ZERO_COLLATERAL_FACTOR";
    string private constant ERROR_ZERO_MIN_ACTIVE_BALANCE = "CONF_ZERO_MIN_ACTIVE_BALANCE";
    string private constant ERROR_MIN_MAX_TOTAL_SUPPLY_ZERO = "CONF_MIN_MAX_TOTAL_SUPPLY_ZERO";
    string private constant ERROR_INVALID_MAX_MAX_TOTAL_SUPPLY_PCT = "CONF_INVALID_MAX_MAX_TOTAL_SUPPLY_PCT";
    string private constant ERROR_MIN_MORE_THAN_MAX_ACTIVE_PCT = "CONF_MIN_MORE_THAN_MAX_ACTIVE_PCT";

    // Max number of terms that each of the different adjudication states can last (if lasted 1h, this would be a year)
    uint64 internal constant MAX_ADJ_STATE_DURATION = 8670;

    // Cap the max number of regular appeal rounds
    uint256 internal constant MAX_REGULAR_APPEAL_ROUNDS_LIMIT = 10;

    // Future term ID in which a config change has been scheduled
    uint64 private configChangeTermId;

    // List of all the configs used in the Court
    Config[] private configs;

    // List of configs indexed by id
    mapping (uint64 => uint256) private configIdByTerm;

    // Holders opt-in config for automatic withdrawals
    mapping (address => bool) private withdrawalsAllowed;

    event NewConfig(uint64 fromTermId, uint64 courtConfigId);
    event AutomaticWithdrawalsAllowedChanged(address indexed holder, bool allowed);

    /**
    * @dev Constructor function
    * @param _feeToken Address of the token contract that is used to pay for fees
    * @param _fees Array containing:
    *        0. jurorFee Amount of fee tokens that is paid per juror per dispute
    *        1. draftFee Amount of fee tokens per juror to cover the drafting cost
    *        2. settleFee Amount of fee tokens per juror to cover round settlement cost
    * @param _maxRulingOptions Max number of selectable outcomes for each dispute
    * @param _roundParams Array containing durations of phases of a dispute and other params for rounds:
    *        0. evidenceTerms Max submitting evidence period duration in terms
    *        1. commitTerms Commit period duration in terms
    *        2. revealTerms Reveal period duration in terms
    *        3. appealTerms Appeal period duration in terms
    *        4. appealConfirmationTerms Appeal confirmation period duration in terms
    *        5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *        6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *        7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *        8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @param _pcts Array containing:
    *        0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
    *        1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000)
    * @param _appealCollateralParams Array containing params for appeal collateral:
    *        0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling
    *        1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal
    * @param _jurorsParams Array containing params for juror registry:
    *        0. minActiveBalance Minimum amount of juror tokens that can be activated
    *        1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake
    *        2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake
    *        3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do
    */
    constructor(
        ERC20 _feeToken,
        uint256[3] memory _fees,
        uint8 _maxRulingOptions,
        uint64[9] memory _roundParams,
        uint16[2] memory _pcts,
        uint256[2] memory _appealCollateralParams,
        uint256[4] memory _jurorsParams
    )
        public
    {
        // Leave config at index 0 empty for non-scheduled config changes
        configs.length = 1;
        _setConfig(
            0,
            0,
            _feeToken,
            _fees,
            _maxRulingOptions,
            _roundParams,
            _pcts,
            _appealCollateralParams,
            _jurorsParams
        );
    }

    /**
    * @notice Set the automatic withdrawals config for the sender to `_allowed`
    * @param _allowed Whether or not the automatic withdrawals are allowed by the sender
    */
    function setAutomaticWithdrawals(bool _allowed) external {
        withdrawalsAllowed[msg.sender] = _allowed;
        emit AutomaticWithdrawalsAllowedChanged(msg.sender, _allowed);
    }

    /**
    * @dev Tell the full Court configuration parameters at a certain term
    * @param _termId Identification number of the term querying the Court config of
    * @return token Address of the token used to pay for fees
    * @return fees Array containing:
    *         0. jurorFee Amount of fee tokens that is paid per juror per dispute
    *         1. draftFee Amount of fee tokens per juror to cover the drafting cost
    *         2. settleFee Amount of fee tokens per juror to cover round settlement cost
    * @return maxRulingOptions Max number of selectable outcomes for each dispute
    * @return roundParams Array containing durations of phases of a dispute and other params for rounds:
    *         0. evidenceTerms Max submitting evidence period duration in terms
    *         1. commitTerms Commit period duration in terms
    *         2. revealTerms Reveal period duration in terms
    *         3. appealTerms Appeal period duration in terms
    *         4. appealConfirmationTerms Appeal confirmation period duration in terms
    *         5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *         6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *         7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *         8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @return pcts Array containing:
    *         0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
    *         1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000)
    * @return appealCollateralParams Array containing params for appeal collateral:
    *         0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling
    *         1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal
    * @return jurorsParams Array containing params for juror registry:
    *         0. minActiveBalance Minimum amount of juror tokens that can be activated
    *         1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake
    *         2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake
    *         3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do
    */
    function getConfig(uint64 _termId) external view
        returns (
            ERC20 feeToken,
            uint256[3] memory fees,
            uint8 maxRulingOptions,
            uint64[9] memory roundParams,
            uint16[2] memory pcts,
            uint256[2] memory appealCollateralParams,
            uint256[4] memory jurorsParams
        );

    /**
    * @dev Tell the draft config at a certain term
    * @param _termId Identification number of the term querying the draft config of
    * @return feeToken Address of the token used to pay for fees
    * @return draftFee Amount of fee tokens per juror to cover the drafting cost
    * @return penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
    */
    function getDraftConfig(uint64 _termId) external view returns (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct);

    /**
    * @dev Tell the min active balance config at a certain term
    * @param _termId Term querying the min active balance config of
    * @return Minimum amount of tokens jurors have to activate to participate in the Court
    */
    function getMinActiveBalance(uint64 _termId) external view returns (uint256);

    /**
    * @dev Tell whether a certain holder accepts automatic withdrawals of tokens or not
    * @param _holder Address of the token holder querying if withdrawals are allowed for
    * @return True if the given holder accepts automatic withdrawals of their tokens, false otherwise
    */
    function areWithdrawalsAllowedFor(address _holder) external view returns (bool) {
        return withdrawalsAllowed[_holder];
    }

    /**
    * @dev Tell the term identification number of the next scheduled config change
    * @return Term identification number of the next scheduled config change
    */
    function getConfigChangeTermId() external view returns (uint64) {
        return configChangeTermId;
    }

    /**
    * @dev Internal to make sure to set a config for the new term, it will copy the previous term config if none
    * @param _termId Identification number of the new current term that has been transitioned
    */
    function _ensureTermConfig(uint64 _termId) internal {
        // If the term being transitioned had no config change scheduled, keep the previous one
        uint256 currentConfigId = configIdByTerm[_termId];
        if (currentConfigId == 0) {
            uint256 previousConfigId = configIdByTerm[_termId.sub(1)];
            configIdByTerm[_termId] = previousConfigId;
        }
    }

    /**
    * @dev Assumes that sender it's allowed (either it's from governor or it's on init)
    * @param _termId Identification number of the current Court term
    * @param _fromTermId Identification number of the term in which the config will be effective at
    * @param _feeToken Address of the token contract that is used to pay for fees.
    * @param _fees Array containing:
    *        0. jurorFee Amount of fee tokens that is paid per juror per dispute
    *        1. draftFee Amount of fee tokens per juror to cover the drafting cost
    *        2. settleFee Amount of fee tokens per juror to cover round settlement cost
    * @param _maxRulingOptions Max number of selectable outcomes for each dispute
    * @param _roundParams Array containing durations of phases of a dispute and other params for rounds:
    *        0. evidenceTerms Max submitting evidence period duration in terms
    *        1. commitTerms Commit period duration in terms
    *        2. revealTerms Reveal period duration in terms
    *        3. appealTerms Appeal period duration in terms
    *        4. appealConfirmationTerms Appeal confirmation period duration in terms
    *        5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *        6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *        7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *        8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @param _pcts Array containing:
    *        0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
    *        1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000)
    * @param _appealCollateralParams Array containing params for appeal collateral:
    *        0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling
    *        1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal
    * @param _jurorsParams Array containing params for juror registry:
    *        0. minActiveBalance Minimum amount of juror tokens that can be activated
    *        1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake
    *        2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake
    *        3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do
    */
    function _setConfig(
        uint64 _termId,
        uint64 _fromTermId,
        ERC20 _feeToken,
        uint256[3] memory _fees,
        uint8 _maxRulingOptions,
        uint64[9] memory _roundParams,
        uint16[2] memory _pcts,
        uint256[2] memory _appealCollateralParams,
        uint256[4] memory _jurorsParams
    )
        internal
    {
        // If the current term is not zero, changes must be scheduled at least after the current period.
        // No need to ensure delays for on-going disputes since these already use their creation term for that.
        require(_termId == 0 || _fromTermId > _termId, ERROR_TOO_OLD_TERM);

        require(_maxRulingOptions >= 2, ERROR_RULING_OPTIONS_LESS_THAN_MIN);
        // Ruling options 0, 1 and 2 are reserved for special cases.
        require(_maxRulingOptions <= uint8(-1) - 3, ERROR_RULING_OPTIONS_MORE_THAN_MAX);

        // Make sure appeal collateral factors are greater than zero
        require(_appealCollateralParams[0] > 0 && _appealCollateralParams[1] > 0, ERROR_ZERO_COLLATERAL_FACTOR);

        // Make sure the given penalty and final round reduction pcts are not greater than 100%
        require(PctHelpers.isValid(_pcts[0]), ERROR_INVALID_PENALTY_PCT);
        require(PctHelpers.isValid(_pcts[1]), ERROR_INVALID_FINAL_ROUND_REDUCTION_PCT);

        // Disputes must request at least one juror to be drafted initially
        require(_roundParams[5] > 0, ERROR_BAD_INITIAL_JURORS_NUMBER);

        // Prevent that further rounds have zero jurors
        require(_roundParams[6] > 0, ERROR_BAD_APPEAL_STEP_FACTOR);

        // Make sure the max number of appeals allowed does not reach the limit
        uint256 _maxRegularAppealRounds = _roundParams[7];
        bool isMaxAppealRoundsValid = _maxRegularAppealRounds > 0 && _maxRegularAppealRounds <= MAX_REGULAR_APPEAL_ROUNDS_LIMIT;
        require(isMaxAppealRoundsValid, ERROR_INVALID_MAX_APPEAL_ROUNDS);

        // Make sure each adjudication round phase duration is valid
        for (uint i = 0; i < 5; i++) {
            require(_roundParams[i] > 0 && _roundParams[i] < MAX_ADJ_STATE_DURATION, ERROR_LARGE_ROUND_PHASE_DURATION);
        }

        // Make sure min active balance is not zero
        require(_jurorsParams[0] > 0, ERROR_ZERO_MIN_ACTIVE_BALANCE);
        // Make sure min max pct of total supply active balance is not zero
        require(_jurorsParams[1] > 0, ERROR_MIN_MAX_TOTAL_SUPPLY_ZERO);
        // Make sure the max max pct of total supply active balance is less than 100%
        require(PctHelpers.isValidHighPrecision(_jurorsParams[2]), ERROR_INVALID_MAX_MAX_TOTAL_SUPPLY_PCT);
        // Make sure min max pct of total supply active balance is less than the max max pct of total supply active balance
        require(_jurorsParams[1] < _jurorsParams[2], ERROR_MIN_MORE_THAN_MAX_ACTIVE_PCT);

        // If there was a config change already scheduled, reset it (in that case we will overwrite last array item).
        // Otherwise, schedule a new config.
        if (configChangeTermId > _termId) {
            configIdByTerm[configChangeTermId] = 0;
        } else {
            configs.length++;
        }

        uint64 courtConfigId = uint64(configs.length - 1);
        Config storage config = configs[courtConfigId];

        config.fees = FeesConfig({
            token: _feeToken,
            jurorFee: _fees[0],
            draftFee: _fees[1],
            settleFee: _fees[2],
            finalRoundReduction: _pcts[1]
        });

        config.disputes = DisputesConfig({
            maxRulingOptions: _maxRulingOptions,
            evidenceTerms: _roundParams[0],
            commitTerms: _roundParams[1],
            revealTerms: _roundParams[2],
            appealTerms: _roundParams[3],
            appealConfirmTerms: _roundParams[4],
            penaltyPct: _pcts[0],
            firstRoundJurorsNumber: _roundParams[5],
            appealStepFactor: _roundParams[6],
            maxRegularAppealRounds: _maxRegularAppealRounds,
            finalRoundLockTerms: _roundParams[8],
            appealCollateralFactor: _appealCollateralParams[0],
            appealConfirmCollateralFactor: _appealCollateralParams[1]
        });

        config.jurors = JurorsConfig({
            minActiveBalance: _jurorsParams[0],
            minMaxPctTotalSupply: _jurorsParams[1],
            maxMaxPctTotalSupply: _jurorsParams[2],
            feeTokenTotalSupply: _jurorsParams[3]
        });

        configIdByTerm[_fromTermId] = courtConfigId;
        configChangeTermId = _fromTermId;

        emit NewConfig(_fromTermId, courtConfigId);
    }

    /**
    * @dev Internal function to get the Court config for a given term
    * @param _termId Identification number of the term querying the Court config of
    * @param _lastEnsuredTermId Identification number of the last ensured term of the Court
    * @return token Address of the token used to pay for fees
    * @return fees Array containing:
    *         0. jurorFee Amount of fee tokens that is paid per juror per dispute
    *         1. draftFee Amount of fee tokens per juror to cover the drafting cost
    *         2. settleFee Amount of fee tokens per juror to cover round settlement cost
    * @return maxRulingOptions Max number of selectable outcomes for each dispute
    * @return roundParams Array containing durations of phases of a dispute and other params for rounds:
    *         0. evidenceTerms Max submitting evidence period duration in terms
    *         1. commitTerms Commit period duration in terms
    *         2. revealTerms Reveal period duration in terms
    *         3. appealTerms Appeal period duration in terms
    *         4. appealConfirmationTerms Appeal confirmation period duration in terms
    *         5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *         6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *         7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *         8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @return pcts Array containing:
    *         0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
    *         1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000)
    * @return appealCollateralParams Array containing params for appeal collateral:
    *         0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling
    *         1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal
    * @return jurorsParams Array containing params for juror registry:
    *         0. minActiveBalance Minimum amount of juror tokens that can be activated
    *         1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake
    *         2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake
    *         3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do
    */
    function _getConfigAt(uint64 _termId, uint64 _lastEnsuredTermId) internal view
        returns (
            ERC20 feeToken,
            uint256[3] memory fees,
            uint8 maxRulingOptions,
            uint64[9] memory roundParams,
            uint16[2] memory pcts,
            uint256[2] memory appealCollateralParams,
            uint256[4] memory jurorsParams
        )
    {
        Config storage config = _getConfigFor(_termId, _lastEnsuredTermId);

        FeesConfig storage feesConfig = config.fees;
        feeToken = feesConfig.token;
        fees = [feesConfig.jurorFee, feesConfig.draftFee, feesConfig.settleFee];

        DisputesConfig storage disputesConfig = config.disputes;
        maxRulingOptions = disputesConfig.maxRulingOptions;
        roundParams = [
            disputesConfig.evidenceTerms,
            disputesConfig.commitTerms,
            disputesConfig.revealTerms,
            disputesConfig.appealTerms,
            disputesConfig.appealConfirmTerms,
            disputesConfig.firstRoundJurorsNumber,
            disputesConfig.appealStepFactor,
            uint64(disputesConfig.maxRegularAppealRounds),
            disputesConfig.finalRoundLockTerms
        ];
        pcts = [disputesConfig.penaltyPct, feesConfig.finalRoundReduction];
        appealCollateralParams = [disputesConfig.appealCollateralFactor, disputesConfig.appealConfirmCollateralFactor];

        JurorsConfig storage jurorsConfig = config.jurors;
        jurorsParams = [
            jurorsConfig.minActiveBalance,
            jurorsConfig.minMaxPctTotalSupply,
            jurorsConfig.maxMaxPctTotalSupply,
            jurorsConfig.feeTokenTotalSupply
        ];
    }

    /**
    * @dev Tell the draft config at a certain term
    * @param _termId Identification number of the term querying the draft config of
    * @param _lastEnsuredTermId Identification number of the last ensured term of the Court
    * @return feeToken Address of the token used to pay for fees
    * @return draftFee Amount of fee tokens per juror to cover the drafting cost
    * @return penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
    */
    function _getDraftConfig(uint64 _termId,  uint64 _lastEnsuredTermId) internal view
        returns (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct)
    {
        Config storage config = _getConfigFor(_termId, _lastEnsuredTermId);
        return (config.fees.token, config.fees.draftFee, config.disputes.penaltyPct);
    }

    /**
    * @dev Internal function to get the min active balance config for a given term
    * @param _termId Identification number of the term querying the min active balance config of
    * @param _lastEnsuredTermId Identification number of the last ensured term of the Court
    * @return Minimum amount of juror tokens that can be activated at the given term
    */
    function _getMinActiveBalance(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns (uint256) {
        Config storage config = _getConfigFor(_termId, _lastEnsuredTermId);
        return config.jurors.minActiveBalance;
    }

    /**
    * @dev Internal function to get the Court config for a given term
    * @param _termId Identification number of the term querying the min active balance config of
    * @param _lastEnsuredTermId Identification number of the last ensured term of the Court
    * @return Court config for the given term
    */
    function _getConfigFor(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns (Config storage) {
        uint256 id = _getConfigIdFor(_termId, _lastEnsuredTermId);
        return configs[id];
    }

    /**
    * @dev Internal function to get the Court config ID for a given term
    * @param _termId Identification number of the term querying the Court config of
    * @param _lastEnsuredTermId Identification number of the last ensured term of the Court
    * @return Identification number of the config for the given terms
    */
    function _getConfigIdFor(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns (uint256) {
        // If the given term is lower or equal to the last ensured Court term, it is safe to use a past Court config
        if (_termId <= _lastEnsuredTermId) {
            return configIdByTerm[_termId];
        }

        // If the given term is in the future but there is a config change scheduled before it, use the incoming config
        uint64 scheduledChangeTermId = configChangeTermId;
        if (scheduledChangeTermId <= _termId) {
            return configIdByTerm[scheduledChangeTermId];
        }

        // If no changes are scheduled, use the Court config of the last ensured term
        return configIdByTerm[_lastEnsuredTermId];
    }
}

// File: contracts/court/controller/Controller.sol

pragma solidity ^0.5.8;





contract Controller is IsContract, CourtClock, CourtConfig {
    string private constant ERROR_SENDER_NOT_GOVERNOR = "CTR_SENDER_NOT_GOVERNOR";
    string private constant ERROR_INVALID_GOVERNOR_ADDRESS = "CTR_INVALID_GOVERNOR_ADDRESS";
    string private constant ERROR_IMPLEMENTATION_NOT_CONTRACT = "CTR_IMPLEMENTATION_NOT_CONTRACT";
    string private constant ERROR_INVALID_IMPLS_INPUT_LENGTH = "CTR_INVALID_IMPLS_INPUT_LENGTH";

    address private constant ZERO_ADDRESS = address(0);

    // DisputeManager module ID - keccak256(abi.encodePacked("DISPUTE_MANAGER"))
    bytes32 internal constant DISPUTE_MANAGER = 0x14a6c70f0f6d449c014c7bbc9e68e31e79e8474fb03b7194df83109a2d888ae6;

    // Treasury module ID - keccak256(abi.encodePacked("TREASURY"))
    bytes32 internal constant TREASURY = 0x06aa03964db1f7257357ef09714a5f0ca3633723df419e97015e0c7a3e83edb7;

    // Voting module ID - keccak256(abi.encodePacked("VOTING"))
    bytes32 internal constant VOTING = 0x7cbb12e82a6d63ff16fe43977f43e3e2b247ecd4e62c0e340da8800a48c67346;

    // JurorsRegistry module ID - keccak256(abi.encodePacked("JURORS_REGISTRY"))
    bytes32 internal constant JURORS_REGISTRY = 0x3b21d36b36308c830e6c4053fb40a3b6d79dde78947fbf6b0accd30720ab5370;

    // Subscriptions module ID - keccak256(abi.encodePacked("SUBSCRIPTIONS"))
    bytes32 internal constant SUBSCRIPTIONS = 0x2bfa3327fe52344390da94c32a346eeb1b65a8b583e4335a419b9471e88c1365;

    // BrightIDRegister module ID - keccak256(abi.encodePacked("BRIGHTID_REGISTER"))
    bytes32 internal constant BRIGHTID_REGISTER = 0xc8d8a5444a51ecc23e5091f18c4162834512a4bc5cae72c637db45c8c37b3329;

    /**
    * @dev Governor of the whole system. Set of three addresses to recover funds, change configuration settings and setup modules
    */
    struct Governor {
        address funds;      // This address can be unset at any time. It is allowed to recover funds from the ControlledRecoverable modules
        address config;     // This address is meant not to be unset. It is allowed to change the different configurations of the whole system
        address feesUpdater;// This is a second address that can update the config. It is expected to be used with a price oracle for updating fees
        address modules;    // This address can be unset at any time. It is allowed to plug/unplug modules from the system
    }

    // Governor addresses of the system
    Governor private governor;

    // List of modules registered for the system indexed by ID
    mapping (bytes32 => address) internal modules;

    event ModuleSet(bytes32 id, address addr);
    event FundsGovernorChanged(address previousGovernor, address currentGovernor);
    event ConfigGovernorChanged(address previousGovernor, address currentGovernor);
    event FeesUpdaterChanged(address previousFeesUpdater, address currentFeesUpdater);
    event ModulesGovernorChanged(address previousGovernor, address currentGovernor);

    /**
    * @dev Ensure the msg.sender is the funds governor
    */
    modifier onlyFundsGovernor {
        require(msg.sender == governor.funds, ERROR_SENDER_NOT_GOVERNOR);
        _;
    }

    /**
    * @dev Ensure the msg.sender is the config governor
    */
    modifier onlyConfigGovernor {
        require(msg.sender == governor.config, ERROR_SENDER_NOT_GOVERNOR);
        _;
    }

    /**
    * @dev Ensure the msg.sender is the config governor or the fees updater
    */
    modifier onlyConfigGovernorOrFeesUpdater {
        require(msg.sender == governor.config || msg.sender == governor.feesUpdater, ERROR_SENDER_NOT_GOVERNOR);
        _;
    }

    /**
    * @dev Ensure the msg.sender is the modules governor
    */
    modifier onlyModulesGovernor {
        require(msg.sender == governor.modules, ERROR_SENDER_NOT_GOVERNOR);
        _;
    }

    /**
    * @dev Constructor function
    * @param _termParams Array containing:
    *        0. _termDuration Duration in seconds per term
    *        1. _firstTermStartTime Timestamp in seconds when the court will open (to give time for juror on-boarding)
    * @param _governors Array containing:
    *        0. _fundsGovernor Address of the funds governor
    *        1. _configGovernor Address of the config governor
    *        2. _feesUpdater Address of the price feesUpdater
    *        3. _modulesGovernor Address of the modules governor
    * @param _feeToken Address of the token contract that is used to pay for fees
    * @param _fees Array containing:
    *        0. jurorFee Amount of fee tokens that is paid per juror per dispute
    *        1. draftFee Amount of fee tokens per juror to cover the drafting cost
    *        2. settleFee Amount of fee tokens per juror to cover round settlement cost
    * @param _maxRulingOptions Max number of selectable outcomes for each dispute
    * @param _roundParams Array containing durations of phases of a dispute and other params for rounds:
    *        0. evidenceTerms Max submitting evidence period duration in terms
    *        1. commitTerms Commit period duration in terms
    *        2. revealTerms Reveal period duration in terms
    *        3. appealTerms Appeal period duration in terms
    *        4. appealConfirmationTerms Appeal confirmation period duration in terms
    *        5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *        6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *        7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *        8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @param _pcts Array containing:
    *        0. penaltyPct Permyriad of min active tokens balance to be locked to each drafted jurors (‱ - 1/10,000)
    *        1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000)
    * @param _appealCollateralParams Array containing params for appeal collateral:
    *        0. appealCollateralFactor Permyriad multiple of dispute fees required to appeal a preliminary ruling
    *        1. appealConfirmCollateralFactor Permyriad multiple of dispute fees required to confirm appeal
    * @param _jurorsParams Array containing params for jurors:
    *        0. minActiveBalance Minimum amount of juror tokens that can be activated
    *        1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake
    *        2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake
    *        3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do
    */
    constructor(
        uint64[2] memory _termParams,
        address[4] memory _governors,
        ERC20 _feeToken,
        uint256[3] memory _fees,
        uint8 _maxRulingOptions,
        uint64[9] memory _roundParams,
        uint16[2] memory _pcts,
        uint256[2] memory _appealCollateralParams,
        uint256[4] memory _jurorsParams
    )
        public
        CourtClock(_termParams, _feeToken)
        CourtConfig(_feeToken, _fees, _maxRulingOptions, _roundParams, _pcts, _appealCollateralParams, _jurorsParams)
    {
        _setFundsGovernor(_governors[0]);
        _setConfigGovernor(_governors[1]);
        _setFeesUpdater(_governors[2]);
        _setModulesGovernor(_governors[3]);
    }

    /**
    * @notice Change Court configuration params
    * @param _fromTermId Identification number of the term in which the config will be effective at
    * @param _feeToken Address of the token contract that is used to pay for fees
    * @param _fees Array containing:
    *        0. jurorFee Amount of fee tokens that is paid per juror per dispute
    *        1. draftFee Amount of fee tokens per juror to cover the drafting cost
    *        2. settleFee Amount of fee tokens per juror to cover round settlement cost
    * @param _maxRulingOptions Max number of selectable outcomes for each dispute
    * @param _roundParams Array containing durations of phases of a dispute and other params for rounds:
    *        0. evidenceTerms Max submitting evidence period duration in terms
    *        1. commitTerms Commit period duration in terms
    *        2. revealTerms Reveal period duration in terms
    *        3. appealTerms Appeal period duration in terms
    *        4. appealConfirmationTerms Appeal confirmation period duration in terms
    *        5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *        6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *        7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *        8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @param _pcts Array containing:
    *        0. penaltyPct Permyriad of min active tokens balance to be locked to each drafted jurors (‱ - 1/10,000)
    *        1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000)
    * @param _appealCollateralParams Array containing params for appeal collateral:
    *        0. appealCollateralFactor Permyriad multiple of dispute fees required to appeal a preliminary ruling
    *        1. appealConfirmCollateralFactor Permyriad multiple of dispute fees required to confirm appeal
    * @param _jurorsParams Array containing params for jurors:
    *        0. minActiveBalance Minimum amount of juror tokens that can be activated
    *        1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake
    *        2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake
    *        3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do
    */
    function setConfig(
        uint64 _fromTermId,
        ERC20 _feeToken,
        uint256[3] calldata _fees,
        uint8 _maxRulingOptions,
        uint64[9] calldata _roundParams,
        uint16[2] calldata _pcts,
        uint256[2] calldata _appealCollateralParams,
        uint256[4] calldata _jurorsParams
    )
        external
        onlyConfigGovernorOrFeesUpdater
    {
        uint64 currentTermId = _ensureCurrentTerm();
        _setConfig(
            currentTermId,
            _fromTermId,
            _feeToken,
            _fees,
            _maxRulingOptions,
            _roundParams,
            _pcts,
            _appealCollateralParams,
            _jurorsParams
        );
    }

    /**
    * @notice Delay the Court start time to `_newFirstTermStartTime`
    * @param _newFirstTermStartTime New timestamp in seconds when the court will open
    */
    function delayStartTime(uint64 _newFirstTermStartTime) external onlyConfigGovernor {
        _delayStartTime(_newFirstTermStartTime);
    }

    /**
    * @notice Change funds governor address to `_newFundsGovernor`
    * @param _newFundsGovernor Address of the new funds governor to be set
    */
    function changeFundsGovernor(address _newFundsGovernor) external onlyFundsGovernor {
        require(_newFundsGovernor != ZERO_ADDRESS, ERROR_INVALID_GOVERNOR_ADDRESS);
        _setFundsGovernor(_newFundsGovernor);
    }

    /**
    * @notice Change config governor address to `_newConfigGovernor`
    * @param _newConfigGovernor Address of the new config governor to be set
    */
    function changeConfigGovernor(address _newConfigGovernor) external onlyConfigGovernor {
        require(_newConfigGovernor != ZERO_ADDRESS, ERROR_INVALID_GOVERNOR_ADDRESS);
        _setConfigGovernor(_newConfigGovernor);
    }

    /**
    * @notice Change fees updater to `_newFeesUpdater`
    * @param _newFeesUpdater Address of the new fees updater to be set
    */
    function changeFeesUpdater(address _newFeesUpdater) external onlyConfigGovernor {
        _setFeesUpdater(_newFeesUpdater);
    }

    /**
    * @notice Change modules governor address to `_newModulesGovernor`
    * @param _newModulesGovernor Address of the new governor to be set
    */
    function changeModulesGovernor(address _newModulesGovernor) external onlyModulesGovernor {
        require(_newModulesGovernor != ZERO_ADDRESS, ERROR_INVALID_GOVERNOR_ADDRESS);
        _setModulesGovernor(_newModulesGovernor);
    }

    /**
    * @notice Remove the funds governor. Set the funds governor to the zero address.
    * @dev This action cannot be rolled back, once the funds governor has been unset, funds cannot be recovered from recoverable modules anymore
    */
    function ejectFundsGovernor() external onlyFundsGovernor {
        _setFundsGovernor(ZERO_ADDRESS);
    }

    /**
    * @notice Remove the modules governor. Set the modules governor to the zero address.
    * @dev This action cannot be rolled back, once the modules governor has been unset, system modules cannot be changed anymore
    */
    function ejectModulesGovernor() external onlyModulesGovernor {
        _setModulesGovernor(ZERO_ADDRESS);
    }

    /**
    * @notice Set module `_id` to `_addr`
    * @param _id ID of the module to be set
    * @param _addr Address of the module to be set
    */
    function setModule(bytes32 _id, address _addr) external onlyModulesGovernor {
        _setModule(_id, _addr);
    }

    /**
    * @notice Set many modules at once
    * @param _ids List of ids of each module to be set
    * @param _addresses List of addressed of each the module to be set
    */
    function setModules(bytes32[] calldata _ids, address[] calldata _addresses) external onlyModulesGovernor {
        require(_ids.length == _addresses.length, ERROR_INVALID_IMPLS_INPUT_LENGTH);

        for (uint256 i = 0; i < _ids.length; i++) {
            _setModule(_ids[i], _addresses[i]);
        }
    }

    /**
    * @dev Tell the full Court configuration parameters at a certain term
    * @param _termId Identification number of the term querying the Court config of
    * @return token Address of the token used to pay for fees
    * @return fees Array containing:
    *         0. jurorFee Amount of fee tokens that is paid per juror per dispute
    *         1. draftFee Amount of fee tokens per juror to cover the drafting cost
    *         2. settleFee Amount of fee tokens per juror to cover round settlement cost
    * @return maxRulingOptions Max number of selectable outcomes for each dispute
    * @return roundParams Array containing durations of phases of a dispute and other params for rounds:
    *         0. evidenceTerms Max submitting evidence period duration in terms
    *         1. commitTerms Commit period duration in terms
    *         2. revealTerms Reveal period duration in terms
    *         3. appealTerms Appeal period duration in terms
    *         4. appealConfirmationTerms Appeal confirmation period duration in terms
    *         5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *         6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *         7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *         8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @return pcts Array containing:
    *         0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
    *         1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000)
    * @return appealCollateralParams Array containing params for appeal collateral:
    *         0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling
    *         1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal
    * @return jurorsParams Array containing params for juror registry:
    *         0. minActiveBalance Minimum amount of juror tokens that can be activated
    *         1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake
    *         2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake\
    *         3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do
    */
    function getConfig(uint64 _termId) external view
        returns (
            ERC20 feeToken,
            uint256[3] memory fees,
            uint8 maxRulingOptions,
            uint64[9] memory roundParams,
            uint16[2] memory pcts,
            uint256[2] memory appealCollateralParams,
            uint256[4] memory jurorsParams
        )
    {
        return _getConfig(_termId);
    }

    /**
    * @dev This function overrides one in the CourtClock, giving the CourtClock access to the config.
    */
    function _getConfig(uint64 _termId) internal view
        returns (
            ERC20 feeToken,
            uint256[3] memory fees,
            uint8 maxRulingOptions,
            uint64[9] memory roundParams,
            uint16[2] memory pcts,
            uint256[2] memory appealCollateralParams,
            uint256[4] memory jurorsParams
        )
    {
        uint64 lastEnsuredTermId = _lastEnsuredTermId();
        return _getConfigAt(_termId, lastEnsuredTermId);
    }

    /**
    * @dev Tell the draft config at a certain term
    * @param _termId Identification number of the term querying the draft config of
    * @return feeToken Address of the token used to pay for fees
    * @return draftFee Amount of fee tokens per juror to cover the drafting cost
    * @return penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000)
    */
    function getDraftConfig(uint64 _termId) external view returns (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct) {
        uint64 lastEnsuredTermId = _lastEnsuredTermId();
        return _getDraftConfig(_termId, lastEnsuredTermId);
    }

    /**
    * @dev Tell the min active balance config at a certain term
    * @param _termId Identification number of the term querying the min active balance config of
    * @return Minimum amount of tokens jurors have to activate to participate in the Court
    */
    function getMinActiveBalance(uint64 _termId) external view returns (uint256) {
        uint64 lastEnsuredTermId = _lastEnsuredTermId();
        return _getMinActiveBalance(_termId, lastEnsuredTermId);
    }

    /**
    * @dev Tell the address of the funds governor
    * @return Address of the funds governor
    */
    function getFundsGovernor() external view returns (address) {
        return governor.funds;
    }

    /**
    * @dev Tell the address of the config governor
    * @return Address of the config governor
    */
    function getConfigGovernor() external view returns (address) {
        return governor.config;
    }

    /**
    * @dev Tell the address of the fees updater
    * @return Address of the fees updater
    */
    function getFeesUpdater() external view returns (address) {
        return governor.feesUpdater;
    }

    /**
    * @dev Tell the address of the modules governor
    * @return Address of the modules governor
    */
    function getModulesGovernor() external view returns (address) {
        return governor.modules;
    }

    /**
    * @dev Tell address of a module based on a given ID
    * @param _id ID of the module being queried
    * @return Address of the requested module
    */
    function getModule(bytes32 _id) external view returns (address) {
        return _getModule(_id);
    }

    /**
    * @dev Tell the address of the DisputeManager module
    * @return Address of the DisputeManager module
    */
    function getDisputeManager() external view returns (address) {
        return _getDisputeManager();
    }

    /**
    * @dev Tell the address of the Treasury module
    * @return Address of the Treasury module
    */
    function getTreasury() external view returns (address) {
        return _getModule(TREASURY);
    }

    /**
    * @dev Tell the address of the Voting module
    * @return Address of the Voting module
    */
    function getVoting() external view returns (address) {
        return _getModule(VOTING);
    }

    /**
    * @dev Tell the address of the JurorsRegistry module
    * @return Address of the JurorsRegistry module
    */
    function getJurorsRegistry() external view returns (address) {
        return _getModule(JURORS_REGISTRY);
    }

    /**
    * @dev Tell the address of the Subscriptions module
    * @return Address of the Subscriptions module
    */
    function getSubscriptions() external view returns (address) {
        return _getSubscriptions();
    }

    /**
    * @dev Tell the address of the BrightId register
    * @return Address of the BrightId register
    */
    function getBrightIdRegister() external view returns (address) {
        return _getBrightIdRegister();
    }

    /**
    * @dev Internal function to set the address of the funds governor
    * @param _newFundsGovernor Address of the new config governor to be set
    */
    function _setFundsGovernor(address _newFundsGovernor) internal {
        emit FundsGovernorChanged(governor.funds, _newFundsGovernor);
        governor.funds = _newFundsGovernor;
    }

    /**
    * @dev Internal function to set the address of the config governor
    * @param _newConfigGovernor Address of the new config governor to be set
    */
    function _setConfigGovernor(address _newConfigGovernor) internal {
        emit ConfigGovernorChanged(governor.config, _newConfigGovernor);
        governor.config = _newConfigGovernor;
    }

    /**
    * @dev Internal function to set the address of the fees updater
    * @param _newFeesUpdater Address of the new fees updater to be set
    */
    function _setFeesUpdater(address _newFeesUpdater) internal {
        emit FeesUpdaterChanged(governor.feesUpdater, _newFeesUpdater);
        governor.feesUpdater = _newFeesUpdater;
    }

    /**
    * @dev Internal function to set the address of the modules governor
    * @param _newModulesGovernor Address of the new modules governor to be set
    */
    function _setModulesGovernor(address _newModulesGovernor) internal {
        emit ModulesGovernorChanged(governor.modules, _newModulesGovernor);
        governor.modules = _newModulesGovernor;
    }

    /**
    * @dev Internal function to set a module
    * @param _id Id of the module to be set
    * @param _addr Address of the module to be set
    */
    function _setModule(bytes32 _id, address _addr) internal {
        require(isContract(_addr), ERROR_IMPLEMENTATION_NOT_CONTRACT);
        modules[_id] = _addr;
        emit ModuleSet(_id, _addr);
    }

    /**
    * @dev Internal function to notify when a term has been transitioned
    * @param _termId Identification number of the new current term that has been transitioned
    */
    function _onTermTransitioned(uint64 _termId) internal {
        _ensureTermConfig(_termId);
    }

    /**
    * @dev Internal function to tell the address of the DisputeManager module
    * @return Address of the DisputeManager module
    */
    function _getDisputeManager() internal view returns (address) {
        return _getModule(DISPUTE_MANAGER);
    }

    /**
    * @dev Internal function to tell the address of the Subscriptions module
    * @return Address of the Subscriptions module
    */
    function _getSubscriptions() internal view returns (address) {
        return _getModule(SUBSCRIPTIONS);
    }


    /**
    * @dev Internal function to tell the address of the BrightId register
    * @return Address of the BrightId register
    */
    function _getBrightIdRegister() internal view returns (address) {
        return _getModule(BRIGHTID_REGISTER);
    }

    /**
    * @dev Internal function to tell address of a module based on a given ID
    * @param _id ID of the module being queried
    * @return Address of the requested module
    */
    function _getModule(bytes32 _id) internal view returns (address) {
        return modules[_id];
    }
}

// File: contracts/court/config/ConfigConsumer.sol

pragma solidity ^0.5.8;





contract ConfigConsumer is CourtConfigData {
    /**
    * @dev Internal function to fetch the address of the Config module from the controller
    * @return Address of the Config module
    */
    function _courtConfig() internal view returns (IConfig);

    /**
    * @dev Internal function to get the Court config for a certain term
    * @param _termId Identification number of the term querying the Court config of
    * @return Court config for the given term
    */
    function _getConfigAt(uint64 _termId) internal view returns (Config memory) {
        (ERC20 _feeToken,
        uint256[3] memory _fees,
        uint8 maxRulingOptions,
        uint64[9] memory _roundParams,
        uint16[2] memory _pcts,
        uint256[2] memory _appealCollateralParams,
        uint256[4] memory _jurorsParams) = _courtConfig().getConfig(_termId);

        Config memory config;

        config.fees = FeesConfig({
            token: _feeToken,
            jurorFee: _fees[0],
            draftFee: _fees[1],
            settleFee: _fees[2],
            finalRoundReduction: _pcts[1]
        });

        config.disputes = DisputesConfig({
            maxRulingOptions: maxRulingOptions,
            evidenceTerms: _roundParams[0],
            commitTerms: _roundParams[1],
            revealTerms: _roundParams[2],
            appealTerms: _roundParams[3],
            appealConfirmTerms: _roundParams[4],
            penaltyPct: _pcts[0],
            firstRoundJurorsNumber: _roundParams[5],
            appealStepFactor: _roundParams[6],
            maxRegularAppealRounds: _roundParams[7],
            finalRoundLockTerms: _roundParams[8],
            appealCollateralFactor: _appealCollateralParams[0],
            appealConfirmCollateralFactor: _appealCollateralParams[1]
        });

        config.jurors = JurorsConfig({
            minActiveBalance: _jurorsParams[0],
            minMaxPctTotalSupply: _jurorsParams[1],
            maxMaxPctTotalSupply: _jurorsParams[2],
            feeTokenTotalSupply: _jurorsParams[3]
        });

        return config;
    }

    /**
    * @dev Internal function to get the draft config for a given term
    * @param _termId Identification number of the term querying the draft config of
    * @return Draft config for the given term
    */
    function _getDraftConfig(uint64 _termId) internal view returns (DraftConfig memory) {
        (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct) = _courtConfig().getDraftConfig(_termId);
        return DraftConfig({ feeToken: feeToken, draftFee: draftFee, penaltyPct: penaltyPct });
    }

    /**
    * @dev Internal function to get the min active balance config for a given term
    * @param _termId Identification number of the term querying the min active balance config of
    * @return Minimum amount of juror tokens that can be activated
    */
    function _getMinActiveBalance(uint64 _termId) internal view returns (uint256) {
        return _courtConfig().getMinActiveBalance(_termId);
    }
}

// File: contracts/brightid/IBrightIdRegister.sol

pragma solidity ^0.5.8;

contract IBrightIdRegister {
    function isVerified(address _brightIdUser) external view returns (bool);
    function hasUniqueUserId(address _brightIdUser) external view returns (bool);
    function uniqueUserId(address _brightIdUser) external view returns (address);
}

// File: contracts/court/controller/Controlled.sol

pragma solidity ^0.5.8;










contract Controlled is IsContract, ConfigConsumer {
    string private constant ERROR_CONTROLLER_NOT_CONTRACT = "CTD_CONTROLLER_NOT_CONTRACT";
    string private constant ERROR_SENDER_NOT_CONTROLLER = "CTD_SENDER_NOT_CONTROLLER";
    string private constant ERROR_SENDER_NOT_CONFIG_GOVERNOR = "CTD_SENDER_NOT_CONFIG_GOVERNOR";
    string private constant ERROR_SENDER_NOT_DISPUTES_MODULE = "CTD_SENDER_NOT_DISPUTES_MODULE";

    // Address of the controller
    Controller internal controller;

    /**
    * @dev Ensure the msg.sender is the controller's config governor
    */
    modifier onlyConfigGovernor {
        require(msg.sender == _configGovernor(), ERROR_SENDER_NOT_CONFIG_GOVERNOR);
        _;
    }

    /**
    * @dev Ensure the msg.sender is the controller
    */
    modifier onlyController() {
        require(msg.sender == address(controller), ERROR_SENDER_NOT_CONTROLLER);
        _;
    }

    /**
    * @dev Ensure the msg.sender is the DisputeManager module
    */
    modifier onlyDisputeManager() {
        require(msg.sender == address(_disputeManager()), ERROR_SENDER_NOT_DISPUTES_MODULE);
        _;
    }

    /**
    * @dev Constructor function
    * @param _controller Address of the controller
    */
    constructor(Controller _controller) public {
        require(isContract(address(_controller)), ERROR_CONTROLLER_NOT_CONTRACT);
        controller = _controller;
    }

    /**
    * @dev Tell the address of the controller
    * @return Address of the controller
    */
    function getController() external view returns (Controller) {
        return controller;
    }

    /**
    * @dev Internal function to ensure the Court term is up-to-date, it will try to update it if not
    * @return Identification number of the current Court term
    */
    function _ensureCurrentTerm() internal returns (uint64) {
        return _clock().ensureCurrentTerm();
    }

    /**
    * @dev Internal function to fetch the last ensured term ID of the Court
    * @return Identification number of the last ensured term
    */
    function _getLastEnsuredTermId() internal view returns (uint64) {
        return _clock().getLastEnsuredTermId();
    }

    /**
    * @dev Internal function to tell the current term identification number
    * @return Identification number of the current term
    */
    function _getCurrentTermId() internal view returns (uint64) {
        return _clock().getCurrentTermId();
    }

    /**
    * @dev Internal function to fetch the controller's config governor
    * @return Address of the controller's governor
    */
    function _configGovernor() internal view returns (address) {
        return controller.getConfigGovernor();
    }

    /**
    * @dev Internal function to fetch the address of the DisputeManager module from the controller
    * @return Address of the DisputeManager module
    */
    function _disputeManager() internal view returns (IDisputeManager) {
        return IDisputeManager(controller.getDisputeManager());
    }

    /**
    * @dev Internal function to fetch the address of the Treasury module implementation from the controller
    * @return Address of the Treasury module implementation
    */
    function _treasury() internal view returns (ITreasury) {
        return ITreasury(controller.getTreasury());
    }

    /**
    * @dev Internal function to fetch the address of the Voting module implementation from the controller
    * @return Address of the Voting module implementation
    */
    function _voting() internal view returns (ICRVoting) {
        return ICRVoting(controller.getVoting());
    }

    /**
    * @dev Internal function to fetch the address of the Voting module owner from the controller
    * @return Address of the Voting module owner
    */
    function _votingOwner() internal view returns (ICRVotingOwner) {
        return ICRVotingOwner(address(_disputeManager()));
    }

    /**
    * @dev Internal function to fetch the address of the JurorRegistry module implementation from the controller
    * @return Address of the JurorRegistry module implementation
    */
    function _jurorsRegistry() internal view returns (IJurorsRegistry) {
        return IJurorsRegistry(controller.getJurorsRegistry());
    }

    /**
    * @dev Internal function to fetch the address of the BrightId register implementation from the controller
    * @return Address of the BrightId register implementation
    */
    function _brightIdRegister() internal view returns (IBrightIdRegister) {
        return IBrightIdRegister(controller.getBrightIdRegister());
    }

    /**
    * @dev Internal function to fetch the address of the Clock module from the controller
    * @return Address of the Clock module
    */
    function _clock() internal view returns (IClock) {
        return IClock(controller);
    }

    /**
    * @dev Internal function to fetch the address of the Config module from the controller
    * @return Address of the Config module
    */
    function _courtConfig() internal view returns (IConfig) {
        return IConfig(controller);
    }
}

// File: contracts/court/controller/ControlledRecoverable.sol

pragma solidity ^0.5.8;





contract ControlledRecoverable is Controlled {
    using SafeERC20 for ERC20;

    string private constant ERROR_SENDER_NOT_FUNDS_GOVERNOR = "CTD_SENDER_NOT_FUNDS_GOVERNOR";
    string private constant ERROR_INSUFFICIENT_RECOVER_FUNDS = "CTD_INSUFFICIENT_RECOVER_FUNDS";
    string private constant ERROR_RECOVER_TOKEN_FUNDS_FAILED = "CTD_RECOVER_TOKEN_FUNDS_FAILED";

    event RecoverFunds(ERC20 token, address recipient, uint256 balance);

    /**
    * @dev Ensure the msg.sender is the controller's funds governor
    */
    modifier onlyFundsGovernor {
        require(msg.sender == controller.getFundsGovernor(), ERROR_SENDER_NOT_FUNDS_GOVERNOR);
        _;
    }

    /**
    * @dev Constructor function
    * @param _controller Address of the controller
    */
    constructor(Controller _controller) Controlled(_controller) public {
        // solium-disable-previous-line no-empty-blocks
    }

    /**
    * @notice Transfer all `_token` tokens to `_to`
    * @param _token ERC20 token to be recovered
    * @param _to Address of the recipient that will be receive all the funds of the requested token
    */
    function recoverFunds(ERC20 _token, address _to) external onlyFundsGovernor {
        uint256 balance = _token.balanceOf(address(this));
        require(balance > 0, ERROR_INSUFFICIENT_RECOVER_FUNDS);
        require(_token.safeTransfer(_to, balance), ERROR_RECOVER_TOKEN_FUNDS_FAILED);
        emit RecoverFunds(_token, _to, balance);
    }
}

// File: contracts/disputes/DisputeManager.sol

pragma solidity ^0.5.8;















contract DisputeManager is ControlledRecoverable, ICRVotingOwner, IDisputeManager {
    using SafeERC20 for ERC20;
    using SafeMath for uint256;
    using SafeMath64 for uint64;
    using PctHelpers for uint256;
    using Uint256Helpers for uint256;

    // Voting-related error messages
    string private constant ERROR_VOTER_WEIGHT_ZERO = "DM_VOTER_WEIGHT_ZERO";
    string private constant ERROR_SENDER_NOT_VOTING = "DM_SENDER_NOT_VOTING";

    // Disputes-related error messages
    string private constant ERROR_SUBJECT_NOT_DISPUTE_SUBJECT = "DM_SUBJECT_NOT_DISPUTE_SUBJECT";
    string private constant ERROR_EVIDENCE_PERIOD_IS_CLOSED = "DM_EVIDENCE_PERIOD_IS_CLOSED";
    string private constant ERROR_TERM_OUTDATED = "DM_TERM_OUTDATED";
    string private constant ERROR_DISPUTE_DOES_NOT_EXIST = "DM_DISPUTE_DOES_NOT_EXIST";
    string private constant ERROR_INVALID_RULING_OPTIONS = "DM_INVALID_RULING_OPTIONS";
    string private constant ERROR_DEPOSIT_FAILED = "DM_DEPOSIT_FAILED";
    string private constant ERROR_BAD_MAX_DRAFT_BATCH_SIZE = "DM_BAD_MAX_DRAFT_BATCH_SIZE";

    // Rounds-related error messages
    string private constant ERROR_ROUND_IS_FINAL = "DM_ROUND_IS_FINAL";
    string private constant ERROR_ROUND_DOES_NOT_EXIST = "DM_ROUND_DOES_NOT_EXIST";
    string private constant ERROR_INVALID_ADJUDICATION_STATE = "DM_INVALID_ADJUDICATION_STATE";
    string private constant ERROR_ROUND_ALREADY_DRAFTED = "DM_ROUND_ALREADY_DRAFTED";
    string private constant ERROR_DRAFT_TERM_NOT_REACHED = "DM_DRAFT_TERM_NOT_REACHED";
    string private constant ERROR_ROUND_NOT_APPEALED = "DM_ROUND_NOT_APPEALED";
    string private constant ERROR_INVALID_APPEAL_RULING = "DM_INVALID_APPEAL_RULING";

    // Settlements-related error messages
    string private constant ERROR_PREV_ROUND_NOT_SETTLED = "DM_PREVIOUS_ROUND_NOT_SETTLED";
    string private constant ERROR_ROUND_ALREADY_SETTLED = "DM_ROUND_ALREADY_SETTLED";
    string private constant ERROR_ROUND_NOT_SETTLED = "DM_ROUND_PENALTIES_NOT_SETTLED";
    string private constant ERROR_JUROR_ALREADY_REWARDED = "DM_JUROR_ALREADY_REWARDED";
    string private constant ERROR_WONT_REWARD_NON_VOTER_JUROR = "DM_WONT_REWARD_NON_VOTER_JUROR";
    string private constant ERROR_WONT_REWARD_INCOHERENT_JUROR = "DM_WONT_REWARD_INCOHERENT_JUROR";
    string private constant ERROR_ROUND_APPEAL_ALREADY_SETTLED = "DM_APPEAL_ALREADY_SETTLED";

    // Minimum possible rulings for a dispute
    uint8 internal constant MIN_RULING_OPTIONS = 2;

    // Precision factor used to improve rounding when computing weights for the final round
    uint256 internal constant FINAL_ROUND_WEIGHT_PRECISION = 1000;

    // Mask used to decode vote IDs
    uint256 internal constant VOTE_ID_MASK = 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    struct Dispute {
        IArbitrable subject;           // Arbitrable associated to a dispute
        uint64 createTermId;           // Term ID when the dispute was created
        uint8 possibleRulings;         // Number of possible rulings jurors can vote for each dispute
        uint8 finalRuling;             // Winning ruling of a dispute
        DisputeState state;            // State of a dispute: pre-draft, adjudicating, or ruled
        AdjudicationRound[] rounds;    // List of rounds for each dispute
    }

    struct AdjudicationRound {
        uint64 draftTermId;            // Term from which the jurors of a round can be drafted
        uint64 jurorsNumber;           // Number of jurors drafted for a round
        bool settledPenalties;         // Whether or not penalties have been settled for a round
        uint256 jurorFees;             // Total amount of fees to be distributed between the winning jurors of a round
        address[] jurors;              // List of jurors drafted for a round
        mapping (address => JurorState) jurorsStates; // List of states for each drafted juror indexed by address
        uint64 delayedTerms;           // Number of terms a round was delayed based on its requested draft term id
        uint64 selectedJurors;         // Number of jurors selected for a round, to allow drafts to be batched
        uint64 coherentJurors;         // Number of drafted jurors that voted in favor of the dispute final ruling
        uint64 settledJurors;          // Number of jurors whose rewards were already settled
        uint256 collectedTokens;       // Total amount of tokens collected from losing jurors
        Appeal appeal;                 // Appeal-related information of a round
    }

    struct JurorState {
        uint64 weight;                 // Weight computed for a juror on a round
        bool rewarded;                 // Whether or not a drafted juror was rewarded
    }

    struct Appeal {
        address maker;                 // Address of the appealer
        uint8 appealedRuling;          // Ruling appealing in favor of
        address taker;                 // Address of the one confirming an appeal
        uint8 opposedRuling;           // Ruling opposed to an appeal
        bool settled;                  // Whether or not an appeal has been settled
    }

    struct DraftParams {
        uint256 disputeId;            // Identification number of the dispute to be drafted
        uint256 roundId;              // Identification number of the round to be drafted
        uint64 termId;                // Identification number of the current term of the Court
        bytes32 draftTermRandomness;  // Randomness of the term in which the dispute was requested to be drafted
        DraftConfig config;           // Draft config of the Court at the draft term
    }

    struct NextRoundDetails {
        uint64 startTerm;              // Term ID from which the next round will start
        uint64 jurorsNumber;           // Jurors number for the next round
        DisputeState newDisputeState;  // New state for the dispute associated to the given round after the appeal
        ERC20 feeToken;                // ERC20 token used for the next round fees
        uint256 totalFees;             // Total amount of fees to be distributed between the winning jurors of the next round
        uint256 jurorFees;             // Total amount of fees for a regular round at the given term
        uint256 appealDeposit;         // Amount to be deposit of fees for a regular round at the given term
        uint256 confirmAppealDeposit;  // Total amount of fees for a regular round at the given term
    }

    // Max jurors to be drafted in each batch. To prevent running out of gas. We allow to change it because max gas per tx can vary
    // As a reference, drafting 100 jurors from a small tree of 4 would cost ~2.4M. Drafting 500, ~7.75M.
    uint64 public maxJurorsPerDraftBatch;

    // List of all the disputes created in the Court
    Dispute[] internal disputes;

    event DisputeStateChanged(uint256 indexed disputeId, DisputeState indexed state);
    event EvidenceSubmitted(uint256 indexed disputeId, address indexed submitter, bytes evidence);
    event EvidencePeriodClosed(uint256 indexed disputeId, uint64 indexed termId);
    event NewDispute(uint256 indexed disputeId, IArbitrable indexed subject, uint64 indexed draftTermId, uint64 jurorsNumber, bytes metadata);
    event JurorDrafted(uint256 indexed disputeId, uint256 indexed roundId, address indexed juror);
    event RulingAppealed(uint256 indexed disputeId, uint256 indexed roundId, uint8 ruling);
    event RulingAppealConfirmed(uint256 indexed disputeId, uint256 indexed roundId, uint64 indexed draftTermId, uint256 jurorsNumber);
    event RulingComputed(uint256 indexed disputeId, uint8 indexed ruling);
    event PenaltiesSettled(uint256 indexed disputeId, uint256 indexed roundId, uint256 collectedTokens);
    event RewardSettled(uint256 indexed disputeId, uint256 indexed roundId, address juror, uint256 tokens, uint256 fees);
    event AppealDepositSettled(uint256 indexed disputeId, uint256 indexed roundId);
    event MaxJurorsPerDraftBatchChanged(uint64 previousMaxJurorsPerDraftBatch, uint64 currentMaxJurorsPerDraftBatch);

    /**
    * @dev Ensure the msg.sender is the CR Voting module
    */
    modifier onlyVoting() {
        ICRVoting voting = _voting();
        require(msg.sender == address(voting), ERROR_SENDER_NOT_VOTING);
        _;
    }

    /**
    * @dev Ensure a dispute exists
    * @param _disputeId Identification number of the dispute to be ensured
    */
    modifier disputeExists(uint256 _disputeId) {
        _checkDisputeExists(_disputeId);
        _;
    }

    /**
    * @dev Ensure a dispute round exists
    * @param _disputeId Identification number of the dispute to be ensured
    * @param _roundId Identification number of the dispute round to be ensured
    */
    modifier roundExists(uint256 _disputeId, uint256 _roundId) {
        _checkRoundExists(_disputeId, _roundId);
        _;
    }

    /**
    * @dev Constructor function
    * @param _controller Address of the controller
    * @param _maxJurorsPerDraftBatch Max number of jurors to be drafted per batch
    * @param _skippedDisputes Number of disputes to be skipped
    */
    constructor(Controller _controller, uint64 _maxJurorsPerDraftBatch, uint256 _skippedDisputes) ControlledRecoverable(_controller) public {
        // No need to explicitly call `Controlled` constructor since `ControlledRecoverable` is already doing it
        _setMaxJurorsPerDraftBatch(_maxJurorsPerDraftBatch);
        _skipDisputes(_skippedDisputes);
    }

    /**
    * @notice Create a dispute over `_subject` with `_possibleRulings` possible rulings
    * @param _subject Arbitrable instance creating the dispute
    * @param _possibleRulings Number of possible rulings allowed for the drafted jurors to vote on the dispute
    * @param _metadata Optional metadata that can be used to provide additional information on the dispute to be created
    * @return Dispute identification number
    */
    function createDispute(IArbitrable _subject, uint8 _possibleRulings, bytes calldata _metadata) external onlyController returns (uint256) {
        uint64 termId = _ensureCurrentTerm();
        Config memory config = _getConfigAt(termId);
        require(_possibleRulings >= MIN_RULING_OPTIONS && _possibleRulings <= config.disputes.maxRulingOptions, ERROR_INVALID_RULING_OPTIONS);

        // Create the dispute
        uint256 disputeId = disputes.length++;
        Dispute storage dispute = disputes[disputeId];
        dispute.subject = _subject;
        dispute.possibleRulings = _possibleRulings;
        dispute.createTermId = termId;

        uint64 jurorsNumber = config.disputes.firstRoundJurorsNumber;
        uint64 draftTermId = termId.add(config.disputes.evidenceTerms);
        emit NewDispute(disputeId, _subject, draftTermId, jurorsNumber, _metadata);

        // Create first adjudication round of the dispute
        (ERC20 feeToken, uint256 jurorFees, uint256 totalFees) = _getRegularRoundFees(config.fees, jurorsNumber);
        _createRound(disputeId, DisputeState.PreDraft, draftTermId, jurorsNumber, jurorFees);

        // Pay round fees and return dispute id
        _depositAmount(address(_subject), feeToken, totalFees);
        return disputeId;
    }

    /**
    * @notice Submit evidence for a dispute #`_disputeId`
    * @param _subject Arbitrable instance submitting the dispute
    * @param _disputeId Identification number of the dispute receiving new evidence
    * @param _submitter Address of the account submitting the evidence
    * @param _evidence Data submitted for the evidence of the dispute
    */
    function submitEvidence(IArbitrable _subject, uint256 _disputeId, address _submitter, bytes calldata _evidence)
        external onlyController disputeExists(_disputeId)
    {
        Dispute storage dispute = disputes[_disputeId];
        require(dispute.subject == _subject, ERROR_SUBJECT_NOT_DISPUTE_SUBJECT);
        emit EvidenceSubmitted(_disputeId, _submitter, _evidence);
    }

    /**
    * @notice Close the evidence period of dispute #`_disputeId`
    * @param _subject IArbitrable instance requesting to close the evidence submission period
    * @param _disputeId Identification number of the dispute to close its evidence submitting period
    */
    function closeEvidencePeriod(IArbitrable _subject, uint256 _disputeId)
        external onlyController roundExists(_disputeId, 0)
    {
        Dispute storage dispute = disputes[_disputeId];
        AdjudicationRound storage round = dispute.rounds[0];
        require(dispute.subject == _subject, ERROR_SUBJECT_NOT_DISPUTE_SUBJECT);

        // Check current term is within the evidence submission period
        uint64 termId = _ensureCurrentTerm();
        uint64 newDraftTermId = termId.add(1);
        require(newDraftTermId < round.draftTermId, ERROR_EVIDENCE_PERIOD_IS_CLOSED);

        // Update the draft term of the first round to the next term
        round.draftTermId = newDraftTermId;
        emit EvidencePeriodClosed(_disputeId, termId);
    }

    /**
    * @notice Draft jurors for the next round of dispute #`_disputeId`
    * @param _disputeId Identification number of the dispute to be drafted
    */
    function draft(uint256 _disputeId) external disputeExists(_disputeId) {
        // Drafts can only be computed when the Court is up-to-date. Note that forcing a term transition won't work since the term randomness
        // is always based on the next term which means it won't be available anyway.
        IClock clock = _clock();
        uint64 requiredTransitions = _clock().getNeededTermTransitions();
        require(uint256(requiredTransitions) == 0, ERROR_TERM_OUTDATED);
        uint64 currentTermId = _getLastEnsuredTermId();

        // Ensure dispute has not been drafted yet
        Dispute storage dispute = disputes[_disputeId];
        require(dispute.state == DisputeState.PreDraft, ERROR_ROUND_ALREADY_DRAFTED);

        // Ensure draft term randomness can be computed for the current block number
        uint256 roundId = dispute.rounds.length - 1;
        AdjudicationRound storage round = dispute.rounds[roundId];
        uint64 draftTermId = round.draftTermId;
        require(draftTermId <= currentTermId, ERROR_DRAFT_TERM_NOT_REACHED);
        bytes32 draftTermRandomness = clock.ensureCurrentTermRandomness();

        // Draft jurors for the given dispute and reimburse fees
        DraftConfig memory config = _getDraftConfig(draftTermId);
        bool draftEnded = _draft(round, _buildDraftParams(_disputeId, roundId, currentTermId, draftTermRandomness, config));

        // If the drafting is over, update its state
        if (draftEnded) {
            // No need for SafeMath: we ensured `currentTermId` is greater than or equal to `draftTermId` above
            round.delayedTerms = currentTermId - draftTermId;
            dispute.state = DisputeState.Adjudicating;
            emit DisputeStateChanged(_disputeId, DisputeState.Adjudicating);
        }
    }

    /**
    * @notice Appeal round #`_roundId` of dispute #`_disputeId` in favor of ruling `_ruling`
    * @param _disputeId Identification number of the dispute being appealed
    * @param _roundId Identification number of the dispute round being appealed
    * @param _ruling Ruling appealing a dispute round in favor of
    */
    function createAppeal(uint256 _disputeId, uint256 _roundId, uint8 _ruling) external roundExists(_disputeId, _roundId) {
        // Ensure current term and check that the given round can be appealed.
        // Note that if there was a final appeal the adjudication state will be 'Ended'.
        Dispute storage dispute = disputes[_disputeId];
        Config memory config = _getDisputeConfig(dispute);
        _ensureAdjudicationState(dispute, _roundId, AdjudicationState.Appealing, config.disputes);

        // Ensure that the ruling being appealed in favor of is valid and different from the current winning ruling
        ICRVoting voting = _voting();
        uint256 voteId = _getVoteId(_disputeId, _roundId);
        uint8 roundWinningRuling = voting.getWinningOutcome(voteId);
        require(roundWinningRuling != _ruling && voting.isValidOutcome(voteId, _ruling), ERROR_INVALID_APPEAL_RULING);

        // Update round appeal state
        AdjudicationRound storage round = dispute.rounds[_roundId];
        Appeal storage appeal = round.appeal;
        appeal.maker = msg.sender;
        appeal.appealedRuling = _ruling;
        emit RulingAppealed(_disputeId, _roundId, _ruling);

        // Pay appeal deposit
        NextRoundDetails memory nextRound = _getNextRoundDetails(round, _roundId, config);
        _depositAmount(msg.sender, nextRound.feeToken, nextRound.appealDeposit);
    }

    /**
    * @notice Confirm appeal for round #`_roundId` of dispute #`_disputeId` in favor of ruling `_ruling`
    * @param _disputeId Identification number of the dispute confirming an appeal of
    * @param _roundId Identification number of the dispute round confirming an appeal of
    * @param _ruling Ruling being confirmed against a dispute round appeal
    */
    function confirmAppeal(uint256 _disputeId, uint256 _roundId, uint8 _ruling) external roundExists(_disputeId, _roundId) {
        // Ensure current term and check that the given round is appealed and can be confirmed.
        // Note that if there was a final appeal the adjudication state will be 'Ended'.
        Dispute storage dispute = disputes[_disputeId];
        Config memory config = _getDisputeConfig(dispute);
        _ensureAdjudicationState(dispute, _roundId, AdjudicationState.ConfirmingAppeal, config.disputes);

        // Ensure that the ruling being confirmed in favor of is valid and different from the appealed ruling
        AdjudicationRound storage round = dispute.rounds[_roundId];
        Appeal storage appeal = round.appeal;
        uint256 voteId = _getVoteId(_disputeId, _roundId);
        require(appeal.appealedRuling != _ruling && _voting().isValidOutcome(voteId, _ruling), ERROR_INVALID_APPEAL_RULING);

        // Create a new adjudication round for the dispute
        NextRoundDetails memory nextRound = _getNextRoundDetails(round, _roundId, config);
        DisputeState newDisputeState = nextRound.newDisputeState;
        uint256 newRoundId = _createRound(_disputeId, newDisputeState, nextRound.startTerm, nextRound.jurorsNumber, nextRound.jurorFees);

        // Update previous round appeal state
        appeal.taker = msg.sender;
        appeal.opposedRuling = _ruling;
        emit RulingAppealConfirmed(_disputeId, newRoundId, nextRound.startTerm, nextRound.jurorsNumber);

        // Pay appeal confirm deposit
        _depositAmount(msg.sender, nextRound.feeToken, nextRound.confirmAppealDeposit);
    }

    /**
    * @notice Compute the final ruling for dispute #`_disputeId`
    * @param _disputeId Identification number of the dispute to compute its final ruling
    * @return subject Arbitrable instance associated to the dispute
    * @return finalRuling Final ruling decided for the given dispute
    */
    function computeRuling(uint256 _disputeId) external disputeExists(_disputeId) returns (IArbitrable subject, uint8 finalRuling) {
        Dispute storage dispute = disputes[_disputeId];
        subject = dispute.subject;

        Config memory config = _getDisputeConfig(dispute);
        finalRuling = _ensureFinalRuling(dispute, _disputeId, config);

        if (dispute.state != DisputeState.Ruled) {
            dispute.state = DisputeState.Ruled;
            emit RulingComputed(_disputeId, finalRuling);
        }
    }

    /**
    * @notice Settle penalties for round #`_roundId` of dispute #`_disputeId`
    * @dev In case of a regular round, all the drafted jurors that didn't vote in favor of the final ruling of the given dispute will be slashed.
    *      In case of a final round, jurors are slashed when voting, thus it is considered these rounds settled at once. Rewards have to be
    *      manually claimed through `settleReward` which will return pre-slashed tokens for the winning jurors of a final round as well.
    * @param _disputeId Identification number of the dispute to settle penalties for
    * @param _roundId Identification number of the dispute round to settle penalties for
    * @param _jurorsToSettle Maximum number of jurors to be slashed in this call. It can be set to zero to slash all the losing jurors of the
    *        given round. This argument is only used when settling regular rounds.
    */
    function settlePenalties(uint256 _disputeId, uint256 _roundId, uint256 _jurorsToSettle) external roundExists(_disputeId, _roundId) {
        // Enforce that rounds are settled in order to avoid one round without incentive to settle. Even if there is a settle fee
        // it may not be big enough and all jurors in the round could be slashed.
        Dispute storage dispute = disputes[_disputeId];
        require(_roundId == 0 || dispute.rounds[_roundId - 1].settledPenalties, ERROR_PREV_ROUND_NOT_SETTLED);

        // Ensure given round has not been fully settled yet
        AdjudicationRound storage round = dispute.rounds[_roundId];
        require(!round.settledPenalties, ERROR_ROUND_ALREADY_SETTLED);

        // Ensure the final ruling of the given dispute is already computed
        Config memory config = _getDisputeConfig(dispute);
        uint8 finalRuling = _ensureFinalRuling(dispute, _disputeId, config);

        // Set the number of jurors that voted in favor of the final ruling if we haven't started settling yet
        uint256 voteId = _getVoteId(_disputeId, _roundId);
        if (round.settledJurors == 0) {
            // Note that we are safe to cast the tally of a ruling to uint64 since the highest value a ruling can have is equal to the jurors
            // number for regular rounds or to the total active balance of the registry for final rounds, and both are ensured to fit in uint64.
            ICRVoting voting = _voting();
            round.coherentJurors = uint64(voting.getOutcomeTally(voteId, finalRuling));
        }

        ITreasury treasury = _treasury();
        ERC20 feeToken = config.fees.token;
        if (_isRegularRound(_roundId, config)) {
            // For regular appeal rounds we compute the amount of locked tokens that needs to get burned in batches.
            // The callers of this function will get rewarded in this case.
            uint256 jurorsSettled = _settleRegularRoundPenalties(round, voteId, finalRuling, config.disputes.penaltyPct, _jurorsToSettle, config.jurors.minActiveBalance);
            treasury.assign(feeToken, msg.sender, config.fees.settleFee.mul(jurorsSettled));
        } else {
            // For the final appeal round, there is no need to settle in batches since, to guarantee scalability,
            // all the tokens are collected from jurors when they vote, and those jurors who
            // voted in favor of the winning ruling can claim their collected tokens back along with their reward.
            // Note that the caller of this function is not being reimbursed.
            round.settledPenalties = true;
        }

        if (round.settledPenalties) {
            uint256 collectedTokens = round.collectedTokens;
            emit PenaltiesSettled(_disputeId, _roundId, collectedTokens);
            _burnCollectedTokensIfNecessary(dispute, round, _roundId, treasury, feeToken, collectedTokens);
        }
    }

    /**
    * @notice Claim reward for round #`_roundId` of dispute #`_disputeId` for juror `_juror`
    * @dev For regular rounds, it will only reward winning jurors
    * @param _disputeId Identification number of the dispute to settle rewards for
    * @param _roundId Identification number of the dispute round to settle rewards for
    * @param _juror Address of the juror to settle their rewards
    */
    function settleReward(uint256 _disputeId, uint256 _roundId, address _juror) external roundExists(_disputeId, _roundId) {
        // Ensure dispute round penalties are settled first
        Dispute storage dispute = disputes[_disputeId];
        AdjudicationRound storage round = dispute.rounds[_roundId];
        require(round.settledPenalties, ERROR_ROUND_NOT_SETTLED);

        // Ensure given juror was not rewarded yet and was drafted for the given round
        JurorState storage jurorState = round.jurorsStates[_juror];
        require(!jurorState.rewarded, ERROR_JUROR_ALREADY_REWARDED);
        require(uint256(jurorState.weight) > 0, ERROR_WONT_REWARD_NON_VOTER_JUROR);
        jurorState.rewarded = true;

        // Check if the given juror has voted in favor of the final ruling of the dispute in this round
        ICRVoting voting = _voting();
        uint256 voteId = _getVoteId(_disputeId, _roundId);
        require(voting.hasVotedInFavorOf(voteId, dispute.finalRuling, _juror), ERROR_WONT_REWARD_INCOHERENT_JUROR);

        uint256 collectedTokens = round.collectedTokens;
        IJurorsRegistry jurorsRegistry = _jurorsRegistry();

        // Distribute the collected tokens of the jurors that were slashed weighted by the winning jurors. Note that we are penalizing jurors
        // that refused intentionally their vote for the final round.
        uint256 rewardTokens;
        if (collectedTokens > 0) {
            // Note that the number of coherent jurors has to be greater than zero since we already ensured the juror has voted in favor of the
            // final ruling, therefore there will be at least one coherent juror and divisions below are safe.
            rewardTokens = _getRoundWeightedAmount(round, jurorState, collectedTokens);
            jurorsRegistry.assignTokens(_juror, rewardTokens);
        }

        // Reward the winning juror with fees
        Config memory config = _getDisputeConfig(dispute);
        // Note that the number of coherent jurors has to be greater than zero since we already ensured the juror has voted in favor of the
        // final ruling, therefore there will be at least one coherent juror and divisions below are safe.
        uint256 rewardFees = _getRoundWeightedAmount(round, jurorState, round.jurorFees);
        _treasury().assign(config.fees.token, _juror, rewardFees);

        // Set the lock for final round
        if (!_isRegularRound(_roundId, config)) {
            // Round end term ID (as it's final there's no draft delay nor appeal) plus the lock period
            DisputesConfig memory disputesConfig = config.disputes;
            jurorsRegistry.lockWithdrawals(
                _juror,
                round.draftTermId + disputesConfig.commitTerms + disputesConfig.revealTerms + disputesConfig.finalRoundLockTerms
            );
        }

        emit RewardSettled(_disputeId, _roundId, _juror, rewardTokens, rewardFees);
    }

    /**
    * @notice Settle appeal deposits for round #`_roundId` of dispute #`_disputeId`
    * @param _disputeId Identification number of the dispute to settle appeal deposits for
    * @param _roundId Identification number of the dispute round to settle appeal deposits for
    */
    function settleAppealDeposit(uint256 _disputeId, uint256 _roundId) external roundExists(_disputeId, _roundId) {
        // Ensure dispute round penalties are settled first
        Dispute storage dispute = disputes[_disputeId];
        AdjudicationRound storage round = dispute.rounds[_roundId];
        require(round.settledPenalties, ERROR_ROUND_NOT_SETTLED);

        // Ensure given round was appealed and has not been settled yet
        Appeal storage appeal = round.appeal;
        require(_existsAppeal(appeal), ERROR_ROUND_NOT_APPEALED);
        require(!appeal.settled, ERROR_ROUND_APPEAL_ALREADY_SETTLED);
        appeal.settled = true;
        emit AppealDepositSettled(_disputeId, _roundId);

        // Load next round details
        Config memory config = _getDisputeConfig(dispute);
        NextRoundDetails memory nextRound = _getNextRoundDetails(round, _roundId, config);
        ERC20 feeToken = nextRound.feeToken;
        uint256 totalFees = nextRound.totalFees;
        uint256 appealDeposit = nextRound.appealDeposit;
        uint256 confirmAppealDeposit = nextRound.confirmAppealDeposit;

        // If the appeal wasn't confirmed, return the entire deposit to appeal maker
        ITreasury treasury = _treasury();
        if (!_isAppealConfirmed(appeal)) {
            treasury.assign(feeToken, appeal.maker, appealDeposit);
            return;
        }

        // If the appeal was confirmed and there is a winner, we transfer the total deposit to that party. Otherwise, if the final ruling wasn't
        // selected by any of the appealing parties or no juror voted in the in favor of the possible outcomes, we split it between both parties.
        // Note that we are safe to access the dispute final ruling, since we already ensured that round penalties were settled.
        uint8 finalRuling = dispute.finalRuling;
        uint256 totalDeposit = appealDeposit.add(confirmAppealDeposit);
        if (appeal.appealedRuling == finalRuling) {
            treasury.assign(feeToken, appeal.maker, totalDeposit.sub(totalFees));
        } else if (appeal.opposedRuling == finalRuling) {
            treasury.assign(feeToken, appeal.taker, totalDeposit.sub(totalFees));
        } else {
            uint256 feesRefund = totalFees / 2;
            treasury.assign(feeToken, appeal.maker, appealDeposit.sub(feesRefund));
            treasury.assign(feeToken, appeal.taker, confirmAppealDeposit.sub(feesRefund));
        }
    }

    /**
    * @notice Ensure votes can be committed for vote #`_voteId`, revert otherwise
    * @dev This function will ensure the current term of the Court and revert in case votes cannot still be committed
    * @param _voteId ID of the vote instance to request the weight of a voter for
    */
    function ensureCanCommit(uint256 _voteId) external {
        (Dispute storage dispute, uint256 roundId) = _decodeVoteId(_voteId);
        Config memory config = _getDisputeConfig(dispute);

        // Ensure current term and check that votes can still be committed for the given round
        _ensureAdjudicationState(dispute, roundId, AdjudicationState.Committing, config.disputes);
    }

    /**
    * @notice Ensure `voter` can commit votes for vote #`_voteId`, revert otherwise
    * @dev This function will ensure the current term of the Court and revert in case the given voter is not allowed to commit votes
    * @param _voteId ID of the vote instance to request the weight of a voter for
    * @param _voter Address of the voter querying the weight of
    */
    function ensureCanCommit(uint256 _voteId, address _voter) external onlyVoting {
        (Dispute storage dispute, uint256 roundId) = _decodeVoteId(_voteId);
        Config memory config = _getDisputeConfig(dispute);

        // Ensure current term and check that votes can still be committed for the given round
        _ensureAdjudicationState(dispute, roundId, AdjudicationState.Committing, config.disputes);
        uint64 weight = _computeJurorWeight(dispute, roundId, _voter, config);
        require(weight > 0, ERROR_VOTER_WEIGHT_ZERO);
    }

    /**
    * @notice Ensure `voter` can reveal votes for vote #`_voteId`, revert otherwise
    * @dev This function will ensure the current term of the Court and revert in case votes cannot still be revealed
    * @param _voteId ID of the vote instance to request the weight of a voter for
    * @param _voter Address of the voter querying the weight of
    * @return Weight of the requested juror for the requested dispute's round
    */
    function ensureCanReveal(uint256 _voteId, address _voter) external returns (uint64) {
        (Dispute storage dispute, uint256 roundId) = _decodeVoteId(_voteId);
        Config memory config = _getDisputeConfig(dispute);

        // Ensure current term and check that votes can still be revealed for the given round
        _ensureAdjudicationState(dispute, roundId, AdjudicationState.Revealing, config.disputes);
        AdjudicationRound storage round = dispute.rounds[roundId];
        return _getJurorWeight(round, _voter);
    }

    /**
    * @notice Sets the global configuration for the max number of jurors to be drafted per batch to `_maxJurorsPerDraftBatch`
    * @param _maxJurorsPerDraftBatch Max number of jurors to be drafted per batch
    */
    function setMaxJurorsPerDraftBatch(uint64 _maxJurorsPerDraftBatch) external onlyConfigGovernor {
        _setMaxJurorsPerDraftBatch(_maxJurorsPerDraftBatch);
    }

    /**
    * @dev Tell the amount of token fees required to create a dispute
    * @return feeToken ERC20 token used for the fees
    * @return totalFees Total amount of fees for a regular round at the given term
    */
    function getDisputeFees() external view returns (ERC20 feeToken, uint256 totalFees) {
        uint64 currentTermId = _getCurrentTermId();
        Config memory config = _getConfigAt(currentTermId);
        (feeToken,, totalFees) = _getRegularRoundFees(config.fees, config.disputes.firstRoundJurorsNumber);
    }

    /**
    * @dev Tell information of a certain dispute
    * @param _disputeId Identification number of the dispute being queried
    * @return subject Arbitrable subject being disputed
    * @return possibleRulings Number of possible rulings allowed for the drafted jurors to vote on the dispute
    * @return state Current state of the dispute being queried: pre-draft, adjudicating, or ruled
    * @return finalRuling The winning ruling in case the dispute is finished
    * @return lastRoundId Identification number of the last round created for the dispute
    * @return createTermId Identification number of the term when the dispute was created
    */
    function getDispute(uint256 _disputeId) external view disputeExists(_disputeId)
        returns (IArbitrable subject, uint8 possibleRulings, DisputeState state, uint8 finalRuling, uint256 lastRoundId, uint64 createTermId)
    {
        Dispute storage dispute = disputes[_disputeId];

        subject = dispute.subject;
        possibleRulings = dispute.possibleRulings;
        state = dispute.state;
        finalRuling = dispute.finalRuling;
        createTermId = dispute.createTermId;
        // If a dispute exists, it has at least one round
        lastRoundId = dispute.rounds.length - 1;
    }

    /**
    * @dev Tell information of a certain adjudication round
    * @param _disputeId Identification number of the dispute being queried
    * @param _roundId Identification number of the round being queried
    * @return draftTerm Term from which the requested round can be drafted
    * @return delayedTerms Number of terms the given round was delayed based on its requested draft term id
    * @return jurorsNumber Number of jurors requested for the round
    * @return selectedJurors Number of jurors already selected for the requested round
    * @return settledPenalties Whether or not penalties have been settled for the requested round
    * @return collectedTokens Amount of juror tokens that were collected from slashed jurors for the requested round
    * @return coherentJurors Number of jurors that voted in favor of the final ruling in the requested round
    * @return state Adjudication state of the requested round
    */
    function getRound(uint256 _disputeId, uint256 _roundId) external view roundExists(_disputeId, _roundId)
        returns (
            uint64 draftTerm,
            uint64 delayedTerms,
            uint64 jurorsNumber,
            uint64 selectedJurors,
            uint256 jurorFees,
            bool settledPenalties,
            uint256 collectedTokens,
            uint64 coherentJurors,
            AdjudicationState state
        )
    {
        Dispute storage dispute = disputes[_disputeId];
        state = _adjudicationStateAt(dispute, _roundId, _getCurrentTermId(), _getDisputeConfig(dispute).disputes);

        AdjudicationRound storage round = dispute.rounds[_roundId];
        draftTerm = round.draftTermId;
        delayedTerms = round.delayedTerms;
        jurorsNumber = round.jurorsNumber;
        selectedJurors = round.selectedJurors;
        jurorFees = round.jurorFees;
        settledPenalties = round.settledPenalties;
        coherentJurors = round.coherentJurors;
        collectedTokens = round.collectedTokens;
    }

    /**
    * @dev Tell appeal-related information of a certain adjudication round
    * @param _disputeId Identification number of the dispute being queried
    * @param _roundId Identification number of the round being queried
    * @return maker Address of the account appealing the given round
    * @return appealedRuling Ruling confirmed by the appealer of the given round
    * @return taker Address of the account confirming the appeal of the given round
    * @return opposedRuling Ruling confirmed by the appeal taker of the given round
    */
    function getAppeal(uint256 _disputeId, uint256 _roundId) external view roundExists(_disputeId, _roundId)
        returns (address maker, uint64 appealedRuling, address taker, uint64 opposedRuling)
    {
        Appeal storage appeal = disputes[_disputeId].rounds[_roundId].appeal;

        maker = appeal.maker;
        appealedRuling = appeal.appealedRuling;
        taker = appeal.taker;
        opposedRuling = appeal.opposedRuling;
    }

    /**
    * @dev Tell information related to the next round due to an appeal of a certain round given.
    * @param _disputeId Identification number of the dispute being queried
    * @param _roundId Identification number of the round requesting the appeal details of
    * @return nextRoundStartTerm Term ID from which the next round will start
    * @return nextRoundJurorsNumber Jurors number for the next round
    * @return newDisputeState New state for the dispute associated to the given round after the appeal
    * @return feeToken ERC20 token used for the next round fees
    * @return jurorFees Total amount of fees to be distributed between the winning jurors of the next round
    * @return totalFees Total amount of fees for a regular round at the given term
    * @return appealDeposit Amount to be deposit of fees for a regular round at the given term
    * @return confirmAppealDeposit Total amount of fees for a regular round at the given term
    */
    function getNextRoundDetails(uint256 _disputeId, uint256 _roundId) external view
        returns (
            uint64 nextRoundStartTerm,
            uint64 nextRoundJurorsNumber,
            DisputeState newDisputeState,
            ERC20 feeToken,
            uint256 totalFees,
            uint256 jurorFees,
            uint256 appealDeposit,
            uint256 confirmAppealDeposit
        )
    {
        _checkRoundExists(_disputeId, _roundId);

        Dispute storage dispute = disputes[_disputeId];
        Config memory config = _getDisputeConfig(dispute);
        require(_isRegularRound(_roundId, config), ERROR_ROUND_IS_FINAL);

        AdjudicationRound storage round = dispute.rounds[_roundId];
        NextRoundDetails memory nextRound = _getNextRoundDetails(round, _roundId, config);
        return (
            nextRound.startTerm,
            nextRound.jurorsNumber,
            nextRound.newDisputeState,
            nextRound.feeToken,
            nextRound.totalFees,
            nextRound.jurorFees,
            nextRound.appealDeposit,
            nextRound.confirmAppealDeposit
        );
    }

    /**
    * @dev Tell juror-related information of a certain adjudication round
    * @param _disputeId Identification number of the dispute being queried
    * @param _roundId Identification number of the round being queried
    * @param _juror Address of the juror being queried
    * @return weight Juror weight drafted for the requested round
    * @return rewarded Whether or not the given juror was rewarded based on the requested round
    */
    function getJuror(uint256 _disputeId, uint256 _roundId, address _juror) external view roundExists(_disputeId, _roundId)
        returns (uint64 weight, bool rewarded)
    {
        Dispute storage dispute = disputes[_disputeId];
        AdjudicationRound storage round = dispute.rounds[_roundId];
        Config memory config = _getDisputeConfig(dispute);

        if (_isRegularRound(_roundId, config)) {
            weight = _getJurorWeight(round, _juror);
        } else {
            IJurorsRegistry jurorsRegistry = _jurorsRegistry();
            uint256 activeBalance = jurorsRegistry.activeBalanceOfAt(_juror, round.draftTermId);
            weight = _getMinActiveBalanceMultiple(activeBalance, config.jurors.minActiveBalance);
        }

        rewarded = round.jurorsStates[_juror].rewarded;
    }

    /**
    * @dev Internal function to create a new round for a given dispute
    * @param _disputeId Identification number of the dispute to create a new round for
    * @param _disputeState New state for the dispute to be changed
    * @param _draftTermId Term ID when the jurors for the new round will be drafted
    * @param _jurorsNumber Number of jurors to be drafted for the new round
    * @param _jurorFees Total amount of fees to be shared between the winning jurors of the new round
    * @return Identification number of the new dispute round
    */
    function _createRound(uint256 _disputeId, DisputeState _disputeState, uint64 _draftTermId, uint64 _jurorsNumber, uint256 _jurorFees) internal
        returns (uint256)
    {
        // Update dispute state
        Dispute storage dispute = disputes[_disputeId];
        dispute.state = _disputeState;

        // Create new requested round
        uint256 roundId = dispute.rounds.length++;
        AdjudicationRound storage round = dispute.rounds[roundId];
        round.draftTermId = _draftTermId;
        round.jurorsNumber = _jurorsNumber;
        round.jurorFees = _jurorFees;

        // Create new vote for the new round
        ICRVoting voting = _voting();
        uint256 voteId = _getVoteId(_disputeId, roundId);
        voting.create(voteId, dispute.possibleRulings);
        return roundId;
    }

    /**
    * @dev Internal function to ensure the adjudication state of a certain dispute round. This function will make sure the court term is updated.
    *      This function assumes the given round exists.
    * @param _dispute Dispute to be checked
    * @param _roundId Identification number of the dispute round to be checked
    * @param _state Expected adjudication state for the given dispute round
    * @param _config Config at the draft term ID of the given dispute
    */
    function _ensureAdjudicationState(Dispute storage _dispute, uint256 _roundId, AdjudicationState _state, DisputesConfig memory _config)
        internal
    {
        uint64 termId = _ensureCurrentTerm();
        AdjudicationState roundState = _adjudicationStateAt(_dispute, _roundId, termId, _config);
        require(roundState == _state, ERROR_INVALID_ADJUDICATION_STATE);
    }

    /**
    * @dev Internal function to ensure the final ruling of a dispute. It will compute it only if missing.
    * @param _dispute Dispute to ensure its final ruling
    * @param _disputeId Identification number of the dispute to ensure its final ruling
    * @param _config Config at the draft term ID of the given dispute
    * @return Number of the final ruling ensured for the given dispute
    */
    function _ensureFinalRuling(Dispute storage _dispute, uint256 _disputeId, Config memory _config) internal returns (uint8) {
        // Check if there was a final ruling already cached
        if (uint256(_dispute.finalRuling) > 0) {
            return _dispute.finalRuling;
        }

        // Ensure current term and check that the last adjudication round has ended.
        // Note that there will always be at least one round.
        uint256 lastRoundId = _dispute.rounds.length - 1;
        _ensureAdjudicationState(_dispute, lastRoundId, AdjudicationState.Ended, _config.disputes);

        // If the last adjudication round was appealed but no-one confirmed it, the final ruling is the outcome the
        // appealer vouched for. Otherwise, fetch the winning outcome from the voting app of the last round.
        AdjudicationRound storage lastRound = _dispute.rounds[lastRoundId];
        Appeal storage lastAppeal = lastRound.appeal;
        bool isRoundAppealedAndNotConfirmed = _existsAppeal(lastAppeal) && !_isAppealConfirmed(lastAppeal);
        uint8 finalRuling = isRoundAppealedAndNotConfirmed
            ? lastAppeal.appealedRuling
            : _voting().getWinningOutcome(_getVoteId(_disputeId, lastRoundId));

        // Store the winning ruling as the final decision for the given dispute
        _dispute.finalRuling = finalRuling;
        return finalRuling;
    }

    /**
    * @dev Internal function to slash all the jurors drafted for a round that didn't vote in favor of the final ruling of a dispute. Note that
    *      the slashing can be batched handling the maximum number of jurors to be slashed on each call.
    * @param _round Round to slash the non-winning jurors of
    * @param _voteId Identification number of the voting associated to the given round
    * @param _finalRuling Winning ruling of the dispute corresponding to the given round
    * @param _penaltyPct Per ten thousand of the minimum active balance of a juror to be slashed
    * @param _jurorsToSettle Maximum number of jurors to be slashed in this call. It can be set to zero to slash all the losing jurors of the round.
    * @param _minActiveBalance Minimum amount of juror tokens that can be activated
    * @return Number of jurors slashed for the given round
    */
    function _settleRegularRoundPenalties(
        AdjudicationRound storage _round,
        uint256 _voteId,
        uint8 _finalRuling,
        uint16 _penaltyPct,
        uint256 _jurorsToSettle,
        uint256 _minActiveBalance
    )
        internal
        returns (uint256)
    {
        uint64 termId = _ensureCurrentTerm();
        // The batch starts where the previous one ended, stored in _round.settledJurors
        uint256 roundSettledJurors = _round.settledJurors;
        // Compute the amount of jurors that are going to be settled in this batch, which is returned by the function for fees calculation
        // Initially we try to reach the end of the jurors array
        uint256 batchSettledJurors = _round.jurors.length.sub(roundSettledJurors);

        // If the requested amount of jurors is not zero and it is lower that the remaining number of jurors to be settled for the given round,
        // we cap the number of jurors that are going to be settled in this batch to the requested amount. If not, we know we have reached the
        // last batch and we are safe to mark round penalties as settled.
        if (_jurorsToSettle > 0 && batchSettledJurors > _jurorsToSettle) {
            batchSettledJurors = _jurorsToSettle;
        } else {
            _round.settledPenalties = true;
        }

        // Update the number of round settled jurors.
        _round.settledJurors = uint64(roundSettledJurors.add(batchSettledJurors));

        // Prepare the list of jurors and penalties to either be slashed or returned based on their votes for the given round
        IJurorsRegistry jurorsRegistry = _jurorsRegistry();
        address[] memory jurors = new address[](batchSettledJurors);
        uint256[] memory penalties = new uint256[](batchSettledJurors);
        for (uint256 i = 0; i < batchSettledJurors; i++) {
            address juror = _round.jurors[roundSettledJurors + i];
            jurors[i] = juror;
            penalties[i] = _minActiveBalance.pct(_penaltyPct).mul(_round.jurorsStates[juror].weight);
        }

        // Check which of the jurors voted in favor of the final ruling of the dispute in this round. Ask the registry to slash or unlocked the
        // locked active tokens of each juror depending on their vote, and finally store the total amount of slashed tokens.
        bool[] memory jurorsInFavor = _voting().getVotersInFavorOf(_voteId, _finalRuling, jurors);
        _round.collectedTokens = _round.collectedTokens.add(jurorsRegistry.slashOrUnlock(termId, jurors, penalties, jurorsInFavor));
        return batchSettledJurors;
    }

    /**
    * @dev Internal function to compute the juror weight for a dispute's round
    * @param _dispute Dispute to calculate the juror's weight of
    * @param _roundId ID of the dispute's round to calculate the juror's weight of
    * @param _juror Address of the juror to calculate the weight of
    * @param _config Config at the draft term ID of the given dispute
    * @return Computed weight of the requested juror for the final round of the given dispute
    */
    function _computeJurorWeight(Dispute storage _dispute, uint256 _roundId, address _juror, Config memory _config) internal returns (uint64) {
        AdjudicationRound storage round = _dispute.rounds[_roundId];

        return _isRegularRound(_roundId, _config)
            ? _getJurorWeight(round, _juror)
            : _computeJurorWeightForFinalRound(_config, round, _juror);
    }

    /**
    * @dev Internal function to compute the juror weight for the final round. Note that for a final round the weight of
    *      each juror is equal to the number of times the min active balance the juror has. This function will try to
    *      collect said amount from the active balance of a juror, acting as a lock to allow them to vote.
    * @param _config Court config to calculate the juror's weight
    * @param _round Dispute round to calculate the juror's weight for
    * @param _juror Address of the juror to calculate the weight of
    * @return Weight of the requested juror for the final round of the given dispute
    */
    function _computeJurorWeightForFinalRound(Config memory _config, AdjudicationRound storage _round, address _juror) internal
        returns (uint64)
    {
        // Fetch active balance and multiples of the min active balance from the registry
        IJurorsRegistry jurorsRegistry = _jurorsRegistry();
        uint256 activeBalance = jurorsRegistry.activeBalanceOfAt(_juror, _round.draftTermId);
        uint64 weight = _getMinActiveBalanceMultiple(activeBalance, _config.jurors.minActiveBalance);

        // If the juror weight for the last round is zero, return zero
        if (weight == 0) {
            return uint64(0);
        }

        // To guarantee scalability of the final round, since all jurors may vote, we try to collect the amount of
        // active tokens that needs to be locked for each juror when they try to commit their vote.
        uint256 weightedPenalty = activeBalance.pct(_config.disputes.penaltyPct);

        // If it was not possible to collect the amount to be locked, return 0 to prevent juror from voting
        if (!jurorsRegistry.collectTokens(_juror, weightedPenalty, _getLastEnsuredTermId())) {
            return uint64(0);
        }

        // If it was possible to collect the amount of active tokens to be locked, update the final round state
        _round.jurorsStates[_juror].weight = weight;
        _round.collectedTokens = _round.collectedTokens.add(weightedPenalty);

        return weight;
    }

    /**
    * @dev Sets the global configuration for the max number of jurors to be drafted per batch
    * @param _maxJurorsPerDraftBatch Max number of jurors to be drafted per batch
    */
    function _setMaxJurorsPerDraftBatch(uint64 _maxJurorsPerDraftBatch) internal {
        require(_maxJurorsPerDraftBatch > 0, ERROR_BAD_MAX_DRAFT_BATCH_SIZE);
        emit MaxJurorsPerDraftBatchChanged(maxJurorsPerDraftBatch, _maxJurorsPerDraftBatch);
        maxJurorsPerDraftBatch = _maxJurorsPerDraftBatch;
    }

    /**
    * @dev Internal function to execute a deposit of tokens from an account to the Court treasury contract
    * @param _from Address transferring the amount of tokens
    * @param _token ERC20 token to execute a transfer from
    * @param _amount Amount of tokens to be transferred from the address transferring the funds to the Court treasury
    */
    function _depositAmount(address _from, ERC20 _token, uint256 _amount) internal {
        if (_amount > 0) {
            ITreasury treasury = _treasury();
            require(_token.safeTransferFrom(_from, address(treasury), _amount), ERROR_DEPOSIT_FAILED);
        }
    }

    /**
    * @dev Internal function to get the stored juror weight for a round. Note that the weight of a juror is:
    *      - For a regular round: the number of times a juror was picked for the round round.
    *      - For a final round: the relative active stake of a juror's state over the total active tokens, only set after the juror has voted.
    * @param _round Dispute round to calculate the juror's weight of
    * @param _juror Address of the juror to calculate the weight of
    * @return Weight of the requested juror for the given round
    */
    function _getJurorWeight(AdjudicationRound storage _round, address _juror) internal view returns (uint64) {
        return _round.jurorsStates[_juror].weight;
    }

    /**
    * @dev Internal function to tell information related to the next round due to an appeal of a certain round given. This function assumes
    *      given round can be appealed and that the given round ID corresponds to the given round pointer.
    * @param _round Round requesting the appeal details of
    * @param _roundId Identification number of the round requesting the appeal details of
    * @param _config Config at the draft term of the given dispute
    * @return Next round details
    */
    function _getNextRoundDetails(AdjudicationRound storage _round, uint256 _roundId, Config memory _config) internal view
        returns (NextRoundDetails memory)
    {
        NextRoundDetails memory nextRound;
        DisputesConfig memory disputesConfig = _config.disputes;

        // Next round start term is current round end term
        uint64 delayedDraftTerm = _round.draftTermId.add(_round.delayedTerms);
        uint64 currentRoundAppealStartTerm = delayedDraftTerm.add(disputesConfig.commitTerms).add(disputesConfig.revealTerms);
        nextRound.startTerm = currentRoundAppealStartTerm.add(disputesConfig.appealTerms).add(disputesConfig.appealConfirmTerms);

        // Compute next round settings depending on if it will be the final round or not
        if (_roundId >= disputesConfig.maxRegularAppealRounds.sub(1)) {
            // If the next round is the final round, no draft is needed.
            nextRound.newDisputeState = DisputeState.Adjudicating;
            // The number of jurors will be the number of times the minimum stake is held in the registry,
            // multiplied by a precision factor to help with division rounding.
            // Total active balance is guaranteed to never be greater than `2^64 * minActiveBalance / FINAL_ROUND_WEIGHT_PRECISION`.
            // Thus, the jurors number for a final round will always fit in uint64.
            IJurorsRegistry jurorsRegistry = _jurorsRegistry();
            uint256 totalActiveBalance = jurorsRegistry.totalActiveBalanceAt(nextRound.startTerm);
            uint64 jurorsNumber = _getMinActiveBalanceMultiple(totalActiveBalance, _config.jurors.minActiveBalance);
            nextRound.jurorsNumber = jurorsNumber;
            // Calculate fees for the final round using the appeal start term of the current round
            (nextRound.feeToken, nextRound.jurorFees, nextRound.totalFees) = _getFinalRoundFees(_config.fees, jurorsNumber);
        } else {
            // For a new regular rounds we need to draft jurors
            nextRound.newDisputeState = DisputeState.PreDraft;
            // The number of jurors will be the number of jurors of the current round multiplied by an appeal factor
            nextRound.jurorsNumber = _getNextRegularRoundJurorsNumber(_round, disputesConfig);
            // Calculate fees for the next regular round using the appeal start term of the current round
            (nextRound.feeToken, nextRound.jurorFees, nextRound.totalFees) = _getRegularRoundFees(_config.fees, nextRound.jurorsNumber);
        }

        // Calculate appeal collateral
        nextRound.appealDeposit = nextRound.totalFees.pct256(disputesConfig.appealCollateralFactor);
        nextRound.confirmAppealDeposit = nextRound.totalFees.pct256(disputesConfig.appealConfirmCollateralFactor);
        return nextRound;
    }

    /**
    * @dev Internal function to calculate the jurors number for the next regular round of a given round. This function assumes Court term is
    *      up-to-date, that the next round of the one given is regular, and the given config corresponds to the draft term of the given round.
    * @param _round Round querying the jurors number of its next round
    * @param _config Disputes config at the draft term of the first round of the dispute
    * @return Jurors number for the next regular round of the given round
    */
    function _getNextRegularRoundJurorsNumber(AdjudicationRound storage _round, DisputesConfig memory _config) internal view returns (uint64) {
        // Jurors number are increased by a step factor on each appeal
        uint64 jurorsNumber = _round.jurorsNumber.mul(_config.appealStepFactor);
        // Make sure it's odd to enforce avoiding a tie. Note that it can happen if any of the jurors don't vote anyway.
        if (uint256(jurorsNumber) % 2 == 0) {
            jurorsNumber++;
        }
        return jurorsNumber;
    }

    /**
    * @dev Internal function to tell adjudication state of a round at a certain term. This function assumes the given round exists.
    * @param _dispute Dispute querying the adjudication round of
    * @param _roundId Identification number of the dispute round querying the adjudication round of
    * @param _termId Identification number of the term to be used for the different round phases durations
    * @param _config Disputes config at the draft term ID of the given dispute
    * @return Adjudication state of the requested dispute round for the given term
    */
    function _adjudicationStateAt(Dispute storage _dispute, uint256 _roundId, uint64 _termId, DisputesConfig memory _config) internal view
        returns (AdjudicationState)
    {
        AdjudicationRound storage round = _dispute.rounds[_roundId];

        // If the dispute is ruled or the given round is not the last one, we consider it ended
        uint256 numberOfRounds = _dispute.rounds.length;
        if (_dispute.state == DisputeState.Ruled || _roundId < numberOfRounds.sub(1)) {
            return AdjudicationState.Ended;
        }

        // If given term is before the actual term when the last round was finally drafted, then the last round adjudication state is invalid
        uint64 draftFinishedTermId = round.draftTermId.add(round.delayedTerms);
        if (_dispute.state == DisputeState.PreDraft || _termId < draftFinishedTermId) {
            return AdjudicationState.Invalid;
        }

        // If given term is before the reveal start term of the last round, then jurors are still allowed to commit votes for the last round
        uint64 revealStartTerm = draftFinishedTermId.add(_config.commitTerms);
        if (_termId < revealStartTerm) {
            return AdjudicationState.Committing;
        }

        // If given term is before the appeal start term of the last round, then jurors are still allowed to reveal votes for the last round
        uint64 appealStartTerm = revealStartTerm.add(_config.revealTerms);
        if (_termId < appealStartTerm) {
            return AdjudicationState.Revealing;
        }

        // If the max number of appeals has been reached, then the last round is the final round and can be considered ended
        bool maxAppealReached = numberOfRounds > _config.maxRegularAppealRounds;
        if (maxAppealReached) {
            return AdjudicationState.Ended;
        }

        // If the last round was not appealed yet, check if the confirmation period has started or not
        bool isLastRoundAppealed = _existsAppeal(round.appeal);
        uint64 appealConfirmationStartTerm = appealStartTerm.add(_config.appealTerms);
        if (!isLastRoundAppealed) {
            // If given term is before the appeal confirmation start term, then the last round can still be appealed. Otherwise, it is ended.
            if (_termId < appealConfirmationStartTerm) {
                return AdjudicationState.Appealing;
            } else {
                return AdjudicationState.Ended;
            }
        }

        // If the last round was appealed and the given term is before the appeal confirmation end term, then the last round appeal can still be
        // confirmed. Note that if the round being checked was already appealed and confirmed, it won't be the last round, thus it will be caught
        // above by the first check and considered 'Ended'.
        uint64 appealConfirmationEndTerm = appealConfirmationStartTerm.add(_config.appealConfirmTerms);
        if (_termId < appealConfirmationEndTerm) {
            return AdjudicationState.ConfirmingAppeal;
        }

        // If non of the above conditions have been met, the last round is considered ended
        return AdjudicationState.Ended;
    }

    /**
    * @dev Internal function to get the Court config used for a dispute
    * @param _dispute Dispute querying the Court config of
    * @return Court config used for the given dispute
    */
    function _getDisputeConfig(Dispute storage _dispute) internal view returns (Config memory) {
        // Note that it is safe to access a Court config directly for a past term
        return _getConfigAt(_dispute.createTermId);
    }

    /**
    * @dev Internal function to check if a certain appeal exists
    * @param _appeal Appeal to be checked
    * @return True if the given appeal has a maker address associated to it, false otherwise
    */
    function _existsAppeal(Appeal storage _appeal) internal view returns (bool) {
        return _appeal.maker != address(0);
    }

    /**
    * @dev Internal function to check if a certain appeal has been confirmed
    * @param _appeal Appeal to be checked
    * @return True if the given appeal was confirmed, false otherwise
    */
    function _isAppealConfirmed(Appeal storage _appeal) internal view returns (bool) {
        return _appeal.taker != address(0);
    }

    /**
    * @dev Internal function to check if a certain dispute exists, it reverts if it doesn't
    * @param _disputeId Identification number of the dispute to be checked
    */
    function _checkDisputeExists(uint256 _disputeId) internal view {
        require(_disputeId < disputes.length, ERROR_DISPUTE_DOES_NOT_EXIST);
    }

    /**
    * @dev Internal function to check if a certain dispute round exists, it reverts if it doesn't
    * @param _disputeId Identification number of the dispute to be checked
    * @param _roundId Identification number of the dispute round to be checked
    */
    function _checkRoundExists(uint256 _disputeId, uint256 _roundId) internal view {
        _checkDisputeExists(_disputeId);
        require(_roundId < disputes[_disputeId].rounds.length, ERROR_ROUND_DOES_NOT_EXIST);
    }

    /**
    * @dev Internal function to get the dispute round of a certain vote identification number
    * @param _voteId Identification number of the vote querying the dispute round of
    * @return dispute Dispute for the given vote
    * @return roundId Identification number of the dispute round for the given vote
    */
    function _decodeVoteId(uint256 _voteId) internal view returns (Dispute storage dispute, uint256 roundId) {
        uint256 disputeId = _voteId >> 128;
        roundId = _voteId & VOTE_ID_MASK;
        _checkRoundExists(disputeId, roundId);
        dispute = disputes[disputeId];
    }

    /**
    * @dev Internal function to get the identification number of the vote of a certain dispute round
    * @param _disputeId Identification number of the dispute querying the vote ID of
    * @param _roundId Identification number of the dispute round querying the vote ID of
    * @return Identification number of the vote of the requested dispute round
    */
    function _getVoteId(uint256 _disputeId, uint256 _roundId) internal pure returns (uint256) {
        return (_disputeId << 128) + _roundId;
    }

    /**
    * @dev Assumes round.coherentJurors is greater than zero
    * @param _round Round which the weighted amount is computed for
    * @param _jurorState Juror with state which the weighted amount is computed for
    * @param _amount Amount to be weighted
    * @return Weighted amount for a juror in a round in relation to total amount of coherent jurors
    */
    function _getRoundWeightedAmount(
        AdjudicationRound storage _round,
        JurorState storage _jurorState,
        uint256 _amount
    )
        internal
        view
        returns (uint256)
    {
        return _amount.mul(_jurorState.weight) / _round.coherentJurors;
    }

    /**
    * @dev Internal function to get fees information for regular rounds for a certain term. This function assumes Court term is up-to-date.
    * @param _config Court config to use in order to get fees
    * @param _jurorsNumber Number of jurors participating in the round being queried
    * @return feeToken ERC20 token used for the fees
    * @return jurorFees Total amount of fees to be distributed between the winning jurors of a round
    * @return totalFees Total amount of fees for a regular round at the given term
    */
    function _getRegularRoundFees(FeesConfig memory _config, uint64 _jurorsNumber) internal pure
        returns (ERC20 feeToken, uint256 jurorFees, uint256 totalFees)
    {
        feeToken = _config.token;
        // For regular rounds the fees for each juror is constant and given by the config of the round
        jurorFees = uint256(_jurorsNumber).mul(_config.jurorFee);
        // The total fees for regular rounds also considers the number of drafts and settles
        uint256 draftAndSettleFees = (_config.draftFee.add(_config.settleFee)).mul(uint256(_jurorsNumber));
        totalFees = jurorFees.add(draftAndSettleFees);
    }

    /**
    * @dev Internal function to get fees information for final rounds for a certain term. This function assumes Court term is up-to-date.
    * @param _config Court config to use in order to get fees
    * @param _jurorsNumber Number of jurors participating in the round being queried
    * @return feeToken ERC20 token used for the fees
    * @return jurorFees Total amount of fees corresponding to the jurors at the given term
    * @return totalFees Total amount of fees for a final round at the given term
    */
    function _getFinalRoundFees(FeesConfig memory _config, uint64 _jurorsNumber) internal pure
        returns (ERC20 feeToken, uint256 jurorFees, uint256 totalFees)
    {
        feeToken = _config.token;
        // For final rounds, the jurors number is computed as the number of times the registry's minimum active balance is held in the registry
        // itself, multiplied by a precision factor. To avoid requesting a huge amount of fees, a final round discount is applied for each juror.
        jurorFees = (uint256(_jurorsNumber).mul(_config.jurorFee) / FINAL_ROUND_WEIGHT_PRECISION).pct(_config.finalRoundReduction);
        // There is no draft and no extra settle fees considered for final rounds
        totalFees = jurorFees;
    }

    /**
    * @dev Internal function to tell whether a round is regular or final. This function assumes the given round exists.
    * @param _roundId Identification number of the round to be checked
    * @param _config Court config to use in order to check if the given round is regular or final
    * @return True if the given round is regular, false in case its a final round
    */
    function _isRegularRound(uint256 _roundId, Config memory _config) internal pure returns (bool) {
        return _roundId < _config.disputes.maxRegularAppealRounds;
    }

    /**
    * @dev Calculate the number of times that an amount contains the min active balance (multiplied by precision).
    *      Used to get the juror weight for the final round. Note that for the final round the weight of
    *      each juror is equal to the number of times the min active balance the juror has, multiplied by a precision
    *      factor to deal with division rounding.
    * @param _activeBalance Juror's or total active balance
    * @param _minActiveBalance Minimum amount of juror tokens that can be activated
    * @return Number of times that the active balance contains the min active balance (multiplied by precision)
    */
    function _getMinActiveBalanceMultiple(uint256 _activeBalance, uint256 _minActiveBalance) internal pure returns (uint64) {
        // Note that jurors may not reach the minimum active balance since some might have been slashed. If that occurs,
        // these jurors cannot vote in the final round.
        if (_activeBalance < _minActiveBalance) {
            return 0;
        }

        // Otherwise, return the times the active balance of the juror fits in the min active balance, multiplying
        // it by a round factor to ensure a better precision rounding.
        return (FINAL_ROUND_WEIGHT_PRECISION.mul(_activeBalance) / _minActiveBalance).toUint64();
    }

    /**
    * @dev Private function to build params to call for a draft. It assumes the given data is correct.
    * @param _disputeId Identification number of the dispute to be drafted
    * @param _roundId Identification number of the round to be drafted
    * @param _termId Identification number of the current term of the Court
    * @param _draftTermRandomness Randomness of the term in which the dispute was requested to be drafted
    * @param _config Draft config of the Court at the draft term
    * @return Draft params object
    */
    function _buildDraftParams(uint256 _disputeId, uint256 _roundId, uint64 _termId, bytes32 _draftTermRandomness, DraftConfig memory _config)
        private
        pure
        returns (DraftParams memory)
    {
        return DraftParams({
            disputeId: _disputeId,
            roundId: _roundId,
            termId: _termId,
            draftTermRandomness: _draftTermRandomness,
            config: _config
        });
    }

    /**
    * @dev Private function to draft jurors for a given dispute and round. It assumes the given data is correct.
    * @param _round Round of the dispute to be drafted
    * @param _draftParams Draft params to be used for the draft
    * @return True if all the requested jurors for the given round were drafted, false otherwise
    */
    function _draft(AdjudicationRound storage _round, DraftParams memory _draftParams) private returns (bool) {
        uint64 jurorsNumber = _round.jurorsNumber;
        uint64 selectedJurors = _round.selectedJurors;
        uint64 maxJurorsPerBatch = maxJurorsPerDraftBatch;
        uint64 jurorsToBeDrafted = jurorsNumber.sub(selectedJurors);
        // Draft the min number of jurors between the one requested by the sender and the one requested by the sender
        uint64 requestedJurors = jurorsToBeDrafted < maxJurorsPerBatch ? jurorsToBeDrafted : maxJurorsPerBatch;

        // Pack draft params
        uint256[7] memory params = [
            uint256(_draftParams.draftTermRandomness),
            _draftParams.disputeId,
            uint256(_draftParams.termId),
            uint256(selectedJurors),
            uint256(requestedJurors),
            uint256(jurorsNumber),
            uint256(_draftParams.config.penaltyPct)
        ];

        // Draft jurors for the requested round
        IJurorsRegistry jurorsRegistry = _jurorsRegistry();
        (address[] memory jurors, uint256 draftedJurors) = jurorsRegistry.draft(params);

        // Update round with drafted jurors information
        uint64 newSelectedJurors = selectedJurors.add(uint64(draftedJurors));
        _round.selectedJurors = newSelectedJurors;
        _updateRoundDraftedJurors(_draftParams.disputeId, _draftParams.roundId, _round, jurors, draftedJurors);
        bool draftEnded = newSelectedJurors == jurorsNumber;

        // Transfer fees corresponding to the actual number of drafted jurors
        uint256 draftFees = _draftParams.config.draftFee.mul(draftedJurors);
        _treasury().assign(_draftParams.config.feeToken, msg.sender, draftFees);
        return draftEnded;
    }

    /**
    * @dev Private function to update the drafted jurors' weight for the given round
    * @param _disputeId Identification number of the dispute being drafted
    * @param _roundId Identification number of the round being drafted
    * @param _round Adjudication round that was drafted
    * @param _jurors List of jurors addresses that were drafted for the given round
    * @param _draftedJurors Number of jurors that were drafted for the given round. Note that this number may not necessarily be equal to the
    *        given list of jurors since the draft could potentially return less jurors than the requested amount.
    */
    function _updateRoundDraftedJurors(
        uint256 _disputeId,
        uint256 _roundId,
        AdjudicationRound storage _round,
        address[] memory _jurors,
        uint256 _draftedJurors
    )
        private
    {
        for (uint256 i = 0; i < _draftedJurors; i++) {
            address juror = _jurors[i];
            JurorState storage jurorState = _round.jurorsStates[juror];

            // If the juror was already registered in the list, then don't add it twice
            if (uint256(jurorState.weight) == 0) {
                _round.jurors.push(juror);
            }

            jurorState.weight = jurorState.weight.add(1);
            emit JurorDrafted(_disputeId, _roundId, juror);
        }
    }

    /**
    * @dev Private function to burn the collected for a certain round in case there were no coherent jurors
    * @param _dispute Dispute to settle penalties for
    * @param _round Dispute round to settle penalties for
    * @param _roundId Identification number of the dispute round to settle penalties for
    * @param _courtTreasury Treasury module to refund the corresponding juror fees
    * @param _feeToken ERC20 token to be used for the fees corresponding to the draft term of the given dispute round
    * @param _collectedTokens Amount of tokens collected during the given dispute round
    */
    function _burnCollectedTokensIfNecessary(
        Dispute storage _dispute,
        AdjudicationRound storage _round,
        uint256 _roundId,
        ITreasury _courtTreasury,
        ERC20 _feeToken,
        uint256 _collectedTokens
    )
        private
    {
        // If there was at least one juror voting in favor of the winning ruling, return
        if (_round.coherentJurors > 0) {
            return;
        }

        // Burn all the collected tokens of the jurors to be slashed. Note that this will happen only when there were no jurors voting
        // in favor of the final winning outcome. Otherwise, these will be re-distributed between the winning jurors in `settleReward`
        // instead of being burned.
        if (_collectedTokens > 0) {
            IJurorsRegistry jurorsRegistry = _jurorsRegistry();
            jurorsRegistry.burnTokens(_collectedTokens);
        }

        // Reimburse juror fees to the Arbtirable subject for round 0 or to the previous appeal parties for other rounds.
        // Note that if the given round is not the first round, we can ensure there was an appeal in the previous round.
        if (_roundId == 0) {
            _courtTreasury.assign(_feeToken, address(_dispute.subject), _round.jurorFees);
        } else {
            uint256 refundFees = _round.jurorFees / 2;
            Appeal storage triggeringAppeal = _dispute.rounds[_roundId - 1].appeal;
            _courtTreasury.assign(_feeToken, triggeringAppeal.maker, refundFees);
            _courtTreasury.assign(_feeToken, triggeringAppeal.taker, refundFees);
        }
    }

    /**
    * @dev Private function only used in the constructor to skip a given number of disputes
    * @param _skippedDisputes Number of disputes to be skipped
    */
    function _skipDisputes(uint256 _skippedDisputes) private {
        assert(disputes.length == 0);
        disputes.length = _skippedDisputes;
    }
}

Contract Security Audit

Contract ABI

[{"constant":false,"inputs":[{"name":"_maxJurorsPerDraftBatch","type":"uint64"}],"name":"setMaxJurorsPerDraftBatch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_voteId","type":"uint256"},{"name":"_voter","type":"address"}],"name":"ensureCanCommit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"},{"name":"_ruling","type":"uint8"}],"name":"createAppeal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_voteId","type":"uint256"}],"name":"ensureCanCommit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_subject","type":"address"},{"name":"_possibleRulings","type":"uint8"},{"name":"_metadata","type":"bytes"}],"name":"createDispute","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_to","type":"address"}],"name":"recoverFunds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getController","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxJurorsPerDraftBatch","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"}],"name":"getRound","outputs":[{"name":"draftTerm","type":"uint64"},{"name":"delayedTerms","type":"uint64"},{"name":"jurorsNumber","type":"uint64"},{"name":"selectedJurors","type":"uint64"},{"name":"jurorFees","type":"uint256"},{"name":"settledPenalties","type":"bool"},{"name":"collectedTokens","type":"uint256"},{"name":"coherentJurors","type":"uint64"},{"name":"state","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"},{"name":"_juror","type":"address"}],"name":"getJuror","outputs":[{"name":"weight","type":"uint64"},{"name":"rewarded","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_subject","type":"address"},{"name":"_disputeId","type":"uint256"},{"name":"_submitter","type":"address"},{"name":"_evidence","type":"bytes"}],"name":"submitEvidence","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"}],"name":"draft","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"}],"name":"getAppeal","outputs":[{"name":"maker","type":"address"},{"name":"appealedRuling","type":"uint64"},{"name":"taker","type":"address"},{"name":"opposedRuling","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getDisputeFees","outputs":[{"name":"feeToken","type":"address"},{"name":"totalFees","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"},{"name":"_juror","type":"address"}],"name":"settleReward","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"},{"name":"_jurorsToSettle","type":"uint256"}],"name":"settlePenalties","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"},{"name":"_ruling","type":"uint8"}],"name":"confirmAppeal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"}],"name":"computeRuling","outputs":[{"name":"subject","type":"address"},{"name":"finalRuling","type":"uint8"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_voteId","type":"uint256"},{"name":"_voter","type":"address"}],"name":"ensureCanReveal","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_subject","type":"address"},{"name":"_disputeId","type":"uint256"}],"name":"closeEvidencePeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"}],"name":"getNextRoundDetails","outputs":[{"name":"nextRoundStartTerm","type":"uint64"},{"name":"nextRoundJurorsNumber","type":"uint64"},{"name":"newDisputeState","type":"uint8"},{"name":"feeToken","type":"address"},{"name":"totalFees","type":"uint256"},{"name":"jurorFees","type":"uint256"},{"name":"appealDeposit","type":"uint256"},{"name":"confirmAppealDeposit","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_disputeId","type":"uint256"}],"name":"getDispute","outputs":[{"name":"subject","type":"address"},{"name":"possibleRulings","type":"uint8"},{"name":"state","type":"uint8"},{"name":"finalRuling","type":"uint8"},{"name":"lastRoundId","type":"uint256"},{"name":"createTermId","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"}],"name":"settleAppealDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_controller","type":"address"},{"name":"_maxJurorsPerDraftBatch","type":"uint64"},{"name":"_skippedDisputes","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"state","type":"uint8"}],"name":"DisputeStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"submitter","type":"address"},{"indexed":false,"name":"evidence","type":"bytes"}],"name":"EvidenceSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"termId","type":"uint64"}],"name":"EvidencePeriodClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"subject","type":"address"},{"indexed":true,"name":"draftTermId","type":"uint64"},{"indexed":false,"name":"jurorsNumber","type":"uint64"},{"indexed":false,"name":"metadata","type":"bytes"}],"name":"NewDispute","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"roundId","type":"uint256"},{"indexed":true,"name":"juror","type":"address"}],"name":"JurorDrafted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"roundId","type":"uint256"},{"indexed":false,"name":"ruling","type":"uint8"}],"name":"RulingAppealed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"roundId","type":"uint256"},{"indexed":true,"name":"draftTermId","type":"uint64"},{"indexed":false,"name":"jurorsNumber","type":"uint256"}],"name":"RulingAppealConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"ruling","type":"uint8"}],"name":"RulingComputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"roundId","type":"uint256"},{"indexed":false,"name":"collectedTokens","type":"uint256"}],"name":"PenaltiesSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"roundId","type":"uint256"},{"indexed":false,"name":"juror","type":"address"},{"indexed":false,"name":"tokens","type":"uint256"},{"indexed":false,"name":"fees","type":"uint256"}],"name":"RewardSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"roundId","type":"uint256"}],"name":"AppealDepositSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousMaxJurorsPerDraftBatch","type":"uint64"},{"indexed":false,"name":"currentMaxJurorsPerDraftBatch","type":"uint64"}],"name":"MaxJurorsPerDraftBatchChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"recipient","type":"address"},{"indexed":false,"name":"balance","type":"uint256"}],"name":"RecoverFunds","type":"event"}]

60806040523480156200001157600080fd5b50604051606080620063e7833981018060405260608110156200003357600080fd5b50805160208083015160409093015191929190839081906200005b90829062000186811b901c565b6040518060400160405280601b81526020017f4354445f434f4e54524f4c4c45525f4e4f545f434f4e545241435400000000008152509062000138576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620000fc578181015183820152602001620000e2565b50505050905090810190601f1680156200012a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600080546001600160a01b0319166001600160a01b0392909216919091179055506200016c82620001ab602090811b901c565b6200017d81620002ef60201b60201c565b50505062000467565b60006001600160a01b038216620001a057506000620001a6565b50803b15155b919050565b60408051808201909152601b81527f444d5f4241445f4d41585f44524146545f42415443485f53495a45000000000060208201526001600160401b03821662000251576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315620000fc578181015183820152602001620000e2565b50600054604080516001600160401b037401000000000000000000000000000000000000000090930483168152918316602083015280517fed22db0c227e21d249167e5f9d39415fd9386958f122075463fef70fd46c95c49281900390910190a1600080546001600160401b039092167401000000000000000000000000000000000000000002600160a01b600160e01b0319909216919091179055565b60015415620002fa57fe5b80620003086001826200030c565b5050565b8154818355818111156200033b576002028160020283600052602060002091820191016200033b919062000340565b505050565b6200039591905b80821115620003915780547fff00000000000000000000000000000000000000000000000000000000000000168155600062000387600183018262000398565b5060020162000347565b5090565b90565b5080546000825560080290600052602060002090810190620003bb9190620003be565b50565b6200039591905b80821115620003915780546001600160881b0319168155600060018201819055620003f4600283018262000430565b5060006004820181905560058201556006810180546001600160a81b03191690556007810180546001600160b01b0319169055600801620003c5565b5080546000825590600052602060002090810190620003bb91906200039591905b8082111562000391576000815560010162000451565b615f7080620004776000396000f3fe608060405234801561001057600080fd5b506004361061017c5760003560e01c8063710cf1ed116100e3578063bd881e531161008c578063cd604ada11610066578063cd604ada14610674578063e3a96cbd146106fe578063eed04b801461077a5761017c565b8063bd881e53146105da578063c1361a7c1461061c578063c39c83d1146106485761017c565b806382a8b3b0116100bd57806382a8b3b014610553578063859ba187146105855780639c0065f7146105ae5761017c565b8063710cf1ed146104ab5780637263bf2a146104c85780637b751b9e146105285761017c565b806324ae6a271161014557806339ec68a31161011f57806339ec68a31461032e5780634b4acfd3146103c75780635bdaf9d81461041c5761017c565b806324ae6a27146102b85780633018205f146102e65780633238f8f41461030a5761017c565b80629230a51461018157806306349cfa146101a95780630d03d126146101d557806315fe5268146102015780631d2fa1fb1461021e575b600080fd5b6101a76004803603602081101561019757600080fd5b50356001600160401b031661079d565b005b6101a7600480360360408110156101bf57600080fd5b50803590602001356001600160a01b0316610888565b6101a7600480360360608110156101eb57600080fd5b508035906020810135906040013560ff16610a04565b6101a76004803603602081101561021757600080fd5b5035610ced565b6102a66004803603606081101561023457600080fd5b6001600160a01b038235169160ff6020820135169181019060608101604082013564010000000081111561026757600080fd5b82018360208201111561027957600080fd5b8035906020019184600183028401116401000000008311171561029b57600080fd5b509092509050610d27565b60408051918252519081900360200190f35b6101a7600480360360408110156102ce57600080fd5b506001600160a01b038135811691602001351661102f565b6102ee61133c565b604080516001600160a01b039092168252519081900360200190f35b61031261134c565b604080516001600160401b039092168252519081900360200190f35b6103516004803603604081101561034457600080fd5b5080359060200135611362565b604080516001600160401b03808c1682528a811660208301528981169282019290925287821660608201526080810187905285151560a082015260c0810185905290831660e082015261010081018260058111156103ab57fe5b60ff168152602001995050505050505050505060405180910390f35b6103f9600480360360608110156103dd57600080fd5b50803590602081013590604001356001600160a01b0316611492565b604080516001600160401b03909316835290151560208301528051918290030190f35b6101a76004803603608081101561043257600080fd5b6001600160a01b03823581169260208101359260408201359092169181019060808101606082013564010000000081111561046c57600080fd5b82018360208201111561047e57600080fd5b803590602001918460018302840111640100000000831117156104a057600080fd5b509092509050611600565b6101a7600480360360208110156104c157600080fd5b50356117c9565b6104eb600480360360408110156104de57600080fd5b5080359060200135611b7d565b604080516001600160a01b0395861681526001600160401b0394851660208201529290941682850152909116606082015290519081900360800190f35b610530611c06565b604080516001600160a01b03909316835260208301919091528051918290030190f35b6101a76004803603606081101561056957600080fd5b50803590602081013590604001356001600160a01b0316611c4b565b6101a76004803603606081101561059b57600080fd5b508035906020810135906040013561226f565b6101a7600480360360608110156105c457600080fd5b508035906020810135906040013560ff1661267e565b6105f7600480360360208110156105f057600080fd5b503561290e565b604080516001600160a01b03909316835260ff90911660208301528051918290030190f35b6103126004803603604081101561063257600080fd5b50803590602001356001600160a01b03166129d4565b6101a76004803603604081101561065e57600080fd5b506001600160a01b038135169060200135612a42565b6106976004803603604081101561068a57600080fd5b5080359060200135612cd1565b604080516001600160401b03808b168252891660208201529081018760028111156106be57fe5b60ff1681526001600160a01b039096166020870152506040808601949094526060850192909252608084015260a0830152519081900360c0019350915050f35b61071b6004803603602081101561071457600080fd5b5035612e28565b604080516001600160a01b038816815260ff8716602082015290810185600281111561074357fe5b60ff9081168252949094166020850152506040808401929092526001600160401b0316606083015251908190036080019350915050f35b6101a76004803603604081101561079057600080fd5b5080359060200135612eb2565b6107a561342e565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f434f4e4649475f474f5645524e4f5200008152509061087b57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610840578181015183820152602001610828565b50505050905090810190601f16801561086d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50610885816134ae565b50565b60006108926135cb565b60408051808201909152601481527f444d5f53454e4445525f4e4f545f564f54494e470000000000000000000000006020820152909150336001600160a01b0383161461092357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000806109308561361a565b9150915061093c615b71565b61094583613661565b9050610958838360018460200151613684565b600061096684848885613747565b90506000816001600160401b0316116040518060400160405280601481526020017f444d5f564f5445525f5745494748545f5a45524f000000000000000000000000815250906109fa57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050505050505050565b8282610a10828261379b565b600060018681548110610a1f57fe5b90600052602060002090600202019050610a37615b71565b610a4082613661565b9050610a53828760038460200151613684565b6000610a5d6135cb565b90506000610a6b8989613852565b90506000826001600160a01b031663084d72f4836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610ab357600080fd5b505afa158015610ac7573d6000803e3d6000fd5b505050506040513d6020811015610add57600080fd5b5051905060ff80821690891614801590610b885750604080517fe2e7ed9f0000000000000000000000000000000000000000000000000000000081526004810184905260ff8a16602482015290516001600160a01b0385169163e2e7ed9f916044808301926020929190829003018186803b158015610b5b57600080fd5b505afa158015610b6f573d6000803e3d6000fd5b505050506040513d6020811015610b8557600080fd5b50515b6040518060400160405280601881526020017f444d5f494e56414c49445f41505045414c5f52554c494e47000000000000000081525090610c0d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000856001018a81548110610c1f57fe5b6000918252602091829020600891909102016006810180543373ffffffffffffffffffffffffffffffffffffffff199091161774ff00000000000000000000000000000000000000001916600160a01b60ff8e16908102919091178255604080519182525192945090928d928f927f57dc4548648c602e9f394f905942ffeba7a2041a6a704128b3a75e5b0efa11a792908290030190a3610cbe615ba4565b610cc9838d8961385c565b9050610cde3382606001518360c00151613ab5565b50505050505050505050505050565b600080610cf98361361a565b91509150610d05615b71565b610d0e83613661565b9050610d21838360018460200151613684565b50505050565b6000805460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b03163314610db957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000610dc4613b6e565b9050610dce615b71565b610dd782613bc6565b9050600260ff871610801590610dfb575080602001516000015160ff168660ff1611155b6040518060400160405280601981526020017f444d5f494e56414c49445f52554c494e475f4f5054494f4e530000000000000081525090610e8057604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060018054600091610e9490828101615bf2565b9050600060018281548110610ea557fe5b90600052602060002090600202019050888160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508781600001601c6101000a81548160ff021916908360ff160217905550838160000160146101000a8154816001600160401b0302191690836001600160401b031602179055506000836020015160e0015190506000610f57856020015160200151876001600160401b0316613ee590919063ffffffff16565b9050806001600160401b03168b6001600160a01b0316857fd4784fc5a2aef689d6639d09cb5b543abfeabd597519d01b93f4ffef74d10396858d8d60405180846001600160401b03166001600160401b03168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a46000806000610ffb886000015186613f86565b92509250925061100f876000868886614000565b5061101b8e8483613ab5565b50949750505050505050505b949350505050565b6000809054906101000a90046001600160a01b03166001600160a01b0316633c28e88b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561107c57600080fd5b505afa158015611090573d6000803e3d6000fd5b505050506040513d60208110156110a657600080fd5b505160408051808201909152601d81527f4354445f53454e4445525f4e4f545f46554e44535f474f5645524e4f520000006020820152906001600160a01b0316331461113657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000916001600160a01b038516916370a0823191602480820192602092909190829003018186803b15801561119a57600080fd5b505afa1580156111ae573d6000803e3d6000fd5b505050506040513d60208110156111c457600080fd5b505160408051808201909152601e81527f4354445f494e53554646494349454e545f5245434f5645525f46554e4453000060208201529091508161124c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506112676001600160a01b038416838363ffffffff61417816565b6040518060400160405280601e81526020017f4354445f5245434f5645525f544f4b454e5f46554e44535f4641494c45440000815250906112ec57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50604080516001600160a01b0380861682528416602082015280820183905290517f724139fea3954691c2c1ee02b3be6be1763b32ec84841f1acad6d3a18695ba0d9181900360600190a1505050565b6000546001600160a01b03165b90565b600054600160a01b90046001600160401b031681565b60008060008060008060008060008a8a61137c828261379b565b600060018e8154811061138b57fe5b906000526020600020906002020190506113ba818e6113a86141ee565b6113b185613661565b60200151614230565b93506000816001018e815481106113cd57fe5b906000526020600020906008020190508060000160009054906101000a90046001600160401b03169c508060040160009054906101000a90046001600160401b03169b508060000160089054906101000a90046001600160401b03169a508060040160089054906101000a90046001600160401b03169950806001015498508060000160109054906101000a900460ff1697508060040160109054906101000a90046001600160401b0316955080600501549650505050509295985092959850929598565b60008084846114a1828261379b565b6000600188815481106114b057fe5b9060005260206000209060020201905060008160010188815481106114d157fe5b906000526020600020906008020190506114e9615b71565b6114f283613661565b90506114fe8982614499565b156115145761150d82896144a6565b96506115c8565b600061151e6144ce565b835460408051600160e01b63e9e67d670281526001600160a01b038d811660048301526001600160401b03909316602482015290519293506000929184169163e9e67d6791604480820192602092909190829003018186803b15801561158357600080fd5b505afa158015611597573d6000803e3d6000fd5b505050506040513d60208110156115ad57600080fd5b50516040840151519091506115c390829061451d565b985050505b506001600160a01b03969096166000908152600390960160205250506040909320549195600160401b90920460ff1694509092505050565b60005460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b0316331461169157604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b508361169c81614552565b6000600186815481106116ab57fe5b6000918252602091829020600290910201805460408051808201909152601e81527f444d5f5355424a4543545f4e4f545f444953505554455f5355424a4543540000938101939093529092506001600160a01b039081169089161461175457604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50846001600160a01b0316867fd25027d3faf6af10da1a82e9d4df3c98b93cb0481f9acaf87718a548fad0abce868660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a350505050505050565b806117d381614552565b60006117dd61133c565b905060006117e961133c565b6001600160a01b03166350c365806040518163ffffffff1660e01b815260040160206040518083038186803b15801561182157600080fd5b505afa158015611835573d6000803e3d6000fd5b505050506040513d602081101561184b57600080fd5b505160408051808201909152601081527f444d5f5445524d5f4f555444415445440000000000000000000000000000000060208201529091506001600160401b038216156118dd57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060006118e86145de565b90506000600186815481106118f957fe5b60009182526020822060029091020191508154600160f01b900460ff16600281111561192157fe5b146040518060400160405280601881526020017f444d5f524f554e445f414c52454144595f445241465445440000000000000000815250906119a757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600181018054600019810191600091839081106119c157fe5b6000918252602091829020600890910201805460408051808201909152601981527f444d5f44524146545f5445524d5f4e4f545f5245414348454400000000000000938101939093529092506001600160401b0390811691908616821115611a6d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000876001600160a01b0316637d1f24c96040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611aab57600080fd5b505af1158015611abf573d6000803e3d6000fd5b505050506040513d6020811015611ad557600080fd5b50519050611ae1615c1e565b611aea83614620565b90506000611b0485611aff8e898c88886146f3565b614733565b90508015611b6f5760048501805467ffffffffffffffff1916858a036001600160401b03161790558654600160f01b60ff021916600160f01b1787556040516001908d907f9bfdc20780e4912d62e8c31a73ffad5cbd841d7f76d114aa9f302ceca2d8258590600090a35b505050505050505050505050565b6000806000808585611b8f828261379b565b600060018981548110611b9e57fe5b90600052602060002090600202016001018881548110611bba57fe5b600091825260209091206006600890920201908101546007909101546001600160a01b038083169c60ff600160a01b9485900481169d509183169b509290910416975095505050505050565b6000806000611c136141ee565b9050611c1d615b71565b611c2682613bc6565b9050611c3e8160000151826020015160e00151613f86565b9196919550909350505050565b8282611c57828261379b565b600060018681548110611c6657fe5b906000526020600020906002020190506000816001018681548110611c8757fe5b906000526020600020906008020190508060000160109054906101000a900460ff166040518060400160405280601e81526020017f444d5f524f554e445f50454e414c544945535f4e4f545f534554544c4544000081525090611d2e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506001600160a01b038516600090815260038201602090815260409182902080548351808501909452601984527f444d5f4a55524f525f414c52454144595f524557415244454400000000000000928401929092529190600160401b900460ff1615611dde57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50805460408051808201909152601e81527f444d5f574f4e545f5245574152445f4e4f4e5f564f5445525f4a55524f5200006020820152906001600160401b0316611e6d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50805468ff00000000000000001916600160401b1781556000611e8e6135cb565b90506000611e9c8a8a613852565b8554604080517fcfa558ba00000000000000000000000000000000000000000000000000000000815260048101849052600160e81b90920460ff1660248301526001600160a01b038b81166044840152905192935084169163cfa558ba91606480820192602092909190829003018186803b158015611f1a57600080fd5b505afa158015611f2e573d6000803e3d6000fd5b505050506040513d6020811015611f4457600080fd5b505160408051808201909152601f81527f444d5f574f4e545f5245574152445f494e434f484552454e545f4a55524f5200602082015290611fc957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060058401546000611fd96144ce565b90506000821561206957611fee878785614a49565b9050816001600160a01b0316634d7edc158c836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b505050505b612071615b71565b61207a89613661565b9050600061208d89898b60010154614a49565b9050612097614a88565b6001600160a01b0316635f52d44e8360000151600001518f846040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b15801561211857600080fd5b505af115801561212c573d6000803e3d6000fd5b5050505061213a8e83614499565b61220357612146615c3e565b82602001519050846001600160a01b031663af8b9d0f8f836101200151846060015185604001518f60000160009054906101000a90046001600160401b03160101016040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b03168152602001826001600160401b03166001600160401b0316815260200192505050600060405180830381600087803b1580156121e957600080fd5b505af11580156121fd573d6000803e3d6000fd5b50505050505b8d8f7f3aea41188dba0e19aa929ada5527b70c76ba34b22bb672818cf2ed788c3c9e778f868560405180846001600160a01b03166001600160a01b03168152602001838152602001828152602001935050505060405180910390a3505050505050505050505050505050565b828261227b828261379b565b60006001868154811061228a57fe5b9060005260206000209060020201905084600014806122d257508060010160018603815481106122b657fe5b6000918252602090912060089091020154600160801b900460ff165b6040518060400160405280601d81526020017f444d5f50524556494f55535f524f554e445f4e4f545f534554544c45440000008152509061235757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600081600101868154811061236957fe5b906000526020600020906008020190508060000160109054906101000a900460ff16156040518060400160405280601881526020017f444d5f524f554e445f414c52454144595f534554544c454400000000000000008152509061241157604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5061241a615b71565b61242383613661565b90506000612432848a84614ad7565b905060006124408a8a613852565b6004850154909150600160c01b90046001600160401b03166125295760006124666135cb565b9050806001600160a01b03166385dbcf7983856040518363ffffffff1660e01b8152600401808381526020018260ff1660ff1681526020019250505060206040518083038186803b1580156124ba57600080fd5b505afa1580156124ce573d6000803e3d6000fd5b505050506040513d60208110156124e457600080fd5b50516004860180546001600160401b03909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909216919091179055505b6000612533614a88565b8451519091506125438b86614499565b15612604576000612568878587896020015160c001518f8b6040015160000151614c39565b9050826001600160a01b0316635f52d44e8333612596858b60000151608001516150f990919063ffffffff16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b1580156125e657600080fd5b505af11580156125fa573d6000803e3d6000fd5b5050505050612623565b855470ff000000000000000000000000000000001916600160801b1786555b8554600160801b900460ff1615611b6f5760058601546040805182815290518d918f917f2f643ff79db9be434873df2e7b4cc272c517e58b5712ea5a20c5d7bfc482f5539181900360200190a3610cde88888e86868661519c565b828261268a828261379b565b60006001868154811061269957fe5b906000526020600020906002020190506126b1615b71565b6126ba82613661565b90506126cd828760048460200151613684565b60008260010187815481106126de57fe5b600091825260208220600890910201915060068201906126fe8a8a613852565b825490915060ff898116600160a01b90920416148015906127a057506127226135cb565b6001600160a01b031663e2e7ed9f828a6040518363ffffffff1660e01b8152600401808381526020018260ff1660ff1681526020019250505060206040518083038186803b15801561277357600080fd5b505afa158015612787573d6000803e3d6000fd5b505050506040513d602081101561279d57600080fd5b50515b6040518060400160405280601881526020017f444d5f494e56414c49445f41505045414c5f52554c494e4700000000000000008152509061282557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5061282e615ba4565b612839848b8761385c565b9050600081604001519050600061285f8d83856000015186602001518760a00151614000565b9050338560010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a8560010160146101000a81548160ff021916908360ff16021790555082600001516001600160401b0316818e7f06c05c98f79e14aad019b270fad6f7d1bcb11dc267667ed908d78e4d5ec9a3eb866020015160405180826001600160401b0316815260200191505060405180910390a4610cde3384606001518560e00151613ab5565b6000808261291b81614552565b60006001858154811061292a57fe5b6000918252602090912060029091020180546001600160a01b031694509050612951615b71565b61295a82613661565b9050612967828783614ad7565b935060028254600160f01b900460ff16600281111561298257fe5b146129cc578154600160f01b60ff021916600160f11b17825560405160ff85169087907f33ebf61f1f1800f29578208d33c8618cf5a27602cd0c4c1978a60651eb531d3b90600090a35b505050915091565b60008060006129e28561361a565b915091506129ee615b71565b6129f783613661565b9050612a0a838360028460200151613684565b6000836001018381548110612a1b57fe5b90600052602060002090600802019050612a3581876144a6565b9450505050505b92915050565b60005460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b03163314612ad357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50806000612ae1828261379b565b600060018481548110612af057fe5b90600052602060002090600202019050600081600101600081548110612b1257fe5b6000918252602091829020845460408051808201909152601e81527f444d5f5355424a4543545f4e4f545f444953505554455f5355424a45435400009481019490945260089092020192506001600160a01b0390811690881614612bba57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000612bc5613b6e565b90506000612be36001600160401b038316600163ffffffff613ee516565b835460408051808201909152601c81527f444d5f45564944454e43455f504552494f445f49535f434c4f5345440000000060208201529192506001600160401b0390811690831610612c7957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50825467ffffffffffffffff19166001600160401b038281169190911784556040519083169088907f1384c9abcdf1fa5a2a50953bad79f58ea7b2999fae7783b5b1e2edff339b8d1c90600090a35050505050505050565b600080600080600080600080612ce78a8a61379b565b600060018b81548110612cf657fe5b90600052602060002090600202019050612d0e615b71565b612d1782613661565b9050612d238b82614499565b6040518060400160405280601181526020017f444d5f524f554e445f49535f46494e414c00000000000000000000000000000081525090612da857604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000826001018c81548110612dba57fe5b90600052602060002090600802019050612dd2615ba4565b612ddd828e8561385c565b9050806000015181602001518260400151836060015184608001518560a001518660c001518760e001519b509b509b509b509b509b509b509b50505050509295985092959890939650565b60008060008060008086612e3b81614552565b600060018981548110612e4a57fe5b6000918252602090912060029091020180546001909101546001600160a01b0382169b600160e01b830460ff9081169c50600160f01b840481169b50600160e81b84041699506000199091019750600160a01b9091046001600160401b031695509350505050565b8181612ebe828261379b565b600060018581548110612ecd57fe5b906000526020600020906002020190506000816001018581548110612eee57fe5b906000526020600020906008020190508060000160109054906101000a900460ff166040518060400160405280601e81526020017f444d5f524f554e445f50454e414c544945535f4e4f545f534554544c4544000081525090612f9557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060068101612fa3816153dd565b6040518060400160405280601581526020017f444d5f524f554e445f4e4f545f41505045414c454400000000000000000000008152509061302857604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600181015460408051808201909152601981527f444d5f41505045414c5f414c52454144595f534554544c454400000000000000602082015290600160a81b900460ff16156130bc57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060018101805475ff0000000000000000000000000000000000000000001916600160a81b179055604051869088907f28d5bc8b3a7bef24e784872d5b3b9069cf63ae040039bcc6040bd0b7af32d2f290600090a3613119615b71565b61312284613661565b905061312c615ba4565b61313784898461385c565b6060810151608082015160c083015160e08401519394509192909190600061315d614a88565b9050613168886153ec565b6131f257875460408051600160e11b632fa96a270281526001600160a01b038881166004830152928316602482015260448101869052905191831691635f52d44e9160648082019260009290919082900301818387803b1580156131cb57600080fd5b505af11580156131df573d6000803e3d6000fd5b5050505050505050505050505050610d21565b8954600160e81b900460ff16600061320a85856153fe565b8a5490915060ff838116600160a01b9092041614156132b75789546001600160a01b0380851691635f52d44e918a911661324a858b63ffffffff61548b16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561329a57600080fd5b505af11580156132ae573d6000803e3d6000fd5b5050505061341c565b60018a015460ff838116600160a01b9092041614156132fa5760018a01546001600160a01b0380851691635f52d44e918a911661324a858b63ffffffff61548b16565b895460028704906001600160a01b0385811691635f52d44e918b91166133208a8661548b565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561337057600080fd5b505af1158015613384573d6000803e3d6000fd5b50505060018c01546001600160a01b038087169250635f52d44e918b91166133b2898663ffffffff61548b16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561340257600080fd5b505af1158015613416573d6000803e3d6000fd5b50505050505b50505050505050505050505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166397023f816040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b505afa158015613491573d6000803e3d6000fd5b505050506040513d60208110156134a757600080fd5b5051905090565b60408051808201909152601b81527f444d5f4241445f4d41585f44524146545f42415443485f53495a45000000000060208201526001600160401b03821661353a57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600054604080516001600160401b03600160a01b90930483168152918316602083015280517fed22db0c227e21d249167e5f9d39415fd9386958f122075463fef70fd46c95c49281900390910190a1600080546001600160401b03909216600160a01b027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60008060009054906101000a90046001600160a01b03166001600160a01b0316631986d3766040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b60006fffffffffffffffffffffffffffffffff8216608083901c61363e818361379b565b6001818154811061364b57fe5b9060005260206000209060020201925050915091565b613669615b71565b8154612a3c90600160a01b90046001600160401b0316613bc6565b600061368e613b6e565b9050600061369e86868486614230565b90508360058111156136ac57fe5b8160058111156136b857fe5b146040518060400160405280601d81526020017f444d5f494e56414c49445f41444a554449434154494f4e5f53544154450000008152509061373e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50505050505050565b60008085600101858154811061375957fe5b906000526020600020906008020190506137738584614499565b6137875761378283828661551d565b613791565b61379181856144a6565b9695505050505050565b6137a482614552565b600182815481106137b157fe5b90600052602060002090600202016001018054905081106040518060400160405280601781526020017f444d5f524f554e445f444f45535f4e4f545f45584953540000000000000000008152509061384d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b505050565b60809190911b0190565b613864615ba4565b61386c615ba4565b613874615c3e565b506020830151600486015486546000916138a0916001600160401b03908116911663ffffffff613ee516565b905060006138e183606001516138cc8560400151856001600160401b0316613ee590919063ffffffff16565b6001600160401b03169063ffffffff613ee516565b905061390b8360a001516138cc8560800151846001600160401b0316613ee590919063ffffffff16565b6001600160401b0316845261014083015161392d90600163ffffffff61548b16565b8710613a24576001604085015260006139446144ce565b90506000816001600160a01b0316638e12779387600001516040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b0316815260200191505060206040518083038186803b1580156139a257600080fd5b505afa1580156139b6573d6000803e3d6000fd5b505050506040513d60208110156139cc57600080fd5b50516040890151519091506000906139e590839061451d565b6001600160401b03811660208901528951909150613a03908261570d565b60808a015260a08901526001600160a01b0316606088015250613a69915050565b60006040850152613a358884615761565b6001600160401b0316602085018190528651613a5091613f86565b608087015260a08601526001600160a01b031660608501525b6101608301516080850151613a839163ffffffff61579d16565b60c08501526101808301516080850151613aa29163ffffffff61579d16565b60e08501525091925050505b9392505050565b801561384d576000613ac5614a88565b9050613ae26001600160a01b03841685838563ffffffff6157c116565b6040518060400160405280601181526020017f444d5f4445504f5349545f4641494c454400000000000000000000000000000081525090613b6757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050505050565b6000613b7861133c565b6001600160a01b0316633f33bf866040518163ffffffff1660e01b8152600401602060405180830381600087803b158015613bb257600080fd5b505af1158015613491573d6000803e3d6000fd5b613bce615b71565b6000613bd8615caa565b6000613be2615cc8565b613bea615ce7565b613bf2615ce7565b613bfa615d05565b613c0261133c565b6001600160a01b031663e008cb628a6040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b031681526020019150506102c06040518083038186803b158015613c5857600080fd5b505afa158015613c6c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506102c0811015613c9257600080fd5b5080516080820151909850602082019750955060a0810194506101c08101935061020081019250610240019050613cc7615b71565b6040805160a0810182526001600160a01b038a16815260208681015161ffff168183015289518284015289810151606083015289830151608083015290835281516101a08101835260ff8916815287516001600160401b03169181019190915290810186600160200201516001600160401b0316815260200186600260098110613d4d57fe5b60200201516001600160401b0316815260200186600360098110613d6d57fe5b60200201516001600160401b0316815260200186600460098110613d8d57fe5b60200201516001600160401b0316815260200185600060028110613dad57fe5b602002015161ffff16815260200186600560098110613dc857fe5b60200201516001600160401b0316815260200186600660098110613de857fe5b60200201516001600160401b0316815260200186600860098110613e0857fe5b60200201516001600160401b0316815260200186600760098110613e2857fe5b60200201516001600160401b0316815260200184600060028110613e4857fe5b6020020151815260200184600160028110613e5f57fe5b60200201518152508160200181905250604051806080016040528083600060048110613e8757fe5b6020020151815260200183600160048110613e9e57fe5b6020020151815260200183600260048110613eb557fe5b6020020151815260200183600360048110613ecc57fe5b6020020151905260408201529998505050505050505050565b60408051808201909152601381527f4d41544836345f4144445f4f564552464c4f57000000000000000000000000006020820152600090838301906001600160401b038086169083161015613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b509392505050565b815160408301516000908190613fac906001600160401b0386169063ffffffff6150f916565b91506000613fe4856001600160401b0316613fd8886080015189606001516153fe90919063ffffffff16565b9063ffffffff6150f916565b9050613ff6838263ffffffff6153fe16565b9150509250925092565b6000806001878154811061401057fe5b906000526020600020906002020190508581600001601e6101000a81548160ff0219169083600281111561404057fe5b0217905550600081600101805480919060010161405d9190615d23565b9050600082600101828154811061407057fe5b60009182526020822060089091020180546001600160401b03898116600160401b026fffffffffffffffff000000000000000019918c1667ffffffffffffffff1990931692909217161781556001810187905591506140cd6135cb565b905060006140db8b85613852565b8554604080517ffaf172f700000000000000000000000000000000000000000000000000000000815260048101849052600160e01b90920460ff166024830152519192506001600160a01b0384169163faf172f79160448082019260009290919082900301818387803b15801561415157600080fd5b505af1158015614165573d6000803e3d6000fd5b50959d9c50505050505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b03167fa9059cbb000000000000000000000000000000000000000000000000000000001790526000906141e58582615832565b95945050505050565b60006141f861133c565b6001600160a01b03166308135a936040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b60008085600101858154811061424257fe5b600091825260209091206001880154600890920201915060028754600160f01b900460ff16600281111561427257fe5b148061428d575061428a81600163ffffffff61548b16565b86105b1561429d57600592505050611027565b600482015482546000916142c3916001600160401b03908116911663ffffffff613ee516565b905060008854600160f01b900460ff1660028111156142de57fe5b14806142fb5750806001600160401b0316866001600160401b0316105b1561430c5760009350505050611027565b600061432e8660400151836001600160401b0316613ee590919063ffffffff16565b9050806001600160401b0316876001600160401b03161015614357576001945050505050611027565b60006143798760600151836001600160401b0316613ee590919063ffffffff16565b9050806001600160401b0316886001600160401b031610156143a357600295505050505050611027565b610140870151841180156143c05760059650505050505050611027565b60006143ce876006016153dd565b905060006143f28a60800151856001600160401b0316613ee590919063ffffffff16565b90508161443557806001600160401b03168b6001600160401b0316101561442457600398505050505050505050611027565b600598505050505050505050611027565b60006144578b60a00151836001600160401b0316613ee590919063ffffffff16565b9050806001600160401b03168c6001600160401b031610156144855760049950505050505050505050611027565b5060059d9c50505050505050505050505050565b6020015161014001511190565b6001600160a01b0316600090815260039190910160205260409020546001600160401b031690565b60008060009054906101000a90046001600160a01b03166001600160a01b031663953e46a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b60008183101561452f57506000612a3c565b613aae826145456103e88663ffffffff6150f916565b8161454c57fe5b0461587d565b60015460408051808201909152601981527f444d5f444953505554455f444f45535f4e4f545f45584953540000000000000060208201529082106145da57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050565b60006145e861133c565b6001600160a01b031663f7fe57896040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b614628615c1e565b600080600061463561133c565b6001600160a01b03166369667005866040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b0316815260200191505060606040518083038186803b15801561468a57600080fd5b505afa15801561469e573d6000803e3d6000fd5b505050506040513d60608110156146b457600080fd5b50805160208083015160409384015184516060810186526001600160a01b03909416845261ffff16918301919091529181019190915295945050505050565b6146fb615d4f565b506040805160a08101825295865260208601949094526001600160401b03909216928401929092526060830191909152608082015290565b815460048301546000805490926001600160401b03600160401b9182900481169391909104811691600160a01b90041683614774848463ffffffff61591416565b90506000826001600160401b0316826001600160401b0316106147975782614799565b815b90506147a3615d8a565b6040518060e00160405280896060015160001c81526020018960000151815260200189604001516001600160401b03168152602001866001600160401b03168152602001836001600160401b03168152602001876001600160401b0316815260200189608001516020015161ffff16815250905060006148216144ce565b905060606000826001600160a01b031663d903bcf4856040518263ffffffff1660e01b81526004018082600760200280838360005b8381101561486e578181015183820152602001614856565b50505050905001915050600060405180830381600087803b15801561489257600080fd5b505af11580156148a6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160409081528110156148cf57600080fd5b8101908080516401000000008111156148e757600080fd5b820160208101848111156148fa57600080fd5b815185602082028301116401000000008211171561491757600080fd5b505060209091015190945092506000915061494390506001600160401b038a168363ffffffff613ee516565b60048e0180546fffffffffffffffff00000000000000001916600160401b6001600160401b038416021790558c5160208e0151919250614985918f86866159b1565b60808c0151604001516001600160401b03828116908c1614906000906149b1908563ffffffff6150f916565b90506149bb614a88565b60808f01515160408051600160e11b632fa96a270281526001600160a01b0392831660048201523360248201526044810185905290519290911691635f52d44e9160648082019260009290919082900301818387803b158015614a1d57600080fd5b505af1158015614a31573d6000803e3d6000fd5b50939e50505050505050505050505050505092915050565b600483015482546000916001600160401b03600160801b909104811691614a789185911663ffffffff6150f916565b81614a7f57fe5b04949350505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316633b19e84a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b8254600090600160e81b900460ff1615614afd57508254600160e81b900460ff16613aae565b600060018560010180549050039050614b1d858260058660200151613684565b6000856001018281548110614b2e57fe5b60009182526020822060089091020191506006820190614b4d826153dd565b8015614b5f5750614b5d826153ec565b155b9050600081614bed57614b706135cb565b6001600160a01b031663084d72f4614b888a88613852565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015614bbc57600080fd5b505afa158015614bd0573d6000803e3d6000fd5b505050506040513d6020811015614be657600080fd5b5051614bfa565b8254600160a01b900460ff165b89547fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160e81b60ff831602179099555096979650505050505050565b600080614c44613b6e565b600489015460028a0154919250600160c01b90046001600160401b031690600090614c6f908361548b565b9050600086118015614c8057508581115b15614c8c575084614cab565b895470ff000000000000000000000000000000001916600160801b178a555b614cbb828263ffffffff6153fe16565b8a60040160186101000a8154816001600160401b0302191690836001600160401b031602179055506000614ced6144ce565b9050606082604051908082528060200260200182016040528015614d1b578160200160208202803883390190505b509050606083604051908082528060200260200182016040528015614d4a578160200160208202803883390190505b50905060005b84811015614e355760008e60020182880181548110614d6b57fe5b9060005260206000200160009054906101000a90046001600160a01b0316905080848381518110614d9857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050614e158f6003016000836001600160a01b03166001600160a01b0316815260200190815260200160002060000160009054906101000a90046001600160401b03166001600160401b0316613fd88e8d615abc90919063ffffffff16565b838381518110614e2157fe5b602090810291909101015250600101614d50565b506060614e406135cb565b6001600160a01b03166318ce8f568e8e866040518463ffffffff1660e01b8152600401808481526020018360ff1660ff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b83811015614eb2578181015183820152602001614e9a565b5050505090500194505050505060006040518083038186803b158015614ed757600080fd5b505afa158015614eeb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015614f1457600080fd5b810190808051640100000000811115614f2c57600080fd5b82016020810184811115614f3f57600080fd5b8151856020820283011164010000000082111715614f5c57600080fd5b505092919050505090506150e1846001600160a01b031663c67106f5898686866040518563ffffffff1660e01b815260040180856001600160401b03166001600160401b03168152602001806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b83811015614feb578181015183820152602001614fd3565b50505050905001848103835286818151815260200191508051906020019060200280838360005b8381101561502a578181015183820152602001615012565b50505050905001848103825285818151815260200191508051906020019060200280838360005b83811015615069578181015183820152602001615051565b50505050905001975050505050505050602060405180830381600087803b15801561509357600080fd5b505af11580156150a7573d6000803e3d6000fd5b505050506040513d60208110156150bd57600080fd5b81019080805190602001909291905050508f600501546153fe90919063ffffffff16565b60058f01555092955050505050509695505050505050565b60008261510857506000612a3c565b8282028284828161511557fe5b04146040518060400160405280601181526020017f4d4154485f4d554c5f4f564552464c4f5700000000000000000000000000000081525090613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b6004850154600160801b90046001600160401b0316156151bb576153d5565b801561522d5760006151cb6144ce565b9050806001600160a01b0316636d1b229d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561521357600080fd5b505af1158015615227573d6000803e3d6000fd5b50505050505b836152b3578554600186015460408051600160e11b632fa96a270281526001600160a01b038681166004830152938416602482015260448101929092525191851691635f52d44e9160648082019260009290919082900301818387803b15801561529657600080fd5b505af11580156152aa573d6000803e3d6000fd5b505050506153d5565b600060028660010154816152c357fe5b04905060008760010160018703815481106152da57fe5b600091825260208220600660089092020101805460408051600160e11b632fa96a270281526001600160a01b038981166004830152928316602482015260448101879052905192945090881692635f52d44e9260648084019382900301818387803b15801561534857600080fd5b505af115801561535c573d6000803e3d6000fd5b505050600182015460408051600160e11b632fa96a270281526001600160a01b03888116600483015292831660248201526044810186905290519188169250635f52d44e91606480830192600092919082900301818387803b1580156153c157600080fd5b505af1158015611b6f573d6000803e3d6000fd5b505050505050565b546001600160a01b0316151590565b600101546001600160a01b0316151590565b60408051808201909152601181527f4d4154485f4144445f4f564552464c4f5700000000000000000000000000000060208201526000908383019084821015613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b6000828211156040518060400160405280601281526020017f4d4154485f5355425f554e444552464c4f5700000000000000000000000000008152509061551657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050900390565b6000806155286144ce565b845460408051600160e01b63e9e67d670281526001600160a01b0387811660048301526001600160401b03909316602482015290519293506000929184169163e9e67d6791604480820192602092909190829003018186803b15801561558d57600080fd5b505afa1580156155a1573d6000803e3d6000fd5b505050506040513d60208110156155b757600080fd5b50516040870151519091506000906155d090839061451d565b90506001600160401b0381166155ec5760009350505050613aae565b6000615609886020015160c0015184615abc90919063ffffffff16565b9050836001600160a01b031663605da1b287836156246145de565b6040805163ffffffff861660e01b81526001600160a01b03909416600485015260248401929092526001600160401b031660448301525160648083019260209291908290030181600087803b15801561567c57600080fd5b505af1158015615690573d6000803e3d6000fd5b505050506040513d60208110156156a657600080fd5b50516156b9576000945050505050613aae565b6001600160a01b03861660009081526003880160205260409020805467ffffffffffffffff19166001600160401b03841617905560058701546156fc90826153fe565b600588015550925050509392505050565b815160208301516040840151600091829161575591906103e890615741906001600160401b0389169063ffffffff6150f916565b8161574857fe5b049063ffffffff615abc16565b91508190509250925092565b6101008101518254600091829161578991600160401b9091046001600160401b031690615ad5565b905060018116613aae576001019392505050565b60006127106157b2848463ffffffff6150f916565b816157b957fe5b049392505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03167f23b872dd0000000000000000000000000000000000000000000000000000000017905260009061379186825b6000806040516020818551602087016000895af18015615873573d8015615860576020811461586957615871565b60019350615871565b600183511493505b505b5090949350505050565b60408051808201909152601581527f55494e5436345f4e554d4245525f544f4f5f424947000000000000000000000060208201526000906001600160401b0383111561590d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5090919050565b6000826001600160401b0316826001600160401b031611156040518060400160405280601481526020017f4d41544836345f5355425f554e444552464c4f570000000000000000000000008152509061551657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b60005b818110156153d55760008382815181106159ca57fe5b6020908102919091018101516001600160a01b03811660009081526003880190925260409091208054919250906001600160401b0316615a42576002860180546001810182556000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384161790555b8054615a5e906001600160401b0316600163ffffffff613ee516565b815467ffffffffffffffff19166001600160401b03919091161781556040516001600160a01b0383169088908a907fbfd1b785c517ac3c709db5d7c9904052346df35e7069c1cb80f3dd966579d52290600090a450506001016159b4565b60006127106157b28461ffff851663ffffffff6150f916565b60408051808201909152601381527f4d41544836345f4d554c5f4f564552464c4f570000000000000000000000000060208201526000906001600160401b038481169084160290600160401b8210613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b604051806102c00160405280615b85615da8565b8152602001615b92615c3e565b8152602001615b9f615de4565b905290565b60408051610100810182526000808252602082018190529091820190815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b81548183558181111561384d5760020281600202836000526020600020918201910161384d9190615e0c565b604080516060810182526000808252602082018190529181019190915290565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081019190915290565b60405180606001604052806003906020820280388339509192915050565b6040518061012001604052806009906020820280388339509192915050565b60405180604001604052806002906020820280388339509192915050565b60405180608001604052806004906020820280388339509192915050565b81548183558181111561384d5760080281600802836000526020600020918201910161384d9190615e5c565b6040518060e00160405280600081526020016000815260200160006001600160401b0316815260200160008019168152602001615b9f615c1e565b6040518060e001604052806007906020820280388339509192915050565b6040518060a0016040528060006001600160a01b03168152602001600061ffff1681526020016000815260200160008152602001600081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b61134991905b80821115615e585780547fff000000000000000000000000000000000000000000000000000000000000001681556000615e4f6001830182615ef0565b50600201615e12565b5090565b61134991905b80821115615e5857805470ffffffffffffffffffffffffffffffffff19168155600060018201819055615e986002830182615f11565b50600060048201819055600582015560068101805474ffffffffffffffffffffffffffffffffffffffffff1916905560078101805475ffffffffffffffffffffffffffffffffffffffffffff19169055600801615e62565b50805460008255600802906000526020600020908101906108859190615e5c565b5080546000825590600052602060002090810190610885919061134991905b80821115615e585760008155600101615f3056fea165627a7a7230582020c137edb6f0f5f0da0d0d361d22809d8f4b8382642960f9058207418aaf2b340029000000000000000000000000f0c8376065fadfacb706cafbaac96b321069c01500000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000001

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061017c5760003560e01c8063710cf1ed116100e3578063bd881e531161008c578063cd604ada11610066578063cd604ada14610674578063e3a96cbd146106fe578063eed04b801461077a5761017c565b8063bd881e53146105da578063c1361a7c1461061c578063c39c83d1146106485761017c565b806382a8b3b0116100bd57806382a8b3b014610553578063859ba187146105855780639c0065f7146105ae5761017c565b8063710cf1ed146104ab5780637263bf2a146104c85780637b751b9e146105285761017c565b806324ae6a271161014557806339ec68a31161011f57806339ec68a31461032e5780634b4acfd3146103c75780635bdaf9d81461041c5761017c565b806324ae6a27146102b85780633018205f146102e65780633238f8f41461030a5761017c565b80629230a51461018157806306349cfa146101a95780630d03d126146101d557806315fe5268146102015780631d2fa1fb1461021e575b600080fd5b6101a76004803603602081101561019757600080fd5b50356001600160401b031661079d565b005b6101a7600480360360408110156101bf57600080fd5b50803590602001356001600160a01b0316610888565b6101a7600480360360608110156101eb57600080fd5b508035906020810135906040013560ff16610a04565b6101a76004803603602081101561021757600080fd5b5035610ced565b6102a66004803603606081101561023457600080fd5b6001600160a01b038235169160ff6020820135169181019060608101604082013564010000000081111561026757600080fd5b82018360208201111561027957600080fd5b8035906020019184600183028401116401000000008311171561029b57600080fd5b509092509050610d27565b60408051918252519081900360200190f35b6101a7600480360360408110156102ce57600080fd5b506001600160a01b038135811691602001351661102f565b6102ee61133c565b604080516001600160a01b039092168252519081900360200190f35b61031261134c565b604080516001600160401b039092168252519081900360200190f35b6103516004803603604081101561034457600080fd5b5080359060200135611362565b604080516001600160401b03808c1682528a811660208301528981169282019290925287821660608201526080810187905285151560a082015260c0810185905290831660e082015261010081018260058111156103ab57fe5b60ff168152602001995050505050505050505060405180910390f35b6103f9600480360360608110156103dd57600080fd5b50803590602081013590604001356001600160a01b0316611492565b604080516001600160401b03909316835290151560208301528051918290030190f35b6101a76004803603608081101561043257600080fd5b6001600160a01b03823581169260208101359260408201359092169181019060808101606082013564010000000081111561046c57600080fd5b82018360208201111561047e57600080fd5b803590602001918460018302840111640100000000831117156104a057600080fd5b509092509050611600565b6101a7600480360360208110156104c157600080fd5b50356117c9565b6104eb600480360360408110156104de57600080fd5b5080359060200135611b7d565b604080516001600160a01b0395861681526001600160401b0394851660208201529290941682850152909116606082015290519081900360800190f35b610530611c06565b604080516001600160a01b03909316835260208301919091528051918290030190f35b6101a76004803603606081101561056957600080fd5b50803590602081013590604001356001600160a01b0316611c4b565b6101a76004803603606081101561059b57600080fd5b508035906020810135906040013561226f565b6101a7600480360360608110156105c457600080fd5b508035906020810135906040013560ff1661267e565b6105f7600480360360208110156105f057600080fd5b503561290e565b604080516001600160a01b03909316835260ff90911660208301528051918290030190f35b6103126004803603604081101561063257600080fd5b50803590602001356001600160a01b03166129d4565b6101a76004803603604081101561065e57600080fd5b506001600160a01b038135169060200135612a42565b6106976004803603604081101561068a57600080fd5b5080359060200135612cd1565b604080516001600160401b03808b168252891660208201529081018760028111156106be57fe5b60ff1681526001600160a01b039096166020870152506040808601949094526060850192909252608084015260a0830152519081900360c0019350915050f35b61071b6004803603602081101561071457600080fd5b5035612e28565b604080516001600160a01b038816815260ff8716602082015290810185600281111561074357fe5b60ff9081168252949094166020850152506040808401929092526001600160401b0316606083015251908190036080019350915050f35b6101a76004803603604081101561079057600080fd5b5080359060200135612eb2565b6107a561342e565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f434f4e4649475f474f5645524e4f5200008152509061087b57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610840578181015183820152602001610828565b50505050905090810190601f16801561086d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50610885816134ae565b50565b60006108926135cb565b60408051808201909152601481527f444d5f53454e4445525f4e4f545f564f54494e470000000000000000000000006020820152909150336001600160a01b0383161461092357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000806109308561361a565b9150915061093c615b71565b61094583613661565b9050610958838360018460200151613684565b600061096684848885613747565b90506000816001600160401b0316116040518060400160405280601481526020017f444d5f564f5445525f5745494748545f5a45524f000000000000000000000000815250906109fa57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050505050505050565b8282610a10828261379b565b600060018681548110610a1f57fe5b90600052602060002090600202019050610a37615b71565b610a4082613661565b9050610a53828760038460200151613684565b6000610a5d6135cb565b90506000610a6b8989613852565b90506000826001600160a01b031663084d72f4836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610ab357600080fd5b505afa158015610ac7573d6000803e3d6000fd5b505050506040513d6020811015610add57600080fd5b5051905060ff80821690891614801590610b885750604080517fe2e7ed9f0000000000000000000000000000000000000000000000000000000081526004810184905260ff8a16602482015290516001600160a01b0385169163e2e7ed9f916044808301926020929190829003018186803b158015610b5b57600080fd5b505afa158015610b6f573d6000803e3d6000fd5b505050506040513d6020811015610b8557600080fd5b50515b6040518060400160405280601881526020017f444d5f494e56414c49445f41505045414c5f52554c494e47000000000000000081525090610c0d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000856001018a81548110610c1f57fe5b6000918252602091829020600891909102016006810180543373ffffffffffffffffffffffffffffffffffffffff199091161774ff00000000000000000000000000000000000000001916600160a01b60ff8e16908102919091178255604080519182525192945090928d928f927f57dc4548648c602e9f394f905942ffeba7a2041a6a704128b3a75e5b0efa11a792908290030190a3610cbe615ba4565b610cc9838d8961385c565b9050610cde3382606001518360c00151613ab5565b50505050505050505050505050565b600080610cf98361361a565b91509150610d05615b71565b610d0e83613661565b9050610d21838360018460200151613684565b50505050565b6000805460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b03163314610db957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000610dc4613b6e565b9050610dce615b71565b610dd782613bc6565b9050600260ff871610801590610dfb575080602001516000015160ff168660ff1611155b6040518060400160405280601981526020017f444d5f494e56414c49445f52554c494e475f4f5054494f4e530000000000000081525090610e8057604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060018054600091610e9490828101615bf2565b9050600060018281548110610ea557fe5b90600052602060002090600202019050888160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508781600001601c6101000a81548160ff021916908360ff160217905550838160000160146101000a8154816001600160401b0302191690836001600160401b031602179055506000836020015160e0015190506000610f57856020015160200151876001600160401b0316613ee590919063ffffffff16565b9050806001600160401b03168b6001600160a01b0316857fd4784fc5a2aef689d6639d09cb5b543abfeabd597519d01b93f4ffef74d10396858d8d60405180846001600160401b03166001600160401b03168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a46000806000610ffb886000015186613f86565b92509250925061100f876000868886614000565b5061101b8e8483613ab5565b50949750505050505050505b949350505050565b6000809054906101000a90046001600160a01b03166001600160a01b0316633c28e88b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561107c57600080fd5b505afa158015611090573d6000803e3d6000fd5b505050506040513d60208110156110a657600080fd5b505160408051808201909152601d81527f4354445f53454e4445525f4e4f545f46554e44535f474f5645524e4f520000006020820152906001600160a01b0316331461113657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000916001600160a01b038516916370a0823191602480820192602092909190829003018186803b15801561119a57600080fd5b505afa1580156111ae573d6000803e3d6000fd5b505050506040513d60208110156111c457600080fd5b505160408051808201909152601e81527f4354445f494e53554646494349454e545f5245434f5645525f46554e4453000060208201529091508161124c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506112676001600160a01b038416838363ffffffff61417816565b6040518060400160405280601e81526020017f4354445f5245434f5645525f544f4b454e5f46554e44535f4641494c45440000815250906112ec57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50604080516001600160a01b0380861682528416602082015280820183905290517f724139fea3954691c2c1ee02b3be6be1763b32ec84841f1acad6d3a18695ba0d9181900360600190a1505050565b6000546001600160a01b03165b90565b600054600160a01b90046001600160401b031681565b60008060008060008060008060008a8a61137c828261379b565b600060018e8154811061138b57fe5b906000526020600020906002020190506113ba818e6113a86141ee565b6113b185613661565b60200151614230565b93506000816001018e815481106113cd57fe5b906000526020600020906008020190508060000160009054906101000a90046001600160401b03169c508060040160009054906101000a90046001600160401b03169b508060000160089054906101000a90046001600160401b03169a508060040160089054906101000a90046001600160401b03169950806001015498508060000160109054906101000a900460ff1697508060040160109054906101000a90046001600160401b0316955080600501549650505050509295985092959850929598565b60008084846114a1828261379b565b6000600188815481106114b057fe5b9060005260206000209060020201905060008160010188815481106114d157fe5b906000526020600020906008020190506114e9615b71565b6114f283613661565b90506114fe8982614499565b156115145761150d82896144a6565b96506115c8565b600061151e6144ce565b835460408051600160e01b63e9e67d670281526001600160a01b038d811660048301526001600160401b03909316602482015290519293506000929184169163e9e67d6791604480820192602092909190829003018186803b15801561158357600080fd5b505afa158015611597573d6000803e3d6000fd5b505050506040513d60208110156115ad57600080fd5b50516040840151519091506115c390829061451d565b985050505b506001600160a01b03969096166000908152600390960160205250506040909320549195600160401b90920460ff1694509092505050565b60005460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b0316331461169157604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b508361169c81614552565b6000600186815481106116ab57fe5b6000918252602091829020600290910201805460408051808201909152601e81527f444d5f5355424a4543545f4e4f545f444953505554455f5355424a4543540000938101939093529092506001600160a01b039081169089161461175457604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50846001600160a01b0316867fd25027d3faf6af10da1a82e9d4df3c98b93cb0481f9acaf87718a548fad0abce868660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a350505050505050565b806117d381614552565b60006117dd61133c565b905060006117e961133c565b6001600160a01b03166350c365806040518163ffffffff1660e01b815260040160206040518083038186803b15801561182157600080fd5b505afa158015611835573d6000803e3d6000fd5b505050506040513d602081101561184b57600080fd5b505160408051808201909152601081527f444d5f5445524d5f4f555444415445440000000000000000000000000000000060208201529091506001600160401b038216156118dd57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060006118e86145de565b90506000600186815481106118f957fe5b60009182526020822060029091020191508154600160f01b900460ff16600281111561192157fe5b146040518060400160405280601881526020017f444d5f524f554e445f414c52454144595f445241465445440000000000000000815250906119a757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600181018054600019810191600091839081106119c157fe5b6000918252602091829020600890910201805460408051808201909152601981527f444d5f44524146545f5445524d5f4e4f545f5245414348454400000000000000938101939093529092506001600160401b0390811691908616821115611a6d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000876001600160a01b0316637d1f24c96040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611aab57600080fd5b505af1158015611abf573d6000803e3d6000fd5b505050506040513d6020811015611ad557600080fd5b50519050611ae1615c1e565b611aea83614620565b90506000611b0485611aff8e898c88886146f3565b614733565b90508015611b6f5760048501805467ffffffffffffffff1916858a036001600160401b03161790558654600160f01b60ff021916600160f01b1787556040516001908d907f9bfdc20780e4912d62e8c31a73ffad5cbd841d7f76d114aa9f302ceca2d8258590600090a35b505050505050505050505050565b6000806000808585611b8f828261379b565b600060018981548110611b9e57fe5b90600052602060002090600202016001018881548110611bba57fe5b600091825260209091206006600890920201908101546007909101546001600160a01b038083169c60ff600160a01b9485900481169d509183169b509290910416975095505050505050565b6000806000611c136141ee565b9050611c1d615b71565b611c2682613bc6565b9050611c3e8160000151826020015160e00151613f86565b9196919550909350505050565b8282611c57828261379b565b600060018681548110611c6657fe5b906000526020600020906002020190506000816001018681548110611c8757fe5b906000526020600020906008020190508060000160109054906101000a900460ff166040518060400160405280601e81526020017f444d5f524f554e445f50454e414c544945535f4e4f545f534554544c4544000081525090611d2e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506001600160a01b038516600090815260038201602090815260409182902080548351808501909452601984527f444d5f4a55524f525f414c52454144595f524557415244454400000000000000928401929092529190600160401b900460ff1615611dde57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50805460408051808201909152601e81527f444d5f574f4e545f5245574152445f4e4f4e5f564f5445525f4a55524f5200006020820152906001600160401b0316611e6d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50805468ff00000000000000001916600160401b1781556000611e8e6135cb565b90506000611e9c8a8a613852565b8554604080517fcfa558ba00000000000000000000000000000000000000000000000000000000815260048101849052600160e81b90920460ff1660248301526001600160a01b038b81166044840152905192935084169163cfa558ba91606480820192602092909190829003018186803b158015611f1a57600080fd5b505afa158015611f2e573d6000803e3d6000fd5b505050506040513d6020811015611f4457600080fd5b505160408051808201909152601f81527f444d5f574f4e545f5245574152445f494e434f484552454e545f4a55524f5200602082015290611fc957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060058401546000611fd96144ce565b90506000821561206957611fee878785614a49565b9050816001600160a01b0316634d7edc158c836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b505050505b612071615b71565b61207a89613661565b9050600061208d89898b60010154614a49565b9050612097614a88565b6001600160a01b0316635f52d44e8360000151600001518f846040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b15801561211857600080fd5b505af115801561212c573d6000803e3d6000fd5b5050505061213a8e83614499565b61220357612146615c3e565b82602001519050846001600160a01b031663af8b9d0f8f836101200151846060015185604001518f60000160009054906101000a90046001600160401b03160101016040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b03168152602001826001600160401b03166001600160401b0316815260200192505050600060405180830381600087803b1580156121e957600080fd5b505af11580156121fd573d6000803e3d6000fd5b50505050505b8d8f7f3aea41188dba0e19aa929ada5527b70c76ba34b22bb672818cf2ed788c3c9e778f868560405180846001600160a01b03166001600160a01b03168152602001838152602001828152602001935050505060405180910390a3505050505050505050505050505050565b828261227b828261379b565b60006001868154811061228a57fe5b9060005260206000209060020201905084600014806122d257508060010160018603815481106122b657fe5b6000918252602090912060089091020154600160801b900460ff165b6040518060400160405280601d81526020017f444d5f50524556494f55535f524f554e445f4e4f545f534554544c45440000008152509061235757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600081600101868154811061236957fe5b906000526020600020906008020190508060000160109054906101000a900460ff16156040518060400160405280601881526020017f444d5f524f554e445f414c52454144595f534554544c454400000000000000008152509061241157604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5061241a615b71565b61242383613661565b90506000612432848a84614ad7565b905060006124408a8a613852565b6004850154909150600160c01b90046001600160401b03166125295760006124666135cb565b9050806001600160a01b03166385dbcf7983856040518363ffffffff1660e01b8152600401808381526020018260ff1660ff1681526020019250505060206040518083038186803b1580156124ba57600080fd5b505afa1580156124ce573d6000803e3d6000fd5b505050506040513d60208110156124e457600080fd5b50516004860180546001600160401b03909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909216919091179055505b6000612533614a88565b8451519091506125438b86614499565b15612604576000612568878587896020015160c001518f8b6040015160000151614c39565b9050826001600160a01b0316635f52d44e8333612596858b60000151608001516150f990919063ffffffff16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b1580156125e657600080fd5b505af11580156125fa573d6000803e3d6000fd5b5050505050612623565b855470ff000000000000000000000000000000001916600160801b1786555b8554600160801b900460ff1615611b6f5760058601546040805182815290518d918f917f2f643ff79db9be434873df2e7b4cc272c517e58b5712ea5a20c5d7bfc482f5539181900360200190a3610cde88888e86868661519c565b828261268a828261379b565b60006001868154811061269957fe5b906000526020600020906002020190506126b1615b71565b6126ba82613661565b90506126cd828760048460200151613684565b60008260010187815481106126de57fe5b600091825260208220600890910201915060068201906126fe8a8a613852565b825490915060ff898116600160a01b90920416148015906127a057506127226135cb565b6001600160a01b031663e2e7ed9f828a6040518363ffffffff1660e01b8152600401808381526020018260ff1660ff1681526020019250505060206040518083038186803b15801561277357600080fd5b505afa158015612787573d6000803e3d6000fd5b505050506040513d602081101561279d57600080fd5b50515b6040518060400160405280601881526020017f444d5f494e56414c49445f41505045414c5f52554c494e4700000000000000008152509061282557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5061282e615ba4565b612839848b8761385c565b9050600081604001519050600061285f8d83856000015186602001518760a00151614000565b9050338560010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a8560010160146101000a81548160ff021916908360ff16021790555082600001516001600160401b0316818e7f06c05c98f79e14aad019b270fad6f7d1bcb11dc267667ed908d78e4d5ec9a3eb866020015160405180826001600160401b0316815260200191505060405180910390a4610cde3384606001518560e00151613ab5565b6000808261291b81614552565b60006001858154811061292a57fe5b6000918252602090912060029091020180546001600160a01b031694509050612951615b71565b61295a82613661565b9050612967828783614ad7565b935060028254600160f01b900460ff16600281111561298257fe5b146129cc578154600160f01b60ff021916600160f11b17825560405160ff85169087907f33ebf61f1f1800f29578208d33c8618cf5a27602cd0c4c1978a60651eb531d3b90600090a35b505050915091565b60008060006129e28561361a565b915091506129ee615b71565b6129f783613661565b9050612a0a838360028460200151613684565b6000836001018381548110612a1b57fe5b90600052602060002090600802019050612a3581876144a6565b9450505050505b92915050565b60005460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b03163314612ad357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50806000612ae1828261379b565b600060018481548110612af057fe5b90600052602060002090600202019050600081600101600081548110612b1257fe5b6000918252602091829020845460408051808201909152601e81527f444d5f5355424a4543545f4e4f545f444953505554455f5355424a45435400009481019490945260089092020192506001600160a01b0390811690881614612bba57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000612bc5613b6e565b90506000612be36001600160401b038316600163ffffffff613ee516565b835460408051808201909152601c81527f444d5f45564944454e43455f504552494f445f49535f434c4f5345440000000060208201529192506001600160401b0390811690831610612c7957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50825467ffffffffffffffff19166001600160401b038281169190911784556040519083169088907f1384c9abcdf1fa5a2a50953bad79f58ea7b2999fae7783b5b1e2edff339b8d1c90600090a35050505050505050565b600080600080600080600080612ce78a8a61379b565b600060018b81548110612cf657fe5b90600052602060002090600202019050612d0e615b71565b612d1782613661565b9050612d238b82614499565b6040518060400160405280601181526020017f444d5f524f554e445f49535f46494e414c00000000000000000000000000000081525090612da857604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000826001018c81548110612dba57fe5b90600052602060002090600802019050612dd2615ba4565b612ddd828e8561385c565b9050806000015181602001518260400151836060015184608001518560a001518660c001518760e001519b509b509b509b509b509b509b509b50505050509295985092959890939650565b60008060008060008086612e3b81614552565b600060018981548110612e4a57fe5b6000918252602090912060029091020180546001909101546001600160a01b0382169b600160e01b830460ff9081169c50600160f01b840481169b50600160e81b84041699506000199091019750600160a01b9091046001600160401b031695509350505050565b8181612ebe828261379b565b600060018581548110612ecd57fe5b906000526020600020906002020190506000816001018581548110612eee57fe5b906000526020600020906008020190508060000160109054906101000a900460ff166040518060400160405280601e81526020017f444d5f524f554e445f50454e414c544945535f4e4f545f534554544c4544000081525090612f9557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060068101612fa3816153dd565b6040518060400160405280601581526020017f444d5f524f554e445f4e4f545f41505045414c454400000000000000000000008152509061302857604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600181015460408051808201909152601981527f444d5f41505045414c5f414c52454144595f534554544c454400000000000000602082015290600160a81b900460ff16156130bc57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060018101805475ff0000000000000000000000000000000000000000001916600160a81b179055604051869088907f28d5bc8b3a7bef24e784872d5b3b9069cf63ae040039bcc6040bd0b7af32d2f290600090a3613119615b71565b61312284613661565b905061312c615ba4565b61313784898461385c565b6060810151608082015160c083015160e08401519394509192909190600061315d614a88565b9050613168886153ec565b6131f257875460408051600160e11b632fa96a270281526001600160a01b038881166004830152928316602482015260448101869052905191831691635f52d44e9160648082019260009290919082900301818387803b1580156131cb57600080fd5b505af11580156131df573d6000803e3d6000fd5b5050505050505050505050505050610d21565b8954600160e81b900460ff16600061320a85856153fe565b8a5490915060ff838116600160a01b9092041614156132b75789546001600160a01b0380851691635f52d44e918a911661324a858b63ffffffff61548b16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561329a57600080fd5b505af11580156132ae573d6000803e3d6000fd5b5050505061341c565b60018a015460ff838116600160a01b9092041614156132fa5760018a01546001600160a01b0380851691635f52d44e918a911661324a858b63ffffffff61548b16565b895460028704906001600160a01b0385811691635f52d44e918b91166133208a8661548b565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561337057600080fd5b505af1158015613384573d6000803e3d6000fd5b50505060018c01546001600160a01b038087169250635f52d44e918b91166133b2898663ffffffff61548b16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561340257600080fd5b505af1158015613416573d6000803e3d6000fd5b50505050505b50505050505050505050505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166397023f816040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b505afa158015613491573d6000803e3d6000fd5b505050506040513d60208110156134a757600080fd5b5051905090565b60408051808201909152601b81527f444d5f4241445f4d41585f44524146545f42415443485f53495a45000000000060208201526001600160401b03821661353a57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600054604080516001600160401b03600160a01b90930483168152918316602083015280517fed22db0c227e21d249167e5f9d39415fd9386958f122075463fef70fd46c95c49281900390910190a1600080546001600160401b03909216600160a01b027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60008060009054906101000a90046001600160a01b03166001600160a01b0316631986d3766040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b60006fffffffffffffffffffffffffffffffff8216608083901c61363e818361379b565b6001818154811061364b57fe5b9060005260206000209060020201925050915091565b613669615b71565b8154612a3c90600160a01b90046001600160401b0316613bc6565b600061368e613b6e565b9050600061369e86868486614230565b90508360058111156136ac57fe5b8160058111156136b857fe5b146040518060400160405280601d81526020017f444d5f494e56414c49445f41444a554449434154494f4e5f53544154450000008152509061373e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50505050505050565b60008085600101858154811061375957fe5b906000526020600020906008020190506137738584614499565b6137875761378283828661551d565b613791565b61379181856144a6565b9695505050505050565b6137a482614552565b600182815481106137b157fe5b90600052602060002090600202016001018054905081106040518060400160405280601781526020017f444d5f524f554e445f444f45535f4e4f545f45584953540000000000000000008152509061384d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b505050565b60809190911b0190565b613864615ba4565b61386c615ba4565b613874615c3e565b506020830151600486015486546000916138a0916001600160401b03908116911663ffffffff613ee516565b905060006138e183606001516138cc8560400151856001600160401b0316613ee590919063ffffffff16565b6001600160401b03169063ffffffff613ee516565b905061390b8360a001516138cc8560800151846001600160401b0316613ee590919063ffffffff16565b6001600160401b0316845261014083015161392d90600163ffffffff61548b16565b8710613a24576001604085015260006139446144ce565b90506000816001600160a01b0316638e12779387600001516040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b0316815260200191505060206040518083038186803b1580156139a257600080fd5b505afa1580156139b6573d6000803e3d6000fd5b505050506040513d60208110156139cc57600080fd5b50516040890151519091506000906139e590839061451d565b6001600160401b03811660208901528951909150613a03908261570d565b60808a015260a08901526001600160a01b0316606088015250613a69915050565b60006040850152613a358884615761565b6001600160401b0316602085018190528651613a5091613f86565b608087015260a08601526001600160a01b031660608501525b6101608301516080850151613a839163ffffffff61579d16565b60c08501526101808301516080850151613aa29163ffffffff61579d16565b60e08501525091925050505b9392505050565b801561384d576000613ac5614a88565b9050613ae26001600160a01b03841685838563ffffffff6157c116565b6040518060400160405280601181526020017f444d5f4445504f5349545f4641494c454400000000000000000000000000000081525090613b6757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050505050565b6000613b7861133c565b6001600160a01b0316633f33bf866040518163ffffffff1660e01b8152600401602060405180830381600087803b158015613bb257600080fd5b505af1158015613491573d6000803e3d6000fd5b613bce615b71565b6000613bd8615caa565b6000613be2615cc8565b613bea615ce7565b613bf2615ce7565b613bfa615d05565b613c0261133c565b6001600160a01b031663e008cb628a6040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b031681526020019150506102c06040518083038186803b158015613c5857600080fd5b505afa158015613c6c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506102c0811015613c9257600080fd5b5080516080820151909850602082019750955060a0810194506101c08101935061020081019250610240019050613cc7615b71565b6040805160a0810182526001600160a01b038a16815260208681015161ffff168183015289518284015289810151606083015289830151608083015290835281516101a08101835260ff8916815287516001600160401b03169181019190915290810186600160200201516001600160401b0316815260200186600260098110613d4d57fe5b60200201516001600160401b0316815260200186600360098110613d6d57fe5b60200201516001600160401b0316815260200186600460098110613d8d57fe5b60200201516001600160401b0316815260200185600060028110613dad57fe5b602002015161ffff16815260200186600560098110613dc857fe5b60200201516001600160401b0316815260200186600660098110613de857fe5b60200201516001600160401b0316815260200186600860098110613e0857fe5b60200201516001600160401b0316815260200186600760098110613e2857fe5b60200201516001600160401b0316815260200184600060028110613e4857fe5b6020020151815260200184600160028110613e5f57fe5b60200201518152508160200181905250604051806080016040528083600060048110613e8757fe5b6020020151815260200183600160048110613e9e57fe5b6020020151815260200183600260048110613eb557fe5b6020020151815260200183600360048110613ecc57fe5b6020020151905260408201529998505050505050505050565b60408051808201909152601381527f4d41544836345f4144445f4f564552464c4f57000000000000000000000000006020820152600090838301906001600160401b038086169083161015613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b509392505050565b815160408301516000908190613fac906001600160401b0386169063ffffffff6150f916565b91506000613fe4856001600160401b0316613fd8886080015189606001516153fe90919063ffffffff16565b9063ffffffff6150f916565b9050613ff6838263ffffffff6153fe16565b9150509250925092565b6000806001878154811061401057fe5b906000526020600020906002020190508581600001601e6101000a81548160ff0219169083600281111561404057fe5b0217905550600081600101805480919060010161405d9190615d23565b9050600082600101828154811061407057fe5b60009182526020822060089091020180546001600160401b03898116600160401b026fffffffffffffffff000000000000000019918c1667ffffffffffffffff1990931692909217161781556001810187905591506140cd6135cb565b905060006140db8b85613852565b8554604080517ffaf172f700000000000000000000000000000000000000000000000000000000815260048101849052600160e01b90920460ff166024830152519192506001600160a01b0384169163faf172f79160448082019260009290919082900301818387803b15801561415157600080fd5b505af1158015614165573d6000803e3d6000fd5b50959d9c50505050505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b03167fa9059cbb000000000000000000000000000000000000000000000000000000001790526000906141e58582615832565b95945050505050565b60006141f861133c565b6001600160a01b03166308135a936040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b60008085600101858154811061424257fe5b600091825260209091206001880154600890920201915060028754600160f01b900460ff16600281111561427257fe5b148061428d575061428a81600163ffffffff61548b16565b86105b1561429d57600592505050611027565b600482015482546000916142c3916001600160401b03908116911663ffffffff613ee516565b905060008854600160f01b900460ff1660028111156142de57fe5b14806142fb5750806001600160401b0316866001600160401b0316105b1561430c5760009350505050611027565b600061432e8660400151836001600160401b0316613ee590919063ffffffff16565b9050806001600160401b0316876001600160401b03161015614357576001945050505050611027565b60006143798760600151836001600160401b0316613ee590919063ffffffff16565b9050806001600160401b0316886001600160401b031610156143a357600295505050505050611027565b610140870151841180156143c05760059650505050505050611027565b60006143ce876006016153dd565b905060006143f28a60800151856001600160401b0316613ee590919063ffffffff16565b90508161443557806001600160401b03168b6001600160401b0316101561442457600398505050505050505050611027565b600598505050505050505050611027565b60006144578b60a00151836001600160401b0316613ee590919063ffffffff16565b9050806001600160401b03168c6001600160401b031610156144855760049950505050505050505050611027565b5060059d9c50505050505050505050505050565b6020015161014001511190565b6001600160a01b0316600090815260039190910160205260409020546001600160401b031690565b60008060009054906101000a90046001600160a01b03166001600160a01b031663953e46a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b60008183101561452f57506000612a3c565b613aae826145456103e88663ffffffff6150f916565b8161454c57fe5b0461587d565b60015460408051808201909152601981527f444d5f444953505554455f444f45535f4e4f545f45584953540000000000000060208201529082106145da57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050565b60006145e861133c565b6001600160a01b031663f7fe57896040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b614628615c1e565b600080600061463561133c565b6001600160a01b03166369667005866040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b0316815260200191505060606040518083038186803b15801561468a57600080fd5b505afa15801561469e573d6000803e3d6000fd5b505050506040513d60608110156146b457600080fd5b50805160208083015160409384015184516060810186526001600160a01b03909416845261ffff16918301919091529181019190915295945050505050565b6146fb615d4f565b506040805160a08101825295865260208601949094526001600160401b03909216928401929092526060830191909152608082015290565b815460048301546000805490926001600160401b03600160401b9182900481169391909104811691600160a01b90041683614774848463ffffffff61591416565b90506000826001600160401b0316826001600160401b0316106147975782614799565b815b90506147a3615d8a565b6040518060e00160405280896060015160001c81526020018960000151815260200189604001516001600160401b03168152602001866001600160401b03168152602001836001600160401b03168152602001876001600160401b0316815260200189608001516020015161ffff16815250905060006148216144ce565b905060606000826001600160a01b031663d903bcf4856040518263ffffffff1660e01b81526004018082600760200280838360005b8381101561486e578181015183820152602001614856565b50505050905001915050600060405180830381600087803b15801561489257600080fd5b505af11580156148a6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160409081528110156148cf57600080fd5b8101908080516401000000008111156148e757600080fd5b820160208101848111156148fa57600080fd5b815185602082028301116401000000008211171561491757600080fd5b505060209091015190945092506000915061494390506001600160401b038a168363ffffffff613ee516565b60048e0180546fffffffffffffffff00000000000000001916600160401b6001600160401b038416021790558c5160208e0151919250614985918f86866159b1565b60808c0151604001516001600160401b03828116908c1614906000906149b1908563ffffffff6150f916565b90506149bb614a88565b60808f01515160408051600160e11b632fa96a270281526001600160a01b0392831660048201523360248201526044810185905290519290911691635f52d44e9160648082019260009290919082900301818387803b158015614a1d57600080fd5b505af1158015614a31573d6000803e3d6000fd5b50939e50505050505050505050505050505092915050565b600483015482546000916001600160401b03600160801b909104811691614a789185911663ffffffff6150f916565b81614a7f57fe5b04949350505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316633b19e84a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b8254600090600160e81b900460ff1615614afd57508254600160e81b900460ff16613aae565b600060018560010180549050039050614b1d858260058660200151613684565b6000856001018281548110614b2e57fe5b60009182526020822060089091020191506006820190614b4d826153dd565b8015614b5f5750614b5d826153ec565b155b9050600081614bed57614b706135cb565b6001600160a01b031663084d72f4614b888a88613852565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015614bbc57600080fd5b505afa158015614bd0573d6000803e3d6000fd5b505050506040513d6020811015614be657600080fd5b5051614bfa565b8254600160a01b900460ff165b89547fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160e81b60ff831602179099555096979650505050505050565b600080614c44613b6e565b600489015460028a0154919250600160c01b90046001600160401b031690600090614c6f908361548b565b9050600086118015614c8057508581115b15614c8c575084614cab565b895470ff000000000000000000000000000000001916600160801b178a555b614cbb828263ffffffff6153fe16565b8a60040160186101000a8154816001600160401b0302191690836001600160401b031602179055506000614ced6144ce565b9050606082604051908082528060200260200182016040528015614d1b578160200160208202803883390190505b509050606083604051908082528060200260200182016040528015614d4a578160200160208202803883390190505b50905060005b84811015614e355760008e60020182880181548110614d6b57fe5b9060005260206000200160009054906101000a90046001600160a01b0316905080848381518110614d9857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050614e158f6003016000836001600160a01b03166001600160a01b0316815260200190815260200160002060000160009054906101000a90046001600160401b03166001600160401b0316613fd88e8d615abc90919063ffffffff16565b838381518110614e2157fe5b602090810291909101015250600101614d50565b506060614e406135cb565b6001600160a01b03166318ce8f568e8e866040518463ffffffff1660e01b8152600401808481526020018360ff1660ff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b83811015614eb2578181015183820152602001614e9a565b5050505090500194505050505060006040518083038186803b158015614ed757600080fd5b505afa158015614eeb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015614f1457600080fd5b810190808051640100000000811115614f2c57600080fd5b82016020810184811115614f3f57600080fd5b8151856020820283011164010000000082111715614f5c57600080fd5b505092919050505090506150e1846001600160a01b031663c67106f5898686866040518563ffffffff1660e01b815260040180856001600160401b03166001600160401b03168152602001806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b83811015614feb578181015183820152602001614fd3565b50505050905001848103835286818151815260200191508051906020019060200280838360005b8381101561502a578181015183820152602001615012565b50505050905001848103825285818151815260200191508051906020019060200280838360005b83811015615069578181015183820152602001615051565b50505050905001975050505050505050602060405180830381600087803b15801561509357600080fd5b505af11580156150a7573d6000803e3d6000fd5b505050506040513d60208110156150bd57600080fd5b81019080805190602001909291905050508f600501546153fe90919063ffffffff16565b60058f01555092955050505050509695505050505050565b60008261510857506000612a3c565b8282028284828161511557fe5b04146040518060400160405280601181526020017f4d4154485f4d554c5f4f564552464c4f5700000000000000000000000000000081525090613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b6004850154600160801b90046001600160401b0316156151bb576153d5565b801561522d5760006151cb6144ce565b9050806001600160a01b0316636d1b229d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561521357600080fd5b505af1158015615227573d6000803e3d6000fd5b50505050505b836152b3578554600186015460408051600160e11b632fa96a270281526001600160a01b038681166004830152938416602482015260448101929092525191851691635f52d44e9160648082019260009290919082900301818387803b15801561529657600080fd5b505af11580156152aa573d6000803e3d6000fd5b505050506153d5565b600060028660010154816152c357fe5b04905060008760010160018703815481106152da57fe5b600091825260208220600660089092020101805460408051600160e11b632fa96a270281526001600160a01b038981166004830152928316602482015260448101879052905192945090881692635f52d44e9260648084019382900301818387803b15801561534857600080fd5b505af115801561535c573d6000803e3d6000fd5b505050600182015460408051600160e11b632fa96a270281526001600160a01b03888116600483015292831660248201526044810186905290519188169250635f52d44e91606480830192600092919082900301818387803b1580156153c157600080fd5b505af1158015611b6f573d6000803e3d6000fd5b505050505050565b546001600160a01b0316151590565b600101546001600160a01b0316151590565b60408051808201909152601181527f4d4154485f4144445f4f564552464c4f5700000000000000000000000000000060208201526000908383019084821015613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b6000828211156040518060400160405280601281526020017f4d4154485f5355425f554e444552464c4f5700000000000000000000000000008152509061551657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050900390565b6000806155286144ce565b845460408051600160e01b63e9e67d670281526001600160a01b0387811660048301526001600160401b03909316602482015290519293506000929184169163e9e67d6791604480820192602092909190829003018186803b15801561558d57600080fd5b505afa1580156155a1573d6000803e3d6000fd5b505050506040513d60208110156155b757600080fd5b50516040870151519091506000906155d090839061451d565b90506001600160401b0381166155ec5760009350505050613aae565b6000615609886020015160c0015184615abc90919063ffffffff16565b9050836001600160a01b031663605da1b287836156246145de565b6040805163ffffffff861660e01b81526001600160a01b03909416600485015260248401929092526001600160401b031660448301525160648083019260209291908290030181600087803b15801561567c57600080fd5b505af1158015615690573d6000803e3d6000fd5b505050506040513d60208110156156a657600080fd5b50516156b9576000945050505050613aae565b6001600160a01b03861660009081526003880160205260409020805467ffffffffffffffff19166001600160401b03841617905560058701546156fc90826153fe565b600588015550925050509392505050565b815160208301516040840151600091829161575591906103e890615741906001600160401b0389169063ffffffff6150f916565b8161574857fe5b049063ffffffff615abc16565b91508190509250925092565b6101008101518254600091829161578991600160401b9091046001600160401b031690615ad5565b905060018116613aae576001019392505050565b60006127106157b2848463ffffffff6150f916565b816157b957fe5b049392505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03167f23b872dd0000000000000000000000000000000000000000000000000000000017905260009061379186825b6000806040516020818551602087016000895af18015615873573d8015615860576020811461586957615871565b60019350615871565b600183511493505b505b5090949350505050565b60408051808201909152601581527f55494e5436345f4e554d4245525f544f4f5f424947000000000000000000000060208201526000906001600160401b0383111561590d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5090919050565b6000826001600160401b0316826001600160401b031611156040518060400160405280601481526020017f4d41544836345f5355425f554e444552464c4f570000000000000000000000008152509061551657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b60005b818110156153d55760008382815181106159ca57fe5b6020908102919091018101516001600160a01b03811660009081526003880190925260409091208054919250906001600160401b0316615a42576002860180546001810182556000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384161790555b8054615a5e906001600160401b0316600163ffffffff613ee516565b815467ffffffffffffffff19166001600160401b03919091161781556040516001600160a01b0383169088908a907fbfd1b785c517ac3c709db5d7c9904052346df35e7069c1cb80f3dd966579d52290600090a450506001016159b4565b60006127106157b28461ffff851663ffffffff6150f916565b60408051808201909152601381527f4d41544836345f4d554c5f4f564552464c4f570000000000000000000000000060208201526000906001600160401b038481169084160290600160401b8210613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b604051806102c00160405280615b85615da8565b8152602001615b92615c3e565b8152602001615b9f615de4565b905290565b60408051610100810182526000808252602082018190529091820190815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b81548183558181111561384d5760020281600202836000526020600020918201910161384d9190615e0c565b604080516060810182526000808252602082018190529181019190915290565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081019190915290565b60405180606001604052806003906020820280388339509192915050565b6040518061012001604052806009906020820280388339509192915050565b60405180604001604052806002906020820280388339509192915050565b60405180608001604052806004906020820280388339509192915050565b81548183558181111561384d5760080281600802836000526020600020918201910161384d9190615e5c565b6040518060e00160405280600081526020016000815260200160006001600160401b0316815260200160008019168152602001615b9f615c1e565b6040518060e001604052806007906020820280388339509192915050565b6040518060a0016040528060006001600160a01b03168152602001600061ffff1681526020016000815260200160008152602001600081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b61134991905b80821115615e585780547fff000000000000000000000000000000000000000000000000000000000000001681556000615e4f6001830182615ef0565b50600201615e12565b5090565b61134991905b80821115615e5857805470ffffffffffffffffffffffffffffffffff19168155600060018201819055615e986002830182615f11565b50600060048201819055600582015560068101805474ffffffffffffffffffffffffffffffffffffffffff1916905560078101805475ffffffffffffffffffffffffffffffffffffffffffff19169055600801615e62565b50805460008255600802906000526020600020908101906108859190615e5c565b5080546000825590600052602060002090810190610885919061134991905b80821115615e585760008155600101615f3056fea165627a7a7230582020c137edb6f0f5f0da0d0d361d22809d8f4b8382642960f9058207418aaf2b340029

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000f0c8376065fadfacb706cafbaac96b321069c01500000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000001

-----Decoded View---------------
Arg [0] : _controller (address): 0xf0C8376065fadfACB706caFbaaC96B321069C015
Arg [1] : _maxJurorsPerDraftBatch (uint64): 81
Arg [2] : _skippedDisputes (uint256): 1

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000f0c8376065fadfacb706cafbaac96b321069c015
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000051
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001


Deployed Bytecode Sourcemap

125219:77809:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;125219:77809:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158158:165;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;158158:165:0;-1:-1:-1;;;;;158158:165:0;;:::i;:::-;;156369:557;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;156369:557:0;;;;;;-1:-1:-1;;;;;156369:557:0;;:::i;140840:1423::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140840:1423:0;;;;;;;;;;;;;;:::i;155582:395::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;155582:395:0;;:::i;135366:1302::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;135366:1302:0;;;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;135366:1302:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;135366:1302:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;135366:1302:0;;-1:-1:-1;135366:1302:0;-1:-1:-1;135366:1302:0;:::i;:::-;;;;;;;;;;;;;;;;124761:346;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;124761:346:0;;;;;;;;;;:::i;119841:96::-;;;:::i;:::-;;;;-1:-1:-1;;;;;119841:96:0;;;;;;;;;;;;;;132077:36;;;:::i;:::-;;;;-1:-1:-1;;;;;132077:36:0;;;;;;;;;;;;;;161131:1069;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;161131:1069:0;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;161131:1069:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;165833:823;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;165833:823:0;;;;;;;;;;;-1:-1:-1;;;;;165833:823:0;;:::i;:::-;;;;-1:-1:-1;;;;;165833:823:0;;;;;;;;;;;;;;;;;;;;;137046:391;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;137046:391:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;137046:391:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;137046:391:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;137046:391:0;;-1:-1:-1;137046:391:0;-1:-1:-1;137046:391:0;:::i;138672:1824::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;138672:1824:0;;:::i;162771:450::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;162771:450:0;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;162771:450:0;;;;;-1:-1:-1;;;;;162771:450:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158557:315;;;:::i;:::-;;;;-1:-1:-1;;;;;158557:315:0;;;;;;;;;;;;;;;;;;;;;149500:2979;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;149500:2979:0;;;;;;;;;;;-1:-1:-1;;;;;149500:2979:0;;:::i;146109:2967::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;146109:2967:0;;;;;;;;;;;;:::i;142646:1675::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;142646:1675:0;;;;;;;;;;;;;;:::i;144641:535::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;144641:535:0;;:::i;:::-;;;;-1:-1:-1;;;;;144641:535:0;;;;;;;;;;;;;;;;;;;;;;157381:542;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;157381:542:0;;;;;;-1:-1:-1;;;;;157381:542:0;;:::i;137725:774::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;137725:774:0;;;;;;;;:::i;164213:1152::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;164213:1152:0;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;164213:1152:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;164213:1152:0;;;;;;;-1:-1:-1;164213:1152:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;164213:1152:0;-1:-1:-1;;164213:1152:0;159551:614;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;159551:614:0;;:::i;:::-;;;;-1:-1:-1;;;;;159551:614:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;159551:614:0;;;;;;;;-1:-1:-1;;;;;159551:614:0;;;;;;;;;;;;;-1:-1:-1;159551:614:0;-1:-1:-1;;159551:614:0;152777:2495;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;152777:2495:0;;;;;;;:::i;158158:165::-;118940:17;:15;:17::i;:::-;-1:-1:-1;;;;;118926:31:0;:10;-1:-1:-1;;;;;118926:31:0;;118959:32;;;;;;;;;;;;;;;;;118918:74;;;;;-1:-1:-1;;;;;118918:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;118918:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158264:51;158291:23;158264:26;:51::i;:::-;158158:165;:::o;156369:557::-;133574:16;133593:9;:7;:9::i;:::-;133652:23;;;;;;;;;;;;;;;;;133574:28;;-1:-1:-1;133621:10:0;-1:-1:-1;;;;;133621:29:0;;;133613:63;;;;-1:-1:-1;;;;;133613:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;133613:63:0;;156459:23;156484:15;156503:22;156517:7;156503:13;:22::i;:::-;156458:67;;;;156536:20;;:::i;:::-;156559:26;156577:7;156559:17;:26::i;:::-;156536:49;;156694:89;156719:7;156728;156737:28;156767:6;:15;;;156694:24;:89::i;:::-;156794:13;156810:53;156830:7;156839;156848:6;156856;156810:19;:53::i;:::-;156794:69;;156891:1;156882:6;-1:-1:-1;;;;;156882:10:0;;156894:23;;;;;;;;;;;;;;;;;156874:44;;;;;-1:-1:-1;;;;;156874:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;156874:44:0;;133687:1;;;;156369:557;;;:::o;140840:1423::-;140936:10;140948:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;141139:23;141165:8;141174:10;141165:20;;;;;;;;;;;;;;;;;;141139:46;;141196:20;;:::i;:::-;141219:26;141237:7;141219:17;:26::i;:::-;141196:49;;141256:89;141281:7;141290:8;141300:27;141329:6;:15;;;141256:24;:89::i;:::-;141475:16;141494:9;:7;:9::i;:::-;141475:28;;141514:14;141531:32;141542:10;141554:8;141531:10;:32::i;:::-;141514:49;;141574:24;141601:6;-1:-1:-1;;;;;141601:24:0;;141626:6;141601:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;141601:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;141601:32:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;141601:32:0;;-1:-1:-1;141652:29:0;;;;;;;;;;;:71;;-1:-1:-1;141685:38:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;141685:21:0;;;;;:38;;;;;;;;;;;;;;:21;:38;;;5:2:-1;;;;30:1;27;20:12;5:2;141685:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;141685:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;141685:38:0;141652:71;141725:27;;;;;;;;;;;;;;;;;141644:109;;;;;-1:-1:-1;;;;;141644:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;141644:109:0;;141804:31;141838:7;:14;;141853:8;141838:24;;;;;;;;;;;;;;;;;;;;;;;141897:12;;;141920:25;;141935:10;-1:-1:-1;;141920:25:0;;;;-1:-1:-1;;141956:31:0;-1:-1:-1;;;141956:31:0;;;;;;;;;;;;142003:45;;;;;;;141838:24;;-1:-1:-1;141897:12:0;;142030:8;;142018:10;;142003:45;;;;;;;;;142092:33;;:::i;:::-;142128:45;142149:5;142156:8;142166:6;142128:20;:45::i;:::-;142092:81;;142184:71;142199:10;142211:9;:18;;;142231:9;:23;;;142184:14;:71::i;:::-;134281:1;;;;;;;;140840:1423;;;;;:::o;155582:395::-;155645:23;155670:15;155689:22;155703:7;155689:13;:22::i;:::-;155644:67;;;;155722:20;;:::i;:::-;155745:26;155763:7;155745:17;:26::i;:::-;155722:49;;155880:89;155905:7;155914;155923:28;155953:6;:15;;;155880:24;:89::i;:::-;155582:395;;;;:::o;135366:1302::-;135494:7;119156:10;;119169:27;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;119156:10:0;119134;:33;119126:71;;;;-1:-1:-1;;;;;119126:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;119126:71:0;;135514:13;135530:20;:18;:20::i;:::-;135514:36;;135561:20;;:::i;:::-;135584;135597:6;135584:12;:20::i;:::-;135561:43;-1:-1:-1;127761:1:0;135623:38;;;;;;;:94;;;135685:6;:15;;;:32;;;135665:52;;:16;:52;;;;135623:94;135719:28;;;;;;;;;;;;;;;;;135615:133;;;;;-1:-1:-1;;;;;135615:133:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;135615:133:0;-1:-1:-1;135812:8:0;:17;;135792;;135812;;;;;;:::i;:::-;135792:37;;135840:23;135866:8;135875:9;135866:19;;;;;;;;;;;;;;;;;;135840:45;;135914:8;135896:7;:15;;;:26;;;;;-1:-1:-1;;;;;135896:26:0;;;;;-1:-1:-1;;;;;135896:26:0;;;;;;135959:16;135933:7;:23;;;:42;;;;;;;;;;;;;;;;;;136009:6;135986:7;:20;;;:29;;;;;-1:-1:-1;;;;;135986:29:0;;;;;-1:-1:-1;;;;;135986:29:0;;;;;;136028:19;136050:6;:15;;;:38;;;136028:60;;136099:18;136120:41;136131:6;:15;;;:29;;;136120:6;-1:-1:-1;;;;;136120:10:0;;;:41;;;;:::i;:::-;136099:62;;136209:11;-1:-1:-1;;;;;136177:69:0;136199:8;-1:-1:-1;;;;;136177:69:0;136188:9;136177:69;136222:12;136236:9;;136177:69;;;;-1:-1:-1;;;;;136177:69:0;-1:-1:-1;;;;;136177:69:0;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;;74:27;136177:69:0;;137:4:-1;117:14;;;-1:-1;;113:30;157:16;;;136177:69:0;;;;-1:-1:-1;136177:69:0;;-1:-1:-1;;;;;136177:69:0;136319:14;136335:17;136354;136375:47;136396:6;:11;;;136409:12;136375:20;:47::i;:::-;136318:104;;;;;;136433:84;136446:9;136457:21;136480:11;136493:12;136507:9;136433:12;:84::i;:::-;;136579:54;136602:8;136613;136623:9;136579:14;:54::i;:::-;-1:-1:-1;136651:9:0;;-1:-1:-1;;;;;;;;119208:1:0;135366:1302;;;;;;:::o;124761:346::-;124208:10;;;;;;;;;-1:-1:-1;;;;;124208:10:0;-1:-1:-1;;;;;124208:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;124208:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;124208:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;124208:29:0;124239:31;;;;;;;;;;;;;124208:29;124239:31;;;;-1:-1:-1;;;;;124194:43:0;:10;:43;124186:85;;;;-1:-1:-1;;;;;124186:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;124186:85:0;-1:-1:-1;124866:31:0;;;;;;124891:4;124866:31;;;;;;124848:15;;-1:-1:-1;;;;;124866:16:0;;;;;:31;;;;;;;;;;;;;;;:16;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;124866:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;124866:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;124866:31:0;124929:32;;;;;;;;;;;;;124866:31;124929:32;;;124866:31;;-1:-1:-1;124916:11:0;124908:54;;;;-1:-1:-1;;;;;124908:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;124908:54:0;-1:-1:-1;124981:33:0;-1:-1:-1;;;;;124981:19:0;;125001:3;125006:7;124981:33;:19;:33;:::i;:::-;125016:32;;;;;;;;;;;;;;;;;124973:76;;;;;-1:-1:-1;;;;;124973:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;124973:76:0;-1:-1:-1;125065:34:0;;;-1:-1:-1;;;;;125065:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;124282:1;124761:346;;:::o;119841:96::-;119889:10;119919;-1:-1:-1;;;;;119919:10:0;119841:96;;:::o;132077:36::-;;;-1:-1:-1;;;132077:36:0;;-1:-1:-1;;;;;132077:36:0;;:::o;161131:1069::-;161267:16;161298:19;161332;161366:21;161402:17;161434:21;161470:23;161508:21;161544:23;161213:10;161225:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;161595:23;161621:8;161630:10;161621:20;;;;;;;;;;;;;;;;;;161595:46;;161660:97;161681:7;161690:8;161700:19;:17;:19::i;:::-;161721:26;161739:7;161721:17;:26::i;:::-;:35;;;161660:20;:97::i;:::-;161652:105;;161770:31;161804:7;:14;;161819:8;161804:24;;;;;;;;;;;;;;;;;;161770:58;;161851:5;:17;;;;;;;;;;-1:-1:-1;;;;;161851:17:0;161839:29;;161894:5;:18;;;;;;;;;;-1:-1:-1;;;;;161894:18:0;161879:33;;161938:5;:18;;;;;;;;;;-1:-1:-1;;;;;161938:18:0;161923:33;;161984:5;:20;;;;;;;;;;-1:-1:-1;;;;;161984:20:0;161967:37;;162027:5;:15;;;162015:27;;162072:5;:22;;;;;;;;;;;;162053:41;;162122:5;:20;;;;;;;;;;-1:-1:-1;;;;;162122:20:0;162105:37;;162171:5;:21;;;162153:39;;134281:1;;161131:1069;;;;;;;;;;;;;:::o;165833:823::-;165971:13;165986;165931:10;165943:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;166017:23;166043:8;166052:10;166043:20;;;;;;;;;;;;;;;;;;166017:46;;166074:31;166108:7;:14;;166123:8;166108:24;;;;;;;;;;;;;;;;;;166074:58;;166143:20;;:::i;:::-;166166:26;166184:7;166166:17;:26::i;:::-;166143:49;;166209:33;166225:8;166235:6;166209:15;:33::i;:::-;166205:385;;;166268:30;166284:5;166291:6;166268:15;:30::i;:::-;166259:39;;166205:385;;;166331:30;166364:17;:15;:17::i;:::-;166461;;166420:59;;;-1:-1:-1;;;;;166420:59:0;;-1:-1:-1;;;;;166420:59:0;;;;;;;-1:-1:-1;;;;;166461:17:0;;;166420:59;;;;;;166331:50;;-1:-1:-1;166396:21:0;;166420:32;;;;;;:59;;;;;;;;;;;;;;;:32;:59;;;5:2:-1;;;;30:1;27;20:12;5:2;166420:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;166420:59:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;166420:59:0;166547:13;;;;:30;166420:59;;-1:-1:-1;166503:75:0;;166420:59;;166503:28;:75::i;:::-;166494:84;;166205:385;;;-1:-1:-1;;;;;;166613:26:0;;;;;;;;:18;;;;:26;;-1:-1:-1;;166613:26:0;;;;:35;165833:823;;-1:-1:-1;;;166613:35:0;;;;;;-1:-1:-1;165833:823:0;;-1:-1:-1;;;165833:823:0:o;137046:391::-;119156:10;;119169:27;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;119156:10:0;119134;:33;119126:71;;;;-1:-1:-1;;;;;119126:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;119126:71:0;;137205:10;133887:31;133907:10;133887:19;:31::i;:::-;137233:23;137259:8;137268:10;137259:20;;;;;;;;;;;;;;;;;;;;;;137298:15;;137327:33;;;;;;;;;;;;;;;;;;;;137259:20;;-1:-1:-1;;;;;;137298:15:0;;;:27;;;;137290:71;;;;-1:-1:-1;;;;;137290:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;137290:71:0;;137407:10;-1:-1:-1;;;;;137377:52:0;137395:10;137377:52;137419:9;;137377:52;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;;74:27;137377:52:0;;137:4:-1;117:14;;;-1:-1;;113:30;157:16;;;137377:52:0;;;;-1:-1:-1;137377:52:0;;-1:-1:-1;;;;137377:52:0;133929:1;119208;137046:391;;;;;:::o;138672:1824::-;138730:10;133887:31;133907:10;133887:19;:31::i;:::-;138983:12;138998:8;:6;:8::i;:::-;138983:23;;139017:26;139046:8;:6;:8::i;:::-;-1:-1:-1;;;;;139046:33:0;;:35;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;139046:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;139046:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;139046:35:0;139135:19;;;;;;;;;;;;;139046:35;139135:19;;;139046:35;;-1:-1:-1;;;;;;139100:28:0;;:33;139092:63;;;;-1:-1:-1;;;;;139092:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;139092:63:0;;139166:20;139189:23;:21;:23::i;:::-;139166:46;;139277:23;139303:8;139312:10;139303:20;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;139342:13:0;;-1:-1:-1;;;139342:13:0;;;;:38;;;;;;;;;139382:27;;;;;;;;;;;;;;;;;139334:76;;;;;-1:-1:-1;;;;;139334:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;139334:76:0;-1:-1:-1;139551:1:0;139527:14;;:21;;-1:-1:-1;;139527:25:0;;;139509:15;;139527:25;;139597:23;;;;;;;;;;;;;;;;;;;;139652:17;;139718:28;;;;;;;;;;;;;;;;;;;;139597:23;;-1:-1:-1;;;;;;139652:17:0;;;;139718:28;139688;;;;;139680:67;;;;-1:-1:-1;;;;;139680:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;139680:67:0;;139758:27;139788:5;-1:-1:-1;;;;;139788:33:0;;:35;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;139788:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;139788:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;139788:35:0;;-1:-1:-1;139902:25:0;;:::i;:::-;139930:28;139946:11;139930:15;:28::i;:::-;139902:56;;139969:15;139987:97;139994:5;140001:82;140019:10;140031:7;140040:13;140055:19;140076:6;140001:17;:82::i;:::-;139987:6;:97::i;:::-;139969:115;;140155:10;140151:338;;;140295:18;;;:48;;-1:-1:-1;;140295:48:0;140316:27;;;-1:-1:-1;;;;;140295:48:0;;;;140358:41;;-1:-1:-1;;;;;;140358:41:0;-1:-1:-1;;;140358:41:0;;;140419:58;;-1:-1:-1;;140439:10:0;;140419:58;;-1:-1:-1;;140419:58:0;140151:338;133929:1;;;;;;;;;;138672:1824;;:::o;162771:450::-;162894:13;162909:21;162932:13;162947:20;162854:10;162866:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;162985:21;163009:8;163018:10;163009:20;;;;;;;;;;;;;;;;;;:27;;163037:8;163009:37;;;;;;;;;;;;;;;;:44;:37;;;;;:44;;;163074:12;163154;;;;;-1:-1:-1;;;;;163074:12:0;;;;163114:21;-1:-1:-1;;;163114:21:0;;;;;;;-1:-1:-1;163154:12:0;;;;-1:-1:-1;163193:20:0;;;;;;-1:-1:-1;162771:450:0;-1:-1:-1;;;;;;162771:450:0:o;158557:315::-;158606:14;158622:17;158652:20;158675:19;:17;:19::i;:::-;158652:42;;158705:20;;:::i;:::-;158728:27;158741:13;158728:12;:27::i;:::-;158705:50;;158791:73;158812:6;:11;;;158825:6;:15;;;:38;;;158791:20;:73::i;:::-;158766:98;;;;-1:-1:-1;158557:315:0;;-1:-1:-1;;;;158557:315:0:o;149500:2979::-;149597:10;149609:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;149691:23;149717:8;149726:10;149717:20;;;;;;;;;;;;;;;;;;149691:46;;149748:31;149782:7;:14;;149797:8;149782:24;;;;;;;;;;;;;;;;;;149748:58;;149825:5;:22;;;;;;;;;;;;149849:23;;;;;;;;;;;;;;;;;149817:56;;;;;-1:-1:-1;;;;;149817:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;149817:56:0;-1:-1:-1;;;;;;150006:26:0;;149974:29;150006:26;;;:18;;;:26;;;;;;;;;150052:19;;150073:28;;;;;;;;;;;;;;;;;;;150006:26;150073:28;-1:-1:-1;;;150052:19:0;;;;150051:20;150043:59;;;;-1:-1:-1;;;;;150043:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;150043:59:0;-1:-1:-1;150129:17:0;;150153:33;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;150129:17:0;150113:74;;;;-1:-1:-1;;;;;150113:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;150113:74:0;-1:-1:-1;150198:26:0;;-1:-1:-1;;150198:26:0;-1:-1:-1;;;150198:26:0;;;:19;150361:9;:7;:9::i;:::-;150342:28;;150381:14;150398:32;150409:10;150421:8;150398:10;:32::i;:::-;150482:19;;150449:61;;;;;;;;;;;;-1:-1:-1;;;150482:19:0;;;;;150449:61;;;;-1:-1:-1;;;;;150449:61:0;;;;;;;;;;;-1:-1:-1;150449:24:0;;;;;:61;;;;;;;;;;;;;;;:24;:61;;;5:2:-1;;;;30:1;27;20:12;5:2;150449:61:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;150449:61:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;150449:61:0;150512:34;;;;;;;;;;;;;150449:61;150512:34;;;;150441:106;;;;-1:-1:-1;;;;;150441:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;150441:106:0;-1:-1:-1;150586:21:0;;;;150560:23;150651:17;:15;:17::i;:::-;150618:50;-1:-1:-1;150895:20:0;150930:19;;150926:447;;151238:59;151262:5;151269:10;151281:15;151238:23;:59::i;:::-;151223:74;;151312:14;-1:-1:-1;;;;;151312:27:0;;151340:6;151348:12;151312:49;;;;;;;;;;;;;-1:-1:-1;;;;;151312:49:0;-1:-1:-1;;;;;151312:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;151312:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;151312:49:0;;;;150926:447;151432:20;;:::i;:::-;151455:26;151473:7;151455:17;:26::i;:::-;151432:49;;151741:18;151762:59;151786:5;151793:10;151805:5;:15;;;151762:23;:59::i;:::-;151741:80;;151832:11;:9;:11::i;:::-;-1:-1:-1;;;;;151832:18:0;;151851:6;:11;;;:17;;;151870:6;151878:10;151832:57;;;;;;;;;;;;;-1:-1:-1;;;;;151832:57:0;-1:-1:-1;;;;;151832:57:0;;;;;;-1:-1:-1;;;;;151832:57:0;-1:-1:-1;;;;;151832:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;151832:57:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;151832:57:0;;;;151948:33;151964:8;151974:6;151948:15;:33::i;:::-;151943:442;;152103:36;;:::i;:::-;152142:6;:15;;;152103:54;;152172:14;-1:-1:-1;;;;;152172:30:0;;152221:6;152324:14;:34;;;152295:14;:26;;;152266:14;:26;;;152246:5;:17;;;;;;;;;;-1:-1:-1;;;;;152246:17:0;:46;:75;:112;152172:201;;;;;;;;;;;;;-1:-1:-1;;;;;152172:201:0;-1:-1:-1;;;;;152172:201:0;;;;;;-1:-1:-1;;;;;152172:201:0;-1:-1:-1;;;;;152172:201:0;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;152172:201:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;152172:201:0;;;;151943:442;;152428:8;152416:10;152402:69;152438:6;152446:12;152460:10;152402:69;;;;-1:-1:-1;;;;;152402:69:0;-1:-1:-1;;;;;152402:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;134281:1;;;;;;;;;;149500:2979;;;;;:::o;146109:2967::-;146218:10;146230:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;146465:23;146491:8;146500:10;146491:20;;;;;;;;;;;;;;;;;;146465:46;;146530:8;146542:1;146530:13;:62;;;;146547:7;:14;;146573:1;146562:8;:12;146547:28;;;;;;;;;;;;;;;;;;;;;:45;-1:-1:-1;;;146547:45:0;;;;146530:62;146594:28;;;;;;;;;;;;;;;;;146522:101;;;;;-1:-1:-1;;;;;146522:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;146522:101:0;;146698:31;146732:7;:14;;146747:8;146732:24;;;;;;;;;;;;;;;;;;146698:58;;146776:5;:22;;;;;;;;;;;;146775:23;146800:27;;;;;;;;;;;;;;;;;146767:61;;;;;-1:-1:-1;;;;;146767:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;146767:61:0;;146918:20;;:::i;:::-;146941:26;146959:7;146941:17;:26::i;:::-;146918:49;;146978:17;146998:47;147017:7;147026:10;147038:6;146998:18;:47::i;:::-;146978:67;;147170:14;147187:32;147198:10;147210:8;147187:10;:32::i;:::-;147234:19;;;;147170:49;;-1:-1:-1;;;;147234:19:0;;-1:-1:-1;;;;;147234:19:0;147230:463;;147564:16;147583:9;:7;:9::i;:::-;147564:28;;147637:6;-1:-1:-1;;;;;147637:22:0;;147660:6;147668:11;147637:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;147637:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;147637:43:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;147637:43:0;147607:20;;;:74;;-1:-1:-1;;;;;147607:74:0;;;-1:-1:-1;;;147607:74:0;;;;;;;;;;;-1:-1:-1;147230:463:0;147705:18;147726:11;:9;:11::i;:::-;147765;;:17;147705:32;;-1:-1:-1;147797:33:0;147813:8;147765:6;147797:15;:33::i;:::-;147793:978;;;148042:21;148066:133;148095:5;148102:6;148110:11;148123:6;:15;;;:26;;;148151:15;148168:6;:13;;;:30;;;148066:28;:133::i;:::-;148042:157;;148214:8;-1:-1:-1;;;;;148214:15:0;;148230:8;148240:10;148252:40;148278:13;148252:6;:11;;;:21;;;:25;;:40;;;;:::i;:::-;148214:79;;;;;;;;;;-1:-1:-1;;;;;148214:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;148214:79:0;;;;;;;-1:-1:-1;148214:79:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;148214:79:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;148214:79:0;;;;147793:978;;;;148730:29;;-1:-1:-1;;148730:29:0;-1:-1:-1;;;148730:29:0;;;147793:978;148787:22;;-1:-1:-1;;;148787:22:0;;;;148783:286;;;148852:21;;;;148893:55;;;;;;;;148922:8;;148910:10;;148893:55;;;;;;;;;148963:94;148995:7;149004:5;149011:8;149021;149031;149041:15;148963:31;:94::i;142646:1675::-;142743:10;142755:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;142963:23;142989:8;142998:10;142989:20;;;;;;;;;;;;;;;;;;142963:46;;143020:20;;:::i;:::-;143043:26;143061:7;143043:17;:26::i;:::-;143020:49;;143080:96;143105:7;143114:8;143124:34;143160:6;:15;;;143080:24;:96::i;:::-;143300:31;143334:7;:14;;143349:8;143334:24;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;143393:12:0;;;;143433:32;143444:10;143456:8;143433:10;:32::i;:::-;143484:21;;143416:49;;-1:-1:-1;143484:32:0;;;;-1:-1:-1;;;143484:21:0;;;;:32;;;;:77;;;143520:9;:7;:9::i;:::-;-1:-1:-1;;;;;143520:24:0;;143545:6;143553:7;143520:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;143520:41:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;143520:41:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;143520:41:0;143484:77;143563:27;;;;;;;;;;;;;;;;;143476:115;;;;;-1:-1:-1;;;;;143476:115:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;143476:115:0;;143664:33;;:::i;:::-;143700:45;143721:5;143728:8;143738:6;143700:20;:45::i;:::-;143664:81;;143756:28;143787:9;:25;;;143756:56;;143823:18;143844:107;143857:10;143869:15;143886:9;:19;;;143907:9;:22;;;143931:9;:19;;;143844:12;:107::i;:::-;143823:128;;144026:10;144011:6;:12;;;:25;;;;;-1:-1:-1;;;;;144011:25:0;;;;;-1:-1:-1;;;;;144011:25:0;;;;;;144070:7;144047:6;:20;;;:30;;;;;;;;;;;;;;;;;;144139:9;:19;;;-1:-1:-1;;;;;144093:90:0;144127:10;144115;144093:90;144160:9;:22;;;144093:90;;;;-1:-1:-1;;;;;144093:90:0;;;;;;;;;;;;;;;144235:78;144250:10;144262:9;:18;;;144282:9;:30;;;144235:14;:78::i;144641:535::-;144728:19;144749:17;144707:10;133887:31;133907:10;133887:19;:31::i;:::-;144779:23;144805:8;144814:10;144805:20;;;;;;;;;;;;;;;;;;;;;144846:15;;-1:-1:-1;;;;;144846:15:0;;-1:-1:-1;144805:20:0;-1:-1:-1;144874:20:0;;:::i;:::-;144897:26;144915:7;144897:17;:26::i;:::-;144874:49;;144948:47;144967:7;144976:10;144988:6;144948:18;:47::i;:::-;144934:61;-1:-1:-1;145029:18:0;145012:13;;-1:-1:-1;;;145012:13:0;;;;:35;;;;;;;;;145008:161;;145064:34;;-1:-1:-1;;;;;;145064:34:0;-1:-1:-1;;;145064:34:0;;;145118:39;;;;;;145133:10;;145118:39;;-1:-1:-1;;145118:39:0;145008:161;133929:1;;144641:535;;;;:::o;157381:542::-;157457:6;157477:23;157502:15;157521:22;157535:7;157521:13;:22::i;:::-;157476:67;;;;157554:20;;:::i;:::-;157577:26;157595:7;157577:17;:26::i;:::-;157554:49;;157711:88;157736:7;157745;157754:27;157783:6;:15;;;157711:24;:88::i;:::-;157810:31;157844:7;:14;;157859:7;157844:23;;;;;;;;;;;;;;;;;;157810:57;;157885:30;157901:5;157908:6;157885:15;:30::i;:::-;157878:37;;;;;;157381:542;;;;;:::o;137725:774::-;119156:10;;119169:27;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;119156:10:0;119134;:33;119126:71;;;;-1:-1:-1;;;;;119126:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;119126:71:0;;137841:10;137853:1;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;137872:23;137898:8;137907:10;137898:20;;;;;;;;;;;;;;;;;;137872:46;;137929:31;137963:7;:14;;137978:1;137963:17;;;;;;;;;;;;;;;;;137999:15;;138028:33;;;;;;;;;;;;;;;;;;;;137963:17;;;;;;-1:-1:-1;;;;;;137999:15:0;;;:27;;;;137991:71;;;;-1:-1:-1;;;;;137991:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;137991:71:0;;138147:13;138163:20;:18;:20::i;:::-;138147:36;-1:-1:-1;138194:21:0;138218:13;-1:-1:-1;;;;;138218:10:0;;138229:1;138218:13;:10;:13;:::i;:::-;138267:17;;138286:31;;;;;;;;;;;;;;;;;138194:37;;-1:-1:-1;;;;;;138267:17:0;;;138250:34;;;;138242:76;;;;-1:-1:-1;;;;;138242:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;138242:76:0;-1:-1:-1;138401:34:0;;-1:-1:-1;;138401:34:0;-1:-1:-1;;;;;138401:34:0;;;;;;;;;138451:40;;;;;;138472:10;;138451:40;;-1:-1:-1;;138451:40:0;134281:1;;;;119208;;137725:774;;:::o;164213:1152::-;164326:25;164366:28;164409;164452:14;164481:17;164513;164545:21;164581:28;164637:39;164655:10;164667:8;164637:17;:39::i;:::-;164689:23;164715:8;164724:10;164715:20;;;;;;;;;;;;;;;;;;164689:46;;164746:20;;:::i;:::-;164769:26;164787:7;164769:17;:26::i;:::-;164746:49;;164814:33;164830:8;164840:6;164814:15;:33::i;:::-;164849:20;;;;;;;;;;;;;;;;;164806:64;;;;;-1:-1:-1;;;;;164806:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;164806:64:0;;164883:31;164917:7;:14;;164932:8;164917:24;;;;;;;;;;;;;;;;;;164883:58;;164952:33;;:::i;:::-;164988:45;165009:5;165016:8;165026:6;164988:20;:45::i;:::-;164952:81;;165066:9;:19;;;165100:9;:22;;;165137:9;:25;;;165177:9;:18;;;165210:9;:19;;;165244:9;:19;;;165278:9;:23;;;165316:9;:30;;;165044:313;;;;;;;;;;;;;;;;;;;;164213:1152;;;;;;;;;;;:::o;159551:614::-;159649:19;159670:21;159693:18;159713:17;159732:19;159753;159619:10;133887:31;133907:10;133887:19;:31::i;:::-;159790:23;159816:8;159825:10;159816:20;;;;;;;;;;;;;;;;;;;;;159859:15;;;160132:14;;;:21;-1:-1:-1;;;;;159859:15:0;;;-1:-1:-1;;;159903:23:0;;;;;;;-1:-1:-1;;;;159945:13:0;;;;;-1:-1:-1;;;;159983:19:0;;;;-1:-1:-1;;;160132:25:0;;;;-1:-1:-1;;;;160028:20:0;;;-1:-1:-1;;;;;160028:20:0;;-1:-1:-1;159859:15:0;-1:-1:-1;;;;159551:614:0:o;152777:2495::-;152865:10;152877:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;152959:23;152985:8;152994:10;152985:20;;;;;;;;;;;;;;;;;;152959:46;;153016:31;153050:7;:14;;153065:8;153050:24;;;;;;;;;;;;;;;;;;153016:58;;153093:5;:22;;;;;;;;;;;;153117:23;;;;;;;;;;;;;;;;;153085:56;;;;;-1:-1:-1;;;;;153085:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;153085:56:0;-1:-1:-1;153251:12:0;;;153282:21;153251:12;153282:13;:21::i;:::-;153305:24;;;;;;;;;;;;;;;;;153274:56;;;;;-1:-1:-1;;;;;153274:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;153274:56:0;-1:-1:-1;153350:14:0;;;;153366:34;;;;;;;;;;;;;;;;;;-1:-1:-1;;;153350:14:0;;;;153349:15;153341:60;;;;-1:-1:-1;;;;;153341:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;153341:60:0;-1:-1:-1;153429:4:0;153412:14;;:21;;-1:-1:-1;;153412:21:0;-1:-1:-1;;;153412:21:0;;;153449:42;;153482:8;;153470:10;;153449:42;;153412:21;;153449:42;153540:20;;:::i;:::-;153563:26;153581:7;153563:17;:26::i;:::-;153540:49;;153600:33;;:::i;:::-;153636:45;153657:5;153664:8;153674:6;153636:20;:45::i;:::-;153709:18;;;;153758:19;;;;153812:23;;;;153877:30;;;;153600:81;;-1:-1:-1;153709:18:0;;153758:19;;153812:23;153692:14;154027:11;:9;:11::i;:::-;154006:32;;154054:26;154073:6;154054:18;:26::i;:::-;154049:135;;154123:12;;154097:54;;;-1:-1:-1;;;;;154097:54:0;;-1:-1:-1;;;;;154097:54:0;;;;;;;154123:12;;;154097:54;;;;;;;;;;;;:15;;;;;;:54;;;;;154123:12;;154097:54;;;;;;;;154123:12;154097:15;:54;;;5:2:-1;;;;30:1;27;20:12;5:2;154097:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;154097:54:0;;;;154166:7;;;;;;;;;;;;154049:135;154639:19;;-1:-1:-1;;;154639:19:0;;;;154619:17;154692:39;:13;154710:20;154692:17;:39::i;:::-;154746:21;;154669:62;;-1:-1:-1;154746:36:0;;;;-1:-1:-1;;;154746:21:0;;;;:36;154742:523;;;154825:12;;-1:-1:-1;;;;;154799:15:0;;;;;;154815:8;;154825:12;154839:27;:12;154856:9;154839:27;:16;:27;:::i;:::-;154799:68;;;;;;;;;;-1:-1:-1;;;;;154799:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;154799:68:0;;;;;;;-1:-1:-1;154799:68:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;154799:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;154799:68:0;;;;154742:523;;;154889:20;;;;:35;;;;-1:-1:-1;;;154889:20:0;;;;:35;154885:380;;;154967:12;;;;-1:-1:-1;;;;;154941:15:0;;;;;;154957:8;;154967:12;154981:27;:12;154998:9;154981:27;:16;:27;:::i;154885:380::-;155117:12;;155075:1;155063:13;;;-1:-1:-1;;;;;155091:15:0;;;;;;155107:8;;155117:12;155131:29;:13;155063;155131:17;:29::i;:::-;155091:70;;;;;;;;;;-1:-1:-1;;;;;155091:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;155091:70:0;;;;;;;-1:-1:-1;155091:70:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;155091:70:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;155202:12:0;;;;-1:-1:-1;;;;;155176:15:0;;;;-1:-1:-1;155176:15:0;;155192:8;;155202:12;155216:36;:20;155241:10;155216:36;:24;:36;:::i;:::-;155176:77;;;;;;;;;;-1:-1:-1;;;;;155176:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;155176:77:0;;;;;;;-1:-1:-1;155176:77:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;155176:77:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;155176:77:0;;;;154885:380;;134281:1;;;;;;;;;;;;152777:2495;;;;:::o;120943:115::-;120993:7;121020:10;;;;;;;;;-1:-1:-1;;;;;121020:10:0;-1:-1:-1;;;;;121020:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;121020:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;121020:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;121020:30:0;;-1:-1:-1;120943:115:0;:::o;177571:317::-;177696:30;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;177667:27:0;;177659:68;;;;-1:-1:-1;;;;;177659:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;177659:68:0;-1:-1:-1;177773:22:0;;177743:78;;;-1:-1:-1;;;;;;;;177773:22:0;;;;;177743:78;;;;;;;;;;;;;;;;;;;;;177832:22;:48;;-1:-1:-1;;;;;177832:48:0;;;-1:-1:-1;;;177832:48:0;;;;;;;;;;;177571:317::o;121877:112::-;121919:9;121958:10;;;;;;;;;-1:-1:-1;;;;;121958:10:0;-1:-1:-1;;;;;121958:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;189943:289:0;190006:23;128012:66;190114:22;;190090:3;190079:14;;;190147:37;190079:14;190114:22;190147:17;:37::i;:::-;190205:8;190214:9;190205:19;;;;;;;;;;;;;;;;;;190195:29;;189943:289;;;;:::o;187814:235::-;187890:13;;:::i;:::-;188019:21;;188006:35;;-1:-1:-1;;;188019:21:0;;-1:-1:-1;;;;;188019:21:0;188006:12;:35::i;168567:386::-;168736:13;168752:20;:18;:20::i;:::-;168736:36;;168783:28;168814:57;168835:8;168845;168855:6;168863:7;168814:20;:57::i;:::-;168783:88;;168904:6;168890:20;;;;;;;;:10;:20;;;;;;;;;168912:32;;;;;;;;;;;;;;;;;168882:63;;;;;-1:-1:-1;;;;;168882:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;168882:63:0;;168567:386;;;;;;:::o;174832:388::-;174962:6;174981:31;175015:8;:15;;175031:8;175015:25;;;;;;;;;;;;;;;;;;174981:59;;175060:34;175076:8;175086:7;175060:15;:34::i;:::-;:152;;175156:56;175189:7;175198:5;175205:6;175156:32;:56::i;:::-;175060:152;;;175110:30;175126:5;175133:6;175110:15;:30::i;:::-;175053:159;174832:388;-1:-1:-1;;;;;;174832:388:0:o;189380:222::-;189470:31;189490:10;189470:19;:31::i;:::-;189531:8;189540:10;189531:20;;;;;;;;;;;;;;;;;;:27;;:34;;;;189520:8;:45;189567:26;;;;;;;;;;;;;;;;;189512:82;;;;;-1:-1:-1;;;;;189512:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;189512:82:0;;189380:222;;:::o;190615:146::-;190738:3;190724:17;;;;190723:30;;190615:146::o;179810:2866::-;179947:23;;:::i;:::-;179988:33;;:::i;:::-;180032:36;;:::i;:::-;-1:-1:-1;180071:16:0;;;;180209:19;;;;180186:18;;180160:23;;180186:43;;-1:-1:-1;;;;;180186:18:0;;;;180209:19;180186:43;:22;:43;:::i;:::-;180160:69;;180240:34;180277:80;180330:14;:26;;;180277:48;180298:14;:26;;;180277:16;-1:-1:-1;;;;;180277:20:0;;;:48;;;;:::i;:::-;-1:-1:-1;;;;;180277:52:0;;:80;:52;:80;:::i;:::-;180240:117;;180390:98;180454:14;:33;;;180390:59;180422:14;:26;;;180390:27;-1:-1:-1;;;;;180390:31:0;;;:59;;;;:::i;:98::-;-1:-1:-1;;;;;180368:120:0;;;180607:37;;;;:44;;180649:1;180607:44;:41;:44;:::i;:::-;180595:8;:56;180591:1791;;180770:25;180742;;;:53;181218:30;181251:17;:15;:17::i;:::-;181218:50;;181283:26;181312:14;-1:-1:-1;;;;;181312:35:0;;181348:9;:19;;;181312:56;;;;;;;;;;;;;-1:-1:-1;;;;;181312:56:0;-1:-1:-1;;;;;181312:56:0;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;181312:56:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;181312:56:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;181312:56:0;181454:14;;;;:31;181312:56;;-1:-1:-1;181383:19:0;;181405:81;;181312:56;;181405:28;:81::i;:::-;-1:-1:-1;;;;;181501:37:0;;:22;;;:37;181737:12;;181383:103;;-1:-1:-1;181718:46:0;;181383:103;181718:18;:46::i;:::-;181695:19;;;181653:111;181674:19;;;181653:111;-1:-1:-1;;;;;181653:111:0;181654:18;;;181653:111;-1:-1:-1;180591:1791:0;;-1:-1:-1;;180591:1791:0;;181890:21;181862:25;;;:49;182069:56;182102:6;182110:14;182069:32;:56::i;:::-;-1:-1:-1;;;;;182044:81:0;:22;;;:81;;;182333:12;;182312:58;;:20;:58::i;:::-;182289:19;;;182247:123;182268:19;;;182247:123;-1:-1:-1;;;;;182247:123:0;182248:18;;;182247:123;180591:1791;182487:37;;;;182460:19;;;;:65;;;:26;:65;:::i;:::-;182434:23;;;:91;182596:44;;;;182569:19;;;;:72;;;:26;:72;:::i;:::-;182536:30;;;:105;-1:-1:-1;182536:9:0;;-1:-1:-1;;;179810:2866:0;;;;;;:::o;178262:277::-;178356:11;;178352:180;;178384:18;178405:11;:9;:11::i;:::-;178384:32;-1:-1:-1;178439:58:0;-1:-1:-1;;;;;178439:23:0;;178463:5;178384:32;178489:7;178439:58;:23;:58;:::i;:::-;178499:20;;;;;;;;;;;;;;;;;178431:89;;;;;-1:-1:-1;;;;;178431:89:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;178431:89:0;;178352:180;178262:277;;;:::o;120127:110::-;120175:6;120201:8;:6;:8::i;:::-;-1:-1:-1;;;;;120201:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;120201:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;115238:1637:0;115299:13;;:::i;:::-;115326:15;115352:23;;:::i;:::-;115386:22;115419:29;;:::i;:::-;115459:22;;:::i;:::-;115492:41;;:::i;:::-;115544:31;;:::i;:::-;115579:14;:12;:14::i;:::-;-1:-1:-1;;;;;115579:24:0;;115604:7;115579:33;;;;;;;;;;;;;-1:-1:-1;;;;;115579:33:0;-1:-1:-1;;;;;115579:33:0;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;115579:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;115579:33:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;13:3;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;115579:33:0;;;;;;;;-1:-1:-1;115579:33:0;;;;-1:-1:-1;115579:33:0;-1:-1:-1;115579:33:0;;;;-1:-1:-1;115579:33:0;;;;-1:-1:-1;115579:33:0;;;;-1:-1:-1;115579:33:0;;;-1:-1:-1;115625:20:0;;:::i;:::-;115672:198;;;;;;;;-1:-1:-1;;;;;115672:198:0;;;;;115850:8;;;;115672:198;;;;;;115739:8;;115672:198;;;;115772:8;;;;115672:198;;;;115806:8;;;;115672:198;;;;115658:212;;;115901:679;;;;;;;;;;;;115995:15;;-1:-1:-1;;;;;115901:679:0;;;;;;;;;;;115995:12;116051:1;116038:15;;;;-1:-1:-1;;;;;115901:679:0;;;;;116081:12;116094:1;116081:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116124:12;116137:1;116124:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116174:12;116187:1;116174:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116216:5;116222:1;116216:8;;;;;;;;;;;115901:679;;;;;;116263:12;116276:1;116263:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116311:12;116324:1;116311:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116416:12;116429:1;116416:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116365:12;116378:1;116365:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116470:23;116494:1;116470:26;;;;;;;;;;;115901:679;;;;116542:23;116566:1;116542:26;;;;;;;;;;;115901:679;;;115883:6;:15;;:697;;;;116609:232;;;;;;;;116655:13;116669:1;116655:16;;;;;;;;;;;116609:232;;;;116708:13;116722:1;116708:16;;;;;;;;;;;116609:232;;;;116761:13;116775:1;116761:16;;;;;;;;;;;116609:232;;;;116813:13;116827:1;116813:16;;;;;;;;;;;116609:232;;116593:13;;;:248;:13;115238:1637;-1:-1:-1;;;;;;;;;115238:1637:0:o;8678:171::-;8801:18;;;;;;;;;;;;;;;;;8736:6;;8766:7;;;;-1:-1:-1;;;;;8792:7:0;;;;;;;;8784:36;;;;-1:-1:-1;;;;;8784:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;8784:36:0;-1:-1:-1;8840:1:0;8678:171;-1:-1:-1;;;8678:171:0:o;191997:643::-;192189:13;;192356:16;;;;192108:14;;;;192329:44;;-1:-1:-1;;;;;192329:22:0;;;:44;:26;:44;:::i;:::-;192317:56;;192478:26;192507:69;192561:13;-1:-1:-1;;;;;192553:22:0;192508:39;192529:7;:17;;;192508:7;:16;;;:20;;:39;;;;:::i;:::-;192507:45;:69;:45;:69;:::i;:::-;192478:98;-1:-1:-1;192599:33:0;:9;192478:98;192599:33;:13;:33;:::i;:::-;192587:45;;191997:643;;;;;;:::o;167236:828::-;167396:7;167454:23;167480:8;167489:10;167480:20;;;;;;;;;;;;;;;;;;167454:46;;167527:13;167511:7;:13;;;:29;;;;;;;;;;;;;;;;;;;;;;;;167592:15;167610:7;:14;;:23;;;;;;;;;;;:::i;:::-;167592:41;;167644:31;167678:7;:14;;167693:7;167678:23;;;;;;;;;;;;;;;;;;;;167712:32;;-1:-1:-1;;;;;167755:34:0;;;-1:-1:-1;;;167755:34:0;-1:-1:-1;;167712:32:0;;;-1:-1:-1;;167712:32:0;;;;;;;167755:34;;;;167712:32;167800:15;;:28;;;167678:23;-1:-1:-1;167906:9:0;:7;:9::i;:::-;167887:28;;167926:14;167943:31;167954:10;167966:7;167943:10;:31::i;:::-;168007:23;;167985:46;;;;;;;;;;;;-1:-1:-1;;;168007:23:0;;;;;167985:46;;;;;;;-1:-1:-1;;;;;;167985:13:0;;;;;:46;;;;;-1:-1:-1;;167985:46:0;;;;;;;;-1:-1:-1;167985:13:0;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;167985:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;168049:7:0;;167236:828;-1:-1:-1;;;;;;;;;;;;;167236:828:0:o;1663:320::-;1796:105;;;-1:-1:-1;;;;;1796:105:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;1796:105:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;1833:17:0;179:29:-1;160:49;;1747:4:0;;1919:56;1949:6;1796:105;1919:21;:56::i;:::-;1912:63;1663:320;-1:-1:-1;;;;;1663:320:0:o;120681:113::-;120733:6;120759:8;:6;:8::i;:::-;-1:-1:-1;;;;;120759:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;184360:3241:0;184513:17;184548:31;184582:8;:15;;184598:8;184582:25;;;;;;;;;;;;;;;;184742:15;;;:22;184582:25;;;;;;-1:-1:-1;184797:18:0;184779:14;;-1:-1:-1;;;184779:14:0;;;;:36;;;;;;;;;:72;;;-1:-1:-1;184830:21:0;:14;184849:1;184830:21;:18;:21;:::i;:::-;184819:8;:32;184779:72;184775:135;;;184875:23;184868:30;;;;;;184775:135;185116:18;;;;185094:17;;185065:26;;185094:41;;-1:-1:-1;;;;;185094:17:0;;;;185116:18;185094:41;:21;:41;:::i;:::-;185065:70;-1:-1:-1;185168:21:0;185150:14;;-1:-1:-1;;;185150:14:0;;;;:39;;;;;;;;;:72;;;;185203:19;-1:-1:-1;;;;;185193:29:0;:7;-1:-1:-1;;;;;185193:29:0;;185150:72;185146:137;;;185246:25;185239:32;;;;;;;185146:137;185437:22;185462:44;185486:7;:19;;;185462;-1:-1:-1;;;;;185462:23:0;;;:44;;;;:::i;:::-;185437:69;;185531:15;-1:-1:-1;;;;;185521:25:0;:7;-1:-1:-1;;;;;185521:25:0;;185517:93;;;185570:28;185563:35;;;;;;;;185517:93;185764:22;185789:40;185809:7;:19;;;185789:15;-1:-1:-1;;;;;185789:19:0;;;:40;;;;:::i;:::-;185764:65;;185854:15;-1:-1:-1;;;;;185844:25:0;:7;-1:-1:-1;;;;;185844:25:0;;185840:92;;;185893:27;185886:34;;;;;;;;;185840:92;186111:30;;;;186094:47;;186152:79;;;;186196:23;186189:30;;;;;;;;;;186152:79;186347:24;186374:27;186388:5;:12;;186374:13;:27::i;:::-;186347:54;;186412:34;186449:40;186469:7;:19;;;186449:15;-1:-1:-1;;;;;186449:19:0;;;:40;;;;:::i;:::-;186412:77;;186505:19;186500:378;;186698:27;-1:-1:-1;;;;;186688:37:0;:7;-1:-1:-1;;;;;186688:37:0;;186684:183;;;186753:27;186746:34;;;;;;;;;;;;186684:183;186828:23;186821:30;;;;;;;;;;;;186684:183;187244:32;187279:59;187311:7;:26;;;187279:27;-1:-1:-1;;;;;187279:31:0;;;:59;;;;:::i;:::-;187244:94;;187363:25;-1:-1:-1;;;;;187353:35:0;:7;-1:-1:-1;;;;;187353:35:0;;187349:109;;;187412:34;187405:41;;;;;;;;;;;;;187349:109;-1:-1:-1;187570:23:0;;184360:3241;-1:-1:-1;;;;;;;;;;;;;184360:3241:0:o;194332:171::-;194456:16;;;:39;;;-1:-1:-1;194445:50:0;194332:171::o;179117:166::-;-1:-1:-1;;;;;179241:27:0;179215:6;179241:27;;;:19;;;;;:27;;;;;:34;-1:-1:-1;;;;;179241:34:0;;179117:166::o;122498:140::-;122548:15;122599:10;;;;;;;;;-1:-1:-1;;;;;122599:10:0;-1:-1:-1;;;;;122599:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;195179:681:0;195291:6;195510:17;195493:14;:34;195489:75;;;-1:-1:-1;195551:1:0;195544:8;;195489:75;195771:81;195823:17;195772:48;127921:4;195805:14;195772:48;:32;:48;:::i;:::-;:68;;;;;;195771:79;:81::i;188951:149::-;189046:8;:15;189063:28;;;;;;;;;;;;;;;;;;189033;;189025:67;;;;-1:-1:-1;;;;;189025:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;189025:67:0;;188951:149;:::o;120401:121::-;120457:6;120483:8;:6;:8::i;:::-;-1:-1:-1;;;;;120483:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;117103:294:0;117167:18;;:::i;:::-;117199:14;117215:16;117233:17;117254:14;:12;:14::i;:::-;-1:-1:-1;;;;;117254:29:0;;117284:7;117254:38;;;;;;;;;;;;;-1:-1:-1;;;;;117254:38:0;-1:-1:-1;;;;;117254:38:0;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;117254:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;117254:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;117254:38:0;;;;;;;;;;;;117310:79;;117254:38;117310:79;;;;-1:-1:-1;;;;;117310:79:0;;;;;;;;;;;;;;;;;;;;;;117103:294;-1:-1:-1;;;;;117103:294:0:o;196422:447::-;196610:18;;:::i;:::-;-1:-1:-1;196653:208:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;196653:208:0;;;;;;;;;;;;;;;;;;;;;;196422:447::o;197227:1804::-;197366:19;;197420:21;;;;197327:4;197479:22;;197327:4;;-1:-1:-1;;;;;;;;197366:19:0;;;;;;;197420:21;;;;;;;-1:-1:-1;;;197479:22:0;;;197327:4;197539:32;197366:19;197420:21;197539:32;:16;:32;:::i;:::-;197512:59;;197701:22;197746:17;-1:-1:-1;;;;;197726:37:0;:17;-1:-1:-1;;;;;197726:37:0;;:77;;197786:17;197726:77;;;197766:17;197726:77;197701:102;;197846:24;;:::i;:::-;:341;;;;;;;;197896:12;:32;;;197888:41;;197846:341;;;;197944:12;:22;;;197846:341;;;;197989:12;:19;;;-1:-1:-1;;;;;197981:28:0;197846:341;;;;198032:14;-1:-1:-1;;;;;198024:23:0;197846:341;;;;198070:15;-1:-1:-1;;;;;198062:24:0;197846:341;;;;198109:12;-1:-1:-1;;;;;198101:21:0;197846:341;;;;198145:12;:19;;;:30;;;198137:39;;197846:341;;;;;198249:30;198282:17;:15;:17::i;:::-;198249:50;;198311:23;198336:21;198361:14;-1:-1:-1;;;;;198361:20:0;;198382:6;198361:28;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;198361:28:0;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;198361:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;198361:28:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;198361:28:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;;;5:11;;2:2;;;29:1;26;19:12;2:2;198361:28:0;;;;;;19:11:-1;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;261:11;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;-1:-1;;198361:28:0;;;;;;;-1:-1:-1;198361:28:0;-1:-1:-1;198459:24:0;;-1:-1:-1;198486:41:0;;-1:-1:-1;;;;;;198486:18:0;;198361:28;198486:41;:18;:41;:::i;:::-;198538:21;;;:41;;-1:-1:-1;;198538:41:0;-1:-1:-1;;;;;;;;198538:41:0;;;;;;198616:22;;198640:20;;;;198538:41;;-1:-1:-1;198590:102:0;;198538:21;198670:6;198678:13;198590:25;:102::i;:::-;198866:19;;;;:28;;;-1:-1:-1;;;;;198721:33:0;;;;;;;;198703:15;;198866:47;;198899:13;198866:47;:32;:47;:::i;:::-;198846:67;;198924:11;:9;:11::i;:::-;198943:19;;;;:28;198924:71;;;-1:-1:-1;;;;;198924:71:0;;-1:-1:-1;;;;;198924:71:0;;;;;;;198973:10;198924:71;;;;;;;;;;;;:18;;;;;;;:71;;;;;198943:28;;198924:71;;;;;;;;198943:28;198924:18;:71;;;5:2:-1;;;;30:1;27;20:12;5:2;198924:71:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;199013:10:0;;-1:-1:-1;;;;;;;;;;;;;;;197227:1804:0;;;;:::o;191147:295::-;191413:21;;;;191391:18;;191347:7;;-1:-1:-1;;;;;;;;191413:21:0;;;;;;191379:31;;:7;;191391:18;191379:31;:11;:31;:::i;:::-;:55;;;;;;;191147:295;-1:-1:-1;;;;191147:295:0:o;121570:116::-;121614:9;121653:10;;;;;;;;;-1:-1:-1;;;;;121653:10:0;-1:-1:-1;;;;;121653:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;169375:1414:0;169581:20;;169490:5;;-1:-1:-1;;;169581:20:0;;;;169573:33;169569:93;;-1:-1:-1;169630:20:0;;-1:-1:-1;;;169630:20:0;;;;169623:27;;169569:93;169823:19;169870:1;169845:8;:15;;:22;;;;:26;169823:48;;169882:90;169907:8;169917:11;169930:23;169955:7;:16;;;169882:24;:90::i;:::-;170212:35;170250:8;:15;;170266:11;170250:28;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;170317:16:0;;;;170382:25;170317:16;170382:13;:25::i;:::-;:60;;;;;170412:30;170431:10;170412:18;:30::i;:::-;170411:31;170382:60;170344:98;;170453:17;170473:30;:151;;170560:9;:7;:9::i;:::-;-1:-1:-1;;;;;170560:27:0;;170588:35;170599:10;170611:11;170588:10;:35::i;:::-;170560:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;170560:64:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;170560:64:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;170560:64:0;170473:151;;;170519:25;;-1:-1:-1;;;170519:25:0;;;;170473:151;170718:34;;;;-1:-1:-1;;;170718:34:0;;;;;;;;-1:-1:-1;170718:34:0;;169375:1414;-1:-1:-1;;;;;;;169375:1414:0:o;171697:2645::-;171975:7;172000:13;172016:20;:18;:20::i;:::-;172166;;;;172432:13;;;:20;172000:36;;-1:-1:-1;;;;172166:20:0;;-1:-1:-1;;;;;172166:20:0;;172137:26;;172432:44;;172166:20;172432:24;:44::i;:::-;172403:73;;172875:1;172857:15;:19;:59;;;;;172901:15;172880:18;:36;172857:59;172853:191;;;-1:-1:-1;172954:15:0;172853:191;;;173002:30;;-1:-1:-1;;173002:30:0;-1:-1:-1;;;173002:30:0;;;172853:191;173141:42;:18;173164;173141:42;:22;:42;:::i;:::-;173111:6;:20;;;:73;;;;;-1:-1:-1;;;;;173111:73:0;;;;;-1:-1:-1;;;;;173111:73:0;;;;;;173324:30;173357:17;:15;:17::i;:::-;173324:50;;173385:23;173425:18;173411:33;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;173411:33:0;;173385:59;;173455:26;173498:18;173484:33;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;173484:33:0;-1:-1:-1;173455:62:0;-1:-1:-1;173533:9:0;173528:264;173552:18;173548:1;:22;173528:264;;;173592:13;173608:6;:13;;173643:1;173622:18;:22;173608:37;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;173608:37:0;173592:53;;173672:5;173660:6;173667:1;173660:9;;;;;;;;;;;;;:17;-1:-1:-1;;;;;173660:17:0;;;-1:-1:-1;;;;;173660:17:0;;;;;173707:73;173746:6;:19;;:26;173766:5;-1:-1:-1;;;;;173746:26:0;-1:-1:-1;;;;;173746:26:0;;;;;;;;;;;;:33;;;;;;;;;;-1:-1:-1;;;;;173746:33:0;-1:-1:-1;;;;;173707:73:0;:34;173729:11;173707:17;:21;;:34;;;;:::i;:73::-;173692:9;173702:1;173692:12;;;;;;;;;;;;;;;;;:88;-1:-1:-1;173572:3:0;;173528:264;;;;174075:27;174105:9;:7;:9::i;:::-;-1:-1:-1;;;;;174105:28:0;;174134:7;174143:12;174157:6;174105:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;174105:59:0;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;174105:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;174105:59:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;174105:59:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;174105:59:0;;;;;;19:11:-1;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;261:11;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;0:373;;174105:59:0;;;;;;174075:89;;174200:98;174227:14;-1:-1:-1;;;;;174227:28:0;;174256:6;174264;174272:9;174283:13;174227:70;;;;;;;;;;;;;-1:-1:-1;;;;;174227:70:0;-1:-1:-1;;;;;174227:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;174227:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;174227:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;174227:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;174227:70:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;174227:70:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;174227:70:0;;;;;;;;;;;;;;;;174200:6;:22;;;:26;;:98;;;;:::i;:::-;174175:22;;;:123;-1:-1:-1;174316:18:0;;-1:-1:-1;;;;;;171697:2645:0;;;;;;;;:::o;5139:460::-;5199:7;5443;5439:48;;-1:-1:-1;5474:1:0;5467:8;;5439:48;5511:7;;;5516:2;5511;:7;:2;5537:6;;;;;:12;5551:18;;;;;;;;;;;;;;;;;5529:41;;;;;-1:-1:-1;;;;;5529:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;201064:1630:0;201440:21;;;;-1:-1:-1;;;201440:21:0;;-1:-1:-1;;;;;201440:21:0;:25;201436:64;;201482:7;;201436:64;201825:20;;201821:161;;201862:30;201895:17;:15;:17::i;:::-;201862:50;;201927:14;-1:-1:-1;;;;;201927:25:0;;201953:16;201927:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;201927:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;201927:43:0;;;;201821:161;;202243:13;202239:448;;202314:16;;;202333;;;202273:77;;;-1:-1:-1;;;;;202273:77:0;;-1:-1:-1;;;;;202273:77:0;;;;;;;202314:16;;;202273:77;;;;;;;;;;;;:21;;;;;;:77;;;;;202314:16;;202273:77;;;;;;;;202314:16;202273:21;:77;;;5:2:-1;;;;30:1;27;20:12;5:2;202273:77:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;202273:77:0;;;;202239:448;;;202383:18;202423:1;202404:6;:16;;;:20;;;;;;202383:41;;202439:31;202473:8;:15;;202500:1;202489:8;:12;202473:29;;;;;;;;;;;;;;;:36;:29;;;;;:36;202557:22;;202524:68;;;-1:-1:-1;;;;;202524:68:0;;-1:-1:-1;;;;;202524:68:0;;;;;;;202557:22;;;202524:68;;;;;;;;;;;;202473:36;;-1:-1:-1;202524:21:0;;;;;;:68;;;;;;;;;;202473:29;202524:21;:68;;;5:2:-1;;;;30:1;27;20:12;5:2;202524:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;202640:22:0;;;;202607:68;;;-1:-1:-1;;;;;202607:68:0;;-1:-1:-1;;;;;202607:68:0;;;;;;;202640:22;;;202607:68;;;;;;;;;;;;:21;;;;-1:-1:-1;202607:21:0;;:68;;;;;202640:22;;202607:68;;;;;;;202640:22;202607:21;:68;;;5:2:-1;;;;30:1;27;20:12;5:2;202607:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;202239:448:0;201064:1630;;;;;;:::o;188277:129::-;188371:13;-1:-1:-1;;;;;188371:13:0;:27;;;188277:129::o;188623:134::-;188722:13;;;-1:-1:-1;;;;;188722:13:0;:27;;;188623:134::o;6420:175::-;6547:18;;;;;;;;;;;;;;;;;6480:7;;6512;;;;6538;;;;6530:36;;;;-1:-1:-1;;;;;6530:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;6167:177:0;6227:7;6261:2;6255;:8;;6265:19;;;;;;;;;;;;;;;;;6247:38;;;;;-1:-1:-1;;;;;6247:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;6247:38:0;-1:-1:-1;;6308:7:0;;;6167:177::o;175886:1482::-;176028:6;176143:30;176176:17;:15;:17::i;:::-;176269:18;;176228:60;;;-1:-1:-1;;;;;176228:60:0;;-1:-1:-1;;;;;176228:60:0;;;;;;;-1:-1:-1;;;;;176269:18:0;;;176228:60;;;;;;176143:50;;-1:-1:-1;176204:21:0;;176228:32;;;;;;:60;;;;;;;;;;;;;;;:32;:60;;;5:2:-1;;;;30:1;27;20:12;5:2;176228:60:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;176228:60:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;176228:60:0;176359:14;;;;:31;176228:60;;-1:-1:-1;176299:13:0;;176315:76;;176228:60;;176315:28;:76::i;:::-;176299:92;-1:-1:-1;;;;;;176480:11:0;;176476:60;;176522:1;176508:16;;;;;;;176476:60;176765:23;176791:46;176809:7;:16;;;:27;;;176791:13;:17;;:46;;;;:::i;:::-;176765:72;;176964:14;-1:-1:-1;;;;;176964:28:0;;176993:6;177001:15;177018:23;:21;:23::i;:::-;176964:78;;;;;;;;;;-1:-1:-1;;;;;176964:78:0;;;;;;;;;;;;;;-1:-1:-1;;;;;176964:78:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;176964:78:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;176964:78:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;176964:78:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;176964:78:0;176959:128;;177073:1;177059:16;;;;;;;;176959:128;-1:-1:-1;;;;;177212:27:0;;;;;;:19;;;:27;;;;;:43;;-1:-1:-1;;177212:43:0;-1:-1:-1;;;;;177212:43:0;;;;;177291:22;;;;:43;;177318:15;177291:26;:43::i;:::-;177266:22;;;:68;-1:-1:-1;177354:6:0;-1:-1:-1;;;175886:1482:0;;;;;:::o;193181:751::-;193371:13;;193781:27;;;;193727:16;;;;193290:14;;;;193699:110;;193781:27;127921:4;;193700:44;;-1:-1:-1;;;;;193700:22:0;;;:44;:26;:44;:::i;:::-;:75;;;;;;;193699:110;:81;:110;:::i;:::-;193687:122;;193915:9;193903:21;;193181:751;;;;;:::o;183224:539::-;183491:24;;;;183467:19;;183354:6;;;;183467:49;;-1:-1:-1;;;183467:19:0;;;-1:-1:-1;;;;;183467:19:0;;:23;:49::i;:::-;183445:71;-1:-1:-1;183653:25:0;;;183649:77;;183700:14;;183743:12;183224:539;-1:-1:-1;;;183224:539:0:o;22939:127::-;23006:7;22447:5;23033:14;:4;23042;23033:14;:8;:14;:::i;:::-;:25;;;;;;;22939:127;-1:-1:-1;;;22939:127:0:o;2171:378::-;2327:136;;;-1:-1:-1;;;;;2327:136:0;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;2327:136:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;2364:28:0;179:29:-1;160:49;;2274:4:0;;2481:60;2364:6;2327:136;3073:1346;3160:4;3177:8;3237:4;3231:11;3668:4;3596:3;3544:9;3538:16;3496:4;3485:9;3481:20;3430:1;3380:5;3322:3;3299:423;3741:14;;3738:2;;3853:14;3941:57;;;;4080:4;4075:189;;;;3846:519;;3941:57;3978:1;3971:8;;3941:57;;4075:189;4243:1;4237:3;4231:10;4228:17;4221:24;;3846:519;;3738:2;-1:-1:-1;4408:3:0;;3073:1346;-1:-1:-1;;;;3073:1346:0:o;9852:159::-;9948:27;;;;;;;;;;;;;;;;;9904:6;;-1:-1:-1;;;;;9931:15:0;;;9923:53;;;;-1:-1:-1;;;;;9923:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;9923:53:0;-1:-1:-1;10001:1:0;;9852:159;-1:-1:-1;9852:159:0:o;8429:173::-;8487:6;8520:2;-1:-1:-1;;;;;8514:8:0;:2;-1:-1:-1;;;;;8514:8:0;;;8524:19;;;;;;;;;;;;;;;;;8506:38;;;;;-1:-1:-1;;;;;8506:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;199690:744:0;199937:9;199932:495;199956:14;199952:1;:18;199932:495;;;199992:13;200008:7;200016:1;200008:10;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;200065:26:0;;200033:29;200065:26;;;:19;;;:26;;;;;;;200209:17;;200008:10;;-1:-1:-1;200065:26:0;-1:-1:-1;;;;;200209:17:0;200197:97;;200253:13;;;27:10:-1;;39:1;23:18;;45:23;;-1:-1;200253:25:0;;;;;;;;;;-1:-1:-1;;200253:25:0;-1:-1:-1;;;;;200253:25:0;;;;;200197:97;200330:17;;:24;;-1:-1:-1;;;;;200330:17:0;200352:1;200330:24;:21;:24;:::i;:::-;200310:44;;-1:-1:-1;;200310:44:0;-1:-1:-1;;;;;200310:44:0;;;;;;;200374:41;;-1:-1:-1;;;;;200374:41:0;;;200399:8;;200387:10;;200374:41;;-1:-1:-1;;200374:41:0;-1:-1:-1;;199972:3:0;;199932:495;;22799:132;22862:7;22447:5;22889:23;:4;22898:13;;;22889:23;:8;:23;:::i;7621:244::-;7780:18;;;;;;;;;;;;;;;;;7679:6;;-1:-1:-1;;;;;7710:11:0;;;7724;;;7710:25;;-1:-1:-1;;;7754:24:0;;7746:53;;;;-1:-1:-1;;;;;7746:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;125219:77809:0;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;-1:-1:-1;125219:77809:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;125219:77809:0;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;125219:77809:0;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;-1:-1:-1;125219:77809:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;125219:77809:0;;;-1:-1:-1;;125219:77809:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;125219:77809:0;;;-1:-1:-1;;125219:77809:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;125219:77809:0;;;-1:-1:-1;;125219:77809:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;125219:77809:0;;;-1:-1:-1;;125219:77809:0:o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;125219:77809:0;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;125219:77809:0;;;-1:-1:-1;;125219:77809:0:o;:::-;;;;;;;;;;-1:-1:-1;;;;;125219:77809:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;125219:77809:0;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;125219:77809:0;;;;;;;;;;;;;;;;-1:-1:-1;;125219:77809:0;;;;;;;;-1:-1:-1;;125219:77809:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Swarm Source

bzzr://20c137edb6f0f5f0da0d0d361d22809d8f4b8382642960f9058207418aaf2b34

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.