ETH Price: $3,341.93 (+1.40%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Unstake204013442024-07-28 0:04:35182 days ago1722125075IN
Aragon: Juror Registry
0 ETH0.000568623.41240635
Deactivate204012132024-07-27 23:38:11182 days ago1722123491IN
Aragon: Juror Registry
0 ETH0.000100282.38244267
Deactivate204012092024-07-27 23:37:23182 days ago1722123443IN
Aragon: Juror Registry
0 ETH0.000532092.3552664
Unstake199837222024-05-30 16:02:59240 days ago1717084979IN
Aragon: Juror Registry
0 ETH0.004481925.03466144
Deactivate199826802024-05-30 12:31:35240 days ago1717072295IN
Aragon: Juror Registry
0 ETH0.002401310.62924565
Unstake196512102024-04-14 3:51:11287 days ago1713066671IN
Aragon: Juror Registry
0 ETH0.001632799.11911109
Deactivate196460962024-04-13 10:36:35287 days ago1713004595IN
Aragon: Juror Registry
0 ETH0.0024853211
Unstake187814362023-12-14 2:33:35409 days ago1702521215IN
Aragon: Juror Registry
0 ETH0.00853747.68528833
Deactivate187785922023-12-13 16:59:23409 days ago1702486763IN
Aragon: Juror Registry
0 ETH0.0164680559.42852122
Deactivate187467412023-12-09 5:59:23413 days ago1702101563IN
Aragon: Juror Registry
0 ETH0.0011906837.06512722
Unstake173994012023-06-03 9:55:47602 days ago1685786147IN
Aragon: Juror Registry
0 ETH0.0050613628.27137585
Deactivate173970132023-06-03 1:53:11603 days ago1685757191IN
Aragon: Juror Registry
0 ETH0.0056704525.09993833
Unstake143912772022-03-15 12:52:541047 days ago1647348774IN
Aragon: Juror Registry
0 ETH0.0021405513
Unstake143321202022-03-06 7:53:431056 days ago1646553223IN
Aragon: Juror Registry
0 ETH0.0039790822.2260241
Unstake141997702022-02-13 19:45:181077 days ago1644781518IN
Aragon: Juror Registry
0 ETH0.010804964.84214554
Deactivate141946242022-02-13 0:48:241078 days ago1644713304IN
Aragon: Juror Registry
0 ETH0.0103311945.73046825
Unstake140887662022-01-27 16:28:101094 days ago1643300890IN
Aragon: Juror Registry
0 ETH0.02788295155.72547969
Deactivate140824782022-01-26 16:57:501095 days ago1643216270IN
Aragon: Juror Registry
0 ETH0.04145903183.49658974
Unstake140564622022-01-22 16:24:591099 days ago1642868699IN
Aragon: Juror Registry
0 ETH0.02080048116.18563497
Deactivate140559182022-01-22 14:21:081099 days ago1642861268IN
Aragon: Juror Registry
0 ETH0.02318082102.60861255
Unstake140427712022-01-20 13:46:371101 days ago1642686397IN
Aragon: Juror Registry
0 ETH0.0169332894.57187946
Unstake140352652022-01-19 9:50:031102 days ago1642585803IN
Aragon: Juror Registry
0 ETH0.0119146266.55173852
Deactivate140310452022-01-18 18:06:351103 days ago1642529195IN
Aragon: Juror Registry
0 ETH0.03068242135.79959385
Deactivate140175982022-01-16 16:19:381105 days ago1642349978IN
Aragon: Juror Registry
0 ETH0.0207577191.88285771
Unstake140175332022-01-16 16:06:511105 days ago1642349211IN
Aragon: Juror Registry
0 ETH0.0185217111.15200173
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
JurorsRegistry

Compiler Version
v0.5.8+commit.23d335f2

Optimization Enabled:
Yes with 3000 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-02-07
*/

/**
* Commit sha: 057b118bce7af86318eb522112350f950e9b7834
* GitHub repository: https://github.com/aragon/aragon-court
* Tool used for the deploy: https://github.com/aragon/aragon-network-deploy
**/

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

// 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/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/BytesHelpers.sol

pragma solidity ^0.5.8;


library BytesHelpers {
    function toBytes4(bytes memory _self) internal pure returns (bytes4 result) {
        if (_self.length < 4) {
            return bytes4(0);
        }

        assembly { result := mload(add(_self, 0x20)) }
    }
}

// File: contracts/lib/Checkpointing.sol

pragma solidity ^0.5.8;


/**
* @title Checkpointing - Library to handle a historic set of numeric values
*/
library Checkpointing {
    uint256 private constant MAX_UINT192 = uint256(uint192(-1));

    string private constant ERROR_VALUE_TOO_BIG = "CHECKPOINT_VALUE_TOO_BIG";
    string private constant ERROR_CANNOT_ADD_PAST_VALUE = "CHECKPOINT_CANNOT_ADD_PAST_VALUE";

    /**
    * @dev To specify a value at a given point in time, we need to store two values:
    *      - `time`: unit-time value to denote the first time when a value was registered
    *      - `value`: a positive numeric value to registered at a given point in time
    *
    *      Note that `time` does not need to refer necessarily to a timestamp value, any time unit could be used
    *      for it like block numbers, terms, etc.
    */
    struct Checkpoint {
        uint64 time;
        uint192 value;
    }

    /**
    * @dev A history simply denotes a list of checkpoints
    */
    struct History {
        Checkpoint[] history;
    }

    /**
    * @dev Add a new value to a history for a given point in time. This function does not allow to add values previous
    *      to the latest registered value, if the value willing to add corresponds to the latest registered value, it
    *      will be updated.
    * @param self Checkpoints history to be altered
    * @param _time Point in time to register the given value
    * @param _value Numeric value to be registered at the given point in time
    */
    function add(History storage self, uint64 _time, uint256 _value) internal {
        require(_value <= MAX_UINT192, ERROR_VALUE_TOO_BIG);
        _add192(self, _time, uint192(_value));
    }

    /**
    * @dev Fetch the latest registered value of history, it will return zero if there was no value registered
    * @param self Checkpoints history to be queried
    */
    function getLast(History storage self) internal view returns (uint256) {
        uint256 length = self.history.length;
        if (length > 0) {
            return uint256(self.history[length - 1].value);
        }

        return 0;
    }

    /**
    * @dev Fetch the most recent registered past value of a history based on a given point in time that is not known
    *      how recent it is beforehand. It will return zero if there is no registered value or if given time is
    *      previous to the first registered value.
    *      It uses a binary search.
    * @param self Checkpoints history to be queried
    * @param _time Point in time to query the most recent registered past value of
    */
    function get(History storage self, uint64 _time) internal view returns (uint256) {
        return _binarySearch(self, _time);
    }

    /**
    * @dev Fetch the most recent registered past value of a history based on a given point in time. It will return zero
    *      if there is no registered value or if given time is previous to the first registered value.
    *      It uses a linear search starting from the end.
    * @param self Checkpoints history to be queried
    * @param _time Point in time to query the most recent registered past value of
    */
    function getRecent(History storage self, uint64 _time) internal view returns (uint256) {
        return _backwardsLinearSearch(self, _time);
    }

    /**
    * @dev Private function to add a new value to a history for a given point in time. This function does not allow to
    *      add values previous to the latest registered value, if the value willing to add corresponds to the latest
    *      registered value, it will be updated.
    * @param self Checkpoints history to be altered
    * @param _time Point in time to register the given value
    * @param _value Numeric value to be registered at the given point in time
    */
    function _add192(History storage self, uint64 _time, uint192 _value) private {
        uint256 length = self.history.length;
        if (length == 0 || self.history[self.history.length - 1].time < _time) {
            // If there was no value registered or the given point in time is after the latest registered value,
            // we can insert it to the history directly.
            self.history.push(Checkpoint(_time, _value));
        } else {
            // If the point in time given for the new value is not after the latest registered value, we must ensure
            // we are only trying to update the latest value, otherwise we would be changing past data.
            Checkpoint storage currentCheckpoint = self.history[length - 1];
            require(_time == currentCheckpoint.time, ERROR_CANNOT_ADD_PAST_VALUE);
            currentCheckpoint.value = _value;
        }
    }

    /**
    * @dev Private function to execute a backwards linear search to find the most recent registered past value of a
    *      history based on a given point in time. It will return zero if there is no registered value or if given time
    *      is previous to the first registered value. Note that this function will be more suitable when we already know
    *      that the time used to index the search is recent in the given history.
    * @param self Checkpoints history to be queried
    * @param _time Point in time to query the most recent registered past value of
    */
    function _backwardsLinearSearch(History storage self, uint64 _time) private view returns (uint256) {
        // If there was no value registered for the given history return simply zero
        uint256 length = self.history.length;
        if (length == 0) {
            return 0;
        }

        uint256 index = length - 1;
        Checkpoint storage checkpoint = self.history[index];
        while (index > 0 && checkpoint.time > _time) {
            index--;
            checkpoint = self.history[index];
        }

        return checkpoint.time > _time ? 0 : uint256(checkpoint.value);
    }

    /**
    * @dev Private function execute a binary search to find the most recent registered past value of a history based on
    *      a given point in time. It will return zero if there is no registered value or if given time is previous to
    *      the first registered value. Note that this function will be more suitable when don't know how recent the
    *      time used to index may be.
    * @param self Checkpoints history to be queried
    * @param _time Point in time to query the most recent registered past value of
    */
    function _binarySearch(History storage self, uint64 _time) private view returns (uint256) {
        // If there was no value registered for the given history return simply zero
        uint256 length = self.history.length;
        if (length == 0) {
            return 0;
        }

        // If the requested time is equal to or after the time of the latest registered value, return latest value
        uint256 lastIndex = length - 1;
        if (_time >= self.history[lastIndex].time) {
            return uint256(self.history[lastIndex].value);
        }

        // If the requested time is previous to the first registered value, return zero to denote missing checkpoint
        if (_time < self.history[0].time) {
            return 0;
        }

        // Execute a binary search between the checkpointed times of the history
        uint256 low = 0;
        uint256 high = lastIndex;

        while (high > low) {
            // No need for SafeMath: for this to overflow array size should be ~2^255
            uint256 mid = (high + low + 1) / 2;
            Checkpoint storage checkpoint = self.history[mid];
            uint64 midTime = checkpoint.time;

            if (_time > midTime) {
                low = mid;
            } else if (_time < midTime) {
                // No need for SafeMath: high > low >= 0 => high >= 1 => mid >= 1
                high = mid - 1;
            } else {
                return uint256(checkpoint.value);
            }
        }

        return uint256(self.history[low].value);
    }
}

// File: contracts/lib/HexSumTree.sol

pragma solidity ^0.5.8;




/**
* @title HexSumTree - Library to operate checkpointed 16-ary (hex) sum trees.
* @dev A sum tree is a particular case of a tree where the value of a node is equal to the sum of the values of its
*      children. This library provides a set of functions to operate 16-ary sum trees, i.e. trees where every non-leaf
*      node has 16 children and its value is equivalent to the sum of the values of all of them. Additionally, a
*      checkpointed tree means that each time a value on a node is updated, its previous value will be saved to allow
*      accessing historic information.
*
*      Example of a checkpointed binary sum tree:
*
*                                          CURRENT                                      PREVIOUS
*
*             Level 2                        100  ---------------------------------------- 70
*                                       ______|_______                               ______|_______
*                                      /              \                             /              \
*             Level 1                 34              66 ------------------------- 23              47
*                                _____|_____      _____|_____                 _____|_____      _____|_____
*                               /           \    /           \               /           \    /           \
*             Level 0          22           12  53           13 ----------- 22            1  17           30
*
*/
library HexSumTree {
    using SafeMath for uint256;
    using Checkpointing for Checkpointing.History;

    string private constant ERROR_UPDATE_OVERFLOW = "SUM_TREE_UPDATE_OVERFLOW";
    string private constant ERROR_KEY_DOES_NOT_EXIST = "SUM_TREE_KEY_DOES_NOT_EXIST";
    string private constant ERROR_SEARCH_OUT_OF_BOUNDS = "SUM_TREE_SEARCH_OUT_OF_BOUNDS";
    string private constant ERROR_MISSING_SEARCH_VALUES = "SUM_TREE_MISSING_SEARCH_VALUES";

    // Constants used to perform tree computations
    // To change any the following constants, the following relationship must be kept: 2^BITS_IN_NIBBLE = CHILDREN
    // The max depth of the tree will be given by: BITS_IN_NIBBLE * MAX_DEPTH = 256 (so in this case it's 64)
    uint256 private constant CHILDREN = 16;
    uint256 private constant BITS_IN_NIBBLE = 4;

    // All items are leaves, inserted at height or level zero. The root height will be increasing as new levels are inserted in the tree.
    uint256 private constant ITEMS_LEVEL = 0;

    // Tree nodes are identified with a 32-bytes length key. Leaves are identified with consecutive incremental keys
    // starting with 0x0000000000000000000000000000000000000000000000000000000000000000, while non-leaf nodes' keys
    // are computed based on their level and their children keys.
    uint256 private constant BASE_KEY = 0;

    // Timestamp used to checkpoint the first value of the tree height during initialization
    uint64 private constant INITIALIZATION_INITIAL_TIME = uint64(0);

    /**
    * @dev The tree is stored using the following structure:
    *      - nodes: A mapping indexed by a pair (level, key) with a history of the values for each node (level -> key -> value).
    *      - height: A history of the heights of the tree. Minimum height is 1, a root with 16 children.
    *      - nextKey: The next key to be used to identify the next new value that will be inserted into the tree.
    */
    struct Tree {
        uint256 nextKey;
        Checkpointing.History height;
        mapping (uint256 => mapping (uint256 => Checkpointing.History)) nodes;
    }

    /**
    * @dev Search params to traverse the tree caching previous results:
    *      - time: Point in time to query the values being searched, this value shouldn't change during a search
    *      - level: Level being analyzed for the search, it starts at the level under the root and decrements till the leaves
    *      - parentKey: Key of the parent of the nodes being analyzed at the given level for the search
    *      - foundValues: Number of values in the list being searched that were already found, it will go from 0 until the size of the list
    *      - visitedTotal: Total sum of values that were already visited during the search, it will go from 0 until the tree total
    */
    struct SearchParams {
        uint64 time;
        uint256 level;
        uint256 parentKey;
        uint256 foundValues;
        uint256 visitedTotal;
    }

    /**
    * @dev Initialize tree setting the next key and first height checkpoint
    */
    function init(Tree storage self) internal {
        self.height.add(INITIALIZATION_INITIAL_TIME, ITEMS_LEVEL + 1);
        self.nextKey = BASE_KEY;
    }

    /**
    * @dev Insert a new item to the tree at given point in time
    * @param _time Point in time to register the given value
    * @param _value New numeric value to be added to the tree
    * @return Unique key identifying the new value inserted
    */
    function insert(Tree storage self, uint64 _time, uint256 _value) internal returns (uint256) {
        // As the values are always stored in the leaves of the tree (level 0), the key to index each of them will be
        // always incrementing, starting from zero. Add a new level if necessary.
        uint256 key = self.nextKey++;
        _addLevelIfNecessary(self, key, _time);

        // If the new value is not zero, first set the value of the new leaf node, then add a new level at the top of
        // the tree if necessary, and finally update sums cached in all the non-leaf nodes.
        if (_value > 0) {
            _add(self, ITEMS_LEVEL, key, _time, _value);
            _updateSums(self, key, _time, _value, true);
        }
        return key;
    }

    /**
    * @dev Set the value of a leaf node indexed by its key at given point in time
    * @param _time Point in time to set the given value
    * @param _key Key of the leaf node to be set in the tree
    * @param _value New numeric value to be set for the given key
    */
    function set(Tree storage self, uint256 _key, uint64 _time, uint256 _value) internal {
        require(_key < self.nextKey, ERROR_KEY_DOES_NOT_EXIST);

        // Set the new value for the requested leaf node
        uint256 lastValue = getItem(self, _key);
        _add(self, ITEMS_LEVEL, _key, _time, _value);

        // Update sums cached in the non-leaf nodes. Note that overflows are being checked at the end of the whole update.
        if (_value > lastValue) {
            _updateSums(self, _key, _time, _value - lastValue, true);
        } else if (_value < lastValue) {
            _updateSums(self, _key, _time, lastValue - _value, false);
        }
    }

    /**
    * @dev Update the value of a non-leaf node indexed by its key at given point in time based on a delta
    * @param _key Key of the leaf node to be updated in the tree
    * @param _time Point in time to update the given value
    * @param _delta Numeric delta to update the value of the given key
    * @param _positive Boolean to tell whether the given delta should be added to or subtracted from the current value
    */
    function update(Tree storage self, uint256 _key, uint64 _time, uint256 _delta, bool _positive) internal {
        require(_key < self.nextKey, ERROR_KEY_DOES_NOT_EXIST);

        // Update the value of the requested leaf node based on the given delta
        uint256 lastValue = getItem(self, _key);
        uint256 newValue = _positive ? lastValue.add(_delta) : lastValue.sub(_delta);
        _add(self, ITEMS_LEVEL, _key, _time, newValue);

        // Update sums cached in the non-leaf nodes. Note that overflows is being checked at the end of the whole update.
        _updateSums(self, _key, _time, _delta, _positive);
    }

    /**
    * @dev Search a list of values in the tree at a given point in time. It will return a list with the nearest
    *      high value in case a value cannot be found. This function assumes the given list of given values to be
    *      searched is in ascending order. In case of searching a value out of bounds, it will return zeroed results.
    * @param _values Ordered list of values to be searched in the tree
    * @param _time Point in time to query the values being searched
    * @return keys List of keys found for each requested value in the same order
    * @return values List of node values found for each requested value in the same order
    */
    function search(Tree storage self, uint256[] memory _values, uint64 _time) internal view
        returns (uint256[] memory keys, uint256[] memory values)
    {
        require(_values.length > 0, ERROR_MISSING_SEARCH_VALUES);

        // Throw out-of-bounds error if there are no items in the tree or the highest value being searched is greater than the total
        uint256 total = getRecentTotalAt(self, _time);
        // No need for SafeMath: positive length of array already checked
        require(total > 0 && total > _values[_values.length - 1], ERROR_SEARCH_OUT_OF_BOUNDS);

        // Build search params for the first iteration
        uint256 rootLevel = getRecentHeightAt(self, _time);
        SearchParams memory searchParams = SearchParams(_time, rootLevel.sub(1), BASE_KEY, 0, 0);

        // These arrays will be used to fill in the results. We are passing them as parameters to avoid extra copies
        uint256 length = _values.length;
        keys = new uint256[](length);
        values = new uint256[](length);
        _search(self, _values, searchParams, keys, values);
    }

    /**
    * @dev Tell the sum of the all the items (leaves) stored in the tree, i.e. value of the root of the tree
    */
    function getTotal(Tree storage self) internal view returns (uint256) {
        uint256 rootLevel = getHeight(self);
        return getNode(self, rootLevel, BASE_KEY);
    }

    /**
    * @dev Tell the sum of the all the items (leaves) stored in the tree, i.e. value of the root of the tree, at a given point in time
    *      It uses a binary search for the root node, a linear one for the height.
    * @param _time Point in time to query the sum of all the items (leaves) stored in the tree
    */
    function getTotalAt(Tree storage self, uint64 _time) internal view returns (uint256) {
        uint256 rootLevel = getRecentHeightAt(self, _time);
        return getNodeAt(self, rootLevel, BASE_KEY, _time);
    }

    /**
    * @dev Tell the sum of the all the items (leaves) stored in the tree, i.e. value of the root of the tree, at a given point in time
    *      It uses a linear search starting from the end.
    * @param _time Point in time to query the sum of all the items (leaves) stored in the tree
    */
    function getRecentTotalAt(Tree storage self, uint64 _time) internal view returns (uint256) {
        uint256 rootLevel = getRecentHeightAt(self, _time);
        return getRecentNodeAt(self, rootLevel, BASE_KEY, _time);
    }

    /**
    * @dev Tell the value of a certain leaf indexed by a given key
    * @param _key Key of the leaf node querying the value of
    */
    function getItem(Tree storage self, uint256 _key) internal view returns (uint256) {
        return getNode(self, ITEMS_LEVEL, _key);
    }

    /**
    * @dev Tell the value of a certain leaf indexed by a given key at a given point in time
    *      It uses a binary search.
    * @param _key Key of the leaf node querying the value of
    * @param _time Point in time to query the value of the requested leaf
    */
    function getItemAt(Tree storage self, uint256 _key, uint64 _time) internal view returns (uint256) {
        return getNodeAt(self, ITEMS_LEVEL, _key, _time);
    }

    /**
    * @dev Tell the value of a certain node indexed by a given (level,key) pair
    * @param _level Level of the node querying the value of
    * @param _key Key of the node querying the value of
    */
    function getNode(Tree storage self, uint256 _level, uint256 _key) internal view returns (uint256) {
        return self.nodes[_level][_key].getLast();
    }

    /**
    * @dev Tell the value of a certain node indexed by a given (level,key) pair at a given point in time
    *      It uses a binary search.
    * @param _level Level of the node querying the value of
    * @param _key Key of the node querying the value of
    * @param _time Point in time to query the value of the requested node
    */
    function getNodeAt(Tree storage self, uint256 _level, uint256 _key, uint64 _time) internal view returns (uint256) {
        return self.nodes[_level][_key].get(_time);
    }

    /**
    * @dev Tell the value of a certain node indexed by a given (level,key) pair at a given point in time
    *      It uses a linear search starting from the end.
    * @param _level Level of the node querying the value of
    * @param _key Key of the node querying the value of
    * @param _time Point in time to query the value of the requested node
    */
    function getRecentNodeAt(Tree storage self, uint256 _level, uint256 _key, uint64 _time) internal view returns (uint256) {
        return self.nodes[_level][_key].getRecent(_time);
    }

    /**
    * @dev Tell the height of the tree
    */
    function getHeight(Tree storage self) internal view returns (uint256) {
        return self.height.getLast();
    }

    /**
    * @dev Tell the height of the tree at a given point in time
    *      It uses a linear search starting from the end.
    * @param _time Point in time to query the height of the tree
    */
    function getRecentHeightAt(Tree storage self, uint64 _time) internal view returns (uint256) {
        return self.height.getRecent(_time);
    }

    /**
    * @dev Private function to update the values of all the ancestors of the given leaf node based on the delta updated
    * @param _key Key of the leaf node to update the ancestors of
    * @param _time Point in time to update the ancestors' values of the given leaf node
    * @param _delta Numeric delta to update the ancestors' values of the given leaf node
    * @param _positive Boolean to tell whether the given delta should be added to or subtracted from ancestors' values
    */
    function _updateSums(Tree storage self, uint256 _key, uint64 _time, uint256 _delta, bool _positive) private {
        uint256 mask = uint256(-1);
        uint256 ancestorKey = _key;
        uint256 currentHeight = getHeight(self);
        for (uint256 level = ITEMS_LEVEL + 1; level <= currentHeight; level++) {
            // Build a mask to get the key of the ancestor at a certain level. For example:
            // Level  0: leaves don't have children
            // Level  1: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0 (up to 16 leaves)
            // Level  2: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 (up to 32 leaves)
            // ...
            // Level 63: 0x0000000000000000000000000000000000000000000000000000000000000000 (up to 16^64 leaves - tree max height)
            mask = mask << BITS_IN_NIBBLE;

            // The key of the ancestor at that level "i" is equivalent to the "(64 - i)-th" most significant nibbles
            // of the ancestor's key of the previous level "i - 1". Thus, we can compute the key of an ancestor at a
            // certain level applying the mask to the ancestor's key of the previous level. Note that for the first
            // iteration, the key of the ancestor of the previous level is simply the key of the leaf being updated.
            ancestorKey = ancestorKey & mask;

            // Update value
            uint256 lastValue = getNode(self, level, ancestorKey);
            uint256 newValue = _positive ? lastValue.add(_delta) : lastValue.sub(_delta);
            _add(self, level, ancestorKey, _time, newValue);
        }

        // Check if there was an overflow. Note that we only need to check the value stored in the root since the
        // sum only increases going up through the tree.
        require(!_positive || getNode(self, currentHeight, ancestorKey) >= _delta, ERROR_UPDATE_OVERFLOW);
    }

    /**
    * @dev Private function to add a new level to the tree based on a new key that will be inserted
    * @param _newKey New key willing to be inserted in the tree
    * @param _time Point in time when the new key will be inserted
    */
    function _addLevelIfNecessary(Tree storage self, uint256 _newKey, uint64 _time) private {
        uint256 currentHeight = getHeight(self);
        if (_shouldAddLevel(currentHeight, _newKey)) {
            // Max height allowed for the tree is 64 since we are using node keys of 32 bytes. However, note that we
            // are not checking if said limit has been hit when inserting new leaves to the tree, for the purpose of
            // this system having 2^256 items inserted is unrealistic.
            uint256 newHeight = currentHeight + 1;
            uint256 rootValue = getNode(self, currentHeight, BASE_KEY);
            _add(self, newHeight, BASE_KEY, _time, rootValue);
            self.height.add(_time, newHeight);
        }
    }

    /**
    * @dev Private function to register a new value in the history of a node at a given point in time
    * @param _level Level of the node to add a new value at a given point in time to
    * @param _key Key of the node to add a new value at a given point in time to
    * @param _time Point in time to register a value for the given node
    * @param _value Numeric value to be registered for the given node at a given point in time
    */
    function _add(Tree storage self, uint256 _level, uint256 _key, uint64 _time, uint256 _value) private {
        self.nodes[_level][_key].add(_time, _value);
    }

    /**
    * @dev Recursive pre-order traversal function
    *      Every time it checks a node, it traverses the input array to find the initial subset of elements that are
    *      below its accumulated value and passes that sub-array to the next iteration. Actually, the array is always
    *      the same, to avoid making extra copies, it just passes the number of values already found , to avoid
    *      checking values that went through a different branch. The same happens with the result lists of keys and
    *      values, these are the same on every recursion step. The visited total is carried over each iteration to
    *      avoid having to subtract all elements in the array.
    * @param _values Ordered list of values to be searched in the tree
    * @param _params Search parameters for the current recursive step
    * @param _resultKeys List of keys found for each requested value in the same order
    * @param _resultValues List of node values found for each requested value in the same order
    */
    function _search(
        Tree storage self,
        uint256[] memory _values,
        SearchParams memory _params,
        uint256[] memory _resultKeys,
        uint256[] memory _resultValues
    )
        private
        view
    {
        uint256 levelKeyLessSignificantNibble = _params.level.mul(BITS_IN_NIBBLE);

        for (uint256 childNumber = 0; childNumber < CHILDREN; childNumber++) {
            // Return if we already found enough values
            if (_params.foundValues >= _values.length) {
                break;
            }

            // Build child node key shifting the child number to the position of the less significant nibble of
            // the keys for the level being analyzed, and adding it to the key of the parent node. For example,
            // for a tree with height 5, if we are checking the children of the second node of the level 3, whose
            // key is    0x0000000000000000000000000000000000000000000000000000000000001000, its children keys are:
            // Child  0: 0x0000000000000000000000000000000000000000000000000000000000001000
            // Child  1: 0x0000000000000000000000000000000000000000000000000000000000001100
            // Child  2: 0x0000000000000000000000000000000000000000000000000000000000001200
            // ...
            // Child 15: 0x0000000000000000000000000000000000000000000000000000000000001f00
            uint256 childNodeKey = _params.parentKey.add(childNumber << levelKeyLessSignificantNibble);
            uint256 childNodeValue = getRecentNodeAt(self, _params.level, childNodeKey, _params.time);

            // Check how many values belong to the subtree of this node. As they are ordered, it will be a contiguous
            // subset starting from the beginning, so we only need to know the length of that subset.
            uint256 newVisitedTotal = _params.visitedTotal.add(childNodeValue);
            uint256 subtreeIncludedValues = _getValuesIncludedInSubtree(_values, _params.foundValues, newVisitedTotal);

            // If there are some values included in the subtree of the child node, visit them
            if (subtreeIncludedValues > 0) {
                // If the child node being analyzed is a leaf, add it to the list of results a number of times equals
                // to the number of values that were included in it. Otherwise, descend one level.
                if (_params.level == ITEMS_LEVEL) {
                    _copyFoundNode(_params.foundValues, subtreeIncludedValues, childNodeKey, _resultKeys, childNodeValue, _resultValues);
                } else {
                    SearchParams memory nextLevelParams = SearchParams(
                        _params.time,
                        _params.level - 1, // No need for SafeMath: we already checked above that the level being checked is greater than zero
                        childNodeKey,
                        _params.foundValues,
                        _params.visitedTotal
                    );
                    _search(self, _values, nextLevelParams, _resultKeys, _resultValues);
                }
                // Update the number of values that were already found
                _params.foundValues = _params.foundValues.add(subtreeIncludedValues);
            }
            // Update the visited total for the next node in this level
            _params.visitedTotal = newVisitedTotal;
        }
    }

    /**
    * @dev Private function to check if a new key can be added to the tree based on the current height of the tree
    * @param _currentHeight Current height of the tree to check if it supports adding the given key
    * @param _newKey Key willing to be added to the tree with the given current height
    * @return True if the current height of the tree should be increased to add the new key, false otherwise.
    */
    function _shouldAddLevel(uint256 _currentHeight, uint256 _newKey) private pure returns (bool) {
        // Build a mask that will match all the possible keys for the given height. For example:
        // Height  1: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0 (up to 16 keys)
        // Height  2: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 (up to 32 keys)
        // ...
        // Height 64: 0x0000000000000000000000000000000000000000000000000000000000000000 (up to 16^64 keys - tree max height)
        uint256 shift = _currentHeight.mul(BITS_IN_NIBBLE);
        uint256 mask = uint256(-1) << shift;

        // Check if the given key can be represented in the tree with the current given height using the mask.
        return (_newKey & mask) != 0;
    }

    /**
    * @dev Private function to tell how many values of a list can be found in a subtree
    * @param _values List of values being searched in ascending order
    * @param _foundValues Number of values that were already found and should be ignore
    * @param _subtreeTotal Total sum of the given subtree to check the numbers that are included in it
    * @return Number of values in the list that are included in the given subtree
    */
    function _getValuesIncludedInSubtree(uint256[] memory _values, uint256 _foundValues, uint256 _subtreeTotal) private pure returns (uint256) {
        // Look for all the values that can be found in the given subtree
        uint256 i = _foundValues;
        while (i < _values.length && _values[i] < _subtreeTotal) {
            i++;
        }
        return i - _foundValues;
    }

    /**
    * @dev Private function to copy a node a given number of times to a results list. This function assumes the given
    *      results list have enough size to support the requested copy.
    * @param _from Index of the results list to start copying the given node
    * @param _times Number of times the given node will be copied
    * @param _key Key of the node to be copied
    * @param _resultKeys Lists of key results to copy the given node key to
    * @param _value Value of the node to be copied
    * @param _resultValues Lists of value results to copy the given node value to
    */
    function _copyFoundNode(
        uint256 _from,
        uint256 _times,
        uint256 _key,
        uint256[] memory _resultKeys,
        uint256 _value,
        uint256[] memory _resultValues
    )
        private
        pure
    {
        for (uint256 i = 0; i < _times; i++) {
            _resultKeys[_from + i] = _key;
            _resultValues[_from + i] = _value;
        }
    }
}

// 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)

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

    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 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/lib/JurorsTreeSortition.sol

pragma solidity ^0.5.8;




/**
* @title JurorsTreeSortition - Library to perform jurors sortition over a `HexSumTree`
*/
library JurorsTreeSortition {
    using SafeMath for uint256;
    using HexSumTree for HexSumTree.Tree;

    string private constant ERROR_INVALID_INTERVAL_SEARCH = "TREE_INVALID_INTERVAL_SEARCH";
    string private constant ERROR_SORTITION_LENGTHS_MISMATCH = "TREE_SORTITION_LENGTHS_MISMATCH";

    /**
    * @dev Search random items in the tree based on certain restrictions
    * @param _termRandomness Randomness to compute the seed for the draft
    * @param _disputeId Identification number of the dispute to draft jurors for
    * @param _termId Current term when the draft is being computed
    * @param _selectedJurors Number of jurors already selected for the draft
    * @param _batchRequestedJurors Number of jurors to be selected in the given batch of the draft
    * @param _roundRequestedJurors Total number of jurors requested to be drafted
    * @param _sortitionIteration Number of sortitions already performed for the given draft
    * @return jurorsIds List of juror ids obtained based on the requested search
    * @return jurorsBalances List of active balances for each juror obtained based on the requested search
    */
    function batchedRandomSearch(
        HexSumTree.Tree storage tree,
        bytes32 _termRandomness,
        uint256 _disputeId,
        uint64 _termId,
        uint256 _selectedJurors,
        uint256 _batchRequestedJurors,
        uint256 _roundRequestedJurors,
        uint256 _sortitionIteration
    )
        internal
        view
        returns (uint256[] memory jurorsIds, uint256[] memory jurorsBalances)
    {
        (uint256 low, uint256 high) = getSearchBatchBounds(tree, _termId, _selectedJurors, _batchRequestedJurors, _roundRequestedJurors);
        uint256[] memory balances = _computeSearchRandomBalances(
            _termRandomness,
            _disputeId,
            _sortitionIteration,
            _batchRequestedJurors,
            low,
            high
        );

        (jurorsIds, jurorsBalances) = tree.search(balances, _termId);

        require(jurorsIds.length == jurorsBalances.length, ERROR_SORTITION_LENGTHS_MISMATCH);
        require(jurorsIds.length == _batchRequestedJurors, ERROR_SORTITION_LENGTHS_MISMATCH);
    }

    /**
    * @dev Get the bounds for a draft batch based on the active balances of the jurors
    * @param _termId Term ID of the active balances that will be used to compute the boundaries
    * @param _selectedJurors Number of jurors already selected for the draft
    * @param _batchRequestedJurors Number of jurors to be selected in the given batch of the draft
    * @param _roundRequestedJurors Total number of jurors requested to be drafted
    * @return low Low bound to be used for the sortition to draft the requested number of jurors for the given batch
    * @return high High bound to be used for the sortition to draft the requested number of jurors for the given batch
    */
    function getSearchBatchBounds(
        HexSumTree.Tree storage tree,
        uint64 _termId,
        uint256 _selectedJurors,
        uint256 _batchRequestedJurors,
        uint256 _roundRequestedJurors
    )
        internal
        view
        returns (uint256 low, uint256 high)
    {
        uint256 totalActiveBalance = tree.getRecentTotalAt(_termId);
        low = _selectedJurors.mul(totalActiveBalance).div(_roundRequestedJurors);

        uint256 newSelectedJurors = _selectedJurors.add(_batchRequestedJurors);
        high = newSelectedJurors.mul(totalActiveBalance).div(_roundRequestedJurors);
    }

    /**
    * @dev Get a random list of active balances to be searched in the jurors tree for a given draft batch
    * @param _termRandomness Randomness to compute the seed for the draft
    * @param _disputeId Identification number of the dispute to draft jurors for (for randomness)
    * @param _sortitionIteration Number of sortitions already performed for the given draft (for randomness)
    * @param _batchRequestedJurors Number of jurors to be selected in the given batch of the draft
    * @param _lowBatchBound Low bound to be used for the sortition batch to draft the requested number of jurors
    * @param _highBatchBound High bound to be used for the sortition batch to draft the requested number of jurors
    * @return Random list of active balances to be searched in the jurors tree for the given draft batch
    */
    function _computeSearchRandomBalances(
        bytes32 _termRandomness,
        uint256 _disputeId,
        uint256 _sortitionIteration,
        uint256 _batchRequestedJurors,
        uint256 _lowBatchBound,
        uint256 _highBatchBound
    )
        internal
        pure
        returns (uint256[] memory)
    {
        // Calculate the interval to be used to search the balances in the tree. Since we are using a modulo function to compute the
        // random balances to be searched, intervals will be closed on the left and open on the right, for example [0,10).
        require(_highBatchBound > _lowBatchBound, ERROR_INVALID_INTERVAL_SEARCH);
        uint256 interval = _highBatchBound - _lowBatchBound;

        // Compute an ordered list of random active balance to be searched in the jurors tree
        uint256[] memory balances = new uint256[](_batchRequestedJurors);
        for (uint256 batchJurorNumber = 0; batchJurorNumber < _batchRequestedJurors; batchJurorNumber++) {
            // Compute a random seed using:
            // - The inherent randomness associated to the term from blockhash
            // - The disputeId, so 2 disputes in the same term will have different outcomes
            // - The sortition iteration, to avoid getting stuck if resulting jurors are dismissed due to locked balance
            // - The juror number in this batch
            bytes32 seed = keccak256(abi.encodePacked(_termRandomness, _disputeId, _sortitionIteration, batchJurorNumber));

            // Compute a random active balance to be searched in the jurors tree using the generated seed within the
            // boundaries computed for the current batch.
            balances[batchJurorNumber] = _lowBatchBound.add(uint256(seed) % interval);

            // Make sure it's ordered, flip values if necessary
            for (uint256 i = batchJurorNumber; i > 0 && balances[i] < balances[i - 1]; i--) {
                uint256 tmp = balances[i - 1];
                balances[i - 1] = balances[i];
                balances[i] = tmp;
            }
        }
        return balances;
    }
}

// File: contracts/standards/ERC900.sol

pragma solidity ^0.5.8;


// Interface for ERC900: https://eips.ethereum.org/EIPS/eip-900
interface ERC900 {
    event Staked(address indexed user, uint256 amount, uint256 total, bytes data);
    event Unstaked(address indexed user, uint256 amount, uint256 total, bytes data);

    /**
    * @dev Stake a certain amount of tokens
    * @param _amount Amount of tokens to be staked
    * @param _data Optional data that can be used to add signalling information in more complex staking applications
    */
    function stake(uint256 _amount, bytes calldata _data) external;

    /**
    * @dev Stake a certain amount of tokens in favor of someone
    * @param _user Address to stake an amount of tokens to
    * @param _amount Amount of tokens to be staked
    * @param _data Optional data that can be used to add signalling information in more complex staking applications
    */
    function stakeFor(address _user, uint256 _amount, bytes calldata _data) external;

    /**
    * @dev Unstake a certain amount of tokens
    * @param _amount Amount of tokens to be unstaked
    * @param _data Optional data that can be used to add signalling information in more complex staking applications
    */
    function unstake(uint256 _amount, bytes calldata _data) external;

    /**
    * @dev Tell the total amount of tokens staked for an address
    * @param _addr Address querying the total amount of tokens staked for
    * @return Total amount of tokens staked for an address
    */
    function totalStakedFor(address _addr) external view returns (uint256);

    /**
    * @dev Tell the total amount of tokens staked
    * @return Total amount of tokens staked
    */
    function totalStaked() external view returns (uint256);

    /**
    * @dev Tell the address of the token used for staking
    * @return Address of the token used for staking
    */
    function token() external view returns (address);

    /*
    * @dev Tell if the current registry supports historic information or not
    * @return True if the optional history functions are implemented, false otherwise
    */
    function supportsHistory() external pure returns (bool);
}

// File: contracts/standards/ApproveAndCall.sol

pragma solidity ^0.5.8;


interface ApproveAndCallFallBack {
    /**
    * @dev This allows users to use their tokens to interact with contracts in one function call instead of two
    * @param _from Address of the account transferring the tokens
    * @param _amount The amount of tokens approved for in the transfer
    * @param _token Address of the token contract calling this function
    * @param _data Optional data that can be used to add signalling information in more complex staking applications
    */
    function receiveApproval(address _from, uint256 _amount, address _token, bytes calldata _data) external;
}

// 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/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/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
    */
    function getTerm(uint64 _termId) external view returns (uint64 startTime, uint64 randomnessBN, bytes32 randomness);

    /**
    * @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);
}

// 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
    }

    // 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) 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;
    }

    /**
    * @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
    */
    function getTerm(uint64 _termId) external view returns (uint64 startTime, uint64 randomnessBN, bytes32 randomness) {
        Term storage term = terms[_termId];
        return (term.startTime, term.randomnessBN, term.randomness);
    }

    /**
    * @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 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];
            _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;
        }

        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);
    }
}

// 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 roundStateDurations Array containing the durations in terms of the different phases of a dispute:
    *         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
    * @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 roundParams Array containing params for rounds:
    *         0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *         1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *         2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    * @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 minActiveBalance Minimum amount of tokens jurors have to activate to participate in the Court
    */
    function getConfig(uint64 _termId) external view
        returns (
            ERC20 feeToken,
            uint256[3] memory fees,
            uint64[5] memory roundStateDurations,
            uint16[2] memory pcts,
            uint64[4] memory roundParams,
            uint256[2] memory appealCollateralParams,
            uint256 minActiveBalance
        );

    /**
    * @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
        uint256 minActiveBalance;               // Minimum amount of tokens jurors have to activate to participate in the Court
    }

    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 {
        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 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_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";

    // 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 _roundStateDurations Array containing the durations in terms of the different phases of a dispute:
    *        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
    * @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 _roundParams Array containing params for rounds:
    *        0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *        1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *        2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *        3. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @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 _minActiveBalance Minimum amount of juror tokens that can be activated
    */
    constructor(
        ERC20 _feeToken,
        uint256[3] memory _fees,
        uint64[5] memory _roundStateDurations,
        uint16[2] memory _pcts,
        uint64[4] memory _roundParams,
        uint256[2] memory _appealCollateralParams,
        uint256 _minActiveBalance
    )
        public
    {
        // Leave config at index 0 empty for non-scheduled config changes
        configs.length = 1;
        _setConfig(
            0,
            0,
            _feeToken,
            _fees,
            _roundStateDurations,
            _pcts,
            _roundParams,
            _appealCollateralParams,
            _minActiveBalance
        );
    }

    /**
    * @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 roundStateDurations Array containing the durations in terms of the different phases of a dispute:
    *         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
    * @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 roundParams Array containing params for rounds:
    *         0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *         1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *         2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    * @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 minActiveBalance Minimum amount of tokens jurors have to activate to participate in the Court
    */
    function getConfig(uint64 _termId) external view
        returns (
            ERC20 feeToken,
            uint256[3] memory fees,
            uint64[5] memory roundStateDurations,
            uint16[2] memory pcts,
            uint64[4] memory roundParams,
            uint256[2] memory appealCollateralParams,
            uint256 minActiveBalance
        );

    /**
    * @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 _roundStateDurations Array containing the durations in terms of the different phases of a dispute:
    *        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
    * @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 _roundParams Array containing params for rounds:
    *        0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *        1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *        2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *        3. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @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 _minActiveBalance Minimum amount of juror tokens that can be activated
    */
    function _setConfig(
        uint64 _termId,
        uint64 _fromTermId,
        ERC20 _feeToken,
        uint256[3] memory _fees,
        uint64[5] memory _roundStateDurations,
        uint16[2] memory _pcts,
        uint64[4] memory _roundParams,
        uint256[2] memory _appealCollateralParams,
        uint256 _minActiveBalance
    )
        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);

        // 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[0] > 0, ERROR_BAD_INITIAL_JURORS_NUMBER);

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

        // Make sure the max number of appeals allowed does not reach the limit
        uint256 _maxRegularAppealRounds = _roundParams[2];
        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 < _roundStateDurations.length; i++) {
            require(_roundStateDurations[i] > 0 && _roundStateDurations[i] < MAX_ADJ_STATE_DURATION, ERROR_LARGE_ROUND_PHASE_DURATION);
        }

        // Make sure min active balance is not zero
        require(_minActiveBalance > 0, ERROR_ZERO_MIN_ACTIVE_BALANCE);

        // 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({
            evidenceTerms: _roundStateDurations[0],
            commitTerms: _roundStateDurations[1],
            revealTerms: _roundStateDurations[2],
            appealTerms: _roundStateDurations[3],
            appealConfirmTerms: _roundStateDurations[4],
            penaltyPct: _pcts[0],
            firstRoundJurorsNumber: _roundParams[0],
            appealStepFactor: _roundParams[1],
            maxRegularAppealRounds: _maxRegularAppealRounds,
            finalRoundLockTerms: _roundParams[3],
            appealCollateralFactor: _appealCollateralParams[0],
            appealConfirmCollateralFactor: _appealCollateralParams[1]
        });

        config.minActiveBalance = _minActiveBalance;

        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 roundStateDurations Array containing the durations in terms of the different phases of a dispute:
    *         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
    * @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 roundParams Array containing params for rounds:
    *         0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *         1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *         2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *         3. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @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 minActiveBalance Minimum amount of juror tokens that can be activated
    */
    function _getConfigAt(uint64 _termId, uint64 _lastEnsuredTermId) internal view
        returns (
            ERC20 feeToken,
            uint256[3] memory fees,
            uint64[5] memory roundStateDurations,
            uint16[2] memory pcts,
            uint64[4] memory roundParams,
            uint256[2] memory appealCollateralParams,
            uint256 minActiveBalance
        )
    {
        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;
        roundStateDurations = [
            disputesConfig.evidenceTerms,
            disputesConfig.commitTerms,
            disputesConfig.revealTerms,
            disputesConfig.appealTerms,
            disputesConfig.appealConfirmTerms
        ];
        pcts = [disputesConfig.penaltyPct, feesConfig.finalRoundReduction];
        roundParams = [
            disputesConfig.firstRoundJurorsNumber,
            disputesConfig.appealStepFactor,
            uint64(disputesConfig.maxRegularAppealRounds),
            disputesConfig.finalRoundLockTerms
        ];
        appealCollateralParams = [disputesConfig.appealCollateralFactor, disputesConfig.appealConfirmCollateralFactor];

        minActiveBalance = config.minActiveBalance;
    }

    /**
    * @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.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;

    /**
    * @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 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 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 modules governor
    */
    modifier onlyConfigGovernor {
        require(msg.sender == governor.config, 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. _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 _roundStateDurations Array containing the durations in terms of the different phases of a dispute:
    *        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
    * @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 _roundParams Array containing params for rounds:
    *        0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *        1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *        2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *        3. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @param _appealCollateralParams Array containing params for appeal collateral:
    *        1. appealCollateralFactor Permyriad multiple of dispute fees required to appeal a preliminary ruling
    *        2. appealConfirmCollateralFactor Permyriad multiple of dispute fees required to confirm appeal
    * @param _minActiveBalance Minimum amount of juror tokens that can be activated
    */
    constructor(
        uint64[2] memory _termParams,
        address[3] memory _governors,
        ERC20 _feeToken,
        uint256[3] memory _fees,
        uint64[5] memory _roundStateDurations,
        uint16[2] memory _pcts,
        uint64[4] memory _roundParams,
        uint256[2] memory _appealCollateralParams,
        uint256 _minActiveBalance
    )
        public
        CourtClock(_termParams)
        CourtConfig(_feeToken, _fees, _roundStateDurations, _pcts, _roundParams, _appealCollateralParams, _minActiveBalance)
    {
        _setFundsGovernor(_governors[0]);
        _setConfigGovernor(_governors[1]);
        _setModulesGovernor(_governors[2]);
    }

    /**
    * @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 _roundStateDurations Array containing the durations in terms of the different phases of a dispute:
    *        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
    * @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 _roundParams Array containing params for rounds:
    *        0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *        1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *        2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *        3. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @param _appealCollateralParams Array containing params for appeal collateral:
    *        1. appealCollateralFactor Permyriad multiple of dispute fees required to appeal a preliminary ruling
    *        2. appealConfirmCollateralFactor Permyriad multiple of dispute fees required to confirm appeal
    * @param _minActiveBalance Minimum amount of juror tokens that can be activated
    */
    function setConfig(
        uint64 _fromTermId,
        ERC20 _feeToken,
        uint256[3] calldata _fees,
        uint64[5] calldata _roundStateDurations,
        uint16[2] calldata _pcts,
        uint64[4] calldata _roundParams,
        uint256[2] calldata _appealCollateralParams,
        uint256 _minActiveBalance
    )
        external
        onlyConfigGovernor
    {
        uint64 currentTermId = _ensureCurrentTerm();
        _setConfig(
            currentTermId,
            _fromTermId,
            _feeToken,
            _fees,
            _roundStateDurations,
            _pcts,
            _roundParams,
            _appealCollateralParams,
            _minActiveBalance
        );
    }

    /**
    * @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 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 roundStateDurations Array containing the durations in terms of the different phases of a dispute:
    *         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
    * @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 roundParams Array containing params for rounds:
    *         0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes
    *         1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute
    *         2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered
    *         3. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks)
    * @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
    */
    function getConfig(uint64 _termId) external view
        returns (
            ERC20 feeToken,
            uint256[3] memory fees,
            uint64[5] memory roundStateDurations,
            uint16[2] memory pcts,
            uint64[4] memory roundParams,
            uint256[2] memory appealCollateralParams,
            uint256 minActiveBalance
        )
    {
        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 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 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 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 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,
        uint64[5] memory _roundStateDurations,
        uint16[2] memory _pcts,
        uint64[4] memory _roundParams,
        uint256[2] memory _appealCollateralParams,
        uint256 _minActiveBalance) = _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({
            evidenceTerms: _roundStateDurations[0],
            commitTerms: _roundStateDurations[1],
            revealTerms: _roundStateDurations[2],
            appealTerms: _roundStateDurations[3],
            appealConfirmTerms: _roundStateDurations[4],
            penaltyPct: _pcts[0],
            firstRoundJurorsNumber: _roundParams[0],
            appealStepFactor: _roundParams[1],
            maxRegularAppealRounds: _roundParams[2],
            finalRoundLockTerms: _roundParams[3],
            appealCollateralFactor: _appealCollateralParams[0],
            appealConfirmCollateralFactor: _appealCollateralParams[1]
        });

        config.minActiveBalance = _minActiveBalance;

        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/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/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 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;

    /**
    * @dev Execute the Arbitrable associated to a dispute based on its final ruling
    * @param _disputeId Identification number of the dispute to be executed
    */
    function executeRuling(uint256 _disputeId) external;

    /**
    * @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);

    /**
    * @dev Tell the subscription fees information for a subscriber to be up-to-date
    * @param _subscriber Address of the account paying the subscription fees for
    * @return recipient Address where the corresponding subscriptions fees must be transferred to
    * @return feeToken ERC20 token used for the subscription fees
    * @return feeAmount Total amount of fees that must be allowed to the recipient
    */
    function getSubscriptionFees(address _subscriber) external view returns (address recipient, ERC20 feeToken, uint256 feeAmount);
}

// File: contracts/standards/ERC165.sol

pragma solidity ^0.5.8;


interface ERC165 {
    /**
    * @dev Query if a contract implements a certain interface
    * @param _interfaceId The interface identifier being queried, as specified in ERC-165
    * @return True if the contract implements the requested interface and if its not 0xffffffff, false otherwise
    */
    function supportsInterface(bytes4 _interfaceId) external pure returns (bool);
}

// File: contracts/arbitration/IArbitrable.sol

pragma solidity ^0.5.8;




contract IArbitrable is ERC165 {
    bytes4 internal constant ERC165_INTERFACE_ID = bytes4(0x01ffc9a7);
    bytes4 internal constant ARBITRABLE_INTERFACE_ID = bytes4(0x88f3ee69);

    /**
    * @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);

    /**
    * @dev Emitted when new evidence is submitted for the IArbitrable instance's 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
    * @param finished Whether or not the submitter has finished submitting evidence
    */
    event EvidenceSubmitted(uint256 indexed disputeId, address indexed submitter, bytes evidence, bool finished);

    /**
    * @dev Submit evidence for a dispute
    * @param _disputeId Id of the dispute in the Court
    * @param _evidence Data submitted for the evidence related to the dispute
    * @param _finished Whether or not the submitter has finished submitting evidence
    */
    function submitEvidence(uint256 _disputeId, bytes calldata _evidence, bool _finished) external;

    /**
    * @dev Give a ruling for a certain dispute, the account calling it must have rights to rule on the contract
    * @param _disputeId Identification number of the dispute to be ruled
    * @param _ruling Ruling given by the arbitrator, where 0 is reserved for "refused to make a decision"
    */
    function rule(uint256 _disputeId, uint256 _ruling) external;

    /**
    * @dev ERC165 - Query if a contract implements a certain interface
    * @param _interfaceId The interface identifier being queried, as specified in ERC-165
    * @return True if this contract supports the given interface, false otherwise
    */
    function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {
        return _interfaceId == ARBITRABLE_INTERFACE_ID || _interfaceId == ERC165_INTERFACE_ID;
    }
}

// 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 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/subscriptions/ISubscriptions.sol

pragma solidity ^0.5.8;



interface ISubscriptions {
    /**
    * @dev Tell whether a certain subscriber has paid all the fees up to current period or not
    * @param _subscriber Address of subscriber being checked
    * @return True if subscriber has paid all the fees up to current period, false otherwise
    */
    function isUpToDate(address _subscriber) external view returns (bool);

    /**
    * @dev Tell the minimum amount of fees to pay and resulting last paid period for a given subscriber in order to be up-to-date
    * @param _subscriber Address of the subscriber willing to pay
    * @return feeToken ERC20 token used for the subscription fees
    * @return amountToPay Amount of subscription fee tokens to be paid
    * @return newLastPeriodId Identification number of the resulting last paid period
    */
    function getOwedFeesDetails(address _subscriber) external view returns (ERC20, uint256, uint256);
}

// 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 Subscriptions module implementation from the controller
    * @return Address of the Subscriptions module implementation
    */
    function _subscriptions() internal view returns (ISubscriptions) {
        return ISubscriptions(controller.getSubscriptions());
    }

    /**
    * @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/registry/JurorsRegistry.sol

pragma solidity ^0.5.8;














contract JurorsRegistry is ControlledRecoverable, IJurorsRegistry, ERC900, ApproveAndCallFallBack {
    using SafeERC20 for ERC20;
    using SafeMath for uint256;
    using PctHelpers for uint256;
    using BytesHelpers for bytes;
    using HexSumTree for HexSumTree.Tree;
    using JurorsTreeSortition for HexSumTree.Tree;

    string private constant ERROR_NOT_CONTRACT = "JR_NOT_CONTRACT";
    string private constant ERROR_INVALID_ZERO_AMOUNT = "JR_INVALID_ZERO_AMOUNT";
    string private constant ERROR_INVALID_ACTIVATION_AMOUNT = "JR_INVALID_ACTIVATION_AMOUNT";
    string private constant ERROR_INVALID_DEACTIVATION_AMOUNT = "JR_INVALID_DEACTIVATION_AMOUNT";
    string private constant ERROR_INVALID_LOCKED_AMOUNTS_LENGTH = "JR_INVALID_LOCKED_AMOUNTS_LEN";
    string private constant ERROR_INVALID_REWARDED_JURORS_LENGTH = "JR_INVALID_REWARDED_JURORS_LEN";
    string private constant ERROR_ACTIVE_BALANCE_BELOW_MIN = "JR_ACTIVE_BALANCE_BELOW_MIN";
    string private constant ERROR_NOT_ENOUGH_AVAILABLE_BALANCE = "JR_NOT_ENOUGH_AVAILABLE_BALANCE";
    string private constant ERROR_CANNOT_REDUCE_DEACTIVATION_REQUEST = "JR_CANT_REDUCE_DEACTIVATION_REQ";
    string private constant ERROR_TOKEN_TRANSFER_FAILED = "JR_TOKEN_TRANSFER_FAILED";
    string private constant ERROR_TOKEN_APPROVE_NOT_ALLOWED = "JR_TOKEN_APPROVE_NOT_ALLOWED";
    string private constant ERROR_BAD_TOTAL_ACTIVE_BALANCE_LIMIT = "JR_BAD_TOTAL_ACTIVE_BAL_LIMIT";
    string private constant ERROR_TOTAL_ACTIVE_BALANCE_EXCEEDED = "JR_TOTAL_ACTIVE_BALANCE_EXCEEDED";
    string private constant ERROR_WITHDRAWALS_LOCK = "JR_WITHDRAWALS_LOCK";

    // Address that will be used to burn juror tokens
    address internal constant BURN_ACCOUNT = address(0x000000000000000000000000000000000000dEaD);

    // Maximum number of sortition iterations allowed per draft call
    uint256 internal constant MAX_DRAFT_ITERATIONS = 10;

    /**
    * @dev Jurors have three kind of balances, these are:
    *      - active: tokens activated for the Court that can be locked in case the juror is drafted
    *      - locked: amount of active tokens that are locked for a draft
    *      - available: tokens that are not activated for the Court and can be withdrawn by the juror at any time
    *
    *      Due to a gas optimization for drafting, the "active" tokens are stored in a `HexSumTree`, while the others
    *      are stored in this contract as `lockedBalance` and `availableBalance` respectively. Given that the jurors'
    *      active balances cannot be affected during the current Court term, if jurors want to deactivate some of their
    *      active tokens, their balance will be updated for the following term, and they won't be allowed to
    *      withdraw them until the current term has ended.
    *
    *      Note that even though jurors balances are stored separately, all the balances are held by this contract.
    */
    struct Juror {
        uint256 id;                                 // Key in the jurors tree used for drafting
        uint256 lockedBalance;                      // Maximum amount of tokens that can be slashed based on the juror's drafts
        uint256 availableBalance;                   // Available tokens that can be withdrawn at any time
        uint64 withdrawalsLockTermId;               // Term ID until which the juror's withdrawals will be locked
        DeactivationRequest deactivationRequest;    // Juror's pending deactivation request
    }

    /**
    * @dev Given that the jurors balances cannot be affected during a Court term, if jurors want to deactivate some
    *      of their tokens, the tree will always be updated for the following term, and they won't be able to
    *      withdraw the requested amount until the current term has finished. Thus, we need to keep track the term
    *      when a token deactivation was requested and its corresponding amount.
    */
    struct DeactivationRequest {
        uint256 amount;                             // Amount requested for deactivation
        uint64 availableTermId;                     // Term ID when jurors can withdraw their requested deactivation tokens
    }

    /**
    * @dev Internal struct to wrap all the params required to perform jurors drafting
    */
    struct DraftParams {
        bytes32 termRandomness;                     // Randomness seed to be used for the draft
        uint256 disputeId;                          // ID of the dispute being drafted
        uint64 termId;                              // Term ID of the dispute's draft term
        uint256 selectedJurors;                     // Number of jurors already selected for the draft
        uint256 batchRequestedJurors;               // Number of jurors to be selected in the given batch of the draft
        uint256 roundRequestedJurors;               // Total number of jurors requested to be drafted
        uint256 draftLockAmount;                    // Amount of tokens to be locked to each drafted juror
        uint256 iteration;                          // Sortition iteration number
    }

    // Maximum amount of total active balance that can be held in the registry
    uint256 internal totalActiveBalanceLimit;

    // Juror ERC20 token
    ERC20 internal jurorsToken;

    // Mapping of juror data indexed by address
    mapping (address => Juror) internal jurorsByAddress;

    // Mapping of juror addresses indexed by id
    mapping (uint256 => address) internal jurorsAddressById;

    // Tree to store jurors active balance by term for the drafting process
    HexSumTree.Tree internal tree;

    event JurorActivated(address indexed juror, uint64 fromTermId, uint256 amount, address sender);
    event JurorDeactivationRequested(address indexed juror, uint64 availableTermId, uint256 amount);
    event JurorDeactivationProcessed(address indexed juror, uint64 availableTermId, uint256 amount, uint64 processedTermId);
    event JurorDeactivationUpdated(address indexed juror, uint64 availableTermId, uint256 amount, uint64 updateTermId);
    event JurorBalanceLocked(address indexed juror, uint256 amount);
    event JurorBalanceUnlocked(address indexed juror, uint256 amount);
    event JurorSlashed(address indexed juror, uint256 amount, uint64 effectiveTermId);
    event JurorTokensAssigned(address indexed juror, uint256 amount);
    event JurorTokensBurned(uint256 amount);
    event JurorTokensCollected(address indexed juror, uint256 amount, uint64 effectiveTermId);
    event TotalActiveBalanceLimitChanged(uint256 previousTotalActiveBalanceLimit, uint256 currentTotalActiveBalanceLimit);

    /**
    * @dev Constructor function
    * @param _controller Address of the controller
    * @param _jurorToken Address of the ERC20 token to be used as juror token for the registry
    * @param _totalActiveBalanceLimit Maximum amount of total active balance that can be held in the registry
    */
    constructor(Controller _controller, ERC20 _jurorToken, uint256 _totalActiveBalanceLimit)
        ControlledRecoverable(_controller)
        public
    {
        // No need to explicitly call `Controlled` constructor since `ControlledRecoverable` is already doing it
        require(isContract(address(_jurorToken)), ERROR_NOT_CONTRACT);

        jurorsToken = _jurorToken;
        _setTotalActiveBalanceLimit(_totalActiveBalanceLimit);

        tree.init();
        // First tree item is an empty juror
        assert(tree.insert(0, 0) == 0);
    }

    /**
    * @notice Activate `_amount == 0 ? 'all available tokens' : @tokenAmount(self.token(), _amount)` for the next term
    * @param _amount Amount of juror tokens to be activated for the next term
    */
    function activate(uint256 _amount) external {
        _activateTokens(msg.sender, _amount, msg.sender);
    }

    /**
    * @notice Deactivate `_amount == 0 ? 'all unlocked tokens' : @tokenAmount(self.token(), _amount)` for the next term
    * @param _amount Amount of juror tokens to be deactivated for the next term
    */
    function deactivate(uint256 _amount) external {
        uint64 termId = _ensureCurrentTerm();
        Juror storage juror = jurorsByAddress[msg.sender];
        uint256 unlockedActiveBalance = _lastUnlockedActiveBalanceOf(juror);
        uint256 amountToDeactivate = _amount == 0 ? unlockedActiveBalance : _amount;
        require(amountToDeactivate > 0, ERROR_INVALID_ZERO_AMOUNT);
        require(amountToDeactivate <= unlockedActiveBalance, ERROR_INVALID_DEACTIVATION_AMOUNT);

        // No need for SafeMath: we already checked values above
        uint256 futureActiveBalance = unlockedActiveBalance - amountToDeactivate;
        uint256 minActiveBalance = _getMinActiveBalance(termId);
        require(futureActiveBalance == 0 || futureActiveBalance >= minActiveBalance, ERROR_INVALID_DEACTIVATION_AMOUNT);

        _createDeactivationRequest(msg.sender, amountToDeactivate);
    }

    /**
    * @notice Stake `@tokenAmount(self.token(), _amount)` for the sender to the Court
    * @param _amount Amount of tokens to be staked
    * @param _data Optional data that can be used to request the activation of the transferred tokens
    */
    function stake(uint256 _amount, bytes calldata _data) external {
        _stake(msg.sender, msg.sender, _amount, _data);
    }

    /**
    * @notice Stake `@tokenAmount(self.token(), _amount)` for `_to` to the Court
    * @param _to Address to stake an amount of tokens to
    * @param _amount Amount of tokens to be staked
    * @param _data Optional data that can be used to request the activation of the transferred tokens
    */
    function stakeFor(address _to, uint256 _amount, bytes calldata _data) external {
        _stake(msg.sender, _to, _amount, _data);
    }

    /**
    * @notice Unstake `@tokenAmount(self.token(), _amount)` for `_to` from the Court
    * @param _amount Amount of tokens to be unstaked
    * @param _data Optional data is never used by this function, only logged
    */
    function unstake(uint256 _amount, bytes calldata _data) external {
        _unstake(msg.sender, _amount, _data);
    }

    /**
    * @dev Callback of approveAndCall, allows staking directly with a transaction to the token contract.
    * @param _from Address making the transfer
    * @param _amount Amount of tokens to transfer
    * @param _token Address of the token
    * @param _data Optional data that can be used to request the activation of the transferred tokens
    */
    function receiveApproval(address _from, uint256 _amount, address _token, bytes calldata _data) external {
        require(msg.sender == _token && _token == address(jurorsToken), ERROR_TOKEN_APPROVE_NOT_ALLOWED);
        _stake(_from, _from, _amount, _data);
    }

    /**
    * @notice Process a token deactivation requested for `_juror` if there is any
    * @param _juror Address of the juror to process the deactivation request of
    */
    function processDeactivationRequest(address _juror) external {
        uint64 termId = _ensureCurrentTerm();
        _processDeactivationRequest(_juror, termId);
    }

    /**
    * @notice Assign `@tokenAmount(self.token(), _amount)` to the available balance of `_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 onlyDisputeManager {
        if (_amount > 0) {
            _updateAvailableBalanceOf(_juror, _amount, true);
            emit JurorTokensAssigned(_juror, _amount);
        }
    }

    /**
    * @notice Burn `@tokenAmount(self.token(), _amount)`
    * @param _amount Amount of tokens to be burned
    */
    function burnTokens(uint256 _amount) external onlyDisputeManager {
        if (_amount > 0) {
            _updateAvailableBalanceOf(BURN_ACCOUNT, _amount, true);
            emit JurorTokensBurned(_amount);
        }
    }

    /**
    * @notice 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 onlyDisputeManager returns (address[] memory jurors, uint256 length) {
        DraftParams memory draftParams = _buildDraftParams(_params);
        jurors = new address[](draftParams.batchRequestedJurors);

        // Jurors returned by the tree multi-sortition may not have enough unlocked active balance to be drafted. Thus,
        // we compute several sortitions until all the requested jurors are selected. To guarantee a different set of
        // jurors on each sortition, the iteration number will be part of the random seed to be used in the sortition.
        // Note that we are capping the number of iterations to avoid an OOG error, which means that this function could
        // return less jurors than the requested number.

        for (draftParams.iteration = 0;
             length < draftParams.batchRequestedJurors && draftParams.iteration < MAX_DRAFT_ITERATIONS;
             draftParams.iteration++
        ) {
            (uint256[] memory jurorIds, uint256[] memory activeBalances) = _treeSearch(draftParams);

            for (uint256 i = 0; i < jurorIds.length && length < draftParams.batchRequestedJurors; i++) {
                // We assume the selected jurors are registered in the registry, we are not checking their addresses exist
                address jurorAddress = jurorsAddressById[jurorIds[i]];
                Juror storage juror = jurorsByAddress[jurorAddress];

                // Compute new locked balance for a juror based on the penalty applied when being drafted
                uint256 newLockedBalance = juror.lockedBalance.add(draftParams.draftLockAmount);

                // Check if there is any deactivation requests for the next term. Drafts are always computed for the current term
                // but we have to make sure we are locking an amount that will exist in the next term.
                uint256 nextTermDeactivationRequestAmount = _deactivationRequestedAmountForTerm(juror, draftParams.termId + 1);

                // Check if juror has enough active tokens to lock the requested amount for the draft, skip it otherwise.
                uint256 currentActiveBalance = activeBalances[i];
                if (currentActiveBalance >= newLockedBalance) {

                    // Check if the amount of active tokens for the next term is enough to lock the required amount for
                    // the draft. Otherwise, reduce the requested deactivation amount of the next term.
                    // Next term deactivation amount should always be less than current active balance, but we make sure using SafeMath
                    uint256 nextTermActiveBalance = currentActiveBalance.sub(nextTermDeactivationRequestAmount);
                    if (nextTermActiveBalance < newLockedBalance) {
                        // No need for SafeMath: we already checked values above
                        _reduceDeactivationRequest(jurorAddress, newLockedBalance - nextTermActiveBalance, draftParams.termId);
                    }

                    // Update the current active locked balance of the juror
                    juror.lockedBalance = newLockedBalance;
                    jurors[length++] = jurorAddress;
                    emit JurorBalanceLocked(jurorAddress, draftParams.draftLockAmount);
                }
            }
        }
    }

    /**
    * @notice Slash a set of jurors based on their votes compared to the winning ruling. This function will unlock the
    *         corresponding locked balances of those jurors that are set to be slashed.
    * @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
        onlyDisputeManager
        returns (uint256)
    {
        require(_jurors.length == _lockedAmounts.length, ERROR_INVALID_LOCKED_AMOUNTS_LENGTH);
        require(_jurors.length == _rewardedJurors.length, ERROR_INVALID_REWARDED_JURORS_LENGTH);

        uint64 nextTermId = _termId + 1;
        uint256 collectedTokens;

        for (uint256 i = 0; i < _jurors.length; i++) {
            uint256 lockedAmount = _lockedAmounts[i];
            address jurorAddress = _jurors[i];
            Juror storage juror = jurorsByAddress[jurorAddress];
            juror.lockedBalance = juror.lockedBalance.sub(lockedAmount);

            // Slash juror if requested. Note that there's no need to check if there was a deactivation
            // request since we're working with already locked balances.
            if (_rewardedJurors[i]) {
                emit JurorBalanceUnlocked(jurorAddress, lockedAmount);
            } else {
                collectedTokens = collectedTokens.add(lockedAmount);
                tree.update(juror.id, nextTermId, lockedAmount, false);
                emit JurorSlashed(jurorAddress, lockedAmount, nextTermId);
            }
        }

        return collectedTokens;
    }

    /**
    * @notice Try to collect `@tokenAmount(self.token(), _amount)` from `_juror` for the term #`_termId + 1`.
    * @dev This function tries to decrease the active balance of a juror for the next term based on the requested
    *      amount. It can be seen as a way to early-slash a juror's active balance.
    * @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 onlyDisputeManager returns (bool) {
        if (_amount == 0) {
            return true;
        }

        uint64 nextTermId = _termId + 1;
        Juror storage juror = jurorsByAddress[_juror];
        uint256 unlockedActiveBalance = _lastUnlockedActiveBalanceOf(juror);
        uint256 nextTermDeactivationRequestAmount = _deactivationRequestedAmountForTerm(juror, nextTermId);

        // Check if the juror has enough unlocked tokens to collect the requested amount
        // Note that we're also considering the deactivation request if there is any
        uint256 totalUnlockedActiveBalance = unlockedActiveBalance.add(nextTermDeactivationRequestAmount);
        if (_amount > totalUnlockedActiveBalance) {
            return false;
        }

        // Check if the amount of active tokens is enough to collect the requested amount, otherwise reduce the requested deactivation amount of
        // the next term. Note that this behaviour is different to the one when drafting jurors since this function is called as a side effect
        // of a juror deliberately voting in a final round, while drafts occur randomly.
        if (_amount > unlockedActiveBalance) {
            // No need for SafeMath: amounts were already checked above
            uint256 amountToReduce = _amount - unlockedActiveBalance;
            _reduceDeactivationRequest(_juror, amountToReduce, _termId);
        }
        tree.update(juror.id, nextTermId, _amount, false);

        emit JurorTokensCollected(_juror, _amount, nextTermId);
        return true;
    }

    /**
    * @notice Lock `_juror`'s withdrawals until term #`_termId`
    * @dev This is intended for jurors who voted in a final round and were coherent with the final ruling to prevent 51% attacks
    * @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 onlyDisputeManager {
        Juror storage juror = jurorsByAddress[_juror];
        juror.withdrawalsLockTermId = _termId;
    }

    /**
    * @notice Set new limit of total active balance of juror tokens
    * @param _totalActiveBalanceLimit New limit of total active balance of juror tokens
    */
    function setTotalActiveBalanceLimit(uint256 _totalActiveBalanceLimit) external onlyConfigGovernor {
        _setTotalActiveBalanceLimit(_totalActiveBalanceLimit);
    }

    /**
    * @dev ERC900 - Tell the address of the token used for staking
    * @return Address of the token used for staking
    */
    function token() external view returns (address) {
        return address(jurorsToken);
    }

    /**
    * @dev ERC900 - Tell the total amount of juror tokens held by the registry contract
    * @return Amount of juror tokens held by the registry contract
    */
    function totalStaked() external view returns (uint256) {
        return jurorsToken.balanceOf(address(this));
    }

    /**
    * @dev Tell the total amount of active juror tokens
    * @return Total amount of active juror tokens
    */
    function totalActiveBalance() external view returns (uint256) {
        return tree.getTotal();
    }

    /**
    * @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) {
        return _totalActiveBalanceAt(_termId);
    }

    /**
    * @dev ERC900 - Tell the total amount of tokens of juror. This includes the active balance, the available
    *      balances, and the pending balance for deactivation. Note that we don't have to include the locked
    *      balances since these represent the amount of active tokens that are locked for drafts, i.e. these
    *      are included in the active balance of the juror.
    * @param _juror Address of the juror querying the total amount of tokens staked of
    * @return Total amount of tokens of a juror
    */
    function totalStakedFor(address _juror) external view returns (uint256) {
        return _totalStakedFor(_juror);
    }

    /**
    * @dev Tell the balance information of a juror
    * @param _juror Address of the juror querying the balance information of
    * @return active Amount of active tokens of a juror
    * @return available Amount of available tokens of a juror
    * @return locked Amount of active tokens that are locked due to ongoing disputes
    * @return pendingDeactivation Amount of active tokens that were requested for deactivation
    */
    function balanceOf(address _juror) external view returns (uint256 active, uint256 available, uint256 locked, uint256 pendingDeactivation) {
        return _balanceOf(_juror);
    }

    /**
    * @dev Tell the balance information of a juror, fecthing tree one at a given term
    * @param _juror Address of the juror querying the balance information of
    * @param _termId Term ID querying the active balance for
    * @return active Amount of active tokens of a juror
    * @return available Amount of available tokens of a juror
    * @return locked Amount of active tokens that are locked due to ongoing disputes
    * @return pendingDeactivation Amount of active tokens that were requested for deactivation
    */
    function balanceOfAt(address _juror, uint64 _termId) external view
        returns (uint256 active, uint256 available, uint256 locked, uint256 pendingDeactivation)
    {
        Juror storage juror = jurorsByAddress[_juror];

        active = _existsJuror(juror) ? tree.getItemAt(juror.id, _termId) : 0;
        (available, locked, pendingDeactivation) = _getBalances(juror);
    }

    /**
    * @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) {
        return _activeBalanceOfAt(_juror, _termId);
    }

    /**
    * @dev Tell the amount of active tokens of a juror at the last ensured term that are not locked due to ongoing disputes
    * @param _juror Address of the juror querying the unlocked balance of
    * @return Amount of active tokens of a juror that are not locked due to ongoing disputes
    */
    function unlockedActiveBalanceOf(address _juror) external view returns (uint256) {
        Juror storage juror = jurorsByAddress[_juror];
        return _currentUnlockedActiveBalanceOf(juror);
    }

    /**
    * @dev Tell the pending deactivation details for a juror
    * @param _juror Address of the juror whose info is requested
    * @return amount Amount to be deactivated
    * @return availableTermId Term in which the deactivated amount will be available
    */
    function getDeactivationRequest(address _juror) external view returns (uint256 amount, uint64 availableTermId) {
        DeactivationRequest storage request = jurorsByAddress[_juror].deactivationRequest;
        return (request.amount, request.availableTermId);
    }

    /**
    * @dev Tell the withdrawals lock term ID for a juror
    * @param _juror Address of the juror whose info is requested
    * @return Term ID until which the juror's withdrawals will be locked
    */
    function getWithdrawalsLockTermId(address _juror) external view returns (uint64) {
        return jurorsByAddress[_juror].withdrawalsLockTermId;
    }

    /**
    * @dev Tell the identification number associated to a juror address
    * @param _juror Address of the juror querying the identification number of
    * @return Identification number associated to a juror address, zero in case it wasn't registered yet
    */
    function getJurorId(address _juror) external view returns (uint256) {
        return jurorsByAddress[_juror].id;
    }

    /**
    * @dev Tell the maximum amount of total active balance that can be held in the registry
    * @return Maximum amount of total active balance that can be held in the registry
    */
    function totalJurorsActiveBalanceLimit() external view returns (uint256) {
        return totalActiveBalanceLimit;
    }

    /**
    * @dev ERC900 - Tell if the current registry supports historic information or not
    * @return Always false
    */
    function supportsHistory() external pure returns (bool) {
        return false;
    }

    /**
    * @dev Internal function to activate a given amount of tokens for a juror.
    *      This function assumes that the given term is the current term and has already been ensured.
    * @param _juror Address of the juror to activate tokens
    * @param _amount Amount of juror tokens to be activated
    * @param _sender Address of the account requesting the activation
    */
    function _activateTokens(address _juror, uint256 _amount, address _sender) internal {
        uint64 termId = _ensureCurrentTerm();

        // Try to clean a previous deactivation request if any
        _processDeactivationRequest(_juror, termId);

        uint256 availableBalance = jurorsByAddress[_juror].availableBalance;
        uint256 amountToActivate = _amount == 0 ? availableBalance : _amount;
        require(amountToActivate > 0, ERROR_INVALID_ZERO_AMOUNT);
        require(amountToActivate <= availableBalance, ERROR_INVALID_ACTIVATION_AMOUNT);

        uint64 nextTermId = termId + 1;
        _checkTotalActiveBalance(nextTermId, amountToActivate);
        Juror storage juror = jurorsByAddress[_juror];
        uint256 minActiveBalance = _getMinActiveBalance(nextTermId);

        if (_existsJuror(juror)) {
            // Even though we are adding amounts, let's check the new active balance is greater than or equal to the
            // minimum active amount. Note that the juror might have been slashed.
            uint256 activeBalance = tree.getItem(juror.id);
            require(activeBalance.add(amountToActivate) >= minActiveBalance, ERROR_ACTIVE_BALANCE_BELOW_MIN);
            tree.update(juror.id, nextTermId, amountToActivate, true);
        } else {
            require(amountToActivate >= minActiveBalance, ERROR_ACTIVE_BALANCE_BELOW_MIN);
            juror.id = tree.insert(nextTermId, amountToActivate);
            jurorsAddressById[juror.id] = _juror;
        }

        _updateAvailableBalanceOf(_juror, amountToActivate, false);
        emit JurorActivated(_juror, nextTermId, amountToActivate, _sender);
    }

    /**
    * @dev Internal function to create a token deactivation request for a juror. Jurors will be allowed
    *      to process a deactivation request from the next term.
    * @param _juror Address of the juror to create a token deactivation request for
    * @param _amount Amount of juror tokens requested for deactivation
    */
    function _createDeactivationRequest(address _juror, uint256 _amount) internal {
        uint64 termId = _ensureCurrentTerm();

        // Try to clean a previous deactivation request if possible
        _processDeactivationRequest(_juror, termId);

        uint64 nextTermId = termId + 1;
        Juror storage juror = jurorsByAddress[_juror];
        DeactivationRequest storage request = juror.deactivationRequest;
        request.amount = request.amount.add(_amount);
        request.availableTermId = nextTermId;
        tree.update(juror.id, nextTermId, _amount, false);

        emit JurorDeactivationRequested(_juror, nextTermId, _amount);
    }

    /**
    * @dev Internal function to process a token deactivation requested by a juror. It will move the requested amount
    *      to the available balance of the juror if the term when the deactivation was requested has already finished.
    * @param _juror Address of the juror to process the deactivation request of
    * @param _termId Current term id
    */
    function _processDeactivationRequest(address _juror, uint64 _termId) internal {
        Juror storage juror = jurorsByAddress[_juror];
        DeactivationRequest storage request = juror.deactivationRequest;
        uint64 deactivationAvailableTermId = request.availableTermId;

        // If there is a deactivation request, ensure that the deactivation term has been reached
        if (deactivationAvailableTermId == uint64(0) || _termId < deactivationAvailableTermId) {
            return;
        }

        uint256 deactivationAmount = request.amount;
        // Note that we can use a zeroed term ID to denote void here since we are storing
        // the minimum allowed term to deactivate tokens which will always be at least 1.
        request.availableTermId = uint64(0);
        request.amount = 0;
        _updateAvailableBalanceOf(_juror, deactivationAmount, true);

        emit JurorDeactivationProcessed(_juror, deactivationAvailableTermId, deactivationAmount, _termId);
    }

    /**
    * @dev Internal function to reduce a token deactivation requested by a juror. It assumes the deactivation request
    *      cannot be processed for the given term yet.
    * @param _juror Address of the juror to reduce the deactivation request of
    * @param _amount Amount to be reduced from the current deactivation request
    * @param _termId Term ID in which the deactivation request is being reduced
    */
    function _reduceDeactivationRequest(address _juror, uint256 _amount, uint64 _termId) internal {
        Juror storage juror = jurorsByAddress[_juror];
        DeactivationRequest storage request = juror.deactivationRequest;
        uint256 currentRequestAmount = request.amount;
        require(currentRequestAmount >= _amount, ERROR_CANNOT_REDUCE_DEACTIVATION_REQUEST);

        // No need for SafeMath: we already checked values above
        uint256 newRequestAmount = currentRequestAmount - _amount;
        request.amount = newRequestAmount;

        // Move amount back to the tree
        tree.update(juror.id, _termId + 1, _amount, true);

        emit JurorDeactivationUpdated(_juror, request.availableTermId, newRequestAmount, _termId);
    }

    /**
    * @dev Internal function to stake an amount of tokens for a juror
    * @param _from Address sending the amount of tokens to be deposited
    * @param _juror Address of the juror to deposit the tokens to
    * @param _amount Amount of tokens to be deposited
    * @param _data Optional data that can be used to request the activation of the deposited tokens
    */
    function _stake(address _from, address _juror, uint256 _amount, bytes memory _data) internal {
        require(_amount > 0, ERROR_INVALID_ZERO_AMOUNT);
        _updateAvailableBalanceOf(_juror, _amount, true);

        // Activate tokens if it was requested by the sender. Note that there's no need to check
        // the activation amount since we have just added it to the available balance of the juror.
        if (_data.toBytes4() == JurorsRegistry(this).activate.selector) {
            _activateTokens(_juror, _amount, _from);
        }

        emit Staked(_juror, _amount, _totalStakedFor(_juror), _data);
        require(jurorsToken.safeTransferFrom(_from, address(this), _amount), ERROR_TOKEN_TRANSFER_FAILED);
    }

    /**
    * @dev Internal function to unstake an amount of tokens of a juror
    * @param _juror Address of the juror to to unstake the tokens of
    * @param _amount Amount of tokens to be unstaked
    * @param _data Optional data is never used by this function, only logged
    */
    function _unstake(address _juror, uint256 _amount, bytes memory _data) internal {
        require(_amount > 0, ERROR_INVALID_ZERO_AMOUNT);

        // Try to process a deactivation request for the current term if there is one. Note that we don't need to ensure
        // the current term this time since deactivation requests always work with future terms, which means that if
        // the current term is outdated, it will never match the deactivation term id. We avoid ensuring the term here
        // to avoid forcing jurors to do that in order to withdraw their available balance. Same applies to final round locks.
        uint64 lastEnsuredTermId = _getLastEnsuredTermId();

        // Check that juror's withdrawals are not locked
        uint64 withdrawalsLockTermId = jurorsByAddress[_juror].withdrawalsLockTermId;
        require(withdrawalsLockTermId == 0 || withdrawalsLockTermId < lastEnsuredTermId, ERROR_WITHDRAWALS_LOCK);

        _processDeactivationRequest(_juror, lastEnsuredTermId);

        _updateAvailableBalanceOf(_juror, _amount, false);
        emit Unstaked(_juror, _amount, _totalStakedFor(_juror), _data);
        require(jurorsToken.safeTransfer(_juror, _amount), ERROR_TOKEN_TRANSFER_FAILED);
    }

    /**
    * @dev Internal function to update the available balance of a juror
    * @param _juror Juror to update the available balance of
    * @param _amount Amount of tokens to be added to or removed from the available balance of a juror
    * @param _positive True if the given amount should be added, or false to remove it from the available balance
    */
    function _updateAvailableBalanceOf(address _juror, uint256 _amount, bool _positive) internal {
        // We are not using a require here to avoid reverting in case any of the treasury maths reaches this point
        // with a zeroed amount value. Instead, we are doing this validation in the external entry points such as
        // stake, unstake, activate, deactivate, among others.
        if (_amount == 0) {
            return;
        }

        Juror storage juror = jurorsByAddress[_juror];
        if (_positive) {
            juror.availableBalance = juror.availableBalance.add(_amount);
        } else {
            require(_amount <= juror.availableBalance, ERROR_NOT_ENOUGH_AVAILABLE_BALANCE);
            // No need for SafeMath: we already checked values right above
            juror.availableBalance -= _amount;
        }
    }

    /**
    * @dev Internal function to set new limit of total active balance of juror tokens
    * @param _totalActiveBalanceLimit New limit of total active balance of juror tokens
    */
    function _setTotalActiveBalanceLimit(uint256 _totalActiveBalanceLimit) internal {
        require(_totalActiveBalanceLimit > 0, ERROR_BAD_TOTAL_ACTIVE_BALANCE_LIMIT);
        emit TotalActiveBalanceLimitChanged(totalActiveBalanceLimit, _totalActiveBalanceLimit);
        totalActiveBalanceLimit = _totalActiveBalanceLimit;
    }

    /**
    * @dev Internal function to tell the total amount of tokens of juror
    * @param _juror Address of the juror querying the total amount of tokens staked of
    * @return Total amount of tokens of a juror
    */
    function _totalStakedFor(address _juror) internal view returns (uint256) {
        (uint256 active, uint256 available, , uint256 pendingDeactivation) = _balanceOf(_juror);
        return available.add(active).add(pendingDeactivation);
    }

    /**
    * @dev Internal function to tell the balance information of a juror
    * @param _juror Address of the juror querying the balance information of
    * @return active Amount of active tokens of a juror
    * @return available Amount of available tokens of a juror
    * @return locked Amount of active tokens that are locked due to ongoing disputes
    * @return pendingDeactivation Amount of active tokens that were requested for deactivation
    */
    function _balanceOf(address _juror) internal view returns (uint256 active, uint256 available, uint256 locked, uint256 pendingDeactivation) {
        Juror storage juror = jurorsByAddress[_juror];

        active = _existsJuror(juror) ? tree.getItem(juror.id) : 0;
        (available, locked, pendingDeactivation) = _getBalances(juror);
    }

    /**
    * @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) internal view returns (uint256) {
        Juror storage juror = jurorsByAddress[_juror];
        return _existsJuror(juror) ? tree.getItemAt(juror.id, _termId) : 0;
    }

    /**
    * @dev Internal function to get the amount of active tokens of a juror that are not locked due to ongoing disputes
    *      It will use the last value, that might be in a future term
    * @param _juror Juror querying the unlocked active balance of
    * @return Amount of active tokens of a juror that are not locked due to ongoing disputes
    */
    function _lastUnlockedActiveBalanceOf(Juror storage _juror) internal view returns (uint256) {
        return _existsJuror(_juror) ? tree.getItem(_juror.id).sub(_juror.lockedBalance) : 0;
    }

    /**
    * @dev Internal function to get the amount of active tokens at the last ensured term of a juror that are not locked due to ongoing disputes
    * @param _juror Juror querying the unlocked active balance of
    * @return Amount of active tokens of a juror that are not locked due to ongoing disputes
    */
    function _currentUnlockedActiveBalanceOf(Juror storage _juror) internal view returns (uint256) {
        uint64 lastEnsuredTermId = _getLastEnsuredTermId();
        return _existsJuror(_juror) ? tree.getItemAt(_juror.id, lastEnsuredTermId).sub(_juror.lockedBalance) : 0;
    }

    /**
    * @dev Internal function to check if a juror was already registered
    * @param _juror Juror to be checked
    * @return True if the given juror was already registered, false otherwise
    */
    function _existsJuror(Juror storage _juror) internal view returns (bool) {
        return _juror.id != 0;
    }

    /**
    * @dev Internal function to get the amount of a deactivation request for a given term id
    * @param _juror Juror to query the deactivation request amount of
    * @param _termId Term ID of the deactivation request to be queried
    * @return Amount of the deactivation request for the given term, 0 otherwise
    */
    function _deactivationRequestedAmountForTerm(Juror storage _juror, uint64 _termId) internal view returns (uint256) {
        DeactivationRequest storage request = _juror.deactivationRequest;
        return request.availableTermId == _termId ? request.amount : 0;
    }

    /**
    * @dev Internal function to 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) internal view returns (uint256) {
        // This function will return always the same values, the only difference remains on gas costs. In case we look for a
        // recent term, in this case current or future ones, we perform a backwards linear search from the last checkpoint.
        // Otherwise, a binary search is computed.
        bool recent = _termId >= _getLastEnsuredTermId();
        return recent ? tree.getRecentTotalAt(_termId) : tree.getTotalAt(_termId);
    }

    /**
    * @dev Internal function to check if its possible to add a given new amount to the registry or not
    * @param _termId Term ID when the new amount will be added
    * @param _amount Amount of tokens willing to be added to the registry
    */
    function _checkTotalActiveBalance(uint64 _termId, uint256 _amount) internal view {
        uint256 currentTotalActiveBalance = _totalActiveBalanceAt(_termId);
        uint256 newTotalActiveBalance = currentTotalActiveBalance.add(_amount);
        require(newTotalActiveBalance <= totalActiveBalanceLimit, ERROR_TOTAL_ACTIVE_BALANCE_EXCEEDED);
    }

    /**
    * @dev Tell the local balance information of a juror (that is not on the tree)
    * @param _juror Address of the juror querying the balance information of
    * @return available Amount of available tokens of a juror
    * @return locked Amount of active tokens that are locked due to ongoing disputes
    * @return pendingDeactivation Amount of active tokens that were requested for deactivation
    */
    function _getBalances(Juror storage _juror) internal view returns (uint256 available, uint256 locked, uint256 pendingDeactivation) {
        available = _juror.availableBalance;
        locked = _juror.lockedBalance;
        pendingDeactivation = _juror.deactivationRequest.amount;
    }

    /**
    * @dev Internal function to search jurors in the tree based on certain search restrictions
    * @param _params Draft params to be used for the jurors search
    * @return ids List of juror ids obtained based on the requested search
    * @return activeBalances List of active balances for each juror obtained based on the requested search
    */
    function _treeSearch(DraftParams memory _params) internal view returns (uint256[] memory ids, uint256[] memory activeBalances) {
        (ids, activeBalances) = tree.batchedRandomSearch(
            _params.termRandomness,
            _params.disputeId,
            _params.termId,
            _params.selectedJurors,
            _params.batchRequestedJurors,
            _params.roundRequestedJurors,
            _params.iteration
        );
    }

    /**
    * @dev Private function to parse a certain set given of draft params
    * @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 Draft params object parsed
    */
    function _buildDraftParams(uint256[7] memory _params) private view returns (DraftParams memory) {
        uint64 termId = uint64(_params[2]);
        uint256 minActiveBalance = _getMinActiveBalance(termId);

        return DraftParams({
            termRandomness: bytes32(_params[0]),
            disputeId: _params[1],
            termId: termId,
            selectedJurors: _params[3],
            batchRequestedJurors: _params[4],
            roundRequestedJurors: _params[5],
            draftLockAmount: minActiveBalance.pct(uint16(_params[6])),
            iteration: 0
        });
    }
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[{"name":"_juror","type":"address"},{"name":"_termId","type":"uint64"}],"name":"balanceOfAt","outputs":[{"name":"active","type":"uint256"},{"name":"available","type":"uint256"},{"name":"locked","type":"uint256"},{"name":"pendingDeactivation","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"stake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"stakeFor","outputs":[],"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":"_juror","type":"address"}],"name":"totalStakedFor","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_juror","type":"address"},{"name":"_amount","type":"uint256"}],"name":"assignTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_juror","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_termId","type":"uint64"}],"name":"collectTokens","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"burnTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_juror","type":"address"}],"name":"getDeactivationRequest","outputs":[{"name":"amount","type":"uint256"},{"name":"availableTermId","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"supportsHistory","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"_juror","type":"address"}],"name":"balanceOf","outputs":[{"name":"active","type":"uint256"},{"name":"available","type":"uint256"},{"name":"locked","type":"uint256"},{"name":"pendingDeactivation","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalStaked","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_termId","type":"uint64"}],"name":"totalActiveBalanceAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_token","type":"address"},{"name":"_data","type":"bytes"}],"name":"receiveApproval","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"deactivate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_juror","type":"address"}],"name":"unlockedActiveBalanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_juror","type":"address"}],"name":"processDeactivationRequest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_juror","type":"address"}],"name":"getWithdrawalsLockTermId","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_juror","type":"address"},{"name":"_termId","type":"uint64"}],"name":"lockWithdrawals","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"activate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_termId","type":"uint64"},{"name":"_jurors","type":"address[]"},{"name":"_lockedAmounts","type":"uint256[]"},{"name":"_rewardedJurors","type":"bool[]"}],"name":"slashOrUnlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"unstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_params","type":"uint256[7]"}],"name":"draft","outputs":[{"name":"jurors","type":"address[]"},{"name":"length","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalJurorsActiveBalanceLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_totalActiveBalanceLimit","type":"uint256"}],"name":"setTotalActiveBalanceLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_juror","type":"address"},{"name":"_termId","type":"uint64"}],"name":"activeBalanceOfAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_juror","type":"address"}],"name":"getJurorId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalActiveBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_controller","type":"address"},{"name":"_jurorToken","type":"address"},{"name":"_totalActiveBalanceLimit","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"juror","type":"address"},{"indexed":false,"name":"fromTermId","type":"uint64"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"sender","type":"address"}],"name":"JurorActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"juror","type":"address"},{"indexed":false,"name":"availableTermId","type":"uint64"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"JurorDeactivationRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"juror","type":"address"},{"indexed":false,"name":"availableTermId","type":"uint64"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"processedTermId","type":"uint64"}],"name":"JurorDeactivationProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"juror","type":"address"},{"indexed":false,"name":"availableTermId","type":"uint64"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"updateTermId","type":"uint64"}],"name":"JurorDeactivationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"juror","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"JurorBalanceLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"juror","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"JurorBalanceUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"juror","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"effectiveTermId","type":"uint64"}],"name":"JurorSlashed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"juror","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"JurorTokensAssigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"JurorTokensBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"juror","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"effectiveTermId","type":"uint64"}],"name":"JurorTokensCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousTotalActiveBalanceLimit","type":"uint256"},{"indexed":false,"name":"currentTotalActiveBalanceLimit","type":"uint256"}],"name":"TotalActiveBalanceLimitChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"total","type":"uint256"},{"indexed":false,"name":"data","type":"bytes"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"total","type":"uint256"},{"indexed":false,"name":"data","type":"bytes"}],"name":"Unstaked","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"}]

60806040523480156200001157600080fd5b50604051606080620051df833981018060405260608110156200003357600080fd5b50805160208083015160409093015191929190839081906200005b9082906200027f811b901c565b6040518060400160405280601b81526020017f4354445f434f4e54524f4c4c45525f4e4f545f434f4e545241435400000000008152509062000138576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620000fc578181015183820152602001620000e2565b50505050905090810190601f1680156200012a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600080546001600160a01b0319166001600160a01b0392909216919091179055506200016c826200027f602090811b901c565b6040518060400160405280600f81526020017f4a525f4e4f545f434f4e54524143540000000000000000000000000000000000815250906200020b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315620000fc578181015183820152602001620000e2565b50600280546001600160a01b0319166001600160a01b0384161790556200023981620002a4602090811b901c565b6200025060056200038460201b620045e71760201c565b6200026e6000806005620003ad60201b6200359c179092919060201c565b156200027657fe5b50505062000b9f565b60006001600160a01b03821662000299575060006200029f565b50803b15155b919050565b60408051808201909152601d81527f4a525f4241445f544f54414c5f4143544956455f42414c5f4c494d495400000060208201528162000341576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315620000fc578181015183820152602001620000e2565b50600154604080519182526020820183905280517f9ce60e2304bd08c7c9e6da0e10912e44f85fd9e2ee71c1842132f12146c586c89281900390910190a1600155565b620003a7600080600101836001016200040760201b6200379c179092919060201c565b60009055565b8254600181018455600090620003cc858286620004c7602090811b901c565b8215620003ff57620003e98560008387876200054e60201b60201c565b620003ff8582868660016200058860201b60201c565b949350505050565b60408051808201909152601881527f434845434b504f494e545f56414c55455f544f4f5f424947000000000000000060208201526001600160c01b03821115620004ae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315620000fc578181015183820152602001620000e2565b50620004c2838383620006ff60201b60201c565b505050565b6000620004da84620008b260201b60201c565b9050620004ee8184620008d360201b60201c565b1562000548576001810160006200050e86848362000903602090811b901c565b9050620005268683600087856200054e60201b60201c565b620005458483886001016200040760201b6200379c179092919060201c565b50505b50505050565b6000848152600286016020908152604080832086845282529091206200058191849084906200379c62000407821b17901c565b5050505050565b600019846000620005a088620008b2602090811b901c565b905060015b8181116200063457600484901b935083831692506000620005ce8a83866200090360201b60201c565b9050600086620005f857620005f288836200093160201b62002c2e1790919060201c565b62000612565b620006128883620009dd60201b6200224b1790919060201c565b9050620006298b84878c856200054e60201b60201c565b5050600101620005a5565b5083158062000655575084620006528983856200090360201b60201c565b10155b6040518060400160405280601881526020017f53554d5f545245455f5550444154455f4f564552464c4f57000000000000000081525090620006f4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315620000fc578181015183820152602001620000e2565b505050505050505050565b82548015806200073f575083546001600160401b03841690859060001981019081106200072857fe5b6000918252602090912001546001600160401b0316105b15620007b557604080518082019091526001600160401b0380851682526001600160c01b0380851660208085019182528854600181018a5560008a815291909120945194018054915190921668010000000000000000029383166001600160401b03199091161790911691909117905562000548565b6000846000016001830381548110620007ca57fe5b6000918252602091829020018054604080518082019091528381527f434845434b504f494e545f43414e4e4f545f4144445f504153545f56414c5545938101939093529092506001600160401b0386811691161462000886576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315620000fc578181015183820152602001620000e2565b5080546001600160c01b03841668010000000000000000026001600160401b0390911617905550505050565b6000620008cd8260010162000a8c60201b62003dfe1760201c565b92915050565b600080620008f160048562000adf60201b620038d71790919060201c565b600019901b8316151591505092915050565b6000828152600284016020908152604080832084845282528220620003ff9162003dfe62000a8c821b17901c565b6000828211156040518060400160405280601281526020017f4d4154485f5355425f554e444552464c4f57000000000000000000000000000081525090620009d6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315620000fc578181015183820152602001620000e2565b5050900390565b60408051808201909152601181527f4d4154485f4144445f4f564552464c4f570000000000000000000000000000006020820152600090838301908482101562000a84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315620000fc578181015183820152602001620000e2565b509392505050565b8054600090801562000ad65782600001600182038154811062000aab57fe5b6000918252602090912001546801000000000000000090046001600160c01b031691506200029f9050565b50600092915050565b60008262000af057506000620008cd565b8282028284828162000afe57fe5b04146040518060400160405280601181526020017f4d4154485f4d554c5f4f564552464c4f570000000000000000000000000000008152509062000a84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315620000fc578181015183820152602001620000e2565b6146308062000baf6000396000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c8063916b9bef11610104578063c8fd6ed0116100a2578063e9e67d6711610071578063e9e67d67146108c7578063f01e7d03146108fd578063f590e92314610923578063fc0c546a1461092b576101da565b8063c8fd6ed0146107b4578063d903bcf41461082b578063dbbd85a6146108a2578063e67a81f4146108aa576101da565b8063af7a9f40116100de578063af7a9f40146105f9578063af8b9d0f1461063c578063b260c42a14610672578063c67106f51461068f576101da565b8063916b9bef1461059057806396a705c1146105ad578063ac8fcfc0146105d3576101da565b8063605da1b21161017c57806370a082311161014b57806370a08231146104ac578063817b1cd2146104d25780638e127793146104da5780638f4ffcb114610501576101da565b8063605da1b2146103ef5780636d1b229d1461043f5780636d6cc6841461045c5780637033e4a6146104a4576101da565b806324ae6a27116101b857806324ae6a27146103395780633018205f146103675780634b341aed1461038b5780634d7edc15146103c3576101da565b8063082b4235146101df5780630e89439b1461023b5780630ef96356146102b4575b600080fd5b610215600480360360408110156101f557600080fd5b5080356001600160a01b0316906020013567ffffffffffffffff16610933565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6102b26004803603604081101561025157600080fd5b8135919081019060408101602082013564010000000081111561027357600080fd5b82018360208201111561028557600080fd5b803590602001918460018302840111640100000000831117156102a757600080fd5b509092509050610993565b005b6102b2600480360360608110156102ca57600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156102fa57600080fd5b82018360208201111561030c57600080fd5b8035906020019184600183028401116401000000008311171561032e57600080fd5b5090925090506109da565b6102b26004803603604081101561034f57600080fd5b506001600160a01b0381358116916020013516610a22565b61036f610d6c565b604080516001600160a01b039092168252519081900360200190f35b6103b1600480360360208110156103a157600080fd5b50356001600160a01b0316610d7b565b60408051918252519081900360200190f35b6102b2600480360360408110156103d957600080fd5b506001600160a01b038135169060200135610d8e565b61042b6004803603606081101561040557600080fd5b5080356001600160a01b0316906020810135906040013567ffffffffffffffff16610e86565b604080519115158252519081900360200190f35b6102b26004803603602081101561045557600080fd5b5035611024565b6104826004803603602081101561047257600080fd5b50356001600160a01b0316611111565b6040805192835267ffffffffffffffff90911660208301528051918290030190f35b61042b611143565b610215600480360360208110156104c257600080fd5b50356001600160a01b0316611148565b6103b1611166565b6103b1600480360360208110156104f057600080fd5b503567ffffffffffffffff166111fb565b6102b26004803603608081101561051757600080fd5b6001600160a01b03823581169260208101359260408201359092169181019060808101606082013564010000000081111561055157600080fd5b82018360208201111561056357600080fd5b8035906020019184600183028401116401000000008311171561058557600080fd5b509092509050611206565b6102b2600480360360208110156105a657600080fd5b50356112fa565b6103b1600480360360208110156105c357600080fd5b50356001600160a01b03166114fa565b6102b2600480360360208110156105e957600080fd5b50356001600160a01b031661151b565b61061f6004803603602081101561060f57600080fd5b50356001600160a01b0316611531565b6040805167ffffffffffffffff9092168252519081900360200190f35b6102b26004803603604081101561065257600080fd5b5080356001600160a01b0316906020013567ffffffffffffffff1661155a565b6102b26004803603602081101561068857600080fd5b503561163b565b6103b1600480360360808110156106a557600080fd5b67ffffffffffffffff82351691908101906040810160208201356401000000008111156106d157600080fd5b8201836020820111156106e357600080fd5b8035906020019184602083028401116401000000008311171561070557600080fd5b91939092909160208101903564010000000081111561072357600080fd5b82018360208201111561073557600080fd5b8035906020019184602083028401116401000000008311171561075757600080fd5b91939092909160208101903564010000000081111561077557600080fd5b82018360208201111561078757600080fd5b803590602001918460208302840111640100000000831117156107a957600080fd5b509092509050611646565b6102b2600480360360408110156107ca57600080fd5b813591908101906040810160208201356401000000008111156107ec57600080fd5b8201836020820111156107fe57600080fd5b8035906020019184600183028401116401000000008311171561082057600080fd5b509092509050611953565b610847600480360360e081101561084157600080fd5b50611994565b6040518080602001838152602001828103825284818151815260200191508051906020019060200280838360005b8381101561088d578181015183820152602001610875565b50505050905001935050505060405180910390f35b6103b1611c67565b6102b2600480360360208110156108c057600080fd5b5035611c6d565b6103b1600480360360408110156108dd57600080fd5b5080356001600160a01b0316906020013567ffffffffffffffff16611d18565b6103b16004803603602081101561091357600080fd5b50356001600160a01b0316611d2d565b6103b1611d48565b61036f611d59565b6001600160a01b038216600090815260036020526040812081908190819061095a81611d68565b61096557600061097a565b805461097a906005908863ffffffff611d6e16565b945061098581611d85565b969991985096509350505050565b6109d533338585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d9992505050565b505050565b610a1c33858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d9992505050565b50505050565b6000809054906101000a90046001600160a01b03166001600160a01b0316633c28e88b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610a6f57600080fd5b505afa158015610a83573d6000803e3d6000fd5b505050506040513d6020811015610a9957600080fd5b505160408051808201909152601d81527f4354445f53454e4445525f4e4f545f46554e44535f474f5645524e4f520000006020820152906001600160a01b03163314610b6657604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610b2b578181015183820152602001610b13565b50505050905090810190601f168015610b585780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000916001600160a01b038516916370a0823191602480820192602092909190829003018186803b158015610bca57600080fd5b505afa158015610bde573d6000803e3d6000fd5b505050506040513d6020811015610bf457600080fd5b505160408051808201909152601e81527f4354445f494e53554646494349454e545f5245434f5645525f46554e44530000602082015290915081610c7c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50610c976001600160a01b038416838363ffffffff611fe416565b6040518060400160405280601e81526020017f4354445f5245434f5645525f544f4b454e5f46554e44535f4641494c4544000081525090610d1c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50604080516001600160a01b0380861682528416602082015280820183905290517f724139fea3954691c2c1ee02b3be6be1763b32ec84841f1acad6d3a18695ba0d9181900360600190a1505050565b6000546001600160a01b031690565b6000610d868261206f565b90505b919050565b610d966120a8565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f44495350555445535f4d4f44554c45000081525090610e2f57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b508015610e8257610e42828260016120f7565b6040805182815290516001600160a01b038416917fbfbd6786419e534c0af90164d33c027ddc81c4541f1047d00bb286d5d4dfe8a7919081900360200190a25b5050565b6000610e906120a8565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f44495350555445535f4d4f44554c45000081525090610f2957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5082610f375750600161101d565b6001600160a01b03841660009081526003602052604081206001840191610f5d826121dc565b90506000610f6b838561221c565b90506000610f7f838363ffffffff61224b16565b905080881115610f975760009550505050505061101d565b82881115610faf57828803610fad8a828a6122e0565b505b8354610fc790600590878b600063ffffffff61241516565b6040805189815267ffffffffffffffff8716602082015281516001600160a01b038c16927f3b522789764bf3f50da1a4e79a6b330fd1ae121df88d89259fa73b55e1e9e360928290030190a26001955050505050505b9392505050565b61102c6120a8565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f44495350555445535f4d4f44554c450000815250906110c557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50801561110e576110da61dead8260016120f7565b6040805182815290517fef08526ce447c7a59448d28b89b25b9be13b2ae0293946c9cf27123c8e71a3769181900360200190a15b50565b6001600160a01b0381166000908152600360205260409020600481015460059091015467ffffffffffffffff16915091565b600090565b600080600080611157856124f4565b93509350935093509193509193565b600254604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156111ca57600080fd5b505afa1580156111de573d6000803e3d6000fd5b505050506040513d60208110156111f457600080fd5b5051905090565b6000610d8682612553565b336001600160a01b03841614801561122b57506002546001600160a01b038481169116145b6040518060400160405280601c81526020017f4a525f544f4b454e5f415050524f56455f4e4f545f414c4c4f57454400000000815250906112b057604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506112f385868685858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d9992505050565b5050505050565b60006113046125a3565b33600090815260036020526040812091925061131f826121dc565b90506000841561132f5784611331565b815b9050600081116040518060400160405280601681526020017f4a525f494e56414c49445f5a45524f5f414d4f554e5400000000000000000000815250906113bc57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060408051808201909152601e81527f4a525f494e56414c49445f444541435449564154494f4e5f414d4f554e54000060208201528282111561144357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b508082036000611452866125fb565b90508115806114615750808210155b6040518060400160405280601e81526020017f4a525f494e56414c49445f444541435449564154494f4e5f414d4f554e540000815250906114e657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506114f1338461268e565b50505050505050565b6001600160a01b038116600090815260036020526040812061101d81612761565b60006115256125a3565b9050610e8282826127a1565b6001600160a01b03166000908152600360208190526040909120015467ffffffffffffffff1690565b6115626120a8565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f44495350555445535f4d4f44554c450000815250906115fb57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506001600160a01b0391909116600090815260036020819052604090912001805467ffffffffffffffff191667ffffffffffffffff909216919091179055565b61110e338233612880565b60006116506120a8565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f44495350555445535f4d4f44554c450000815250906116e957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060408051808201909152601d81527f4a525f494e56414c49445f4c4f434b45445f414d4f554e54535f4c454e000000602082015286851461176f57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060408051808201909152601e81527f4a525f494e56414c49445f52455741524445445f4a55524f52535f4c454e000060208201528683146117f557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50600188016000805b8881101561194557600088888381811061181457fe5b90506020020135905060008b8b8481811061182b57fe5b602090810292909201356001600160a01b0316600081815260039093526040909220600181015492935091611861915084612c2e565b600182015588888581811061187257fe5b90506020020135156118c2576040805184815290516001600160a01b038416917f04205018e3978d4e9bf2627d251200b16b790aff8c89cccc4b6e4b226c6c0531919081900360200190a261193a565b6118d2858463ffffffff61224b16565b81549095506118ed906005908886600063ffffffff61241516565b6040805184815267ffffffffffffffff8816602082015281516001600160a01b038516927fb0f2cd2d530eb7a84b780655bd7cd315af71951aedf4ff554889d56cfc3c4ae9928290030190a25b5050506001016117fe565b509998505050505050505050565b6109d5338484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612cc092505050565b606060006119a06120a8565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f44495350555445535f4d4f44554c45000081525090611a3957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50611a4261455c565b6040805160e0818101909252611a709186906007908390839080828437600092019190915250612f99915050565b90508060800151604051908082528060200260200182016040528015611aa0578160200160208202803883390190505b50600060e083015292505b806080015182108015611ac25750600a8160e00151105b15611c6157606080611ad38361303b565b909250905060005b825181108015611aee5750836080015185105b15611c4e57600060046000858481518110611b0557fe5b60209081029190910181015182528181019290925260409081016000908120546001600160a01b0316808252600390935290812060c088015160018201549394509092611b579163ffffffff61224b16565b90506000611b6c83896040015160010161221c565b90506000868681518110611b7c57fe5b60200260200101519050828110611c3d576000611b9f828463ffffffff612c2e16565b905083811015611bba57611bba868286038c604001516122e0565b838560010181905550858c8c806001019d5081518110611bd657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050856001600160a01b03167fab9783755c502b2e2e2a8f5d7c88344973a1400de6c46334a7d60d70a17f64588b60c001516040518082815260200191505060405180910390a2505b505060019093019250611adb915050565b50505060e0810180516001019052611aab565b50915091565b60015490565b611c75613084565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f434f4e4649475f474f5645524e4f52000081525090611d0e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5061110e816130d3565b6000611d248383613199565b90505b92915050565b6001600160a01b031660009081526003602052604090205490565b6000611d5460056131da565b905090565b6002546001600160a01b031690565b54151590565b6000611d7d84600085856131f4565b949350505050565b600281015460018201546004909201549092565b60408051808201909152601681527f4a525f494e56414c49445f5a45524f5f414d4f554e5400000000000000000000602082015282611e1c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50611e29838360016120f7565b7fb260c42a00000000000000000000000000000000000000000000000000000000611e538261321f565b7fffffffff00000000000000000000000000000000000000000000000000000000161415611e8657611e86838386612880565b826001600160a01b03167fc65e53b88159e7d2c0fc12a0600072e28ae53ff73b4c1715369c30f16093514283611ebb8661206f565b846040518084815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611f05578181015183820152602001611eed565b50505050905090810190601f168015611f325780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a2600254611f5f906001600160a01b031685308563ffffffff61323b16565b6040518060400160405280601881526020017f4a525f544f4b454e5f5452414e534645525f4641494c45440000000000000000815250906112f357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905260009061206685826132cf565b95945050505050565b60008060008061207e856124f4565b935050925092506120668161209c858561224b90919063ffffffff16565b9063ffffffff61224b16565b60008060009054906101000a90046001600160a01b03166001600160a01b031663db9bee466040518163ffffffff1660e01b815260040160206040518083038186803b1580156111ca57600080fd5b81612101576109d5565b6001600160a01b0383166000908152600360205260409020811561213e576002810154612134908463ffffffff61224b16565b6002820155610a1c565b80600201548311156040518060400160405280601f81526020017f4a525f4e4f545f454e4f5547485f415641494c41424c455f42414c414e434500815250906121cb57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506002018054929092039091555050565b60006121e782611d68565b6121f2576000610d86565b60018201548254610d8691906122109060059063ffffffff61331a16565b9063ffffffff612c2e16565b6005820154600090600484019067ffffffffffffffff848116911614612243576000611d7d565b549392505050565b60408051808201909152601181527f4d4154485f4144445f4f564552464c4f57000000000000000000000000000000602082015260009083830190848210156122d857604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b509392505050565b6001600160a01b0383166000908152600360209081526040918290206004810180548451808601909552601f85527f4a525f43414e545f5245445543455f444541435449564154494f4e5f524551009385019390935290929091908582101561238d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5084810380835583546123b0906005906001808901908a9063ffffffff61241516565b60018301546040805167ffffffffffffffff92831681526020810184905291871682820152516001600160a01b038916917fc8eaece66ffd12e5066e2ef36d5943fa8fb8104362f92f75152c39788d85b184919081900360600190a250505050505050565b845460408051808201909152601b81527f53554d5f545245455f4b45595f444f45535f4e4f545f45584953540000000000602082015290851061249c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060006124a9868661331a565b90506000826124c7576124c2828563ffffffff612c2e16565b6124d7565b6124d7828563ffffffff61224b16565b90506124e7876000888885613328565b6114f18787878787613354565b6001600160a01b038116600090815260036020526040812081908190819061251b81611d68565b61252657600061253a565b805461253a9060059063ffffffff61331a16565b945061254581611d85565b969891975095945092505050565b60008061255e613476565b67ffffffffffffffff168367ffffffffffffffff1610159050806125925761258d60058463ffffffff6134b816565b61101d565b61101d60058463ffffffff6134d416565b60006125ad610d6c565b6001600160a01b0316633f33bf866040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156125e757600080fd5b505af11580156111de573d6000803e3d6000fd5b6000612605610d6c565b6001600160a01b03166395f3c2da836040518263ffffffff1660e01b8152600401808267ffffffffffffffff1667ffffffffffffffff16815260200191505060206040518083038186803b15801561265c57600080fd5b505afa158015612670573d6000803e3d6000fd5b505050506040513d602081101561268657600080fd5b505192915050565b60006126986125a3565b90506126a483826127a1565b6001600160a01b0383166000908152600360205260409020600481018054600184019291906126d9908663ffffffff61224b16565b815560018101805467ffffffffffffffff191667ffffffffffffffff8516179055815461270c9060059085886000612415565b6040805167ffffffffffffffff851681526020810187905281516001600160a01b038916927fe26ea88625a55cdd86472d3d0e9efd8dd884b5baa05b79bb95a3408df76cede9928290030190a2505050505050565b60008061276c613476565b905061277783611d68565b61278257600061101d565b6001830154835461101d9190612210906005908563ffffffff611d6e16565b6001600160a01b03821660009081526003602052604090206005810154600482019067ffffffffffffffff168015806127ed57508067ffffffffffffffff168467ffffffffffffffff16105b156127fa57505050610e82565b81546001808401805467ffffffffffffffff191690556000845561282190879083906120f7565b6040805167ffffffffffffffff80851682526020820184905287168183015290516001600160a01b038816917f8969a0b11c2c7f08ef80af31a680937503d444cdc933ba9091cdc20f098a7f36919081900360600190a2505050505050565b600061288a6125a3565b905061289684826127a1565b6001600160a01b0384166000908152600360205260408120600201549084156128bf57846128c1565b815b9050600081116040518060400160405280601681526020017f4a525f494e56414c49445f5a45524f5f414d4f554e54000000000000000000008152509061294c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060408051808201909152601c81527f4a525f494e56414c49445f41435449564154494f4e5f414d4f554e54000000006020820152828211156129d357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50600183016129e281836134f0565b6001600160a01b038716600090815260036020526040812090612a04836125fb565b9050612a0f82611d68565b15612ae4578154600090612a2b9060059063ffffffff61331a16565b905081612a3e828763ffffffff61224b16565b10156040518060400160405280601b81526020017f4a525f4143544956455f42414c414e43455f42454c4f575f4d494e000000000081525090612ac557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b508254612ade906005908688600163ffffffff61241516565b50612bc0565b60408051808201909152601b81527f4a525f4143544956455f42414c414e43455f42454c4f575f4d494e0000000000602082015281851015612b6a57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50612b7d6005848663ffffffff61359c16565b808355600090815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b161790555b612bcc898560006120f7565b6040805167ffffffffffffffff85168152602081018690526001600160a01b03898116828401529151918b16917fee90556a99bb0d072721fedb6d8d458371d132b715762b023fba4d367fbd57b29181900360600190a2505050505050505050565b6000828211156040518060400160405280601281526020017f4d4154485f5355425f554e444552464c4f57000000000000000000000000000081525090612cb957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5050900390565b60408051808201909152601681527f4a525f494e56414c49445f5a45524f5f414d4f554e5400000000000000000000602082015282612d4357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506000612d4e613476565b6001600160a01b0385166000908152600360208190526040909120015490915067ffffffffffffffff16801580612d9857508167ffffffffffffffff168167ffffffffffffffff16105b6040518060400160405280601381526020017f4a525f5749544844524157414c535f4c4f434b0000000000000000000000000081525090612e1d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50612e2885836127a1565b612e34858560006120f7565b846001600160a01b03167faf01bfc8475df280aca00b578c4a948e6d95700f0db8c13365240f7f973c875485612e698861206f565b866040518084815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015612eb3578181015183820152602001612e9b565b50505050905090810190601f168015612ee05780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a2600254612f0c906001600160a01b0316868663ffffffff611fe416565b6040518060400160405280601881526020017f4a525f544f4b454e5f5452414e534645525f4641494c4544000000000000000081525090612f9157604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b505050505050565b612fa161455c565b60408201516000612fb1826125fb565b905060405180610100016040528085600060078110612fcc57fe5b602090810291909101518252868101519082015267ffffffffffffffff84166040820152606080870151908201526080808701519082015260a0808701519082015260c0016130298660066020020151849063ffffffff6135d416565b81526000602090910152949350505050565b60608061307a836000015184602001518560400151866060015187608001518860a001518960e0015160056135fc90979695949392919063ffffffff16565b9094909350915050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166397023f816040518163ffffffff1660e01b815260040160206040518083038186803b1580156111ca57600080fd5b60408051808201909152601d81527f4a525f4241445f544f54414c5f4143544956455f42414c5f4c494d495400000060208201528161315657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50600154604080519182526020820183905280517f9ce60e2304bd08c7c9e6da0e10912e44f85fd9e2ee71c1842132f12146c586c89281900390910190a1600155565b6001600160a01b03821660009081526003602052604081206131ba81611d68565b6131c5576000611d7d565b8054611d7d906005908563ffffffff611d6e16565b6000806131e68361375e565b905061101d8382600061376c565b600083815260028501602090815260408083208584529091528120612066908363ffffffff61379016565b600060048251101561323357506000610d89565b506020015190565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526000906132c586826132cf565b9695505050505050565b6000806040516020818551602087016000895af18015613310573d80156132fd57602081146133065761330e565b6001935061330e565b600183511493505b505b5090949350505050565b6000611d248360008461376c565b6000848152600286016020908152604080832086845290915290206112f390838363ffffffff61379c16565b6000198460006133638861375e565b905060015b8181116133ce5760049390931b929183169160006133878a838661376c565b90506000866133a5576133a0828963ffffffff612c2e16565b6133b5565b6133b5828963ffffffff61224b16565b90506133c48b84878c85613328565b5050600101613368565b508315806133e65750846133e389838561376c565b10155b6040518060400160405280601881526020017f53554d5f545245455f5550444154455f4f564552464c4f5700000000000000008152509061346b57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b505050505050505050565b6000613480610d6c565b6001600160a01b031663f7fe57896040518163ffffffff1660e01b815260040160206040518083038186803b1580156111ca57600080fd5b6000806134c58484613846565b9050611d7d84826000866131f4565b6000806134e18484613846565b9050611d7d848260008661385b565b60006134fb83612553565b9050600061350f828463ffffffff61224b16565b90506001548111156040518060400160405280602081526020017f4a525f544f54414c5f4143544956455f42414c414e43455f4558434545444544815250906112f357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b82546001810184556000906135b2858286613886565b8215611d7d576135c6856000838787613328565b611d7d858286866001613354565b60006127106135ed8461ffff851663ffffffff6138d716565b816135f457fe5b049392505050565b60608060008061360f8c8a8a8a8a61397a565b9150915060606136238c8c888b87876139e8565b90506136368d828c63ffffffff613be016565b8051825160408051808201909152601f81527f545245455f534f52544954494f4e5f4c454e475448535f4d49534d41544348006020820152939850919650146136c357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50878551146040518060400160405280601f81526020017f545245455f534f52544954494f4e5f4c454e475448535f4d49534d41544348008152509061374d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b505050509850989650505050505050565b6000610d8682600101613dfe565b600082815260028401602090815260408083208484529091528120611d7d90613dfe565b6000611d248383613e5f565b60408051808201909152601881527f434845434b504f494e545f56414c55455f544f4f5f4249470000000000000000602082015277ffffffffffffffffffffffffffffffffffffffffffffffff82111561383a57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506109d5838383614033565b6000611d24600184018363ffffffff6141ef16565b600083815260028501602090815260408083208584529091528120612066908363ffffffff6141ef16565b60006138918461375e565b905061389d81846141fb565b15610a1c576001810160006138b386848361376c565b90506138c3868360008785613328565b612f9160018701858463ffffffff61379c16565b6000826138e657506000611d27565b828202828482816138f357fe5b04146040518060400160405280601181526020017f4d4154485f4d554c5f4f564552464c4f57000000000000000000000000000000815250906122d857604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b6000808061398e888863ffffffff6134d416565b90506139b0846139a4888463ffffffff6138d716565b9063ffffffff61422116565b925060006139c4878763ffffffff61224b16565b90506139da856139a4838563ffffffff6138d716565b925050509550959350505050565b60608282116040518060400160405280601c81526020017f545245455f494e56414c49445f494e54455256414c5f5345415243480000000081525090613a7257604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060008383039050606085604051908082528060200260200182016040528015613aa6578160200160208202803883390190505b50905060005b86811015613bd3576040805160208082018d90528183018c9052606082018b905260808083018590528351808403909101815260a09092019092528051910120613b07848281613af857fe5b8991900663ffffffff61224b16565b838381518110613b1357fe5b6020908102919091010152815b600081118015613b585750836001820381518110613b3a57fe5b6020026020010151848281518110613b4e57fe5b6020026020010151105b15613bc9576000846001830381518110613b6e57fe5b60200260200101519050848281518110613b8457fe5b6020026020010151856001840381518110613b9b57fe5b60200260200101818152505080858381518110613bb457fe5b60209081029190910101525060001901613b20565b5050600101613aac565b5098975050505050505050565b60608060008451116040518060400160405280601e81526020017f53554d5f545245455f4d495353494e475f5345415243485f56414c554553000081525090613c6d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506000613c7a86856134d4565b9050600081118015613ca2575084600186510381518110613c9757fe5b602002602001015181115b6040518060400160405280601d81526020017f53554d5f545245455f5345415243485f4f55545f4f465f424f554e445300000081525090613d2757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506000613d348786613846565b9050613d3e6145ae565b6040805160a0810190915267ffffffffffffffff8716815260208101613d6b84600163ffffffff612c2e16565b815260200160008152602001600081526020016000815250905060008751905080604051908082528060200260200182016040528015613db5578160200160208202803883390190505b50955080604051908082528060200260200182016040528015613de2578160200160208202803883390190505b509450613df289898489896142c0565b50505050935093915050565b80546000908015613e5657826000016001820381548110613e1b57fe5b60009182526020909120015468010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff169150610d899050565b50600092915050565b815460009080613e73576000915050611d27565b8354600019820190859082908110613e8757fe5b60009182526020909120015467ffffffffffffffff90811690851610613ef257846000018181548110613eb657fe5b60009182526020909120015468010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff169250611d27915050565b84600001600081548110613f0257fe5b60009182526020909120015467ffffffffffffffff9081169085161015613f2e57600092505050611d27565b6000815b81811115613fe757865460028383016001010490600090899083908110613f5557fe5b6000918252602090912001805490915067ffffffffffffffff908116908916811015613f8357829450613fdf565b8067ffffffffffffffff168967ffffffffffffffff161015613faa57600183039350613fdf565b505468010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff169550611d27945050505050565b505050613f32565b866000018281548110613ff657fe5b60009182526020909120015468010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff16979650505050505050565b82548015806140735750835467ffffffffffffffff8416908590600019810190811061405b57fe5b60009182526020909120015467ffffffffffffffff16105b156140fa576040805180820190915267ffffffffffffffff808516825277ffffffffffffffffffffffffffffffffffffffffffffffff80851660208085019182528854600181018a5560008a8152919091209451940180549151909216680100000000000000000293831667ffffffffffffffff1990911617909116919091179055610a1c565b600084600001600183038154811061410e57fe5b6000918252602091829020018054604080518082019091528381527f434845434b504f494e545f43414e4e4f545f4144445f504153545f56414c55459381019390935290925067ffffffffffffffff8681169116146141b157604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50805477ffffffffffffffffffffffffffffffffffffffffffffffff8416680100000000000000000267ffffffffffffffff90911617905550505050565b6000611d248383614408565b60008061420f84600463ffffffff6138d716565b600019901b8316151591505092915050565b60008082116040518060400160405280600d81526020017f4d4154485f4449565f5a45524f00000000000000000000000000000000000000815250906142ab57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060008284816142b757fe5b04949350505050565b60208301516000906142d990600463ffffffff6138d716565b905060005b60108110156114f15785518560600151106142f8576114f1565b60408501516000906143129083851b63ffffffff61224b16565b9050600061432a898860200151848a6000015161385b565b9050600061434582896080015161224b90919063ffffffff16565b905060006143588a8a60600151846144d6565b905080156143f85760208901516143805761437b896060015182868b878c614514565b6143dd565b6143886145ae565b6040518060a001604052808b6000015167ffffffffffffffff16815260200160018c602001510381526020018681526020018b6060015181526020018b6080015181525090506143db8c8c838c8c6142c0565b505b60608901516143f2908263ffffffff61224b16565b60608a01525b50608088015250506001016142de565b81546000908061441c576000915050611d27565b835460001982019060009086908390811061443357fe5b9060005260206000200190505b60008211801561445d5750805467ffffffffffffffff8087169116115b156144885785546000199092019186908390811061447757fe5b906000526020600020019050614440565b805467ffffffffffffffff8087169116116144ca57805468010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff166132c5565b60009695505050505050565b6000825b8451811080156144fc5750828582815181106144f257fe5b6020026020010151105b15614509576001016144da565b929092039392505050565b60005b858110156114f15784848289018151811061452e57fe5b60200260200101818152505082828289018151811061454957fe5b6020908102919091010152600101614517565b6040518061010001604052806000801916815260200160008152602001600067ffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060a00160405280600067ffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b6145fe60018281019060009063ffffffff61379c16565b6000905556fea165627a7a723058200f1569b86ba4df4896c73943c86f522b57715b54798a50aae9ef13dfef05753f0029000000000000000000000000ee4650cbe7a2b23701d416f58b41d8b76b617797000000000000000000000000cd62b1c403fa761baadfc74c525ce2b51780b184000000000000000000000000000000008ac7230489e7feb210d3bd1429c00000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101da5760003560e01c8063916b9bef11610104578063c8fd6ed0116100a2578063e9e67d6711610071578063e9e67d67146108c7578063f01e7d03146108fd578063f590e92314610923578063fc0c546a1461092b576101da565b8063c8fd6ed0146107b4578063d903bcf41461082b578063dbbd85a6146108a2578063e67a81f4146108aa576101da565b8063af7a9f40116100de578063af7a9f40146105f9578063af8b9d0f1461063c578063b260c42a14610672578063c67106f51461068f576101da565b8063916b9bef1461059057806396a705c1146105ad578063ac8fcfc0146105d3576101da565b8063605da1b21161017c57806370a082311161014b57806370a08231146104ac578063817b1cd2146104d25780638e127793146104da5780638f4ffcb114610501576101da565b8063605da1b2146103ef5780636d1b229d1461043f5780636d6cc6841461045c5780637033e4a6146104a4576101da565b806324ae6a27116101b857806324ae6a27146103395780633018205f146103675780634b341aed1461038b5780634d7edc15146103c3576101da565b8063082b4235146101df5780630e89439b1461023b5780630ef96356146102b4575b600080fd5b610215600480360360408110156101f557600080fd5b5080356001600160a01b0316906020013567ffffffffffffffff16610933565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6102b26004803603604081101561025157600080fd5b8135919081019060408101602082013564010000000081111561027357600080fd5b82018360208201111561028557600080fd5b803590602001918460018302840111640100000000831117156102a757600080fd5b509092509050610993565b005b6102b2600480360360608110156102ca57600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156102fa57600080fd5b82018360208201111561030c57600080fd5b8035906020019184600183028401116401000000008311171561032e57600080fd5b5090925090506109da565b6102b26004803603604081101561034f57600080fd5b506001600160a01b0381358116916020013516610a22565b61036f610d6c565b604080516001600160a01b039092168252519081900360200190f35b6103b1600480360360208110156103a157600080fd5b50356001600160a01b0316610d7b565b60408051918252519081900360200190f35b6102b2600480360360408110156103d957600080fd5b506001600160a01b038135169060200135610d8e565b61042b6004803603606081101561040557600080fd5b5080356001600160a01b0316906020810135906040013567ffffffffffffffff16610e86565b604080519115158252519081900360200190f35b6102b26004803603602081101561045557600080fd5b5035611024565b6104826004803603602081101561047257600080fd5b50356001600160a01b0316611111565b6040805192835267ffffffffffffffff90911660208301528051918290030190f35b61042b611143565b610215600480360360208110156104c257600080fd5b50356001600160a01b0316611148565b6103b1611166565b6103b1600480360360208110156104f057600080fd5b503567ffffffffffffffff166111fb565b6102b26004803603608081101561051757600080fd5b6001600160a01b03823581169260208101359260408201359092169181019060808101606082013564010000000081111561055157600080fd5b82018360208201111561056357600080fd5b8035906020019184600183028401116401000000008311171561058557600080fd5b509092509050611206565b6102b2600480360360208110156105a657600080fd5b50356112fa565b6103b1600480360360208110156105c357600080fd5b50356001600160a01b03166114fa565b6102b2600480360360208110156105e957600080fd5b50356001600160a01b031661151b565b61061f6004803603602081101561060f57600080fd5b50356001600160a01b0316611531565b6040805167ffffffffffffffff9092168252519081900360200190f35b6102b26004803603604081101561065257600080fd5b5080356001600160a01b0316906020013567ffffffffffffffff1661155a565b6102b26004803603602081101561068857600080fd5b503561163b565b6103b1600480360360808110156106a557600080fd5b67ffffffffffffffff82351691908101906040810160208201356401000000008111156106d157600080fd5b8201836020820111156106e357600080fd5b8035906020019184602083028401116401000000008311171561070557600080fd5b91939092909160208101903564010000000081111561072357600080fd5b82018360208201111561073557600080fd5b8035906020019184602083028401116401000000008311171561075757600080fd5b91939092909160208101903564010000000081111561077557600080fd5b82018360208201111561078757600080fd5b803590602001918460208302840111640100000000831117156107a957600080fd5b509092509050611646565b6102b2600480360360408110156107ca57600080fd5b813591908101906040810160208201356401000000008111156107ec57600080fd5b8201836020820111156107fe57600080fd5b8035906020019184600183028401116401000000008311171561082057600080fd5b509092509050611953565b610847600480360360e081101561084157600080fd5b50611994565b6040518080602001838152602001828103825284818151815260200191508051906020019060200280838360005b8381101561088d578181015183820152602001610875565b50505050905001935050505060405180910390f35b6103b1611c67565b6102b2600480360360208110156108c057600080fd5b5035611c6d565b6103b1600480360360408110156108dd57600080fd5b5080356001600160a01b0316906020013567ffffffffffffffff16611d18565b6103b16004803603602081101561091357600080fd5b50356001600160a01b0316611d2d565b6103b1611d48565b61036f611d59565b6001600160a01b038216600090815260036020526040812081908190819061095a81611d68565b61096557600061097a565b805461097a906005908863ffffffff611d6e16565b945061098581611d85565b969991985096509350505050565b6109d533338585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d9992505050565b505050565b610a1c33858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d9992505050565b50505050565b6000809054906101000a90046001600160a01b03166001600160a01b0316633c28e88b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610a6f57600080fd5b505afa158015610a83573d6000803e3d6000fd5b505050506040513d6020811015610a9957600080fd5b505160408051808201909152601d81527f4354445f53454e4445525f4e4f545f46554e44535f474f5645524e4f520000006020820152906001600160a01b03163314610b6657604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610b2b578181015183820152602001610b13565b50505050905090810190601f168015610b585780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000916001600160a01b038516916370a0823191602480820192602092909190829003018186803b158015610bca57600080fd5b505afa158015610bde573d6000803e3d6000fd5b505050506040513d6020811015610bf457600080fd5b505160408051808201909152601e81527f4354445f494e53554646494349454e545f5245434f5645525f46554e44530000602082015290915081610c7c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50610c976001600160a01b038416838363ffffffff611fe416565b6040518060400160405280601e81526020017f4354445f5245434f5645525f544f4b454e5f46554e44535f4641494c4544000081525090610d1c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50604080516001600160a01b0380861682528416602082015280820183905290517f724139fea3954691c2c1ee02b3be6be1763b32ec84841f1acad6d3a18695ba0d9181900360600190a1505050565b6000546001600160a01b031690565b6000610d868261206f565b90505b919050565b610d966120a8565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f44495350555445535f4d4f44554c45000081525090610e2f57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b508015610e8257610e42828260016120f7565b6040805182815290516001600160a01b038416917fbfbd6786419e534c0af90164d33c027ddc81c4541f1047d00bb286d5d4dfe8a7919081900360200190a25b5050565b6000610e906120a8565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f44495350555445535f4d4f44554c45000081525090610f2957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5082610f375750600161101d565b6001600160a01b03841660009081526003602052604081206001840191610f5d826121dc565b90506000610f6b838561221c565b90506000610f7f838363ffffffff61224b16565b905080881115610f975760009550505050505061101d565b82881115610faf57828803610fad8a828a6122e0565b505b8354610fc790600590878b600063ffffffff61241516565b6040805189815267ffffffffffffffff8716602082015281516001600160a01b038c16927f3b522789764bf3f50da1a4e79a6b330fd1ae121df88d89259fa73b55e1e9e360928290030190a26001955050505050505b9392505050565b61102c6120a8565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f44495350555445535f4d4f44554c450000815250906110c557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50801561110e576110da61dead8260016120f7565b6040805182815290517fef08526ce447c7a59448d28b89b25b9be13b2ae0293946c9cf27123c8e71a3769181900360200190a15b50565b6001600160a01b0381166000908152600360205260409020600481015460059091015467ffffffffffffffff16915091565b600090565b600080600080611157856124f4565b93509350935093509193509193565b600254604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156111ca57600080fd5b505afa1580156111de573d6000803e3d6000fd5b505050506040513d60208110156111f457600080fd5b5051905090565b6000610d8682612553565b336001600160a01b03841614801561122b57506002546001600160a01b038481169116145b6040518060400160405280601c81526020017f4a525f544f4b454e5f415050524f56455f4e4f545f414c4c4f57454400000000815250906112b057604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506112f385868685858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d9992505050565b5050505050565b60006113046125a3565b33600090815260036020526040812091925061131f826121dc565b90506000841561132f5784611331565b815b9050600081116040518060400160405280601681526020017f4a525f494e56414c49445f5a45524f5f414d4f554e5400000000000000000000815250906113bc57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060408051808201909152601e81527f4a525f494e56414c49445f444541435449564154494f4e5f414d4f554e54000060208201528282111561144357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b508082036000611452866125fb565b90508115806114615750808210155b6040518060400160405280601e81526020017f4a525f494e56414c49445f444541435449564154494f4e5f414d4f554e540000815250906114e657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506114f1338461268e565b50505050505050565b6001600160a01b038116600090815260036020526040812061101d81612761565b60006115256125a3565b9050610e8282826127a1565b6001600160a01b03166000908152600360208190526040909120015467ffffffffffffffff1690565b6115626120a8565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f44495350555445535f4d4f44554c450000815250906115fb57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506001600160a01b0391909116600090815260036020819052604090912001805467ffffffffffffffff191667ffffffffffffffff909216919091179055565b61110e338233612880565b60006116506120a8565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f44495350555445535f4d4f44554c450000815250906116e957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060408051808201909152601d81527f4a525f494e56414c49445f4c4f434b45445f414d4f554e54535f4c454e000000602082015286851461176f57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060408051808201909152601e81527f4a525f494e56414c49445f52455741524445445f4a55524f52535f4c454e000060208201528683146117f557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50600188016000805b8881101561194557600088888381811061181457fe5b90506020020135905060008b8b8481811061182b57fe5b602090810292909201356001600160a01b0316600081815260039093526040909220600181015492935091611861915084612c2e565b600182015588888581811061187257fe5b90506020020135156118c2576040805184815290516001600160a01b038416917f04205018e3978d4e9bf2627d251200b16b790aff8c89cccc4b6e4b226c6c0531919081900360200190a261193a565b6118d2858463ffffffff61224b16565b81549095506118ed906005908886600063ffffffff61241516565b6040805184815267ffffffffffffffff8816602082015281516001600160a01b038516927fb0f2cd2d530eb7a84b780655bd7cd315af71951aedf4ff554889d56cfc3c4ae9928290030190a25b5050506001016117fe565b509998505050505050505050565b6109d5338484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612cc092505050565b606060006119a06120a8565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f44495350555445535f4d4f44554c45000081525090611a3957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50611a4261455c565b6040805160e0818101909252611a709186906007908390839080828437600092019190915250612f99915050565b90508060800151604051908082528060200260200182016040528015611aa0578160200160208202803883390190505b50600060e083015292505b806080015182108015611ac25750600a8160e00151105b15611c6157606080611ad38361303b565b909250905060005b825181108015611aee5750836080015185105b15611c4e57600060046000858481518110611b0557fe5b60209081029190910181015182528181019290925260409081016000908120546001600160a01b0316808252600390935290812060c088015160018201549394509092611b579163ffffffff61224b16565b90506000611b6c83896040015160010161221c565b90506000868681518110611b7c57fe5b60200260200101519050828110611c3d576000611b9f828463ffffffff612c2e16565b905083811015611bba57611bba868286038c604001516122e0565b838560010181905550858c8c806001019d5081518110611bd657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050856001600160a01b03167fab9783755c502b2e2e2a8f5d7c88344973a1400de6c46334a7d60d70a17f64588b60c001516040518082815260200191505060405180910390a2505b505060019093019250611adb915050565b50505060e0810180516001019052611aab565b50915091565b60015490565b611c75613084565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f434f4e4649475f474f5645524e4f52000081525090611d0e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5061110e816130d3565b6000611d248383613199565b90505b92915050565b6001600160a01b031660009081526003602052604090205490565b6000611d5460056131da565b905090565b6002546001600160a01b031690565b54151590565b6000611d7d84600085856131f4565b949350505050565b600281015460018201546004909201549092565b60408051808201909152601681527f4a525f494e56414c49445f5a45524f5f414d4f554e5400000000000000000000602082015282611e1c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50611e29838360016120f7565b7fb260c42a00000000000000000000000000000000000000000000000000000000611e538261321f565b7fffffffff00000000000000000000000000000000000000000000000000000000161415611e8657611e86838386612880565b826001600160a01b03167fc65e53b88159e7d2c0fc12a0600072e28ae53ff73b4c1715369c30f16093514283611ebb8661206f565b846040518084815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611f05578181015183820152602001611eed565b50505050905090810190601f168015611f325780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a2600254611f5f906001600160a01b031685308563ffffffff61323b16565b6040518060400160405280601881526020017f4a525f544f4b454e5f5452414e534645525f4641494c45440000000000000000815250906112f357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905260009061206685826132cf565b95945050505050565b60008060008061207e856124f4565b935050925092506120668161209c858561224b90919063ffffffff16565b9063ffffffff61224b16565b60008060009054906101000a90046001600160a01b03166001600160a01b031663db9bee466040518163ffffffff1660e01b815260040160206040518083038186803b1580156111ca57600080fd5b81612101576109d5565b6001600160a01b0383166000908152600360205260409020811561213e576002810154612134908463ffffffff61224b16565b6002820155610a1c565b80600201548311156040518060400160405280601f81526020017f4a525f4e4f545f454e4f5547485f415641494c41424c455f42414c414e434500815250906121cb57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506002018054929092039091555050565b60006121e782611d68565b6121f2576000610d86565b60018201548254610d8691906122109060059063ffffffff61331a16565b9063ffffffff612c2e16565b6005820154600090600484019067ffffffffffffffff848116911614612243576000611d7d565b549392505050565b60408051808201909152601181527f4d4154485f4144445f4f564552464c4f57000000000000000000000000000000602082015260009083830190848210156122d857604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b509392505050565b6001600160a01b0383166000908152600360209081526040918290206004810180548451808601909552601f85527f4a525f43414e545f5245445543455f444541435449564154494f4e5f524551009385019390935290929091908582101561238d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5084810380835583546123b0906005906001808901908a9063ffffffff61241516565b60018301546040805167ffffffffffffffff92831681526020810184905291871682820152516001600160a01b038916917fc8eaece66ffd12e5066e2ef36d5943fa8fb8104362f92f75152c39788d85b184919081900360600190a250505050505050565b845460408051808201909152601b81527f53554d5f545245455f4b45595f444f45535f4e4f545f45584953540000000000602082015290851061249c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060006124a9868661331a565b90506000826124c7576124c2828563ffffffff612c2e16565b6124d7565b6124d7828563ffffffff61224b16565b90506124e7876000888885613328565b6114f18787878787613354565b6001600160a01b038116600090815260036020526040812081908190819061251b81611d68565b61252657600061253a565b805461253a9060059063ffffffff61331a16565b945061254581611d85565b969891975095945092505050565b60008061255e613476565b67ffffffffffffffff168367ffffffffffffffff1610159050806125925761258d60058463ffffffff6134b816565b61101d565b61101d60058463ffffffff6134d416565b60006125ad610d6c565b6001600160a01b0316633f33bf866040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156125e757600080fd5b505af11580156111de573d6000803e3d6000fd5b6000612605610d6c565b6001600160a01b03166395f3c2da836040518263ffffffff1660e01b8152600401808267ffffffffffffffff1667ffffffffffffffff16815260200191505060206040518083038186803b15801561265c57600080fd5b505afa158015612670573d6000803e3d6000fd5b505050506040513d602081101561268657600080fd5b505192915050565b60006126986125a3565b90506126a483826127a1565b6001600160a01b0383166000908152600360205260409020600481018054600184019291906126d9908663ffffffff61224b16565b815560018101805467ffffffffffffffff191667ffffffffffffffff8516179055815461270c9060059085886000612415565b6040805167ffffffffffffffff851681526020810187905281516001600160a01b038916927fe26ea88625a55cdd86472d3d0e9efd8dd884b5baa05b79bb95a3408df76cede9928290030190a2505050505050565b60008061276c613476565b905061277783611d68565b61278257600061101d565b6001830154835461101d9190612210906005908563ffffffff611d6e16565b6001600160a01b03821660009081526003602052604090206005810154600482019067ffffffffffffffff168015806127ed57508067ffffffffffffffff168467ffffffffffffffff16105b156127fa57505050610e82565b81546001808401805467ffffffffffffffff191690556000845561282190879083906120f7565b6040805167ffffffffffffffff80851682526020820184905287168183015290516001600160a01b038816917f8969a0b11c2c7f08ef80af31a680937503d444cdc933ba9091cdc20f098a7f36919081900360600190a2505050505050565b600061288a6125a3565b905061289684826127a1565b6001600160a01b0384166000908152600360205260408120600201549084156128bf57846128c1565b815b9050600081116040518060400160405280601681526020017f4a525f494e56414c49445f5a45524f5f414d4f554e54000000000000000000008152509061294c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060408051808201909152601c81527f4a525f494e56414c49445f41435449564154494f4e5f414d4f554e54000000006020820152828211156129d357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50600183016129e281836134f0565b6001600160a01b038716600090815260036020526040812090612a04836125fb565b9050612a0f82611d68565b15612ae4578154600090612a2b9060059063ffffffff61331a16565b905081612a3e828763ffffffff61224b16565b10156040518060400160405280601b81526020017f4a525f4143544956455f42414c414e43455f42454c4f575f4d494e000000000081525090612ac557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b508254612ade906005908688600163ffffffff61241516565b50612bc0565b60408051808201909152601b81527f4a525f4143544956455f42414c414e43455f42454c4f575f4d494e0000000000602082015281851015612b6a57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50612b7d6005848663ffffffff61359c16565b808355600090815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038b161790555b612bcc898560006120f7565b6040805167ffffffffffffffff85168152602081018690526001600160a01b03898116828401529151918b16917fee90556a99bb0d072721fedb6d8d458371d132b715762b023fba4d367fbd57b29181900360600190a2505050505050505050565b6000828211156040518060400160405280601281526020017f4d4154485f5355425f554e444552464c4f57000000000000000000000000000081525090612cb957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5050900390565b60408051808201909152601681527f4a525f494e56414c49445f5a45524f5f414d4f554e5400000000000000000000602082015282612d4357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506000612d4e613476565b6001600160a01b0385166000908152600360208190526040909120015490915067ffffffffffffffff16801580612d9857508167ffffffffffffffff168167ffffffffffffffff16105b6040518060400160405280601381526020017f4a525f5749544844524157414c535f4c4f434b0000000000000000000000000081525090612e1d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50612e2885836127a1565b612e34858560006120f7565b846001600160a01b03167faf01bfc8475df280aca00b578c4a948e6d95700f0db8c13365240f7f973c875485612e698861206f565b866040518084815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015612eb3578181015183820152602001612e9b565b50505050905090810190601f168015612ee05780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a2600254612f0c906001600160a01b0316868663ffffffff611fe416565b6040518060400160405280601881526020017f4a525f544f4b454e5f5452414e534645525f4641494c4544000000000000000081525090612f9157604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b505050505050565b612fa161455c565b60408201516000612fb1826125fb565b905060405180610100016040528085600060078110612fcc57fe5b602090810291909101518252868101519082015267ffffffffffffffff84166040820152606080870151908201526080808701519082015260a0808701519082015260c0016130298660066020020151849063ffffffff6135d416565b81526000602090910152949350505050565b60608061307a836000015184602001518560400151866060015187608001518860a001518960e0015160056135fc90979695949392919063ffffffff16565b9094909350915050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166397023f816040518163ffffffff1660e01b815260040160206040518083038186803b1580156111ca57600080fd5b60408051808201909152601d81527f4a525f4241445f544f54414c5f4143544956455f42414c5f4c494d495400000060208201528161315657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50600154604080519182526020820183905280517f9ce60e2304bd08c7c9e6da0e10912e44f85fd9e2ee71c1842132f12146c586c89281900390910190a1600155565b6001600160a01b03821660009081526003602052604081206131ba81611d68565b6131c5576000611d7d565b8054611d7d906005908563ffffffff611d6e16565b6000806131e68361375e565b905061101d8382600061376c565b600083815260028501602090815260408083208584529091528120612066908363ffffffff61379016565b600060048251101561323357506000610d89565b506020015190565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526000906132c586826132cf565b9695505050505050565b6000806040516020818551602087016000895af18015613310573d80156132fd57602081146133065761330e565b6001935061330e565b600183511493505b505b5090949350505050565b6000611d248360008461376c565b6000848152600286016020908152604080832086845290915290206112f390838363ffffffff61379c16565b6000198460006133638861375e565b905060015b8181116133ce5760049390931b929183169160006133878a838661376c565b90506000866133a5576133a0828963ffffffff612c2e16565b6133b5565b6133b5828963ffffffff61224b16565b90506133c48b84878c85613328565b5050600101613368565b508315806133e65750846133e389838561376c565b10155b6040518060400160405280601881526020017f53554d5f545245455f5550444154455f4f564552464c4f5700000000000000008152509061346b57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b505050505050505050565b6000613480610d6c565b6001600160a01b031663f7fe57896040518163ffffffff1660e01b815260040160206040518083038186803b1580156111ca57600080fd5b6000806134c58484613846565b9050611d7d84826000866131f4565b6000806134e18484613846565b9050611d7d848260008661385b565b60006134fb83612553565b9050600061350f828463ffffffff61224b16565b90506001548111156040518060400160405280602081526020017f4a525f544f54414c5f4143544956455f42414c414e43455f4558434545444544815250906112f357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b82546001810184556000906135b2858286613886565b8215611d7d576135c6856000838787613328565b611d7d858286866001613354565b60006127106135ed8461ffff851663ffffffff6138d716565b816135f457fe5b049392505050565b60608060008061360f8c8a8a8a8a61397a565b9150915060606136238c8c888b87876139e8565b90506136368d828c63ffffffff613be016565b8051825160408051808201909152601f81527f545245455f534f52544954494f4e5f4c454e475448535f4d49534d41544348006020820152939850919650146136c357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50878551146040518060400160405280601f81526020017f545245455f534f52544954494f4e5f4c454e475448535f4d49534d41544348008152509061374d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b505050509850989650505050505050565b6000610d8682600101613dfe565b600082815260028401602090815260408083208484529091528120611d7d90613dfe565b6000611d248383613e5f565b60408051808201909152601881527f434845434b504f494e545f56414c55455f544f4f5f4249470000000000000000602082015277ffffffffffffffffffffffffffffffffffffffffffffffff82111561383a57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506109d5838383614033565b6000611d24600184018363ffffffff6141ef16565b600083815260028501602090815260408083208584529091528120612066908363ffffffff6141ef16565b60006138918461375e565b905061389d81846141fb565b15610a1c576001810160006138b386848361376c565b90506138c3868360008785613328565b612f9160018701858463ffffffff61379c16565b6000826138e657506000611d27565b828202828482816138f357fe5b04146040518060400160405280601181526020017f4d4154485f4d554c5f4f564552464c4f57000000000000000000000000000000815250906122d857604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b6000808061398e888863ffffffff6134d416565b90506139b0846139a4888463ffffffff6138d716565b9063ffffffff61422116565b925060006139c4878763ffffffff61224b16565b90506139da856139a4838563ffffffff6138d716565b925050509550959350505050565b60608282116040518060400160405280601c81526020017f545245455f494e56414c49445f494e54455256414c5f5345415243480000000081525090613a7257604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060008383039050606085604051908082528060200260200182016040528015613aa6578160200160208202803883390190505b50905060005b86811015613bd3576040805160208082018d90528183018c9052606082018b905260808083018590528351808403909101815260a09092019092528051910120613b07848281613af857fe5b8991900663ffffffff61224b16565b838381518110613b1357fe5b6020908102919091010152815b600081118015613b585750836001820381518110613b3a57fe5b6020026020010151848281518110613b4e57fe5b6020026020010151105b15613bc9576000846001830381518110613b6e57fe5b60200260200101519050848281518110613b8457fe5b6020026020010151856001840381518110613b9b57fe5b60200260200101818152505080858381518110613bb457fe5b60209081029190910101525060001901613b20565b5050600101613aac565b5098975050505050505050565b60608060008451116040518060400160405280601e81526020017f53554d5f545245455f4d495353494e475f5345415243485f56414c554553000081525090613c6d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506000613c7a86856134d4565b9050600081118015613ca2575084600186510381518110613c9757fe5b602002602001015181115b6040518060400160405280601d81526020017f53554d5f545245455f5345415243485f4f55545f4f465f424f554e445300000081525090613d2757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b506000613d348786613846565b9050613d3e6145ae565b6040805160a0810190915267ffffffffffffffff8716815260208101613d6b84600163ffffffff612c2e16565b815260200160008152602001600081526020016000815250905060008751905080604051908082528060200260200182016040528015613db5578160200160208202803883390190505b50955080604051908082528060200260200182016040528015613de2578160200160208202803883390190505b509450613df289898489896142c0565b50505050935093915050565b80546000908015613e5657826000016001820381548110613e1b57fe5b60009182526020909120015468010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff169150610d899050565b50600092915050565b815460009080613e73576000915050611d27565b8354600019820190859082908110613e8757fe5b60009182526020909120015467ffffffffffffffff90811690851610613ef257846000018181548110613eb657fe5b60009182526020909120015468010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff169250611d27915050565b84600001600081548110613f0257fe5b60009182526020909120015467ffffffffffffffff9081169085161015613f2e57600092505050611d27565b6000815b81811115613fe757865460028383016001010490600090899083908110613f5557fe5b6000918252602090912001805490915067ffffffffffffffff908116908916811015613f8357829450613fdf565b8067ffffffffffffffff168967ffffffffffffffff161015613faa57600183039350613fdf565b505468010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff169550611d27945050505050565b505050613f32565b866000018281548110613ff657fe5b60009182526020909120015468010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff16979650505050505050565b82548015806140735750835467ffffffffffffffff8416908590600019810190811061405b57fe5b60009182526020909120015467ffffffffffffffff16105b156140fa576040805180820190915267ffffffffffffffff808516825277ffffffffffffffffffffffffffffffffffffffffffffffff80851660208085019182528854600181018a5560008a8152919091209451940180549151909216680100000000000000000293831667ffffffffffffffff1990911617909116919091179055610a1c565b600084600001600183038154811061410e57fe5b6000918252602091829020018054604080518082019091528381527f434845434b504f494e545f43414e4e4f545f4144445f504153545f56414c55459381019390935290925067ffffffffffffffff8681169116146141b157604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b50805477ffffffffffffffffffffffffffffffffffffffffffffffff8416680100000000000000000267ffffffffffffffff90911617905550505050565b6000611d248383614408565b60008061420f84600463ffffffff6138d716565b600019901b8316151591505092915050565b60008082116040518060400160405280600d81526020017f4d4154485f4449565f5a45524f00000000000000000000000000000000000000815250906142ab57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610b2b578181015183820152602001610b13565b5060008284816142b757fe5b04949350505050565b60208301516000906142d990600463ffffffff6138d716565b905060005b60108110156114f15785518560600151106142f8576114f1565b60408501516000906143129083851b63ffffffff61224b16565b9050600061432a898860200151848a6000015161385b565b9050600061434582896080015161224b90919063ffffffff16565b905060006143588a8a60600151846144d6565b905080156143f85760208901516143805761437b896060015182868b878c614514565b6143dd565b6143886145ae565b6040518060a001604052808b6000015167ffffffffffffffff16815260200160018c602001510381526020018681526020018b6060015181526020018b6080015181525090506143db8c8c838c8c6142c0565b505b60608901516143f2908263ffffffff61224b16565b60608a01525b50608088015250506001016142de565b81546000908061441c576000915050611d27565b835460001982019060009086908390811061443357fe5b9060005260206000200190505b60008211801561445d5750805467ffffffffffffffff8087169116115b156144885785546000199092019186908390811061447757fe5b906000526020600020019050614440565b805467ffffffffffffffff8087169116116144ca57805468010000000000000000900477ffffffffffffffffffffffffffffffffffffffffffffffff166132c5565b60009695505050505050565b6000825b8451811080156144fc5750828582815181106144f257fe5b6020026020010151105b15614509576001016144da565b929092039392505050565b60005b858110156114f15784848289018151811061452e57fe5b60200260200101818152505082828289018151811061454957fe5b6020908102919091010152600101614517565b6040518061010001604052806000801916815260200160008152602001600067ffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060a00160405280600067ffffffffffffffff168152602001600081526020016000815260200160008152602001600081525090565b6145fe60018281019060009063ffffffff61379c16565b6000905556fea165627a7a723058200f1569b86ba4df4896c73943c86f522b57715b54798a50aae9ef13dfef05753f0029

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

000000000000000000000000ee4650cbe7a2b23701d416f58b41d8b76b617797000000000000000000000000cd62b1c403fa761baadfc74c525ce2b51780b184000000000000000000000000000000008ac7230489e7feb210d3bd1429c00000

-----Decoded View---------------
Arg [0] : _controller (address): 0xee4650cBe7a2B23701D416f58b41D8B76b617797
Arg [1] : _jurorToken (address): 0xcD62b1C403fa761BAadFC74C525ce2B51780b184
Arg [2] : _totalActiveBalanceLimit (uint256): 184467440737095510000000000000000000000

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000ee4650cbe7a2b23701d416f58b41d8b76b617797
Arg [1] : 000000000000000000000000cd62b1c403fa761baadfc74c525ce2b51780b184
Arg [2] : 000000000000000000000000000000008ac7230489e7feb210d3bd1429c00000


Deployed Bytecode Sourcemap

157628:46042:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;157628:46042:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;182110:388;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;182110:388:0;;-1:-1:-1;;;;;182110:388:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;166943:128;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;166943:128:0;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;166943:128:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;166943:128: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;166943:128:0;;-1:-1:-1;166943:128:0;-1:-1:-1;166943:128:0;:::i;:::-;;167391:137;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;167391:137:0;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;167391:137:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;167391:137: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;167391:137:0;;-1:-1:-1;167391:137:0;-1:-1:-1;167391:137:0;:::i;157172:346::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;157172:346:0;;;;;;;;;;:::i;152258:96::-;;;:::i;:::-;;;;-1:-1:-1;;;;;152258:96:0;;;;;;;;;;;;;;180796:121;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;180796:121:0;-1:-1:-1;;;;;180796:121:0;;:::i;:::-;;;;;;;;;;;;;;;;169157:249;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;169157:249:0;;;;;;;;:::i;176522:1661::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;176522:1661:0;;-1:-1:-1;;;;;176522:1661:0;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;169541:227;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;169541:227:0;;:::i;183762:270::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;183762:270:0;-1:-1:-1;;;;;183762:270:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;185278:87;;;:::i;181374:182::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;181374:182:0;-1:-1:-1;;;;;181374:182:0;;:::i;179512:117::-;;;:::i;180108:134::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;180108:134:0;;;;:::i;168266:266::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;168266:266:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;168266:266:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;168266:266: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;168266:266:0;;-1:-1:-1;168266:266:0;-1:-1:-1;168266:266:0;:::i;165774:902::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;165774:902:0;;:::i;183275:201::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;183275:201:0;-1:-1:-1;;;;;183275:201:0;;:::i;168721:170::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;168721:170:0;-1:-1:-1;;;;;168721:170:0;;:::i;184255:152::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;184255:152:0;-1:-1:-1;;;;;184255:152:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;178539:197;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;178539:197:0;;-1:-1:-1;;;;;178539:197:0;;;;;;;;:::i;165436:111::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;165436:111:0;;:::i;174484:1388::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;174484:1388:0;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;174484:1388:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;174484:1388:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;174484:1388:0;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;174484:1388:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;174484:1388:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;174484:1388:0;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;174484:1388:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;174484:1388:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;174484:1388:0;;-1:-1:-1;174484:1388:0;-1:-1:-1;174484:1388:0;:::i;167771:120::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;167771:120:0;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;167771:120:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;167771:120: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;167771:120:0;;-1:-1:-1;167771:120:0;-1:-1:-1;167771:120:0;:::i;170447:3425::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;170447:3425:0;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;170447:3425:0;;;;;;;;;;;;;;;;;;185016:122;;;:::i;178919:170::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;178919:170:0;;:::i;182804:152::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;182804:152:0;;-1:-1:-1;;;;;182804:152:0;;;;;;;;:::i;184691:120::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;184691:120:0;-1:-1:-1;;;;;184691:120:0;;:::i;179762:103::-;;;:::i;179235:95::-;;;:::i;182110:388::-;-1:-1:-1;;;;;182313:23:0;;182195:14;182313:23;;;:15;:23;;;;;182195:14;;;;;;182358:19;182313:23;182358:12;:19::i;:::-;:59;;182416:1;182358:59;;;182395:8;;182380:33;;:4;;182405:7;182380:33;:14;:33;:::i;:::-;182349:68;;182471:19;182484:5;182471:12;:19::i;:::-;182110:388;;182428:62;;-1:-1:-1;182428:62:0;-1:-1:-1;182110:388:0;-1:-1:-1;;;;182110:388:0:o;166943:128::-;167017:46;167024:10;167036;167048:7;167057:5;;167017:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;167017:6:0;;-1:-1:-1;;;167017:46:0:i;:::-;166943:128;;;:::o;167391:137::-;167481:39;167488:10;167500:3;167505:7;167514:5;;167481:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;167481:6:0;;-1:-1:-1;;;167481:39:0:i;:::-;167391:137;;;;:::o;157172:346::-;156619:10;;;;;;;;;-1:-1:-1;;;;;156619:10:0;-1:-1:-1;;;;;156619:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;156619:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;156619:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;156619:29:0;156650:31;;;;;;;;;;;;;156619:29;156650:31;;;;-1:-1:-1;;;;;156605:43:0;:10;:43;156597:85;;;;-1:-1:-1;;;;;156597:85: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;156597:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;157277:31:0;;;;;;157302:4;157277:31;;;;;;157259:15;;-1:-1:-1;;;;;157277:16:0;;;;;:31;;;;;;;;;;;;;;;:16;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;157277:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;157277:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;157277:31:0;157340:32;;;;;;;;;;;;;157277:31;157340:32;;;157277:31;;-1:-1:-1;157327:11:0;157319:54;;;;-1:-1:-1;;;;;157319:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;157319:54:0;-1:-1:-1;157392:33:0;-1:-1:-1;;;;;157392:19:0;;157412:3;157417:7;157392:33;:19;:33;:::i;:::-;157427:32;;;;;;;;;;;;;;;;;157384:76;;;;;-1:-1:-1;;;;;157384:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;157384:76:0;-1:-1:-1;157476:34:0;;;-1:-1:-1;;;;;157476:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;156693:1;157172:346;;:::o;152258:96::-;152306:10;152336;-1:-1:-1;;;;;152336:10:0;152258:96;:::o;180796:121::-;180859:7;180886:23;180902:6;180886:15;:23::i;:::-;180879:30;;180796:121;;;;:::o;169157:249::-;151793:17;:15;:17::i;:::-;-1:-1:-1;;;;;151771:40:0;:10;-1:-1:-1;;;;;151771:40:0;;151813:32;;;;;;;;;;;;;;;;;151763:83;;;;;-1:-1:-1;;;;;151763:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;151763:83:0;-1:-1:-1;169255:11:0;;169251:148;;169283:48;169309:6;169317:7;169326:4;169283:25;:48::i;:::-;169351:36;;;;;;;;-1:-1:-1;;;;;169351:36:0;;;;;;;;;;;;;169251:148;169157:249;;:::o;176522:1661::-;176631:4;151793:17;:15;:17::i;:::-;-1:-1:-1;;;;;151771:40:0;:10;-1:-1:-1;;;;;151771:40:0;;151813:32;;;;;;;;;;;;;;;;;151763:83;;;;;-1:-1:-1;;;;;151763:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;151763:83:0;-1:-1:-1;176652:12:0;176648:56;;-1:-1:-1;176688:4:0;176681:11;;176648:56;-1:-1:-1;;;;;176780:23:0;;176716:17;176780:23;;;:15;:23;;;;;176746:1;176736:11;;;176846:35;176780:23;176846:28;:35::i;:::-;176814:67;;176892:41;176936:54;176972:5;176979:10;176936:35;:54::i;:::-;176892:98;-1:-1:-1;177179:34:0;177216:60;:21;176892:98;177216:60;:25;:60;:::i;:::-;177179:97;;177301:26;177291:7;:36;177287:81;;;177351:5;177344:12;;;;;;;;;177287:81;177774:21;177764:7;:31;177760:267;;;177910:31;;;177956:59;177983:6;177910:31;178007:7;177956:26;:59::i;:::-;177760:267;;178049:8;;178037:49;;:4;;178059:10;178071:7;178049:8;178037:49;:11;:49;:::i;:::-;178104;;;;;;;;;;;;;;;-1:-1:-1;;;;;178104:49:0;;;;;;;;;;;178171:4;178164:11;;;;;;;151857:1;176522:1661;;;;;:::o;169541:227::-;151793:17;:15;:17::i;:::-;-1:-1:-1;;;;;151771:40:0;:10;-1:-1:-1;;;;;151771:40:0;;151813:32;;;;;;;;;;;;;;;;;151763:83;;;;;-1:-1:-1;;;;;151763:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;151763:83:0;-1:-1:-1;169621:11:0;;169617:144;;169649:54;159383:42;169689:7;169698:4;169649:25;:54::i;:::-;169723:26;;;;;;;;;;;;;;;;;169617:144;169541:227;:::o;183762:270::-;-1:-1:-1;;;;;183922:23:0;;183833:14;183922:23;;;:15;:23;;;;;:43;;;183984:14;184000:23;;;;;;;183762:270;;;:::o;185278:87::-;185328:4;185278:87;:::o;181374:182::-;181432:14;181448:17;181467:14;181483:27;181530:18;181541:6;181530:10;:18::i;:::-;181523:25;;;;;;;;181374:182;;;;;:::o;179512:117::-;179585:11;;:36;;;;;;179615:4;179585:36;;;;;;179558:7;;-1:-1:-1;;;;;179585:11:0;;:21;;:36;;;;;;;;;;;;;;:11;:36;;;5:2:-1;;;;30:1;27;20:12;5:2;179585:36:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;179585:36:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;179585:36:0;;-1:-1:-1;179512:117:0;:::o;180108:134::-;180177:7;180204:30;180226:7;180204:21;:30::i;168266:266::-;168389:10;-1:-1:-1;;;;;168389:20:0;;;:54;;;;-1:-1:-1;168431:11:0;;-1:-1:-1;;;;;168413:30:0;;;168431:11;;168413:30;168389:54;168445:31;;;;;;;;;;;;;;;;;168381:96;;;;;-1:-1:-1;;;;;168381:96:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;168381:96:0;;168488:36;168495:5;168502;168509:7;168518:5;;168488:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;168488:6:0;;-1:-1:-1;;;168488:36:0:i;:::-;168266:266;;;;;:::o;165774:902::-;165831:13;165847:20;:18;:20::i;:::-;165916:10;165878:19;165900:27;;;:15;:27;;;;;165831:36;;-1:-1:-1;165970:35:0;165900:27;165970:28;:35::i;:::-;165938:67;-1:-1:-1;166016:26:0;166045:12;;:46;;166084:7;166045:46;;;166060:21;166045:46;166016:75;;166131:1;166110:18;:22;166134:25;;;;;;;;;;;;;;;;;166102:58;;;;;-1:-1:-1;;;;;166102:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;166102:58:0;-1:-1:-1;166224:33:0;;;;;;;;;;;;;;;;;166179:43;;;;166171:87;;;;-1:-1:-1;;;;;166171:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;166171:87:0;-1:-1:-1;166367:42:0;;;166337:27;166447:28;166468:6;166447:20;:28::i;:::-;166420:55;-1:-1:-1;166494:24:0;;;:67;;;166545:16;166522:19;:39;;166494:67;166563:33;;;;;;;;;;;;;;;;;166486:111;;;;;-1:-1:-1;;;;;166486:111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;166486:111:0;;166610:58;166637:10;166649:18;166610:26;:58::i;:::-;165774:902;;;;;;;:::o;183275:201::-;-1:-1:-1;;;;;183389:23:0;;183347:7;183389:23;;;:15;:23;;;;;183430:38;183389:23;183430:31;:38::i;168721:170::-;168793:13;168809:20;:18;:20::i;:::-;168793:36;;168840:43;168868:6;168876;168840:27;:43::i;184255:152::-;-1:-1:-1;;;;;184354:23:0;184328:6;184354:23;;;:15;:23;;;;;;;;:45;;;;;184255:152::o;178539:197::-;151793:17;:15;:17::i;:::-;-1:-1:-1;;;;;151771:40:0;:10;-1:-1:-1;;;;;151771:40:0;;151813:32;;;;;;;;;;;;;;;;;151763:83;;;;;-1:-1:-1;;;;;151763:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;151763:83:0;-1:-1:-1;;;;;;178657:23:0;;;;178635:19;178657:23;;;:15;:23;;;;;;;;178691:27;:37;;-1:-1:-1;;178691:37:0;;;;;;;;;;;178539:197::o;165436:111::-;165491:48;165507:10;165519:7;165528:10;165491:15;:48::i;174484:1388::-;174683:7;151793:17;:15;:17::i;:::-;-1:-1:-1;;;;;151771:40:0;:10;-1:-1:-1;;;;;151771:40:0;;151813:32;;;;;;;;;;;;;;;;;151763:83;;;;;-1:-1:-1;;;;;151763:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;151763:83:0;-1:-1:-1;174757:35:0;;;;;;;;;;;;;;;;;174716:39;;;174708:85;;;;-1:-1:-1;;;;;174708:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;174708:85:0;-1:-1:-1;174854:36:0;;;;;;;;;;;;;;;;;174812:40;;;174804:87;;;;-1:-1:-1;;;;;174804:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;174804:87:0;-1:-1:-1;174934:1:0;174924:11;;174904:17;;174982:848;175002:18;;;174982:848;;;175042:20;175065:14;;175080:1;175065:17;;;;;;;;;;;;;175042:40;;175097:20;175120:7;;175128:1;175120:10;;;;;;;;;;;;;;;;-1:-1:-1;;;;;175120:10:0;175145:19;175167:29;;;:15;:29;;;;;;;175233:19;;;;175120:10;;-1:-1:-1;175167:29:0;175233:37;;-1:-1:-1;175257:12:0;175233:23;:37::i;:::-;175211:19;;;:59;175470:15;;175486:1;175470:18;;;;;;;;;;;;;;175466:353;;175514:48;;;;;;;;-1:-1:-1;;;;;175514:48:0;;;;;;;;;;;;;175466:353;;;175621:33;:15;175641:12;175621:33;:19;:33;:::i;:::-;175685:8;;175603:51;;-1:-1:-1;175673:54:0;;:4;;175695:10;175707:12;175685:8;175673:54;:11;:54;:::i;:::-;175751:52;;;;;;;;;;;;;;;-1:-1:-1;;;;;175751:52:0;;;;;;;;;;;175466:353;-1:-1:-1;;;175022:3:0;;174982:848;;;-1:-1:-1;175849:15:0;174484:1388;-1:-1:-1;;;;;;;;;174484:1388:0:o;167771:120::-;167847:36;167856:10;167868:7;167877:5;;167847:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;167847:8:0;;-1:-1:-1;;;167847:36:0:i;170447:3425::-;170528:23;170553:14;151793:17;:15;:17::i;:::-;-1:-1:-1;;;;;151771:40:0;:10;-1:-1:-1;;;;;151771:40:0;;151813:32;;;;;;;;;;;;;;;;;151763:83;;;;;-1:-1:-1;;;;;151763:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;151763:83:0;;170580:30;;:::i;:::-;170613:26;;;;;;;;;;;;170631:7;;170613:26;;;;170631:7;;170613:26;170631:7;170613:26;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;170613:17:0;;-1:-1:-1;;170613:26:0:i;:::-;170580:59;;170673:11;:32;;;170659:47;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;170659:47:0;-1:-1:-1;171290:1:0;171266:21;;;:25;170650:56;-1:-1:-1;171261:2604:0;171316:11;:32;;;171307:6;:41;:89;;;;;159554:2;171352:11;:21;;;:44;171307:89;171261:2604;;;171463:25;171490:31;171525:24;171537:11;171525;:24::i;:::-;171462:87;;-1:-1:-1;171462:87:0;-1:-1:-1;171571:9:0;171566:2288;171590:8;:15;171586:1;:19;:64;;;;;171618:11;:32;;;171609:6;:41;171586:64;171566:2288;;;171800:20;171823:17;:30;171841:8;171850:1;171841:11;;;;;;;;;;;;;;;;;;;171823:30;;;;;;;;;;;;;-1:-1:-1;171823:30:0;;;;-1:-1:-1;;;;;171823:30:0;171894:29;;;:15;:29;;;;;;172102:27;;;;171823:30;172078:19;;;171823:30;;-1:-1:-1;171894:29:0;;172078:52;;;:23;:52;:::i;:::-;172051:79;;172386:41;172430:66;172466:5;172473:11;:18;;;172494:1;172473:22;172430:35;:66::i;:::-;172386:110;;172640:28;172671:14;172686:1;172671:17;;;;;;;;;;;;;;172640:48;;172735:16;172711:20;:40;172707:1132;;173141:29;173173:59;:20;173198:33;173173:59;:24;:59;:::i;:::-;173141:91;;173283:16;173259:21;:40;173255:281;;;173410:102;173437:12;173470:21;173451:16;:40;173493:11;:18;;;173410:26;:102::i;:::-;173660:16;173638:5;:19;;:38;;;;173718:12;173699:6;173706:8;;;;;;173699:16;;;;;;;;;;;;;:31;-1:-1:-1;;;;;173699:31:0;;;-1:-1:-1;;;;;173699:31:0;;;;;173777:12;-1:-1:-1;;;;;173758:61:0;;173791:11;:27;;;173758:61;;;;;;;;;;;;;;;;;;172707:1132;;-1:-1:-1;;171652:3:0;;;;;-1:-1:-1;171566:2288:0;;-1:-1:-1;;171566:2288:0;;-1:-1:-1;;;171412:21:0;;;:23;;;;;;171261:2604;;;151857:1;170447:3425;;;:::o;185016:122::-;185107:23;;185016:122;:::o;178919:170::-;151357:17;:15;:17::i;:::-;-1:-1:-1;;;;;151343:31:0;:10;-1:-1:-1;;;;;151343:31:0;;151376:32;;;;;;;;;;;;;;;;;151335:74;;;;;-1:-1:-1;;;;;151335:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;151335:74:0;;179028:53;179056:24;179028:27;:53::i;182804:152::-;182886:7;182913:35;182932:6;182940:7;182913:18;:35::i;:::-;182906:42;;182804:152;;;;;:::o;184691:120::-;-1:-1:-1;;;;;184777:23:0;184750:7;184777:23;;;:15;:23;;;;;:26;;184691:120::o;179762:103::-;179815:7;179842:15;:4;:13;:15::i;:::-;179835:22;;179762:103;:::o;179235:95::-;179310:11;;-1:-1:-1;;;;;179310:11:0;179235:95;:::o;198762:113::-;198853:9;:14;;;198762:113::o;30990:165::-;31079:7;31106:41;31116:4;21814:1;31135:4;31141:5;31106:9;:41::i;:::-;31099:48;30990:165;-1:-1:-1;;;;30990:165:0:o;201340:291::-;201494:23;;;;201537:20;;;;201590:26;;;;:33;201494:23;;201340:291::o;191458:740::-;191583:25;;;;;;;;;;;;;;;;;191570:11;191562:47;;;;-1:-1:-1;;;;;191562:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;191562:47:0;;191620:48;191646:6;191654:7;191663:4;191620:25;:48::i;:::-;191904:38;191884:16;:5;:14;:16::i;:::-;:58;;;191880:130;;;191959:39;191975:6;191983:7;191992:5;191959:15;:39::i;:::-;192034:6;-1:-1:-1;;;;;192027:55:0;;192042:7;192051:23;192067:6;192051:15;:23::i;:::-;192076:5;192027:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;192027:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;192101:11;;:59;;-1:-1:-1;;;;;192101:11:0;192130:5;192145:4;192152:7;192101:59;:28;:59;:::i;:::-;192162:27;;;;;;;;;;;;;;;;;192093:97;;;;;-1:-1:-1;;;;;192093:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;1908:320:0;2041:105;;;-1:-1:-1;;;;;2041:105:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;2041:105:0;;;;;;;;25:18:-1;;61:17;;2041:105:0;182:15:-1;2078:17:0;179:29:-1;160:49;;1992:4:0;;2164:56;2194:6;2041:105;2164:21;:56::i;:::-;2157:63;1908:320;-1:-1:-1;;;;;1908:320:0:o;195757:243::-;195821:7;195842:14;195858:17;195879:27;195910:18;195921:6;195910:10;:18::i;:::-;195841:87;;;;;;;195946:46;195972:19;195946:21;195960:6;195946:9;:13;;:21;;;;:::i;:::-;:25;:46;:25;:46;:::i;153652:140::-;153702:15;153753:10;;;;;;;;;-1:-1:-1;;;;;153753:10:0;-1:-1:-1;;;;;153753:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;194126:862:0;194529:12;194525:51;;194558:7;;194525:51;-1:-1:-1;;;;;194610:23:0;;194588:19;194610:23;;;:15;:23;;;;;194644:337;;;;194699:22;;;;:35;;194726:7;194699:35;:26;:35;:::i;:::-;194674:22;;;:60;194644:337;;;194786:5;:22;;;194775:7;:33;;194810:34;;;;;;;;;;;;;;;;;194767:78;;;;;-1:-1:-1;;;;;194767:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;194767:78:0;-1:-1:-1;194936:22:0;;:33;;;;;;;;;-1:-1:-1;;194126:862:0:o;197740:194::-;197823:7;197850:20;197863:6;197850:12;:20::i;:::-;:76;;197925:1;197850:76;;;197901:20;;;;197886:9;;197873:49;;197901:20;197873:23;;:4;;:23;:12;:23;:::i;:::-;:27;:49;:27;:49;:::i;199219:271::-;199427:23;;;;199325:7;;199383:26;;;;199427:34;;;;:23;;:34;:55;;199481:1;199427:55;;;199464:14;;199420:62;-1:-1:-1;;;199219:271:0:o;6665:175::-;6792:18;;;;;;;;;;;;;;;;;6725:7;;6757;;;;6783;;;;6775:36;;;;-1:-1:-1;;;;;6775:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;6775:36:0;-1:-1:-1;6831:1:0;6665:175;-1:-1:-1;;;6665:175:0:o;190300:766::-;-1:-1:-1;;;;;190427:23:0;;190405:19;190427:23;;;:15;:23;;;;;;;;;190499:25;;;190566:14;;190632:40;;;;;;;;;;;;;;;;;;;190427:23;;190499:25;;190566:14;190599:31;;;;190591:82;;;;-1:-1:-1;;;;;190591:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;190591:82:0;-1:-1:-1;190779:30:0;;;190820:33;;;190919:8;;190907:49;;:4;;190939:1;190929:11;;;;190802:7;;190907:49;:11;:49;:::i;:::-;191007:23;;;;190974:84;;;191007:23;;;;190974:84;;;;;;;;;;;;;;;;-1:-1:-1;;;;;190974:84:0;;;;;;;;;;;;;190300:766;;;;;;;:::o;26550:639::-;26680:12;;26694:24;;;;;;;;;;;;;;;;;;26673:19;;26665:54;;;;-1:-1:-1;;;;;26665:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;26665:54:0;;26813:17;26833:19;26841:4;26847;26833:7;:19::i;:::-;26813:39;;26863:16;26882:9;:57;;26918:21;:9;26932:6;26918:21;:13;:21;:::i;:::-;26882:57;;;26894:21;:9;26908:6;26894:21;:13;:21;:::i;:::-;26863:76;;26950:46;26955:4;21814:1;26974:4;26980:5;26987:8;26950:4;:46::i;:::-;27132:49;27144:4;27150;27156:5;27163:6;27171:9;27132:11;:49::i;196478:346::-;-1:-1:-1;;;;;196650:23:0;;196537:14;196650:23;;;:15;:23;;;;;196537:14;;;;;;196695:19;196650:23;196695:12;:19::i;:::-;:48;;196742:1;196695:48;;;196730:8;;196717:22;;:4;;:22;:12;:22;:::i;:::-;196686:57;;196797:19;196810:5;196797:12;:19::i;:::-;196478:346;;196754:62;;-1:-1:-1;196754:62:0;;-1:-1:-1;196478:346:0;-1:-1:-1;;;196478:346:0:o;199754:534::-;199824:7;200148:11;200173:23;:21;:23::i;:::-;200162:34;;:7;:34;;;;200148:48;;200214:6;:66;;200256:24;:4;200272:7;200256:24;:15;:24;:::i;:::-;200214:66;;;200223:30;:4;200245:7;200223:30;:21;:30;:::i;152544:110::-;152592:6;152618:8;:6;:8::i;:::-;-1:-1:-1;;;;;152618:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;152618:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;130220:147:0;130289:7;130316:14;:12;:14::i;:::-;-1:-1:-1;;;;;130316:34:0;;130351:7;130316:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;130316:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;130316:43:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;130316:43:0;;130220:147;-1:-1:-1;;130220:147:0:o;187799:666::-;187888:13;187904:20;:18;:20::i;:::-;187888:36;;188006:43;188034:6;188042;188006:27;:43::i;:::-;-1:-1:-1;;;;;188125:23:0;;188062:17;188125:23;;;:15;:23;;;;;188197:25;;;188250:14;;188091:1;188082:10;;;188125:23;188197:25;188250:27;;188269:7;188250:27;:18;:27;:::i;:::-;188233:44;;188288:23;;;:36;;-1:-1:-1;;188288:36:0;;;;;;;188347:8;;188335:49;;:4;;188288:36;188369:7;-1:-1:-1;188335:11:0;:49::i;:::-;188402:55;;;;;;;;;;;;;;;;-1:-1:-1;;;;;188402:55:0;;;;;;;;;;;187799:666;;;;;;:::o;198265:279::-;198351:7;198371:24;198398:23;:21;:23::i;:::-;198371:50;;198439:20;198452:6;198439:12;:20::i;:::-;:97;;198535:1;198439:97;;;198511:20;;;;198477:9;;198462:70;;198511:20;198462:44;;:4;;198488:17;198462:44;:14;:44;:::i;188847:1011::-;-1:-1:-1;;;;;188958:23:0;;188936:19;188958:23;;;:15;:23;;;;;189103;;;;189030:25;;;;189103:23;;189242:40;;;:81;;;189296:27;189286:37;;:7;:37;;;189242:81;189238:120;;;189340:7;;;;;189238:120;189399:14;;189606:23;;;;:35;;-1:-1:-1;;189606:35:0;;;189370:26;189652:18;;189681:59;;189707:6;;189399:14;;189681:25;:59::i;:::-;189758:92;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;189758:92:0;;;;;;;;;;;;;188847:1011;;;;;;:::o;185767:1679::-;185862:13;185878:20;:18;:20::i;:::-;185862:36;;185975:43;186003:6;186011;185975:27;:43::i;:::-;-1:-1:-1;;;;;186058:23:0;;186031:24;186058:23;;;:15;:23;;;;;:40;;;;186136:12;;:41;;186170:7;186136:41;;;186151:16;186136:41;186109:68;;186215:1;186196:16;:20;186218:25;;;;;;;;;;;;;;;;;186188:56;;;;;-1:-1:-1;;;;;186188:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;186188:56:0;-1:-1:-1;186301:31:0;;;;;;;;;;;;;;;;;186263:36;;;;186255:78;;;;-1:-1:-1;;;;;186255:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;186255:78:0;-1:-1:-1;186375:1:0;186366:10;;186387:54;186366:10;186424:16;186387:24;:54::i;:::-;-1:-1:-1;;;;;186474:23:0;;186452:19;186474:23;;;:15;:23;;;;;;186535:32;186556:10;186535:20;:32::i;:::-;186508:59;;186584:19;186597:5;186584:12;:19::i;:::-;186580:711;;;186859:8;;186822:21;;186846:22;;:4;;:22;:12;:22;:::i;:::-;186822:46;-1:-1:-1;186930:16:0;186891:35;186822:46;186909:16;186891:35;:17;:35;:::i;:::-;:55;;186948:30;;;;;;;;;;;;;;;;;186883:96;;;;;-1:-1:-1;;;;;186883:96:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;186883:96:0;-1:-1:-1;187006:8:0;;186994:57;;:4;;187016:10;187028:16;187046:4;186994:57;:11;:57;:::i;:::-;186580:711;;;;187130:30;;;;;;;;;;;;;;;;;187092:36;;;;187084:77;;;;-1:-1:-1;;;;;187084:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;187084:77:0;-1:-1:-1;187187:41:0;:4;187199:10;187211:16;187187:41;:11;:41;:::i;:::-;187176:52;;;:8;187243:27;;;:17;:27;;;;;:36;;;;-1:-1:-1;;;;;187243:36:0;;;;;186580:711;187303:58;187329:6;187337:16;187355:5;187303:25;:58::i;:::-;187377:61;;;;;;;;;;;;;;-1:-1:-1;;;;;187377:61:0;;;;;;;;;;;;;;;;;;;;;;185767:1679;;;;;;;;;:::o;6412:177::-;6472:7;6506:2;6500;:8;;6510:19;;;;;;;;;;;;;;;;;6492:38;;;;;-1:-1:-1;;;;;6492:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;6492:38:0;-1:-1:-1;;6553:7:0;;;6412:177::o;192497:1251::-;192609:25;;;;;;;;;;;;;;;;;192596:11;192588:47;;;;-1:-1:-1;;;;;192588:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;192588:47:0;;193136:24;193163:23;:21;:23::i;:::-;-1:-1:-1;;;;;193288:23:0;;193257:28;193288:23;;;:15;:23;;;;;;;;:45;;193136:50;;-1:-1:-1;193288:45:0;;193352:26;;;:71;;;193406:17;193382:41;;:21;:41;;;193352:71;193425:22;;;;;;;;;;;;;;;;;193344:104;;;;;-1:-1:-1;;;;;193344:104:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;193344:104:0;;193461:54;193489:6;193497:17;193461:27;:54::i;:::-;193528:49;193554:6;193562:7;193571:5;193528:25;:49::i;:::-;193602:6;-1:-1:-1;;;;;193593:57:0;;193610:7;193619:23;193635:6;193619:15;:23::i;:::-;193644:5;193593:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;193593:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;193669:11;;:41;;-1:-1:-1;;;;;193669:11:0;193694:6;193702:7;193669:41;:24;:41;:::i;:::-;193712:27;;;;;;;;;;;;;;;;;193661:79;;;;;-1:-1:-1;;;;;193661:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;193661:79:0;;192497:1251;;;;;:::o;203059:608::-;203135:18;;:::i;:::-;203189:10;;;;203166:13;203238:28;203189:10;203238:20;:28::i;:::-;203211:55;;203286:373;;;;;;;;203337:7;203345:1;203337:10;;;;;;;;;;;;;;;;203286:373;;203374:10;;;;203286:373;;;;;;;;;;;;203444:10;;;;203286:373;;;;;203491:10;;;;203286:373;;;;;203538:10;;;;203286:373;;;;;;203580:40;203374:10;203616:1;203608:10;;;;203580:16;;:40;:20;:40;:::i;:::-;203286:373;;203646:1;203286:373;;;;;203279:380;203059:608;-1:-1:-1;;;;203059:608:0:o;202004:458::-;202076:20;202098:31;202166:288;202205:7;:22;;;202242:7;:17;;;202274:7;:14;;;202303:7;:22;;;202340:7;:28;;;202383:7;:28;;;202426:7;:17;;;202166:4;:24;;:288;;;;;;;;;;:::i;:::-;202142:312;;;;-1:-1:-1;202004:458:0;-1:-1:-1;;202004:458:0:o;153360:115::-;153410:7;153437:10;;;;;;;;;-1:-1:-1;;;;;153437:10:0;-1:-1:-1;;;;;153437:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;195189:332:0;195318:36;;;;;;;;;;;;;;;;;195288:28;195280:75;;;;-1:-1:-1;;;;;195280:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;195280:75:0;-1:-1:-1;195402:23:0;;195371:81;;;;;;;;;;;;;;;;;;;;;;;;195463:23;:50;195189:332::o;197130:233::-;-1:-1:-1;;;;;197255:23:0;;197213:7;197255:23;;;:15;:23;;;;;197296:19;197255:23;197296:12;:19::i;:::-;:59;;197354:1;197296:59;;;197333:8;;197318:33;;:4;;197343:7;197318:33;:14;:33;:::i;29129:175::-;29189:7;29209:17;29229:15;29239:4;29229:9;:15::i;:::-;29209:35;;29262:34;29270:4;29276:9;22162:1;29262:7;:34::i;31898:175::-;32003:7;32030:18;;;:10;;;:18;;;;;;;;:24;;;;;;;;:35;;32059:5;32030:35;:28;:35;:::i;10816:217::-;10877:13;10922:1;10907:5;:12;:16;10903:65;;;-1:-1:-1;10954:1:0;10940:16;;10903:65;-1:-1:-1;11018:4:0;11007:16;11001:23;;10989:37::o;2416:378::-;2572:136;;;-1:-1:-1;;;;;2572:136:0;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;2572:136:0;;;;;;;;25:18:-1;;61:17;;2572:136:0;182:15:-1;2609:28:0;179:29:-1;160:49;;2519:4:0;;2726:60;2609:6;2572:136;2726:21;:60::i;:::-;2719:67;2416:378;-1:-1:-1;;;;;;2416:378:0:o;3318:1346::-;3405:4;3422:8;3482:4;3476:11;3913:4;3841:3;3789:9;3783:16;3741:4;3730:9;3726:20;3675:1;3625:5;3567:3;3544:423;3986:14;;3983:2;;4098:14;4186:57;;;;4325:4;4320:189;;;;4091:519;;4186:57;4223:1;4216:8;;4186:57;;4320:189;4488:1;4482:3;4476:10;4473:17;4466:24;;4091:519;;3983:2;-1:-1:-1;4653:3:0;;3318:1346;-1:-1:-1;;;;3318:1346:0:o;30558:140::-;30631:7;30658:32;30666:4;21814:1;30685:4;30658:7;:32::i;37132:163::-;37244:18;;;;:10;;;:18;;;;;;;;:24;;;;;;;;:43;;37273:5;37280:6;37244:43;:28;:43;:::i;33698:1952::-;-1:-1:-1;;33876:4:0;33817:12;33915:15;33925:4;33915:9;:15::i;:::-;33891:39;-1:-1:-1;33976:1:0;33941:1419;33988:13;33979:5;:22;33941:1419;;21626:1;34554:22;;;;;35078:18;;;;35142:17;35162:33;35170:4;35176:5;35078:18;35162:7;:33::i;:::-;35142:53;;35210:16;35229:9;:57;;35265:21;:9;35279:6;35265:21;:13;:21;:::i;:::-;35229:57;;;35241:21;:9;35255:6;35241:21;:13;:21;:::i;:::-;35210:76;;35301:47;35306:4;35312:5;35319:11;35332:5;35339:8;35301:4;:47::i;:::-;-1:-1:-1;;34003:7:0;;33941:1419;;;;35554:9;35553:10;:65;;;;35612:6;35567:41;35575:4;35581:13;35596:11;35567:7;:41::i;:::-;:51;;35553:65;35620:21;;;;;;;;;;;;;;;;;35545:97;;;;;-1:-1:-1;;;;;35545:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;35545:97:0;;33698:1952;;;;;;;;:::o;152818:121::-;152874:6;152900:8;:6;:8::i;:::-;-1:-1:-1;;;;;152900:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;29645:215:0;29721:7;29741:17;29761:30;29779:4;29785:5;29761:17;:30::i;:::-;29741:50;;29809:43;29819:4;29825:9;22162:1;29846:5;29809:9;:43::i;30176:227::-;30258:7;30278:17;30298:30;30316:4;30322:5;30298:17;:30::i;:::-;30278:50;;30346:49;30362:4;30368:9;22162:1;30389:5;30346:15;:49::i;200556:352::-;200648:33;200684:30;200706:7;200684:21;:30::i;:::-;200648:66;-1:-1:-1;200725:29:0;200757:38;200648:66;200787:7;200757:38;:29;:38;:::i;:::-;200725:70;;200839:23;;200814:21;:48;;200864:35;;;;;;;;;;;;;;;;;200806:94;;;;;-1:-1:-1;;;;;200806:94:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;24347:779:0;24666:14;;;;;;;24430:7;;24691:38;24666:4;:14;24723:5;24691:20;:38::i;:::-;24958:10;;24954:144;;24985:43;24990:4;21814:1;25009:3;25014:5;25021:6;24985:4;:43::i;:::-;25043;25055:4;25061:3;25066:5;25073:6;25081:4;25043:11;:43::i;45263:132::-;45326:7;45120:5;45353:23;:4;45362:13;;;45353:23;:8;:23;:::i;:::-;:34;;;;;;;45263:132;-1:-1:-1;;;45263:132:0:o;47140:1083::-;47505:26;47533:31;47583:11;47596:12;47612:98;47633:4;47639:7;47648:15;47665:21;47688;47612:20;:98::i;:::-;47582:128;;;;47721:25;47749:201;47792:15;47822:10;47847:19;47881:21;47917:3;47935:4;47749:28;:201::i;:::-;47721:229;-1:-1:-1;47993:30:0;:4;47721:229;48015:7;47993:30;:11;:30;:::i;:::-;48064:21;;48044:16;;48087:32;;;;;;;;;;;;;;;;;47963:60;;-1:-1:-1;47963:60:0;;-1:-1:-1;48044:41:0;48036:84;;;;-1:-1:-1;;;;;48036:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;48036:84:0;;48159:21;48139:9;:16;:41;48182:32;;;;;;;;;;;;;;;;;48131:84;;;;;-1:-1:-1;;;;;48131:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;48131:84:0;;47140:1083;;;;;;;;;;;;;;:::o;32708:117::-;32769:7;32796:21;:4;:11;;:19;:21::i;31379:158::-;31468:7;31495:18;;;:10;;;:18;;;;;;;;:24;;;;;;;;:34;;:32;:34::i;13731:133::-;13803:7;13830:26;13844:4;13850:5;13830:13;:26::i;12622:192::-;12738:19;;;;;;;;;;;;;;;;;11267:20;12715:21;;;12707:51;;;;-1:-1:-1;;;;;12707:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;12707:51:0;;12769:37;12777:4;12783:5;12798:6;12769:7;:37::i;33040:146::-;33123:7;33150:28;:11;;;33172:5;33150:28;:21;:28;:::i;32456:187::-;32567:7;32594:18;;;:10;;;:18;;;;;;;;:24;;;;;;;;:41;;32629:5;32594:41;:34;:41;:::i;35909:758::-;36008:21;36032:15;36042:4;36032:9;:15::i;:::-;36008:39;;36062;36078:13;36093:7;36062:15;:39::i;:::-;36058:602;;;36462:1;36446:17;;36426;36498:38;36506:4;36446:13;36426:17;36498:7;:38::i;:::-;36478:58;;36551:49;36556:4;36562:9;22162:1;36583:5;36590:9;36551:4;:49::i;:::-;36615:33;:11;;;36631:5;36638:9;36615:33;:15;:33;:::i;5384:460::-;5444:7;5688;5684:48;;-1:-1:-1;5719:1:0;5712:8;;5684:48;5756:7;;;5761:2;5756;:7;:2;5782:6;;;;;:12;5796:18;;;;;;;;;;;;;;;;;5774:41;;;;;-1:-1:-1;;;;;5774:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;48932:627:0;49197:11;;;49269:30;:4;49291:7;49269:30;:21;:30;:::i;:::-;49240:59;-1:-1:-1;49316:66:0;49360:21;49316:39;:15;49240:59;49316:39;:19;:39;:::i;:::-;:43;:66;:43;:66;:::i;:::-;49310:72;-1:-1:-1;49395:25:0;49423:42;:15;49443:21;49423:42;:19;:42;:::i;:::-;49395:70;-1:-1:-1;49483:68:0;49529:21;49483:41;49395:70;49505:18;49483:41;:21;:41;:::i;:68::-;49476:75;;48932:627;;;;;;;;;;:::o;50411:2144::-;50714:16;51032:14;51014:15;:32;51048:29;;;;;;;;;;;;;;;;;51006:72;;;;;-1:-1:-1;;;;;51006:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;51006:72:0;;51089:16;51126:14;51108:15;:32;51089:51;;51248:25;51290:21;51276:36;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;51276:36:0;-1:-1:-1;51248:64:0;-1:-1:-1;51328:24:0;51323:1199;51377:21;51358:16;:40;51323:1199;;;51849:84;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;51849:84:0;;;;;;;51839:95;;;;;52157:44;52192:8;51839:95;52192:8;52176:24;;;;52157:14;;52176:24;;52157:44;:18;:44;:::i;:::-;52128:8;52137:16;52128:26;;;;;;;;;;;;;;;;;:73;52300:16;52283:228;52322:1;52318;:5;:38;;;;;52341:8;52354:1;52350;:5;52341:15;;;;;;;;;;;;;;52327:8;52336:1;52327:11;;;;;;;;;;;;;;:29;52318:38;52283:228;;;52382:11;52396:8;52409:1;52405;:5;52396:15;;;;;;;;;;;;;;52382:29;;52448:8;52457:1;52448:11;;;;;;;;;;;;;;52430:8;52443:1;52439;:5;52430:15;;;;;;;;;;;;;:29;;;;;52492:3;52478:8;52487:1;52478:11;;;;;;;;;;;;;;;;;:17;-1:-1:-1;;;52358:3:0;52283:228;;;-1:-1:-1;;51400:18:0;;51323:1199;;;-1:-1:-1;52539:8:0;50411:2144;-1:-1:-1;;;;;;;;50411:2144:0:o;27875:1119::-;27982:21;28005:23;28071:1;28054:7;:14;:18;28074:27;;;;;;;;;;;;;;;;;28046:56;;;;;-1:-1:-1;;;;;28046:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;28046:56:0;;28249:13;28265:29;28282:4;28288:5;28265:16;:29::i;:::-;28249:45;;28396:1;28388:5;:9;:48;;;;;28409:7;28434:1;28417:7;:14;:18;28409:27;;;;;;;;;;;;;;28401:5;:35;28388:48;28438:26;;;;;;;;;;;;;;;;;28380:85;;;;;-1:-1:-1;;;;;28380:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;28380:85:0;;28534:17;28554:30;28572:4;28578:5;28554:17;:30::i;:::-;28534:50;;28595:32;;:::i;:::-;28630:53;;;;;;;;;;;;;;;;;28650:16;:9;28664:1;28650:16;:13;:16;:::i;:::-;28630:53;;;;22162:1;28630:53;;;;28678:1;28630:53;;;;28681:1;28630:53;;;28595:88;;28814:14;28831:7;:14;28814:31;;28877:6;28863:21;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;28863:21:0;;28856:28;;28918:6;28904:21;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;28904:21:0;;28895:30;;28936:50;28944:4;28950:7;28959:12;28973:4;28979:6;28936:7;:50::i;:::-;27875:1119;;;;;;;;;;:::o;13003:246::-;13102:19;;13065:7;;13136:10;;13132:89;;13178:4;:12;;13200:1;13191:6;:10;13178:24;;;;;;;;;;;;;;;;;:30;;;;;;;-1:-1:-1;13163:46:0;;-1:-1:-1;13163:46:0;13132:89;-1:-1:-1;13240:1:0;;13003:246;-1:-1:-1;;13003:246:0:o;17648:1576::-;17852:19;;17729:7;;17886:11;17882:52;;17921:1;17914:8;;;;;17882:52;18116:23;;-1:-1:-1;;18082:10:0;;;18116:4;;18082:10;;18116:23;;;;;;;;;;;;;;;:28;;;;;18107:37;;;;18103:115;;18176:4;:12;;18189:9;18176:23;;;;;;;;;;;;;;;;;:29;;;;;;;-1:-1:-1;18161:45:0;;-1:-1:-1;;18161:45:0;18103:115;18360:4;:12;;18373:1;18360:15;;;;;;;;;;;;;;;;;:20;;;;;18352:28;;;;18348:69;;;18404:1;18397:8;;;;;;18348:69;18511:11;18552:9;18574:591;18588:3;18581:4;:10;18574:591;;;18776:17;;18728:1;18710:10;;;18723:1;18710:14;18709:20;;18695:11;;18776:4;;18709:20;;18776:17;;;;;;;;;;;;;;;18825:15;;18776:17;;-1:-1:-1;18825:15:0;;;;;18861;;;-1:-1:-1;18857:297:0;;;18903:3;18897:9;;18857:297;;;18940:7;18932:15;;:5;:15;;;18928:226;;;19064:1;19058:3;:7;19051:14;;18928:226;;;-1:-1:-1;19121:16:0;;;;;;;-1:-1:-1;19106:32:0;;-1:-1:-1;;;;;19106:32:0;18928:226;18574:591;;;;;;19192:4;:12;;19205:3;19192:17;;;;;;;;;;;;;;;;;:23;;;;;;;17648:1576;-1:-1:-1;;;;;;;17648:1576:0:o;14965:906::-;15070:19;;15104:11;;;:65;;-1:-1:-1;15132:19:0;;15119:50;;;;:4;;-1:-1:-1;;15132:23:0;;;15119:37;;;;;;;;;;;;;;;:42;;;:50;15104:65;15100:764;;;15376:25;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;39:1;23:18;;45:23;;15358:12:0;:44;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;15358:44:0;;;;;;;;;;;;;15100:764;;;15658:36;15697:4;:12;;15719:1;15710:6;:10;15697:24;;;;;;;;;;;;;;;;;;15753:22;;15777:27;;;;;;;;;;;;;;;;;;;;15697:24;;-1:-1:-1;15753:22:0;15744:31;;;15753:22;;15744:31;15736:69;;;;-1:-1:-1;;;;;15736:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;15736:69:0;-1:-1:-1;15820:32:0;;;;;;;;;;;;;;14965:906;;;;:::o;14310:148::-;14388:7;14415:35;14438:4;14444:5;14415:22;:35::i;42254:815::-;42342:4;;42828:34;:14;21626:1;42828:34;:18;:34;:::i;:::-;-1:-1:-1;;42888:20:0;;43041:14;;43040:21;;;-1:-1:-1;;42254:815:0;;;;:::o;5967:319::-;6027:7;6060:1;6055:2;:6;6063:14;;;;;;;;;;;;;;;;;6047:31;;;;;-1:-1:-1;;;;;6047:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;6047:31:0;;6147:9;6164:2;6159;:7;;;;;;;5967:319;-1:-1:-1;;;;5967:319:0:o;38346:3467::-;38638:13;;;;38598:37;;38638:33;;21626:1;38638:33;:17;:33;:::i;:::-;38598:73;-1:-1:-1;38689:19:0;38684:3122;21575:2;38714:11;:22;38684:3122;;;38852:7;:14;38829:7;:19;;;:37;38825:83;;38887:5;;38825:83;39797:17;;;;39774:20;;39797:67;;39819:44;;;39797:67;:21;:67;:::i;:::-;39774:90;;39879:22;39904:64;39920:4;39926:7;:13;;;39941:12;39955:7;:12;;;39904:15;:64::i;:::-;39879:89;;40207:23;40233:40;40258:14;40233:7;:20;;;:24;;:40;;;;:::i;:::-;40207:66;;40288:29;40320:74;40348:7;40357;:19;;;40378:15;40320:27;:74::i;:::-;40288:106;-1:-1:-1;40510:25:0;;40506:1163;;40779:13;;;;40775:720;;40832:116;40847:7;:19;;;40868:21;40891:12;40905:11;40918:14;40934:13;40832:14;:116::i;:::-;40775:720;;;40997:35;;:::i;:::-;41035:350;;;;;;;;41074:7;:12;;;41035:350;;;;;;41129:1;41113:7;:13;;;:17;41035:350;;;;41257:12;41035:350;;;;41296:7;:19;;;41035:350;;;;41342:7;:20;;;41035:350;;;40997:388;;41408:67;41416:4;41422:7;41431:15;41448:11;41461:13;41408:7;:67::i;:::-;40775:720;;41607:19;;;;:46;;41631:21;41607:46;:23;:46;:::i;:::-;41585:19;;;:68;40506:1163;-1:-1:-1;41756:20:0;;;:38;-1:-1:-1;;38738:13:0;;38684:3122;;16476:614;16689:19;;16566:7;;16723:11;16719:52;;16758:1;16751:8;;;;;16719:52;16852:19;;-1:-1:-1;;16799:10:0;;;16783:13;;16852:4;;16799:10;;16852:19;;;;;;;;;;;;;16820:51;;16882:126;16897:1;16889:5;:9;:36;;;;-1:-1:-1;16902:15:0;;:23;;;;:15;;:23;16889:36;16882:126;;;16977:19;;-1:-1:-1;;16942:7:0;;;;16977:4;;16942:7;;16977:19;;;;;;;;;;;;;16964:32;;16882:126;;;17027:15;;:23;;;;:15;;:23;:55;;17065:16;;;;;;;17027:55;;;17053:1;17020:62;16476:614;-1:-1:-1;;;;;;16476:614:0:o;43530:388::-;43660:7;43767:12;43790:87;43801:7;:14;43797:1;:18;:48;;;;;43832:13;43819:7;43827:1;43819:10;;;;;;;;;;;;;;:26;43797:48;43790:87;;;43862:3;;43790:87;;;43894:16;;;;;43530:388;-1:-1:-1;;;43530:388:0:o;44540:403::-;44800:9;44795:141;44819:6;44815:1;:10;44795:141;;;44872:4;44847:11;44867:1;44859:5;:9;44847:22;;;;;;;;;;;;;:29;;;;;44918:6;44891:13;44913:1;44905:5;:9;44891:24;;;;;;;;;;;;;;;;;:33;44827:3;;44795:141;;157628:46042;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;23915:156::-;23968:61;24027:1;23968:11;;;;22327:1;;23968:61;:15;:61;:::i;:::-;22162:1;24040:23;;23915:156::o

Swarm Source

bzzr://0f1569b86ba4df4896c73943c86f522b57715b54798a50aae9ef13dfef05753f

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

OVERVIEW

Aragon Court handles subjective disputes that require the judgment of human jurors. These jurors stake a token called ANJ which allows them to be drafted into juries and earn fees for successfully adjudicating disputes.

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ 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.