Overview
POL Balance
0 POL
POL Value
$0.00More Info
Private Name Tags
ContractCreator
Sponsored
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 21936389 | 1019 days ago | IN | 0 POL | 0.16160106 |
Loading...
Loading
Contract Name:
DisputeManager
Compiler Version
v0.5.8+commit.23d335f2
Contract Source Code (Solidity)
/** *Submitted for verification at polygonscan.com on 2021-11-29 */ // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/lib/token/ERC20.sol // Adapted to use pragma ^0.5.8 and satisfy our linter rules pragma solidity ^0.5.8; /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ contract ERC20 { function totalSupply() public view returns (uint256); function balanceOf(address _who) public view returns (uint256); function allowance(address _owner, address _spender) public view returns (uint256); function transfer(address _to, uint256 _value) public returns (bool); function approve(address _spender, uint256 _value) public returns (bool); function transferFrom(address _from, address _to, uint256 _value) public returns (bool); event Transfer( address indexed from, address indexed to, uint256 value ); event Approval( address indexed owner, address indexed spender, uint256 value ); } // File: contracts/lib/os/SafeERC20.sol // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/SafeERC20.sol // Adapted to use pragma ^0.5.8 and satisfy our linter rules pragma solidity ^0.5.8; library SafeERC20 { // Before 0.5, solidity has a mismatch between `address.transfer()` and `token.transfer()`: // https://github.com/ethereum/solidity/issues/3544 bytes4 private constant TRANSFER_SELECTOR = 0xa9059cbb; /** * @dev Same as a standards-compliant ERC20.transfer() that never reverts (returns false). * Note that this makes an external call to the token. */ function safeTransfer(ERC20 _token, address _to, uint256 _amount) internal returns (bool) { bytes memory transferCallData = abi.encodeWithSelector( TRANSFER_SELECTOR, _to, _amount ); return invokeAndCheckSuccess(address(_token), transferCallData); } /** * @dev Same as a standards-compliant ERC20.transferFrom() that never reverts (returns false). * Note that this makes an external call to the token. */ function safeTransferFrom(ERC20 _token, address _from, address _to, uint256 _amount) internal returns (bool) { bytes memory transferFromCallData = abi.encodeWithSelector( _token.transferFrom.selector, _from, _to, _amount ); return invokeAndCheckSuccess(address(_token), transferFromCallData); } /** * @dev Same as a standards-compliant ERC20.approve() that never reverts (returns false). * Note that this makes an external call to the token. */ function safeApprove(ERC20 _token, address _spender, uint256 _amount) internal returns (bool) { bytes memory approveCallData = abi.encodeWithSelector( _token.approve.selector, _spender, _amount ); return invokeAndCheckSuccess(address(_token), approveCallData); } function invokeAndCheckSuccess(address _addr, bytes memory _calldata) private returns (bool) { bool ret; assembly { let ptr := mload(0x40) // free memory pointer let success := call( gas, // forward all gas _addr, // address 0, // no value add(_calldata, 0x20), // calldata start mload(_calldata), // calldata length ptr, // write output over free memory 0x20 // uint256 return ) if gt(success, 0) { // Check number of bytes returned from last function call switch returndatasize // No bytes returned: assume success case 0 { ret := 1 } // 32 bytes returned: check if non-zero case 0x20 { // Only return success if returned data was true // Already have output in ptr ret := eq(mload(ptr), 1) } // Not sure what was returned: don't mark as success default { } } } return ret; } } // File: contracts/lib/os/SafeMath.sol // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/lib/math/SafeMath.sol // Adapted to use pragma ^0.5.8 and satisfy our linter rules pragma solidity >=0.4.24 <0.6.0; /** * @title SafeMath * @dev Math operations with safety checks that revert on error */ library SafeMath { string private constant ERROR_ADD_OVERFLOW = "MATH_ADD_OVERFLOW"; string private constant ERROR_SUB_UNDERFLOW = "MATH_SUB_UNDERFLOW"; string private constant ERROR_MUL_OVERFLOW = "MATH_MUL_OVERFLOW"; string private constant ERROR_DIV_ZERO = "MATH_DIV_ZERO"; /** * @dev Multiplies two numbers, reverts on overflow. */ function mul(uint256 _a, uint256 _b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (_a == 0) { return 0; } uint256 c = _a * _b; require(c / _a == _b, ERROR_MUL_OVERFLOW); return c; } /** * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. */ function div(uint256 _a, uint256 _b) internal pure returns (uint256) { require(_b > 0, ERROR_DIV_ZERO); // Solidity only automatically asserts when dividing by 0 uint256 c = _a / _b; // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold return c; } /** * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 _a, uint256 _b) internal pure returns (uint256) { require(_b <= _a, ERROR_SUB_UNDERFLOW); uint256 c = _a - _b; return c; } /** * @dev Adds two numbers, reverts on overflow. */ function add(uint256 _a, uint256 _b) internal pure returns (uint256) { uint256 c = _a + _b; require(c >= _a, ERROR_ADD_OVERFLOW); return c; } /** * @dev Divides two numbers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, ERROR_DIV_ZERO); return a % b; } } // File: contracts/lib/os/SafeMath64.sol // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/lib/math/SafeMath64.sol // Adapted to use pragma ^0.5.8 and satisfy our linter rules pragma solidity ^0.5.8; /** * @title SafeMath64 * @dev Math operations for uint64 with safety checks that revert on error */ library SafeMath64 { string private constant ERROR_ADD_OVERFLOW = "MATH64_ADD_OVERFLOW"; string private constant ERROR_SUB_UNDERFLOW = "MATH64_SUB_UNDERFLOW"; string private constant ERROR_MUL_OVERFLOW = "MATH64_MUL_OVERFLOW"; string private constant ERROR_DIV_ZERO = "MATH64_DIV_ZERO"; /** * @dev Multiplies two numbers, reverts on overflow. */ function mul(uint64 _a, uint64 _b) internal pure returns (uint64) { uint256 c = uint256(_a) * uint256(_b); require(c < 0x010000000000000000, ERROR_MUL_OVERFLOW); // 2**64 (less gas this way) return uint64(c); } /** * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. */ function div(uint64 _a, uint64 _b) internal pure returns (uint64) { require(_b > 0, ERROR_DIV_ZERO); // Solidity only automatically asserts when dividing by 0 uint64 c = _a / _b; // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold return c; } /** * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint64 _a, uint64 _b) internal pure returns (uint64) { require(_b <= _a, ERROR_SUB_UNDERFLOW); uint64 c = _a - _b; return c; } /** * @dev Adds two numbers, reverts on overflow. */ function add(uint64 _a, uint64 _b) internal pure returns (uint64) { uint64 c = _a + _b; require(c >= _a, ERROR_ADD_OVERFLOW); return c; } /** * @dev Divides two numbers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint64 a, uint64 b) internal pure returns (uint64) { require(b != 0, ERROR_DIV_ZERO); return a % b; } } // File: contracts/lib/os/Uint256Helpers.sol // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/Uint256Helpers.sol // Adapted to use pragma ^0.5.8 and satisfy our linter rules pragma solidity ^0.5.8; library Uint256Helpers { uint256 private constant MAX_UINT8 = uint8(-1); uint256 private constant MAX_UINT64 = uint64(-1); string private constant ERROR_UINT8_NUMBER_TOO_BIG = "UINT8_NUMBER_TOO_BIG"; string private constant ERROR_UINT64_NUMBER_TOO_BIG = "UINT64_NUMBER_TOO_BIG"; function toUint8(uint256 a) internal pure returns (uint8) { require(a <= MAX_UINT8, ERROR_UINT8_NUMBER_TOO_BIG); return uint8(a); } function toUint64(uint256 a) internal pure returns (uint64) { require(a <= MAX_UINT64, ERROR_UINT64_NUMBER_TOO_BIG); return uint64(a); } } // File: contracts/arbitration/IArbitrator.sol pragma solidity ^0.5.8; interface IArbitrator { /** * @dev Create a dispute over the Arbitrable sender with a number of possible rulings * @param _possibleRulings Number of possible rulings allowed for the dispute * @param _metadata Optional metadata that can be used to provide additional information on the dispute to be created * @return Dispute identification number */ function createDispute(uint256 _possibleRulings, bytes calldata _metadata) external returns (uint256); /** * @dev Submit evidence for a dispute * @param _disputeId Id of the dispute in the Protocol * @param _submitter Address of the account submitting the evidence * @param _evidence Data submitted for the evidence related to the dispute */ function submitEvidence(uint256 _disputeId, address _submitter, bytes calldata _evidence) external; /** * @dev Close the evidence period of a dispute * @param _disputeId Identification number of the dispute to close its evidence submitting period */ function closeEvidencePeriod(uint256 _disputeId) external; /** * @notice Rule dispute #`_disputeId` if ready * @param _disputeId Identification number of the dispute to be ruled * @return subject Arbitrable instance associated to the dispute * @return ruling Ruling number computed for the given dispute */ function rule(uint256 _disputeId) external returns (address subject, uint256 ruling); /** * @dev Tell the dispute fees information to create a dispute * @return recipient Address where the corresponding dispute fees must be transferred to * @return feeToken ERC20 token used for the fees * @return feeAmount Total amount of fees that must be allowed to the recipient */ function getDisputeFees() external view returns (address recipient, ERC20 feeToken, uint256 feeAmount); } // File: contracts/arbitration/IArbitrable.sol pragma solidity ^0.5.8; contract IArbitrable { /** * @dev Emitted when an IArbitrable instance's dispute is ruled by an IArbitrator * @param arbitrator IArbitrator instance ruling the dispute * @param disputeId Identification number of the dispute being ruled by the arbitrator * @param ruling Ruling given by the arbitrator */ event Ruled(IArbitrator indexed arbitrator, uint256 indexed disputeId, uint256 ruling); } // File: contracts/disputes/IDisputeManager.sol pragma solidity ^0.5.8; interface IDisputeManager { enum DisputeState { PreDraft, Adjudicating, Ruled } enum AdjudicationState { Invalid, Committing, Revealing, Appealing, ConfirmingAppeal, Ended } /** * @dev Create a dispute to be drafted in a future term * @param _subject Arbitrable instance creating the dispute * @param _possibleRulings Number of possible rulings allowed for the drafted jurors to vote on the dispute * @param _metadata Optional metadata that can be used to provide additional information on the dispute to be created * @return Dispute identification number */ function createDispute(IArbitrable _subject, uint8 _possibleRulings, bytes calldata _metadata) external returns (uint256); /** * @dev Submit evidence for a dispute * @param _subject Arbitrable instance submitting the dispute * @param _disputeId Identification number of the dispute receiving new evidence * @param _submitter Address of the account submitting the evidence * @param _evidence Data submitted for the evidence of the dispute */ function submitEvidence(IArbitrable _subject, uint256 _disputeId, address _submitter, bytes calldata _evidence) external; /** * @dev Close the evidence period of a dispute * @param _subject IArbitrable instance requesting to close the evidence submission period * @param _disputeId Identification number of the dispute to close its evidence submitting period */ function closeEvidencePeriod(IArbitrable _subject, uint256 _disputeId) external; /** * @dev Draft jurors for the next round of a dispute * @param _disputeId Identification number of the dispute to be drafted */ function draft(uint256 _disputeId) external; /** * @dev Appeal round of a dispute in favor of a certain ruling * @param _disputeId Identification number of the dispute being appealed * @param _roundId Identification number of the dispute round being appealed * @param _ruling Ruling appealing a dispute round in favor of */ function createAppeal(uint256 _disputeId, uint256 _roundId, uint8 _ruling) external; /** * @dev Confirm appeal for a round of a dispute in favor of a ruling * @param _disputeId Identification number of the dispute confirming an appeal of * @param _roundId Identification number of the dispute round confirming an appeal of * @param _ruling Ruling being confirmed against a dispute round appeal */ function confirmAppeal(uint256 _disputeId, uint256 _roundId, uint8 _ruling) external; /** * @dev Compute the final ruling for a dispute * @param _disputeId Identification number of the dispute to compute its final ruling * @return subject Arbitrable instance associated to the dispute * @return finalRuling Final ruling decided for the given dispute */ function computeRuling(uint256 _disputeId) external returns (IArbitrable subject, uint8 finalRuling); /** * @dev Settle penalties for a round of a dispute * @param _disputeId Identification number of the dispute to settle penalties for * @param _roundId Identification number of the dispute round to settle penalties for * @param _jurorsToSettle Maximum number of jurors to be slashed in this call */ function settlePenalties(uint256 _disputeId, uint256 _roundId, uint256 _jurorsToSettle) external; /** * @dev Claim rewards for a round of a dispute for juror * @dev For regular rounds, it will only reward winning jurors * @param _disputeId Identification number of the dispute to settle rewards for * @param _roundId Identification number of the dispute round to settle rewards for * @param _juror Address of the juror to settle their rewards */ function settleReward(uint256 _disputeId, uint256 _roundId, address _juror) external; /** * @dev Settle appeal deposits for a round of a dispute * @param _disputeId Identification number of the dispute to settle appeal deposits for * @param _roundId Identification number of the dispute round to settle appeal deposits for */ function settleAppealDeposit(uint256 _disputeId, uint256 _roundId) external; /** * @dev Tell the amount of token fees required to create a dispute * @return feeToken ERC20 token used for the fees * @return feeAmount Total amount of fees to be paid for a dispute at the given term */ function getDisputeFees() external view returns (ERC20 feeToken, uint256 feeAmount); /** * @dev Tell information of a certain dispute * @param _disputeId Identification number of the dispute being queried * @return subject Arbitrable subject being disputed * @return possibleRulings Number of possible rulings allowed for the drafted jurors to vote on the dispute * @return state Current state of the dispute being queried: pre-draft, adjudicating, or ruled * @return finalRuling The winning ruling in case the dispute is finished * @return lastRoundId Identification number of the last round created for the dispute * @return createTermId Identification number of the term when the dispute was created */ function getDispute(uint256 _disputeId) external view returns (IArbitrable subject, uint8 possibleRulings, DisputeState state, uint8 finalRuling, uint256 lastRoundId, uint64 createTermId); /** * @dev Tell information of a certain adjudication round * @param _disputeId Identification number of the dispute being queried * @param _roundId Identification number of the round being queried * @return draftTerm Term from which the requested round can be drafted * @return delayedTerms Number of terms the given round was delayed based on its requested draft term id * @return jurorsNumber Number of jurors requested for the round * @return selectedJurors Number of jurors already selected for the requested round * @return settledPenalties Whether or not penalties have been settled for the requested round * @return collectedTokens Amount of juror tokens that were collected from slashed jurors for the requested round * @return coherentJurors Number of jurors that voted in favor of the final ruling in the requested round * @return state Adjudication state of the requested round */ function getRound(uint256 _disputeId, uint256 _roundId) external view returns ( uint64 draftTerm, uint64 delayedTerms, uint64 jurorsNumber, uint64 selectedJurors, uint256 jurorFees, bool settledPenalties, uint256 collectedTokens, uint64 coherentJurors, AdjudicationState state ); /** * @dev Tell appeal-related information of a certain adjudication round * @param _disputeId Identification number of the dispute being queried * @param _roundId Identification number of the round being queried * @return maker Address of the account appealing the given round * @return appealedRuling Ruling confirmed by the appealer of the given round * @return taker Address of the account confirming the appeal of the given round * @return opposedRuling Ruling confirmed by the appeal taker of the given round */ function getAppeal(uint256 _disputeId, uint256 _roundId) external view returns (address maker, uint64 appealedRuling, address taker, uint64 opposedRuling); /** * @dev Tell information related to the next round due to an appeal of a certain round given. * @param _disputeId Identification number of the dispute being queried * @param _roundId Identification number of the round requesting the appeal details of * @return nextRoundStartTerm Term ID from which the next round will start * @return nextRoundJurorsNumber Jurors number for the next round * @return newDisputeState New state for the dispute associated to the given round after the appeal * @return feeToken ERC20 token used for the next round fees * @return jurorFees Total amount of fees to be distributed between the winning jurors of the next round * @return totalFees Total amount of fees for a regular round at the given term * @return appealDeposit Amount to be deposit of fees for a regular round at the given term * @return confirmAppealDeposit Total amount of fees for a regular round at the given term */ function getNextRoundDetails(uint256 _disputeId, uint256 _roundId) external view returns ( uint64 nextRoundStartTerm, uint64 nextRoundJurorsNumber, DisputeState newDisputeState, ERC20 feeToken, uint256 totalFees, uint256 jurorFees, uint256 appealDeposit, uint256 confirmAppealDeposit ); /** * @dev Tell juror-related information of a certain adjudication round * @param _disputeId Identification number of the dispute being queried * @param _roundId Identification number of the round being queried * @param _juror Address of the juror being queried * @return weight Juror weight drafted for the requested round * @return rewarded Whether or not the given juror was rewarded based on the requested round */ function getJuror(uint256 _disputeId, uint256 _roundId, address _juror) external view returns (uint64 weight, bool rewarded); } // File: contracts/lib/PctHelpers.sol pragma solidity ^0.5.8; library PctHelpers { using SafeMath for uint256; uint256 internal constant PCT_BASE = 10000; // ‱ (1 / 10,000) uint256 internal constant PCT_BASE_HIGH_PRECISION = 1e18; // 100% function isValid(uint16 _pct) internal pure returns (bool) { return _pct <= PCT_BASE; } function isValidHighPrecision(uint256 _pct) internal pure returns (bool) { return _pct <= PCT_BASE_HIGH_PRECISION; } function pct(uint256 self, uint16 _pct) internal pure returns (uint256) { return self.mul(uint256(_pct)) / PCT_BASE; } function pct256(uint256 self, uint256 _pct) internal pure returns (uint256) { return self.mul(_pct) / PCT_BASE; } function pctHighPrecision(uint256 self, uint256 _pct) internal pure returns (uint256) { return self.mul(_pct) / PCT_BASE_HIGH_PRECISION; } function pctIncrease(uint256 self, uint16 _pct) internal pure returns (uint256) { // No need for SafeMath: for addition note that `PCT_BASE` is lower than (2^256 - 2^16) return self.mul(PCT_BASE + uint256(_pct)) / PCT_BASE; } } // File: contracts/voting/ICRVotingOwner.sol pragma solidity ^0.5.8; interface ICRVotingOwner { /** * @dev Ensure votes can be committed for a vote instance, revert otherwise * @param _voteId ID of the vote instance to request the weight of a voter for */ function ensureCanCommit(uint256 _voteId) external; /** * @dev Ensure a certain voter can commit votes for a vote instance, revert otherwise * @param _voteId ID of the vote instance to request the weight of a voter for * @param _voter Address of the voter querying the weight of */ function ensureCanCommit(uint256 _voteId, address _voter) external; /** * @dev Ensure a certain voter can reveal votes for vote instance, revert otherwise * @param _voteId ID of the vote instance to request the weight of a voter for * @param _voter Address of the voter querying the weight of * @return Weight of the requested juror for the requested vote instance */ function ensureCanReveal(uint256 _voteId, address _voter) external returns (uint64); } // File: contracts/voting/ICRVoting.sol pragma solidity ^0.5.8; interface ICRVoting { /** * @dev Create a new vote instance * @dev This function can only be called by the CRVoting owner * @param _voteId ID of the new vote instance to be created * @param _possibleOutcomes Number of possible outcomes for the new vote instance to be created */ function create(uint256 _voteId, uint8 _possibleOutcomes) external; /** * @dev Get the winning outcome of a vote instance * @param _voteId ID of the vote instance querying the winning outcome of * @return Winning outcome of the given vote instance or refused in case it's missing */ function getWinningOutcome(uint256 _voteId) external view returns (uint8); /** * @dev Get the tally of an outcome for a certain vote instance * @param _voteId ID of the vote instance querying the tally of * @param _outcome Outcome querying the tally of * @return Tally of the outcome being queried for the given vote instance */ function getOutcomeTally(uint256 _voteId, uint8 _outcome) external view returns (uint256); /** * @dev Tell whether an outcome is valid for a given vote instance or not * @param _voteId ID of the vote instance to check the outcome of * @param _outcome Outcome to check if valid or not * @return True if the given outcome is valid for the requested vote instance, false otherwise */ function isValidOutcome(uint256 _voteId, uint8 _outcome) external view returns (bool); /** * @dev Get the outcome voted by a voter for a certain vote instance * @param _voteId ID of the vote instance querying the outcome of * @param _voter Address of the voter querying the outcome of * @return Outcome of the voter for the given vote instance */ function getVoterOutcome(uint256 _voteId, address _voter) external view returns (uint8); /** * @dev Tell whether a voter voted in favor of a certain outcome in a vote instance or not * @param _voteId ID of the vote instance to query if a voter voted in favor of a certain outcome * @param _outcome Outcome to query if the given voter voted in favor of * @param _voter Address of the voter to query if voted in favor of the given outcome * @return True if the given voter voted in favor of the given outcome, false otherwise */ function hasVotedInFavorOf(uint256 _voteId, uint8 _outcome, address _voter) external view returns (bool); /** * @dev Filter a list of voters based on whether they voted in favor of a certain outcome in a vote instance or not * @param _voteId ID of the vote instance to be checked * @param _outcome Outcome to filter the list of voters of * @param _voters List of addresses of the voters to be filtered * @return List of results to tell whether a voter voted in favor of the given outcome or not */ function getVotersInFavorOf(uint256 _voteId, uint8 _outcome, address[] calldata _voters) external view returns (bool[] memory); } // File: contracts/treasury/ITreasury.sol pragma solidity ^0.5.8; interface ITreasury { /** * @dev Assign a certain amount of tokens to an account * @param _token ERC20 token to be assigned * @param _to Address of the recipient that will be assigned the tokens to * @param _amount Amount of tokens to be assigned to the recipient */ function assign(ERC20 _token, address _to, uint256 _amount) external; /** * @dev Withdraw a certain amount of tokens * @param _token ERC20 token to be withdrawn * @param _to Address of the recipient that will receive the tokens * @param _amount Amount of tokens to be withdrawn from the sender */ function withdraw(ERC20 _token, address _to, uint256 _amount) external; } // File: contracts/registry/IJurorsRegistry.sol pragma solidity ^0.5.8; interface IJurorsRegistry { /** * @dev Assign a requested amount of juror tokens to a juror * @param _juror Juror to add an amount of tokens to * @param _amount Amount of tokens to be added to the available balance of a juror */ function assignTokens(address _juror, uint256 _amount) external; /** * @dev Burn a requested amount of juror tokens * @param _amount Amount of tokens to be burned */ function burnTokens(uint256 _amount) external; /** * @dev Draft a set of jurors based on given requirements for a term id * @param _params Array containing draft requirements: * 0. bytes32 Term randomness * 1. uint256 Dispute id * 2. uint64 Current term id * 3. uint256 Number of seats already filled * 4. uint256 Number of seats left to be filled * 5. uint64 Number of jurors required for the draft * 6. uint16 Permyriad of the minimum active balance to be locked for the draft * * @return jurors List of jurors selected for the draft * @return length Size of the list of the draft result */ function draft(uint256[7] calldata _params) external returns (address[] memory jurors, uint256 length); /** * @dev Slash a set of jurors based on their votes compared to the winning ruling * @param _termId Current term id * @param _jurors List of juror addresses to be slashed * @param _lockedAmounts List of amounts locked for each corresponding juror that will be either slashed or returned * @param _rewardedJurors List of booleans to tell whether a juror's active balance has to be slashed or not * @return Total amount of slashed tokens */ function slashOrUnlock(uint64 _termId, address[] calldata _jurors, uint256[] calldata _lockedAmounts, bool[] calldata _rewardedJurors) external returns (uint256 collectedTokens); /** * @dev Try to collect a certain amount of tokens from a juror for the next term * @param _juror Juror to collect the tokens from * @param _amount Amount of tokens to be collected from the given juror and for the requested term id * @param _termId Current term id * @return True if the juror has enough unlocked tokens to be collected for the requested term, false otherwise */ function collectTokens(address _juror, uint256 _amount, uint64 _termId) external returns (bool); /** * @dev Lock a juror's withdrawals until a certain term ID * @param _juror Address of the juror to be locked * @param _termId Term ID until which the juror's withdrawals will be locked */ function lockWithdrawals(address _juror, uint64 _termId) external; /** * @dev Tell the active balance of a juror for a given term id * @param _juror Address of the juror querying the active balance of * @param _termId Term ID querying the active balance for * @return Amount of active tokens for juror in the requested past term id */ function activeBalanceOfAt(address _juror, uint64 _termId) external view returns (uint256); /** * @dev Tell the total amount of active juror tokens at the given term id * @param _termId Term ID querying the total active balance for * @return Total amount of active juror tokens at the given term id */ function totalActiveBalanceAt(uint64 _termId) external view returns (uint256); } // File: contracts/lib/os/IsContract.sol // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/IsContract.sol // Adapted to use pragma ^0.5.8 and satisfy our linter rules pragma solidity ^0.5.8; contract IsContract { /* * NOTE: this should NEVER be used for authentication * (see pitfalls: https://github.com/fergarrui/ethereum-security/tree/master/contracts/extcodesize). * * This is only intended to be used as a sanity check that an address is actually a contract, * RATHER THAN an address not being a contract. */ function isContract(address _target) internal view returns (bool) { if (_target == address(0)) { return false; } uint256 size; assembly { size := extcodesize(_target) } return size > 0; } } // File: contracts/lib/os/TimeHelpers.sol // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/TimeHelpers.sol // Adapted to use pragma ^0.5.8 and satisfy our linter rules pragma solidity ^0.5.8; contract TimeHelpers { using Uint256Helpers for uint256; /** * @dev Returns the current block number. * Using a function rather than `block.number` allows us to easily mock the block number in * tests. */ function getBlockNumber() internal view returns (uint256) { return block.number; } /** * @dev Returns the current block number, converted to uint64. * Using a function rather than `block.number` allows us to easily mock the block number in * tests. */ function getBlockNumber64() internal view returns (uint64) { return getBlockNumber().toUint64(); } /** * @dev Returns the current timestamp. * Using a function rather than `block.timestamp` allows us to easily mock it in * tests. */ function getTimestamp() internal view returns (uint256) { return block.timestamp; // solium-disable-line security/no-block-members } /** * @dev Returns the current timestamp, converted to uint64. * Using a function rather than `block.timestamp` allows us to easily mock it in * tests. */ function getTimestamp64() internal view returns (uint64) { return getTimestamp().toUint64(); } } // File: contracts/court/clock/IClock.sol pragma solidity ^0.5.8; interface IClock { /** * @dev Ensure that the current term of the clock is up-to-date * @return Identification number of the current term */ function ensureCurrentTerm() external returns (uint64); /** * @dev Transition up to a certain number of terms to leave the clock up-to-date * @param _maxRequestedTransitions Max number of term transitions allowed by the sender * @return Identification number of the term ID after executing the heartbeat transitions */ function heartbeat(uint64 _maxRequestedTransitions) external returns (uint64); /** * @dev Ensure that a certain term has its randomness set * @return Randomness of the current term */ function ensureCurrentTermRandomness() external returns (bytes32); /** * @dev Tell the last ensured term identification number * @return Identification number of the last ensured term */ function getLastEnsuredTermId() external view returns (uint64); /** * @dev Tell the current term identification number. Note that there may be pending term transitions. * @return Identification number of the current term */ function getCurrentTermId() external view returns (uint64); /** * @dev Tell the number of terms the clock should transition to be up-to-date * @return Number of terms the clock should transition to be up-to-date */ function getNeededTermTransitions() external view returns (uint64); /** * @dev Tell the information related to a term based on its ID * @param _termId ID of the term being queried * @return startTime Term start time * @return randomnessBN Block number used for randomness in the requested term * @return randomness Randomness computed for the requested term * @return celesteTokenTotalSupply Total supply of the Celeste token */ function getTerm(uint64 _termId) external view returns (uint64 startTime, uint64 randomnessBN, bytes32 randomness, uint256 celesteTokenTotalSupply); /** * @dev Tell the randomness of a term even if it wasn't computed yet * @param _termId Identification number of the term being queried * @return Randomness of the requested term */ function getTermRandomness(uint64 _termId) external view returns (bytes32); /** * @dev Tell the total supply of the celeste token at a specific term * @param _termId Identification number of the term being queried * @return Total supply of celeste token */ function getTermTokenTotalSupply(uint64 _termId) external view returns (uint256); } // File: contracts/court/clock/CourtClock.sol pragma solidity ^0.5.8; contract CourtClock is IClock, TimeHelpers { using SafeMath64 for uint64; string private constant ERROR_TERM_DOES_NOT_EXIST = "CLK_TERM_DOES_NOT_EXIST"; string private constant ERROR_TERM_DURATION_TOO_LONG = "CLK_TERM_DURATION_TOO_LONG"; string private constant ERROR_TERM_RANDOMNESS_NOT_YET = "CLK_TERM_RANDOMNESS_NOT_YET"; string private constant ERROR_TERM_RANDOMNESS_UNAVAILABLE = "CLK_TERM_RANDOMNESS_UNAVAILABLE"; string private constant ERROR_BAD_FIRST_TERM_START_TIME = "CLK_BAD_FIRST_TERM_START_TIME"; string private constant ERROR_TOO_MANY_TRANSITIONS = "CLK_TOO_MANY_TRANSITIONS"; string private constant ERROR_INVALID_TRANSITION_TERMS = "CLK_INVALID_TRANSITION_TERMS"; string private constant ERROR_CANNOT_DELAY_STARTED_COURT = "CLK_CANNOT_DELAY_STARTED_COURT"; string private constant ERROR_CANNOT_DELAY_PAST_START_TIME = "CLK_CANNOT_DELAY_PAST_START_TIME"; // Maximum number of term transitions a callee may have to assume in order to call certain functions that require the Court being up-to-date uint64 internal constant MAX_AUTO_TERM_TRANSITIONS_ALLOWED = 1; // Max duration in seconds that a term can last uint64 internal constant MAX_TERM_DURATION = 365 days; // Max time until first term starts since contract is deployed uint64 internal constant MAX_FIRST_TERM_DELAY_PERIOD = 2 * MAX_TERM_DURATION; struct Term { uint64 startTime; // Timestamp when the term started uint64 randomnessBN; // Block number for entropy bytes32 randomness; // Entropy from randomnessBN block hash uint256 celesteTokenTotalSupply; } // Duration in seconds for each term of the Court uint64 private termDuration; // Last ensured term id uint64 private termId; // List of Court terms indexed by id mapping (uint64 => Term) private terms; event Heartbeat(uint64 previousTermId, uint64 currentTermId); event StartTimeDelayed(uint64 previousStartTime, uint64 currentStartTime); /** * @dev Ensure a certain term has already been processed * @param _termId Identification number of the term to be checked */ modifier termExists(uint64 _termId) { require(_termId <= termId, ERROR_TERM_DOES_NOT_EXIST); _; } /** * @dev Constructor function * @param _termParams Array containing: * 0. _termDuration Duration in seconds per term * 1. _firstTermStartTime Timestamp in seconds when the court will open (to give time for juror on-boarding) */ constructor(uint64[2] memory _termParams, ERC20 _celesteToken) public { uint64 _termDuration = _termParams[0]; uint64 _firstTermStartTime = _termParams[1]; require(_termDuration < MAX_TERM_DURATION, ERROR_TERM_DURATION_TOO_LONG); require(_firstTermStartTime >= getTimestamp64() + _termDuration, ERROR_BAD_FIRST_TERM_START_TIME); require(_firstTermStartTime <= getTimestamp64() + MAX_FIRST_TERM_DELAY_PERIOD, ERROR_BAD_FIRST_TERM_START_TIME); termDuration = _termDuration; // No need for SafeMath: we already checked values above terms[0].startTime = _firstTermStartTime - _termDuration; terms[0].celesteTokenTotalSupply = _celesteToken.totalSupply(); } /** * @notice Ensure that the current term of the Court is up-to-date. If the Court is outdated by more than `MAX_AUTO_TERM_TRANSITIONS_ALLOWED` * terms, the heartbeat function must be called manually instead. * @return Identification number of the current term */ function ensureCurrentTerm() external returns (uint64) { return _ensureCurrentTerm(); } /** * @notice Transition up to `_maxRequestedTransitions` terms * @param _maxRequestedTransitions Max number of term transitions allowed by the sender * @return Identification number of the term ID after executing the heartbeat transitions */ function heartbeat(uint64 _maxRequestedTransitions) external returns (uint64) { return _heartbeat(_maxRequestedTransitions); } /** * @notice Ensure that a certain term has its randomness set. As we allow to draft disputes requested for previous terms, if there * were mined more than 256 blocks for the current term, the blockhash of its randomness BN is no longer available, given * round will be able to be drafted in the following term. * @return Randomness of the current term */ function ensureCurrentTermRandomness() external returns (bytes32) { // If the randomness for the given term was already computed, return uint64 currentTermId = termId; Term storage term = terms[currentTermId]; bytes32 termRandomness = term.randomness; if (termRandomness != bytes32(0)) { return termRandomness; } // Compute term randomness bytes32 newRandomness = _computeTermRandomness(currentTermId); require(newRandomness != bytes32(0), ERROR_TERM_RANDOMNESS_UNAVAILABLE); term.randomness = newRandomness; return newRandomness; } /** * @dev Tell the term duration of the Court * @return Duration in seconds of the Court term */ function getTermDuration() external view returns (uint64) { return termDuration; } /** * @dev Tell the last ensured term identification number * @return Identification number of the last ensured term */ function getLastEnsuredTermId() external view returns (uint64) { return _lastEnsuredTermId(); } /** * @dev Tell the current term identification number. Note that there may be pending term transitions. * @return Identification number of the current term */ function getCurrentTermId() external view returns (uint64) { return _currentTermId(); } /** * @dev Tell the number of terms the Court should transition to be up-to-date * @return Number of terms the Court should transition to be up-to-date */ function getNeededTermTransitions() external view returns (uint64) { return _neededTermTransitions(); } /** * @dev Tell the information related to a term based on its ID. Note that if the term has not been reached, the * information returned won't be computed yet. This function allows querying future terms that were not computed yet. * @param _termId ID of the term being queried * @return startTime Term start time * @return randomnessBN Block number used for randomness in the requested term * @return randomness Randomness computed for the requested term * @return celesteTokenTotalSupply Total supply of the Celeste token */ function getTerm(uint64 _termId) external view returns (uint64 startTime, uint64 randomnessBN, bytes32 randomness, uint256 celesteTokenTotalSupply) { Term storage term = terms[_termId]; return (term.startTime, term.randomnessBN, term.randomness, term.celesteTokenTotalSupply); } /** * @dev Tell the randomness of a term even if it wasn't computed yet * @param _termId Identification number of the term being queried * @return Randomness of the requested term */ function getTermRandomness(uint64 _termId) external view termExists(_termId) returns (bytes32) { return _computeTermRandomness(_termId); } /** * @dev Tell the total supply of the celeste token at a specific term * @param _termId Identification number of the term being queried * @return Total supply of celeste token */ function getTermTokenTotalSupply(uint64 _termId) external view termExists(_termId) returns (uint256) { return terms[_termId].celesteTokenTotalSupply; } /** * @dev Internal function to ensure that the current term of the Court is up-to-date. If the Court is outdated by more than * `MAX_AUTO_TERM_TRANSITIONS_ALLOWED` terms, the heartbeat function must be called manually. * @return Identification number of the resultant term ID after executing the corresponding transitions */ function _ensureCurrentTerm() internal returns (uint64) { // Check the required number of transitions does not exceeds the max allowed number to be processed automatically uint64 requiredTransitions = _neededTermTransitions(); require(requiredTransitions <= MAX_AUTO_TERM_TRANSITIONS_ALLOWED, ERROR_TOO_MANY_TRANSITIONS); // If there are no transitions pending, return the last ensured term id if (uint256(requiredTransitions) == 0) { return termId; } // Process transition if there is at least one pending return _heartbeat(requiredTransitions); } /** * @dev Internal function to transition the Court terms up to a requested number of terms * @param _maxRequestedTransitions Max number of term transitions allowed by the sender * @return Identification number of the resultant term ID after executing the requested transitions */ function _heartbeat(uint64 _maxRequestedTransitions) internal returns (uint64) { // Transition the minimum number of terms between the amount requested and the amount actually needed uint64 neededTransitions = _neededTermTransitions(); uint256 transitions = uint256(_maxRequestedTransitions < neededTransitions ? _maxRequestedTransitions : neededTransitions); require(transitions > 0, ERROR_INVALID_TRANSITION_TERMS); uint64 blockNumber = getBlockNumber64(); uint64 previousTermId = termId; uint64 currentTermId = previousTermId; for (uint256 transition = 1; transition <= transitions; transition++) { // Term IDs are incremented by one based on the number of time periods since the Court started. Since time is represented in uint64, // even if we chose the minimum duration possible for a term (1 second), we can ensure terms will never reach 2^64 since time is // already assumed to fit in uint64. Term storage previousTerm = terms[currentTermId++]; Term storage currentTerm = terms[currentTermId]; (ERC20 feeToken,,,,,, uint256[4] memory jurorsParams) = _getConfig(currentTermId); _onTermTransitioned(currentTermId); // Set the start time of the new term. Note that we are using a constant term duration value to guarantee // equally long terms, regardless of heartbeats. currentTerm.startTime = previousTerm.startTime.add(termDuration); // In order to draft a random number of jurors in a term, we use a randomness factor for each term based on a // block number that is set once the term has started. Note that this information could not be known beforehand. currentTerm.randomnessBN = blockNumber + 1; // We check if the feeTokenTotalSupply is set, which means this networks feeToken doesn't have an accurate // totalSupply so we will use the hardcoded value currentTerm.celesteTokenTotalSupply = jurorsParams[3] > 0 ? jurorsParams[3] : feeToken.totalSupply(); } termId = currentTermId; emit Heartbeat(previousTermId, currentTermId); return currentTermId; } /** * @dev Internal function to delay the first term start time only if it wasn't reached yet * @param _newFirstTermStartTime New timestamp in seconds when the court will open */ function _delayStartTime(uint64 _newFirstTermStartTime) internal { require(_currentTermId() == 0, ERROR_CANNOT_DELAY_STARTED_COURT); Term storage term = terms[0]; uint64 currentFirstTermStartTime = term.startTime.add(termDuration); require(_newFirstTermStartTime > currentFirstTermStartTime, ERROR_CANNOT_DELAY_PAST_START_TIME); // No need for SafeMath: we already checked above that `_newFirstTermStartTime` > `currentFirstTermStartTime` >= `termDuration` term.startTime = _newFirstTermStartTime - termDuration; emit StartTimeDelayed(currentFirstTermStartTime, _newFirstTermStartTime); } /** * @dev Internal function to notify when a term has been transitioned. This function must be overridden to provide custom behavior. * @param _termId Identification number of the new current term that has been transitioned */ function _onTermTransitioned(uint64 _termId) internal; /** * @dev Internal function to tell the last ensured term identification number * @return Identification number of the last ensured term */ function _lastEnsuredTermId() internal view returns (uint64) { return termId; } /** * @dev Internal function to tell the current term identification number. Note that there may be pending term transitions. * @return Identification number of the current term */ function _currentTermId() internal view returns (uint64) { return termId.add(_neededTermTransitions()); } /** * @dev Internal function to tell the number of terms the Court should transition to be up-to-date * @return Number of terms the Court should transition to be up-to-date */ function _neededTermTransitions() internal view returns (uint64) { // Note that the Court is always initialized providing a start time for the first-term in the future. If that's the case, // no term transitions are required. uint64 currentTermStartTime = terms[termId].startTime; if (getTimestamp64() < currentTermStartTime) { return uint64(0); } // No need for SafeMath: we already know that the start time of the current term is in the past return (getTimestamp64() - currentTermStartTime) / termDuration; } /** * @dev Internal function to compute the randomness that will be used to draft jurors for the given term. This * function assumes the given term exists. To determine the randomness factor for a term we use the hash of a * block number that is set once the term has started to ensure it cannot be known beforehand. Note that the * hash function being used only works for the 256 most recent block numbers. * @param _termId Identification number of the term being queried * @return Randomness computed for the given term */ function _computeTermRandomness(uint64 _termId) internal view returns (bytes32) { Term storage term = terms[_termId]; require(getBlockNumber64() > term.randomnessBN, ERROR_TERM_RANDOMNESS_NOT_YET); return blockhash(term.randomnessBN); } /** * @dev Tell the full Court configuration parameters at a certain term * @param _termId Identification number of the term querying the Court config of * @return token Address of the token used to pay for fees * @return fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @return maxRulingOptions Max number of selectable outcomes for each dispute * @return roundParams Array containing durations of phases of a dispute and other params for rounds: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * 5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @return pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @return appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal * @return jurorsParams Array containing params for juror registry: * 0. minActiveBalance Minimum amount of juror tokens that can be activated * 1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake * 2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake * 3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do */ function _getConfig(uint64 _termId) internal view returns ( ERC20 feeToken, uint256[3] memory fees, uint8 maxRulingOptions, uint64[9] memory roundParams, uint16[2] memory pcts, uint256[2] memory appealCollateralParams, uint256[4] memory jurorsParams ); } // File: contracts/court/config/IConfig.sol pragma solidity ^0.5.8; interface IConfig { /** * @dev Tell the full Court configuration parameters at a certain term * @param _termId Identification number of the term querying the Court config of * @return token Address of the token used to pay for fees * @return fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @return maxRulingOptions Max number of selectable outcomes for each dispute * @return roundParams Array containing durations of phases of a dispute and other params for rounds: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * 5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @return pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @return appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal * @return jurorsParams Array containing params for juror registry: * 0. minActiveBalance Minimum amount of juror tokens that can be activated * 1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake * 2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake * 3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do */ function getConfig(uint64 _termId) external view returns ( ERC20 feeToken, uint256[3] memory fees, uint8 maxRulingOptions, uint64[9] memory roundParams, uint16[2] memory pcts, uint256[2] memory appealCollateralParams, uint256[4] memory jurorsParams ); /** * @dev Tell the draft config at a certain term * @param _termId Identification number of the term querying the draft config of * @return feeToken Address of the token used to pay for fees * @return draftFee Amount of fee tokens per juror to cover the drafting cost * @return penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) */ function getDraftConfig(uint64 _termId) external view returns (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct); /** * @dev Tell the min active balance config at a certain term * @param _termId Term querying the min active balance config of * @return Minimum amount of tokens jurors have to activate to participate in the Court */ function getMinActiveBalance(uint64 _termId) external view returns (uint256); /** * @dev Tell whether a certain holder accepts automatic withdrawals of tokens or not * @return True if the given holder accepts automatic withdrawals of their tokens, false otherwise */ function areWithdrawalsAllowedFor(address _holder) external view returns (bool); } // File: contracts/court/config/CourtConfigData.sol pragma solidity ^0.5.8; contract CourtConfigData { struct Config { FeesConfig fees; // Full fees-related config DisputesConfig disputes; // Full disputes-related config JurorsConfig jurors; // Full juror-related config } struct FeesConfig { ERC20 token; // ERC20 token to be used for the fees of the Court uint16 finalRoundReduction; // Permyriad of fees reduction applied for final appeal round (‱ - 1/10,000) uint256 jurorFee; // Amount of tokens paid to draft a juror to adjudicate a dispute uint256 draftFee; // Amount of tokens paid per round to cover the costs of drafting jurors uint256 settleFee; // Amount of tokens paid per round to cover the costs of slashing jurors } struct DisputesConfig { uint8 maxRulingOptions; // Max number of ruling options selectable by jurors for a dispute uint64 evidenceTerms; // Max submitting evidence period duration in terms uint64 commitTerms; // Committing period duration in terms uint64 revealTerms; // Revealing period duration in terms uint64 appealTerms; // Appealing period duration in terms uint64 appealConfirmTerms; // Confirmation appeal period duration in terms uint16 penaltyPct; // Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) uint64 firstRoundJurorsNumber; // Number of jurors drafted on first round uint64 appealStepFactor; // Factor in which the jurors number is increased on each appeal uint64 finalRoundLockTerms; // Period a coherent juror in the final round will remain locked uint256 maxRegularAppealRounds; // Before the final appeal uint256 appealCollateralFactor; // Permyriad multiple of dispute fees required to appeal a preliminary ruling (‱ - 1/10,000) uint256 appealConfirmCollateralFactor; // Permyriad multiple of dispute fees required to confirm appeal (‱ - 1/10,000) } struct JurorsConfig { uint256 minActiveBalance; // Minimum amount of tokens jurors have to activate to participate in the Court uint256 minMaxPctTotalSupply; // Minimum max percent of the total supply a juror can activate, applied for total supply active stake uint256 maxMaxPctTotalSupply; // Maximum max percent of the total supply a juror can activate, applied for 0 active stake uint256 feeTokenTotalSupply; // Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do } struct DraftConfig { ERC20 feeToken; // ERC20 token to be used for the fees of the Court uint16 penaltyPct; // Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) uint256 draftFee; // Amount of tokens paid per round to cover the costs of drafting jurors } } // File: contracts/court/config/CourtConfig.sol pragma solidity ^0.5.8; contract CourtConfig is IConfig, CourtConfigData { using SafeMath64 for uint64; using PctHelpers for uint256; string private constant ERROR_TOO_OLD_TERM = "CONF_TOO_OLD_TERM"; string private constant ERROR_RULING_OPTIONS_LESS_THAN_MIN = "CONF_RULING_OPTIONS_LESS_THAN_MIN"; string private constant ERROR_RULING_OPTIONS_MORE_THAN_MAX = "CONF_RULING_OPTIONS_MORE_THAN_MAX"; string private constant ERROR_INVALID_PENALTY_PCT = "CONF_INVALID_PENALTY_PCT"; string private constant ERROR_INVALID_FINAL_ROUND_REDUCTION_PCT = "CONF_INVALID_FINAL_ROUND_RED_PCT"; string private constant ERROR_INVALID_MAX_APPEAL_ROUNDS = "CONF_INVALID_MAX_APPEAL_ROUNDS"; string private constant ERROR_LARGE_ROUND_PHASE_DURATION = "CONF_LARGE_ROUND_PHASE_DURATION"; string private constant ERROR_BAD_INITIAL_JURORS_NUMBER = "CONF_BAD_INITIAL_JURORS_NUMBER"; string private constant ERROR_BAD_APPEAL_STEP_FACTOR = "CONF_BAD_APPEAL_STEP_FACTOR"; string private constant ERROR_ZERO_COLLATERAL_FACTOR = "CONF_ZERO_COLLATERAL_FACTOR"; string private constant ERROR_ZERO_MIN_ACTIVE_BALANCE = "CONF_ZERO_MIN_ACTIVE_BALANCE"; string private constant ERROR_MIN_MAX_TOTAL_SUPPLY_ZERO = "CONF_MIN_MAX_TOTAL_SUPPLY_ZERO"; string private constant ERROR_INVALID_MAX_MAX_TOTAL_SUPPLY_PCT = "CONF_INVALID_MAX_MAX_TOTAL_SUPPLY_PCT"; string private constant ERROR_MIN_MORE_THAN_MAX_ACTIVE_PCT = "CONF_MIN_MORE_THAN_MAX_ACTIVE_PCT"; // Max number of terms that each of the different adjudication states can last (if lasted 1h, this would be a year) uint64 internal constant MAX_ADJ_STATE_DURATION = 8670; // Cap the max number of regular appeal rounds uint256 internal constant MAX_REGULAR_APPEAL_ROUNDS_LIMIT = 10; // Future term ID in which a config change has been scheduled uint64 private configChangeTermId; // List of all the configs used in the Court Config[] private configs; // List of configs indexed by id mapping (uint64 => uint256) private configIdByTerm; // Holders opt-in config for automatic withdrawals mapping (address => bool) private withdrawalsAllowed; event NewConfig(uint64 fromTermId, uint64 courtConfigId); event AutomaticWithdrawalsAllowedChanged(address indexed holder, bool allowed); /** * @dev Constructor function * @param _feeToken Address of the token contract that is used to pay for fees * @param _fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @param _maxRulingOptions Max number of selectable outcomes for each dispute * @param _roundParams Array containing durations of phases of a dispute and other params for rounds: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * 5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @param _pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @param _appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal * @param _jurorsParams Array containing params for juror registry: * 0. minActiveBalance Minimum amount of juror tokens that can be activated * 1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake * 2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake * 3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do */ constructor( ERC20 _feeToken, uint256[3] memory _fees, uint8 _maxRulingOptions, uint64[9] memory _roundParams, uint16[2] memory _pcts, uint256[2] memory _appealCollateralParams, uint256[4] memory _jurorsParams ) public { // Leave config at index 0 empty for non-scheduled config changes configs.length = 1; _setConfig( 0, 0, _feeToken, _fees, _maxRulingOptions, _roundParams, _pcts, _appealCollateralParams, _jurorsParams ); } /** * @notice Set the automatic withdrawals config for the sender to `_allowed` * @param _allowed Whether or not the automatic withdrawals are allowed by the sender */ function setAutomaticWithdrawals(bool _allowed) external { withdrawalsAllowed[msg.sender] = _allowed; emit AutomaticWithdrawalsAllowedChanged(msg.sender, _allowed); } /** * @dev Tell the full Court configuration parameters at a certain term * @param _termId Identification number of the term querying the Court config of * @return token Address of the token used to pay for fees * @return fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @return maxRulingOptions Max number of selectable outcomes for each dispute * @return roundParams Array containing durations of phases of a dispute and other params for rounds: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * 5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @return pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @return appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal * @return jurorsParams Array containing params for juror registry: * 0. minActiveBalance Minimum amount of juror tokens that can be activated * 1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake * 2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake * 3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do */ function getConfig(uint64 _termId) external view returns ( ERC20 feeToken, uint256[3] memory fees, uint8 maxRulingOptions, uint64[9] memory roundParams, uint16[2] memory pcts, uint256[2] memory appealCollateralParams, uint256[4] memory jurorsParams ); /** * @dev Tell the draft config at a certain term * @param _termId Identification number of the term querying the draft config of * @return feeToken Address of the token used to pay for fees * @return draftFee Amount of fee tokens per juror to cover the drafting cost * @return penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) */ function getDraftConfig(uint64 _termId) external view returns (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct); /** * @dev Tell the min active balance config at a certain term * @param _termId Term querying the min active balance config of * @return Minimum amount of tokens jurors have to activate to participate in the Court */ function getMinActiveBalance(uint64 _termId) external view returns (uint256); /** * @dev Tell whether a certain holder accepts automatic withdrawals of tokens or not * @param _holder Address of the token holder querying if withdrawals are allowed for * @return True if the given holder accepts automatic withdrawals of their tokens, false otherwise */ function areWithdrawalsAllowedFor(address _holder) external view returns (bool) { return withdrawalsAllowed[_holder]; } /** * @dev Tell the term identification number of the next scheduled config change * @return Term identification number of the next scheduled config change */ function getConfigChangeTermId() external view returns (uint64) { return configChangeTermId; } /** * @dev Internal to make sure to set a config for the new term, it will copy the previous term config if none * @param _termId Identification number of the new current term that has been transitioned */ function _ensureTermConfig(uint64 _termId) internal { // If the term being transitioned had no config change scheduled, keep the previous one uint256 currentConfigId = configIdByTerm[_termId]; if (currentConfigId == 0) { uint256 previousConfigId = configIdByTerm[_termId.sub(1)]; configIdByTerm[_termId] = previousConfigId; } } /** * @dev Assumes that sender it's allowed (either it's from governor or it's on init) * @param _termId Identification number of the current Court term * @param _fromTermId Identification number of the term in which the config will be effective at * @param _feeToken Address of the token contract that is used to pay for fees. * @param _fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @param _maxRulingOptions Max number of selectable outcomes for each dispute * @param _roundParams Array containing durations of phases of a dispute and other params for rounds: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * 5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @param _pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @param _appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal * @param _jurorsParams Array containing params for juror registry: * 0. minActiveBalance Minimum amount of juror tokens that can be activated * 1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake * 2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake * 3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do */ function _setConfig( uint64 _termId, uint64 _fromTermId, ERC20 _feeToken, uint256[3] memory _fees, uint8 _maxRulingOptions, uint64[9] memory _roundParams, uint16[2] memory _pcts, uint256[2] memory _appealCollateralParams, uint256[4] memory _jurorsParams ) internal { // If the current term is not zero, changes must be scheduled at least after the current period. // No need to ensure delays for on-going disputes since these already use their creation term for that. require(_termId == 0 || _fromTermId > _termId, ERROR_TOO_OLD_TERM); require(_maxRulingOptions >= 2, ERROR_RULING_OPTIONS_LESS_THAN_MIN); // Ruling options 0, 1 and 2 are reserved for special cases. require(_maxRulingOptions <= uint8(-1) - 3, ERROR_RULING_OPTIONS_MORE_THAN_MAX); // Make sure appeal collateral factors are greater than zero require(_appealCollateralParams[0] > 0 && _appealCollateralParams[1] > 0, ERROR_ZERO_COLLATERAL_FACTOR); // Make sure the given penalty and final round reduction pcts are not greater than 100% require(PctHelpers.isValid(_pcts[0]), ERROR_INVALID_PENALTY_PCT); require(PctHelpers.isValid(_pcts[1]), ERROR_INVALID_FINAL_ROUND_REDUCTION_PCT); // Disputes must request at least one juror to be drafted initially require(_roundParams[5] > 0, ERROR_BAD_INITIAL_JURORS_NUMBER); // Prevent that further rounds have zero jurors require(_roundParams[6] > 0, ERROR_BAD_APPEAL_STEP_FACTOR); // Make sure the max number of appeals allowed does not reach the limit uint256 _maxRegularAppealRounds = _roundParams[7]; bool isMaxAppealRoundsValid = _maxRegularAppealRounds > 0 && _maxRegularAppealRounds <= MAX_REGULAR_APPEAL_ROUNDS_LIMIT; require(isMaxAppealRoundsValid, ERROR_INVALID_MAX_APPEAL_ROUNDS); // Make sure each adjudication round phase duration is valid for (uint i = 0; i < 5; i++) { require(_roundParams[i] > 0 && _roundParams[i] < MAX_ADJ_STATE_DURATION, ERROR_LARGE_ROUND_PHASE_DURATION); } // Make sure min active balance is not zero require(_jurorsParams[0] > 0, ERROR_ZERO_MIN_ACTIVE_BALANCE); // Make sure min max pct of total supply active balance is not zero require(_jurorsParams[1] > 0, ERROR_MIN_MAX_TOTAL_SUPPLY_ZERO); // Make sure the max max pct of total supply active balance is less than 100% require(PctHelpers.isValidHighPrecision(_jurorsParams[2]), ERROR_INVALID_MAX_MAX_TOTAL_SUPPLY_PCT); // Make sure min max pct of total supply active balance is less than the max max pct of total supply active balance require(_jurorsParams[1] < _jurorsParams[2], ERROR_MIN_MORE_THAN_MAX_ACTIVE_PCT); // If there was a config change already scheduled, reset it (in that case we will overwrite last array item). // Otherwise, schedule a new config. if (configChangeTermId > _termId) { configIdByTerm[configChangeTermId] = 0; } else { configs.length++; } uint64 courtConfigId = uint64(configs.length - 1); Config storage config = configs[courtConfigId]; config.fees = FeesConfig({ token: _feeToken, jurorFee: _fees[0], draftFee: _fees[1], settleFee: _fees[2], finalRoundReduction: _pcts[1] }); config.disputes = DisputesConfig({ maxRulingOptions: _maxRulingOptions, evidenceTerms: _roundParams[0], commitTerms: _roundParams[1], revealTerms: _roundParams[2], appealTerms: _roundParams[3], appealConfirmTerms: _roundParams[4], penaltyPct: _pcts[0], firstRoundJurorsNumber: _roundParams[5], appealStepFactor: _roundParams[6], maxRegularAppealRounds: _maxRegularAppealRounds, finalRoundLockTerms: _roundParams[8], appealCollateralFactor: _appealCollateralParams[0], appealConfirmCollateralFactor: _appealCollateralParams[1] }); config.jurors = JurorsConfig({ minActiveBalance: _jurorsParams[0], minMaxPctTotalSupply: _jurorsParams[1], maxMaxPctTotalSupply: _jurorsParams[2], feeTokenTotalSupply: _jurorsParams[3] }); configIdByTerm[_fromTermId] = courtConfigId; configChangeTermId = _fromTermId; emit NewConfig(_fromTermId, courtConfigId); } /** * @dev Internal function to get the Court config for a given term * @param _termId Identification number of the term querying the Court config of * @param _lastEnsuredTermId Identification number of the last ensured term of the Court * @return token Address of the token used to pay for fees * @return fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @return maxRulingOptions Max number of selectable outcomes for each dispute * @return roundParams Array containing durations of phases of a dispute and other params for rounds: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * 5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @return pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @return appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal * @return jurorsParams Array containing params for juror registry: * 0. minActiveBalance Minimum amount of juror tokens that can be activated * 1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake * 2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake * 3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do */ function _getConfigAt(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns ( ERC20 feeToken, uint256[3] memory fees, uint8 maxRulingOptions, uint64[9] memory roundParams, uint16[2] memory pcts, uint256[2] memory appealCollateralParams, uint256[4] memory jurorsParams ) { Config storage config = _getConfigFor(_termId, _lastEnsuredTermId); FeesConfig storage feesConfig = config.fees; feeToken = feesConfig.token; fees = [feesConfig.jurorFee, feesConfig.draftFee, feesConfig.settleFee]; DisputesConfig storage disputesConfig = config.disputes; maxRulingOptions = disputesConfig.maxRulingOptions; roundParams = [ disputesConfig.evidenceTerms, disputesConfig.commitTerms, disputesConfig.revealTerms, disputesConfig.appealTerms, disputesConfig.appealConfirmTerms, disputesConfig.firstRoundJurorsNumber, disputesConfig.appealStepFactor, uint64(disputesConfig.maxRegularAppealRounds), disputesConfig.finalRoundLockTerms ]; pcts = [disputesConfig.penaltyPct, feesConfig.finalRoundReduction]; appealCollateralParams = [disputesConfig.appealCollateralFactor, disputesConfig.appealConfirmCollateralFactor]; JurorsConfig storage jurorsConfig = config.jurors; jurorsParams = [ jurorsConfig.minActiveBalance, jurorsConfig.minMaxPctTotalSupply, jurorsConfig.maxMaxPctTotalSupply, jurorsConfig.feeTokenTotalSupply ]; } /** * @dev Tell the draft config at a certain term * @param _termId Identification number of the term querying the draft config of * @param _lastEnsuredTermId Identification number of the last ensured term of the Court * @return feeToken Address of the token used to pay for fees * @return draftFee Amount of fee tokens per juror to cover the drafting cost * @return penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) */ function _getDraftConfig(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct) { Config storage config = _getConfigFor(_termId, _lastEnsuredTermId); return (config.fees.token, config.fees.draftFee, config.disputes.penaltyPct); } /** * @dev Internal function to get the min active balance config for a given term * @param _termId Identification number of the term querying the min active balance config of * @param _lastEnsuredTermId Identification number of the last ensured term of the Court * @return Minimum amount of juror tokens that can be activated at the given term */ function _getMinActiveBalance(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns (uint256) { Config storage config = _getConfigFor(_termId, _lastEnsuredTermId); return config.jurors.minActiveBalance; } /** * @dev Internal function to get the Court config for a given term * @param _termId Identification number of the term querying the min active balance config of * @param _lastEnsuredTermId Identification number of the last ensured term of the Court * @return Court config for the given term */ function _getConfigFor(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns (Config storage) { uint256 id = _getConfigIdFor(_termId, _lastEnsuredTermId); return configs[id]; } /** * @dev Internal function to get the Court config ID for a given term * @param _termId Identification number of the term querying the Court config of * @param _lastEnsuredTermId Identification number of the last ensured term of the Court * @return Identification number of the config for the given terms */ function _getConfigIdFor(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns (uint256) { // If the given term is lower or equal to the last ensured Court term, it is safe to use a past Court config if (_termId <= _lastEnsuredTermId) { return configIdByTerm[_termId]; } // If the given term is in the future but there is a config change scheduled before it, use the incoming config uint64 scheduledChangeTermId = configChangeTermId; if (scheduledChangeTermId <= _termId) { return configIdByTerm[scheduledChangeTermId]; } // If no changes are scheduled, use the Court config of the last ensured term return configIdByTerm[_lastEnsuredTermId]; } } // File: contracts/court/controller/Controller.sol pragma solidity ^0.5.8; contract Controller is IsContract, CourtClock, CourtConfig { string private constant ERROR_SENDER_NOT_GOVERNOR = "CTR_SENDER_NOT_GOVERNOR"; string private constant ERROR_INVALID_GOVERNOR_ADDRESS = "CTR_INVALID_GOVERNOR_ADDRESS"; string private constant ERROR_IMPLEMENTATION_NOT_CONTRACT = "CTR_IMPLEMENTATION_NOT_CONTRACT"; string private constant ERROR_INVALID_IMPLS_INPUT_LENGTH = "CTR_INVALID_IMPLS_INPUT_LENGTH"; address private constant ZERO_ADDRESS = address(0); // DisputeManager module ID - keccak256(abi.encodePacked("DISPUTE_MANAGER")) bytes32 internal constant DISPUTE_MANAGER = 0x14a6c70f0f6d449c014c7bbc9e68e31e79e8474fb03b7194df83109a2d888ae6; // Treasury module ID - keccak256(abi.encodePacked("TREASURY")) bytes32 internal constant TREASURY = 0x06aa03964db1f7257357ef09714a5f0ca3633723df419e97015e0c7a3e83edb7; // Voting module ID - keccak256(abi.encodePacked("VOTING")) bytes32 internal constant VOTING = 0x7cbb12e82a6d63ff16fe43977f43e3e2b247ecd4e62c0e340da8800a48c67346; // JurorsRegistry module ID - keccak256(abi.encodePacked("JURORS_REGISTRY")) bytes32 internal constant JURORS_REGISTRY = 0x3b21d36b36308c830e6c4053fb40a3b6d79dde78947fbf6b0accd30720ab5370; // Subscriptions module ID - keccak256(abi.encodePacked("SUBSCRIPTIONS")) bytes32 internal constant SUBSCRIPTIONS = 0x2bfa3327fe52344390da94c32a346eeb1b65a8b583e4335a419b9471e88c1365; // BrightIDRegister module ID - keccak256(abi.encodePacked("BRIGHTID_REGISTER")) bytes32 internal constant BRIGHTID_REGISTER = 0xc8d8a5444a51ecc23e5091f18c4162834512a4bc5cae72c637db45c8c37b3329; /** * @dev Governor of the whole system. Set of three addresses to recover funds, change configuration settings and setup modules */ struct Governor { address funds; // This address can be unset at any time. It is allowed to recover funds from the ControlledRecoverable modules address config; // This address is meant not to be unset. It is allowed to change the different configurations of the whole system address feesUpdater;// This is a second address that can update the config. It is expected to be used with a price oracle for updating fees address modules; // This address can be unset at any time. It is allowed to plug/unplug modules from the system } // Governor addresses of the system Governor private governor; // List of modules registered for the system indexed by ID mapping (bytes32 => address) internal modules; event ModuleSet(bytes32 id, address addr); event FundsGovernorChanged(address previousGovernor, address currentGovernor); event ConfigGovernorChanged(address previousGovernor, address currentGovernor); event FeesUpdaterChanged(address previousFeesUpdater, address currentFeesUpdater); event ModulesGovernorChanged(address previousGovernor, address currentGovernor); /** * @dev Ensure the msg.sender is the funds governor */ modifier onlyFundsGovernor { require(msg.sender == governor.funds, ERROR_SENDER_NOT_GOVERNOR); _; } /** * @dev Ensure the msg.sender is the config governor */ modifier onlyConfigGovernor { require(msg.sender == governor.config, ERROR_SENDER_NOT_GOVERNOR); _; } /** * @dev Ensure the msg.sender is the config governor or the fees updater */ modifier onlyConfigGovernorOrFeesUpdater { require(msg.sender == governor.config || msg.sender == governor.feesUpdater, ERROR_SENDER_NOT_GOVERNOR); _; } /** * @dev Ensure the msg.sender is the modules governor */ modifier onlyModulesGovernor { require(msg.sender == governor.modules, ERROR_SENDER_NOT_GOVERNOR); _; } /** * @dev Constructor function * @param _termParams Array containing: * 0. _termDuration Duration in seconds per term * 1. _firstTermStartTime Timestamp in seconds when the court will open (to give time for juror on-boarding) * @param _governors Array containing: * 0. _fundsGovernor Address of the funds governor * 1. _configGovernor Address of the config governor * 2. _feesUpdater Address of the price feesUpdater * 3. _modulesGovernor Address of the modules governor * @param _feeToken Address of the token contract that is used to pay for fees * @param _fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @param _maxRulingOptions Max number of selectable outcomes for each dispute * @param _roundParams Array containing durations of phases of a dispute and other params for rounds: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * 5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @param _pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked to each drafted jurors (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @param _appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Permyriad multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Permyriad multiple of dispute fees required to confirm appeal * @param _jurorsParams Array containing params for jurors: * 0. minActiveBalance Minimum amount of juror tokens that can be activated * 1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake * 2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake * 3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do */ constructor( uint64[2] memory _termParams, address[4] memory _governors, ERC20 _feeToken, uint256[3] memory _fees, uint8 _maxRulingOptions, uint64[9] memory _roundParams, uint16[2] memory _pcts, uint256[2] memory _appealCollateralParams, uint256[4] memory _jurorsParams ) public CourtClock(_termParams, _feeToken) CourtConfig(_feeToken, _fees, _maxRulingOptions, _roundParams, _pcts, _appealCollateralParams, _jurorsParams) { _setFundsGovernor(_governors[0]); _setConfigGovernor(_governors[1]); _setFeesUpdater(_governors[2]); _setModulesGovernor(_governors[3]); } /** * @notice Change Court configuration params * @param _fromTermId Identification number of the term in which the config will be effective at * @param _feeToken Address of the token contract that is used to pay for fees * @param _fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @param _maxRulingOptions Max number of selectable outcomes for each dispute * @param _roundParams Array containing durations of phases of a dispute and other params for rounds: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * 5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @param _pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked to each drafted jurors (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @param _appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Permyriad multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Permyriad multiple of dispute fees required to confirm appeal * @param _jurorsParams Array containing params for jurors: * 0. minActiveBalance Minimum amount of juror tokens that can be activated * 1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake * 2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake * 3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do */ function setConfig( uint64 _fromTermId, ERC20 _feeToken, uint256[3] calldata _fees, uint8 _maxRulingOptions, uint64[9] calldata _roundParams, uint16[2] calldata _pcts, uint256[2] calldata _appealCollateralParams, uint256[4] calldata _jurorsParams ) external onlyConfigGovernorOrFeesUpdater { uint64 currentTermId = _ensureCurrentTerm(); _setConfig( currentTermId, _fromTermId, _feeToken, _fees, _maxRulingOptions, _roundParams, _pcts, _appealCollateralParams, _jurorsParams ); } /** * @notice Delay the Court start time to `_newFirstTermStartTime` * @param _newFirstTermStartTime New timestamp in seconds when the court will open */ function delayStartTime(uint64 _newFirstTermStartTime) external onlyConfigGovernor { _delayStartTime(_newFirstTermStartTime); } /** * @notice Change funds governor address to `_newFundsGovernor` * @param _newFundsGovernor Address of the new funds governor to be set */ function changeFundsGovernor(address _newFundsGovernor) external onlyFundsGovernor { require(_newFundsGovernor != ZERO_ADDRESS, ERROR_INVALID_GOVERNOR_ADDRESS); _setFundsGovernor(_newFundsGovernor); } /** * @notice Change config governor address to `_newConfigGovernor` * @param _newConfigGovernor Address of the new config governor to be set */ function changeConfigGovernor(address _newConfigGovernor) external onlyConfigGovernor { require(_newConfigGovernor != ZERO_ADDRESS, ERROR_INVALID_GOVERNOR_ADDRESS); _setConfigGovernor(_newConfigGovernor); } /** * @notice Change fees updater to `_newFeesUpdater` * @param _newFeesUpdater Address of the new fees updater to be set */ function changeFeesUpdater(address _newFeesUpdater) external onlyConfigGovernor { _setFeesUpdater(_newFeesUpdater); } /** * @notice Change modules governor address to `_newModulesGovernor` * @param _newModulesGovernor Address of the new governor to be set */ function changeModulesGovernor(address _newModulesGovernor) external onlyModulesGovernor { require(_newModulesGovernor != ZERO_ADDRESS, ERROR_INVALID_GOVERNOR_ADDRESS); _setModulesGovernor(_newModulesGovernor); } /** * @notice Remove the funds governor. Set the funds governor to the zero address. * @dev This action cannot be rolled back, once the funds governor has been unset, funds cannot be recovered from recoverable modules anymore */ function ejectFundsGovernor() external onlyFundsGovernor { _setFundsGovernor(ZERO_ADDRESS); } /** * @notice Remove the modules governor. Set the modules governor to the zero address. * @dev This action cannot be rolled back, once the modules governor has been unset, system modules cannot be changed anymore */ function ejectModulesGovernor() external onlyModulesGovernor { _setModulesGovernor(ZERO_ADDRESS); } /** * @notice Set module `_id` to `_addr` * @param _id ID of the module to be set * @param _addr Address of the module to be set */ function setModule(bytes32 _id, address _addr) external onlyModulesGovernor { _setModule(_id, _addr); } /** * @notice Set many modules at once * @param _ids List of ids of each module to be set * @param _addresses List of addressed of each the module to be set */ function setModules(bytes32[] calldata _ids, address[] calldata _addresses) external onlyModulesGovernor { require(_ids.length == _addresses.length, ERROR_INVALID_IMPLS_INPUT_LENGTH); for (uint256 i = 0; i < _ids.length; i++) { _setModule(_ids[i], _addresses[i]); } } /** * @dev Tell the full Court configuration parameters at a certain term * @param _termId Identification number of the term querying the Court config of * @return token Address of the token used to pay for fees * @return fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @return maxRulingOptions Max number of selectable outcomes for each dispute * @return roundParams Array containing durations of phases of a dispute and other params for rounds: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * 5. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 6. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 7. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 8. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @return pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @return appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal * @return jurorsParams Array containing params for juror registry: * 0. minActiveBalance Minimum amount of juror tokens that can be activated * 1. minMaxPctTotalSupply The min max percent of the total supply a juror can activate, applied for total supply active stake * 2. maxMaxPctTotalSupply The max max percent of the total supply a juror can activate, applied for 0 active stake\ * 3. feeTokenTotalSupply Set for networks that don't have access to the fee token's total supply, set to 0 for networks that do */ function getConfig(uint64 _termId) external view returns ( ERC20 feeToken, uint256[3] memory fees, uint8 maxRulingOptions, uint64[9] memory roundParams, uint16[2] memory pcts, uint256[2] memory appealCollateralParams, uint256[4] memory jurorsParams ) { return _getConfig(_termId); } /** * @dev This function overrides one in the CourtClock, giving the CourtClock access to the config. */ function _getConfig(uint64 _termId) internal view returns ( ERC20 feeToken, uint256[3] memory fees, uint8 maxRulingOptions, uint64[9] memory roundParams, uint16[2] memory pcts, uint256[2] memory appealCollateralParams, uint256[4] memory jurorsParams ) { uint64 lastEnsuredTermId = _lastEnsuredTermId(); return _getConfigAt(_termId, lastEnsuredTermId); } /** * @dev Tell the draft config at a certain term * @param _termId Identification number of the term querying the draft config of * @return feeToken Address of the token used to pay for fees * @return draftFee Amount of fee tokens per juror to cover the drafting cost * @return penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) */ function getDraftConfig(uint64 _termId) external view returns (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct) { uint64 lastEnsuredTermId = _lastEnsuredTermId(); return _getDraftConfig(_termId, lastEnsuredTermId); } /** * @dev Tell the min active balance config at a certain term * @param _termId Identification number of the term querying the min active balance config of * @return Minimum amount of tokens jurors have to activate to participate in the Court */ function getMinActiveBalance(uint64 _termId) external view returns (uint256) { uint64 lastEnsuredTermId = _lastEnsuredTermId(); return _getMinActiveBalance(_termId, lastEnsuredTermId); } /** * @dev Tell the address of the funds governor * @return Address of the funds governor */ function getFundsGovernor() external view returns (address) { return governor.funds; } /** * @dev Tell the address of the config governor * @return Address of the config governor */ function getConfigGovernor() external view returns (address) { return governor.config; } /** * @dev Tell the address of the fees updater * @return Address of the fees updater */ function getFeesUpdater() external view returns (address) { return governor.feesUpdater; } /** * @dev Tell the address of the modules governor * @return Address of the modules governor */ function getModulesGovernor() external view returns (address) { return governor.modules; } /** * @dev Tell address of a module based on a given ID * @param _id ID of the module being queried * @return Address of the requested module */ function getModule(bytes32 _id) external view returns (address) { return _getModule(_id); } /** * @dev Tell the address of the DisputeManager module * @return Address of the DisputeManager module */ function getDisputeManager() external view returns (address) { return _getDisputeManager(); } /** * @dev Tell the address of the Treasury module * @return Address of the Treasury module */ function getTreasury() external view returns (address) { return _getModule(TREASURY); } /** * @dev Tell the address of the Voting module * @return Address of the Voting module */ function getVoting() external view returns (address) { return _getModule(VOTING); } /** * @dev Tell the address of the JurorsRegistry module * @return Address of the JurorsRegistry module */ function getJurorsRegistry() external view returns (address) { return _getModule(JURORS_REGISTRY); } /** * @dev Tell the address of the Subscriptions module * @return Address of the Subscriptions module */ function getSubscriptions() external view returns (address) { return _getSubscriptions(); } /** * @dev Tell the address of the BrightId register * @return Address of the BrightId register */ function getBrightIdRegister() external view returns (address) { return _getBrightIdRegister(); } /** * @dev Internal function to set the address of the funds governor * @param _newFundsGovernor Address of the new config governor to be set */ function _setFundsGovernor(address _newFundsGovernor) internal { emit FundsGovernorChanged(governor.funds, _newFundsGovernor); governor.funds = _newFundsGovernor; } /** * @dev Internal function to set the address of the config governor * @param _newConfigGovernor Address of the new config governor to be set */ function _setConfigGovernor(address _newConfigGovernor) internal { emit ConfigGovernorChanged(governor.config, _newConfigGovernor); governor.config = _newConfigGovernor; } /** * @dev Internal function to set the address of the fees updater * @param _newFeesUpdater Address of the new fees updater to be set */ function _setFeesUpdater(address _newFeesUpdater) internal { emit FeesUpdaterChanged(governor.feesUpdater, _newFeesUpdater); governor.feesUpdater = _newFeesUpdater; } /** * @dev Internal function to set the address of the modules governor * @param _newModulesGovernor Address of the new modules governor to be set */ function _setModulesGovernor(address _newModulesGovernor) internal { emit ModulesGovernorChanged(governor.modules, _newModulesGovernor); governor.modules = _newModulesGovernor; } /** * @dev Internal function to set a module * @param _id Id of the module to be set * @param _addr Address of the module to be set */ function _setModule(bytes32 _id, address _addr) internal { require(isContract(_addr), ERROR_IMPLEMENTATION_NOT_CONTRACT); modules[_id] = _addr; emit ModuleSet(_id, _addr); } /** * @dev Internal function to notify when a term has been transitioned * @param _termId Identification number of the new current term that has been transitioned */ function _onTermTransitioned(uint64 _termId) internal { _ensureTermConfig(_termId); } /** * @dev Internal function to tell the address of the DisputeManager module * @return Address of the DisputeManager module */ function _getDisputeManager() internal view returns (address) { return _getModule(DISPUTE_MANAGER); } /** * @dev Internal function to tell the address of the Subscriptions module * @return Address of the Subscriptions module */ function _getSubscriptions() internal view returns (address) { return _getModule(SUBSCRIPTIONS); } /** * @dev Internal function to tell the address of the BrightId register * @return Address of the BrightId register */ function _getBrightIdRegister() internal view returns (address) { return _getModule(BRIGHTID_REGISTER); } /** * @dev Internal function to tell address of a module based on a given ID * @param _id ID of the module being queried * @return Address of the requested module */ function _getModule(bytes32 _id) internal view returns (address) { return modules[_id]; } } // File: contracts/court/config/ConfigConsumer.sol pragma solidity ^0.5.8; contract ConfigConsumer is CourtConfigData { /** * @dev Internal function to fetch the address of the Config module from the controller * @return Address of the Config module */ function _courtConfig() internal view returns (IConfig); /** * @dev Internal function to get the Court config for a certain term * @param _termId Identification number of the term querying the Court config of * @return Court config for the given term */ function _getConfigAt(uint64 _termId) internal view returns (Config memory) { (ERC20 _feeToken, uint256[3] memory _fees, uint8 maxRulingOptions, uint64[9] memory _roundParams, uint16[2] memory _pcts, uint256[2] memory _appealCollateralParams, uint256[4] memory _jurorsParams) = _courtConfig().getConfig(_termId); Config memory config; config.fees = FeesConfig({ token: _feeToken, jurorFee: _fees[0], draftFee: _fees[1], settleFee: _fees[2], finalRoundReduction: _pcts[1] }); config.disputes = DisputesConfig({ maxRulingOptions: maxRulingOptions, evidenceTerms: _roundParams[0], commitTerms: _roundParams[1], revealTerms: _roundParams[2], appealTerms: _roundParams[3], appealConfirmTerms: _roundParams[4], penaltyPct: _pcts[0], firstRoundJurorsNumber: _roundParams[5], appealStepFactor: _roundParams[6], maxRegularAppealRounds: _roundParams[7], finalRoundLockTerms: _roundParams[8], appealCollateralFactor: _appealCollateralParams[0], appealConfirmCollateralFactor: _appealCollateralParams[1] }); config.jurors = JurorsConfig({ minActiveBalance: _jurorsParams[0], minMaxPctTotalSupply: _jurorsParams[1], maxMaxPctTotalSupply: _jurorsParams[2], feeTokenTotalSupply: _jurorsParams[3] }); return config; } /** * @dev Internal function to get the draft config for a given term * @param _termId Identification number of the term querying the draft config of * @return Draft config for the given term */ function _getDraftConfig(uint64 _termId) internal view returns (DraftConfig memory) { (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct) = _courtConfig().getDraftConfig(_termId); return DraftConfig({ feeToken: feeToken, draftFee: draftFee, penaltyPct: penaltyPct }); } /** * @dev Internal function to get the min active balance config for a given term * @param _termId Identification number of the term querying the min active balance config of * @return Minimum amount of juror tokens that can be activated */ function _getMinActiveBalance(uint64 _termId) internal view returns (uint256) { return _courtConfig().getMinActiveBalance(_termId); } } // File: contracts/brightid/IBrightIdRegister.sol pragma solidity ^0.5.8; contract IBrightIdRegister { function isVerified(address _brightIdUser) external view returns (bool); function hasUniqueUserId(address _brightIdUser) external view returns (bool); function uniqueUserId(address _brightIdUser) external view returns (address); } // File: contracts/court/controller/Controlled.sol pragma solidity ^0.5.8; contract Controlled is IsContract, ConfigConsumer { string private constant ERROR_CONTROLLER_NOT_CONTRACT = "CTD_CONTROLLER_NOT_CONTRACT"; string private constant ERROR_SENDER_NOT_CONTROLLER = "CTD_SENDER_NOT_CONTROLLER"; string private constant ERROR_SENDER_NOT_CONFIG_GOVERNOR = "CTD_SENDER_NOT_CONFIG_GOVERNOR"; string private constant ERROR_SENDER_NOT_DISPUTES_MODULE = "CTD_SENDER_NOT_DISPUTES_MODULE"; // Address of the controller Controller internal controller; /** * @dev Ensure the msg.sender is the controller's config governor */ modifier onlyConfigGovernor { require(msg.sender == _configGovernor(), ERROR_SENDER_NOT_CONFIG_GOVERNOR); _; } /** * @dev Ensure the msg.sender is the controller */ modifier onlyController() { require(msg.sender == address(controller), ERROR_SENDER_NOT_CONTROLLER); _; } /** * @dev Ensure the msg.sender is the DisputeManager module */ modifier onlyDisputeManager() { require(msg.sender == address(_disputeManager()), ERROR_SENDER_NOT_DISPUTES_MODULE); _; } /** * @dev Constructor function * @param _controller Address of the controller */ constructor(Controller _controller) public { require(isContract(address(_controller)), ERROR_CONTROLLER_NOT_CONTRACT); controller = _controller; } /** * @dev Tell the address of the controller * @return Address of the controller */ function getController() external view returns (Controller) { return controller; } /** * @dev Internal function to ensure the Court term is up-to-date, it will try to update it if not * @return Identification number of the current Court term */ function _ensureCurrentTerm() internal returns (uint64) { return _clock().ensureCurrentTerm(); } /** * @dev Internal function to fetch the last ensured term ID of the Court * @return Identification number of the last ensured term */ function _getLastEnsuredTermId() internal view returns (uint64) { return _clock().getLastEnsuredTermId(); } /** * @dev Internal function to tell the current term identification number * @return Identification number of the current term */ function _getCurrentTermId() internal view returns (uint64) { return _clock().getCurrentTermId(); } /** * @dev Internal function to fetch the controller's config governor * @return Address of the controller's governor */ function _configGovernor() internal view returns (address) { return controller.getConfigGovernor(); } /** * @dev Internal function to fetch the address of the DisputeManager module from the controller * @return Address of the DisputeManager module */ function _disputeManager() internal view returns (IDisputeManager) { return IDisputeManager(controller.getDisputeManager()); } /** * @dev Internal function to fetch the address of the Treasury module implementation from the controller * @return Address of the Treasury module implementation */ function _treasury() internal view returns (ITreasury) { return ITreasury(controller.getTreasury()); } /** * @dev Internal function to fetch the address of the Voting module implementation from the controller * @return Address of the Voting module implementation */ function _voting() internal view returns (ICRVoting) { return ICRVoting(controller.getVoting()); } /** * @dev Internal function to fetch the address of the Voting module owner from the controller * @return Address of the Voting module owner */ function _votingOwner() internal view returns (ICRVotingOwner) { return ICRVotingOwner(address(_disputeManager())); } /** * @dev Internal function to fetch the address of the JurorRegistry module implementation from the controller * @return Address of the JurorRegistry module implementation */ function _jurorsRegistry() internal view returns (IJurorsRegistry) { return IJurorsRegistry(controller.getJurorsRegistry()); } /** * @dev Internal function to fetch the address of the BrightId register implementation from the controller * @return Address of the BrightId register implementation */ function _brightIdRegister() internal view returns (IBrightIdRegister) { return IBrightIdRegister(controller.getBrightIdRegister()); } /** * @dev Internal function to fetch the address of the Clock module from the controller * @return Address of the Clock module */ function _clock() internal view returns (IClock) { return IClock(controller); } /** * @dev Internal function to fetch the address of the Config module from the controller * @return Address of the Config module */ function _courtConfig() internal view returns (IConfig) { return IConfig(controller); } } // File: contracts/court/controller/ControlledRecoverable.sol pragma solidity ^0.5.8; contract ControlledRecoverable is Controlled { using SafeERC20 for ERC20; string private constant ERROR_SENDER_NOT_FUNDS_GOVERNOR = "CTD_SENDER_NOT_FUNDS_GOVERNOR"; string private constant ERROR_INSUFFICIENT_RECOVER_FUNDS = "CTD_INSUFFICIENT_RECOVER_FUNDS"; string private constant ERROR_RECOVER_TOKEN_FUNDS_FAILED = "CTD_RECOVER_TOKEN_FUNDS_FAILED"; event RecoverFunds(ERC20 token, address recipient, uint256 balance); /** * @dev Ensure the msg.sender is the controller's funds governor */ modifier onlyFundsGovernor { require(msg.sender == controller.getFundsGovernor(), ERROR_SENDER_NOT_FUNDS_GOVERNOR); _; } /** * @dev Constructor function * @param _controller Address of the controller */ constructor(Controller _controller) Controlled(_controller) public { // solium-disable-previous-line no-empty-blocks } /** * @notice Transfer all `_token` tokens to `_to` * @param _token ERC20 token to be recovered * @param _to Address of the recipient that will be receive all the funds of the requested token */ function recoverFunds(ERC20 _token, address _to) external onlyFundsGovernor { uint256 balance = _token.balanceOf(address(this)); require(balance > 0, ERROR_INSUFFICIENT_RECOVER_FUNDS); require(_token.safeTransfer(_to, balance), ERROR_RECOVER_TOKEN_FUNDS_FAILED); emit RecoverFunds(_token, _to, balance); } } // File: contracts/disputes/DisputeManager.sol pragma solidity ^0.5.8; contract DisputeManager is ControlledRecoverable, ICRVotingOwner, IDisputeManager { using SafeERC20 for ERC20; using SafeMath for uint256; using SafeMath64 for uint64; using PctHelpers for uint256; using Uint256Helpers for uint256; // Voting-related error messages string private constant ERROR_VOTER_WEIGHT_ZERO = "DM_VOTER_WEIGHT_ZERO"; string private constant ERROR_SENDER_NOT_VOTING = "DM_SENDER_NOT_VOTING"; // Disputes-related error messages string private constant ERROR_SUBJECT_NOT_DISPUTE_SUBJECT = "DM_SUBJECT_NOT_DISPUTE_SUBJECT"; string private constant ERROR_EVIDENCE_PERIOD_IS_CLOSED = "DM_EVIDENCE_PERIOD_IS_CLOSED"; string private constant ERROR_TERM_OUTDATED = "DM_TERM_OUTDATED"; string private constant ERROR_DISPUTE_DOES_NOT_EXIST = "DM_DISPUTE_DOES_NOT_EXIST"; string private constant ERROR_INVALID_RULING_OPTIONS = "DM_INVALID_RULING_OPTIONS"; string private constant ERROR_DEPOSIT_FAILED = "DM_DEPOSIT_FAILED"; string private constant ERROR_BAD_MAX_DRAFT_BATCH_SIZE = "DM_BAD_MAX_DRAFT_BATCH_SIZE"; // Rounds-related error messages string private constant ERROR_ROUND_IS_FINAL = "DM_ROUND_IS_FINAL"; string private constant ERROR_ROUND_DOES_NOT_EXIST = "DM_ROUND_DOES_NOT_EXIST"; string private constant ERROR_INVALID_ADJUDICATION_STATE = "DM_INVALID_ADJUDICATION_STATE"; string private constant ERROR_ROUND_ALREADY_DRAFTED = "DM_ROUND_ALREADY_DRAFTED"; string private constant ERROR_DRAFT_TERM_NOT_REACHED = "DM_DRAFT_TERM_NOT_REACHED"; string private constant ERROR_ROUND_NOT_APPEALED = "DM_ROUND_NOT_APPEALED"; string private constant ERROR_INVALID_APPEAL_RULING = "DM_INVALID_APPEAL_RULING"; // Settlements-related error messages string private constant ERROR_PREV_ROUND_NOT_SETTLED = "DM_PREVIOUS_ROUND_NOT_SETTLED"; string private constant ERROR_ROUND_ALREADY_SETTLED = "DM_ROUND_ALREADY_SETTLED"; string private constant ERROR_ROUND_NOT_SETTLED = "DM_ROUND_PENALTIES_NOT_SETTLED"; string private constant ERROR_JUROR_ALREADY_REWARDED = "DM_JUROR_ALREADY_REWARDED"; string private constant ERROR_WONT_REWARD_NON_VOTER_JUROR = "DM_WONT_REWARD_NON_VOTER_JUROR"; string private constant ERROR_WONT_REWARD_INCOHERENT_JUROR = "DM_WONT_REWARD_INCOHERENT_JUROR"; string private constant ERROR_ROUND_APPEAL_ALREADY_SETTLED = "DM_APPEAL_ALREADY_SETTLED"; // Minimum possible rulings for a dispute uint8 internal constant MIN_RULING_OPTIONS = 2; // Precision factor used to improve rounding when computing weights for the final round uint256 internal constant FINAL_ROUND_WEIGHT_PRECISION = 1000; // Mask used to decode vote IDs uint256 internal constant VOTE_ID_MASK = 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; struct Dispute { IArbitrable subject; // Arbitrable associated to a dispute uint64 createTermId; // Term ID when the dispute was created uint8 possibleRulings; // Number of possible rulings jurors can vote for each dispute uint8 finalRuling; // Winning ruling of a dispute DisputeState state; // State of a dispute: pre-draft, adjudicating, or ruled AdjudicationRound[] rounds; // List of rounds for each dispute } struct AdjudicationRound { uint64 draftTermId; // Term from which the jurors of a round can be drafted uint64 jurorsNumber; // Number of jurors drafted for a round bool settledPenalties; // Whether or not penalties have been settled for a round uint256 jurorFees; // Total amount of fees to be distributed between the winning jurors of a round address[] jurors; // List of jurors drafted for a round mapping (address => JurorState) jurorsStates; // List of states for each drafted juror indexed by address uint64 delayedTerms; // Number of terms a round was delayed based on its requested draft term id uint64 selectedJurors; // Number of jurors selected for a round, to allow drafts to be batched uint64 coherentJurors; // Number of drafted jurors that voted in favor of the dispute final ruling uint64 settledJurors; // Number of jurors whose rewards were already settled uint256 collectedTokens; // Total amount of tokens collected from losing jurors Appeal appeal; // Appeal-related information of a round } struct JurorState { uint64 weight; // Weight computed for a juror on a round bool rewarded; // Whether or not a drafted juror was rewarded } struct Appeal { address maker; // Address of the appealer uint8 appealedRuling; // Ruling appealing in favor of address taker; // Address of the one confirming an appeal uint8 opposedRuling; // Ruling opposed to an appeal bool settled; // Whether or not an appeal has been settled } struct DraftParams { uint256 disputeId; // Identification number of the dispute to be drafted uint256 roundId; // Identification number of the round to be drafted uint64 termId; // Identification number of the current term of the Court bytes32 draftTermRandomness; // Randomness of the term in which the dispute was requested to be drafted DraftConfig config; // Draft config of the Court at the draft term } struct NextRoundDetails { uint64 startTerm; // Term ID from which the next round will start uint64 jurorsNumber; // Jurors number for the next round DisputeState newDisputeState; // New state for the dispute associated to the given round after the appeal ERC20 feeToken; // ERC20 token used for the next round fees uint256 totalFees; // Total amount of fees to be distributed between the winning jurors of the next round uint256 jurorFees; // Total amount of fees for a regular round at the given term uint256 appealDeposit; // Amount to be deposit of fees for a regular round at the given term uint256 confirmAppealDeposit; // Total amount of fees for a regular round at the given term } // Max jurors to be drafted in each batch. To prevent running out of gas. We allow to change it because max gas per tx can vary // As a reference, drafting 100 jurors from a small tree of 4 would cost ~2.4M. Drafting 500, ~7.75M. uint64 public maxJurorsPerDraftBatch; // List of all the disputes created in the Court Dispute[] internal disputes; event DisputeStateChanged(uint256 indexed disputeId, DisputeState indexed state); event EvidenceSubmitted(uint256 indexed disputeId, address indexed submitter, bytes evidence); event EvidencePeriodClosed(uint256 indexed disputeId, uint64 indexed termId); event NewDispute(uint256 indexed disputeId, IArbitrable indexed subject, uint64 indexed draftTermId, uint64 jurorsNumber, bytes metadata); event JurorDrafted(uint256 indexed disputeId, uint256 indexed roundId, address indexed juror); event RulingAppealed(uint256 indexed disputeId, uint256 indexed roundId, uint8 ruling); event RulingAppealConfirmed(uint256 indexed disputeId, uint256 indexed roundId, uint64 indexed draftTermId, uint256 jurorsNumber); event RulingComputed(uint256 indexed disputeId, uint8 indexed ruling); event PenaltiesSettled(uint256 indexed disputeId, uint256 indexed roundId, uint256 collectedTokens); event RewardSettled(uint256 indexed disputeId, uint256 indexed roundId, address juror, uint256 tokens, uint256 fees); event AppealDepositSettled(uint256 indexed disputeId, uint256 indexed roundId); event MaxJurorsPerDraftBatchChanged(uint64 previousMaxJurorsPerDraftBatch, uint64 currentMaxJurorsPerDraftBatch); /** * @dev Ensure the msg.sender is the CR Voting module */ modifier onlyVoting() { ICRVoting voting = _voting(); require(msg.sender == address(voting), ERROR_SENDER_NOT_VOTING); _; } /** * @dev Ensure a dispute exists * @param _disputeId Identification number of the dispute to be ensured */ modifier disputeExists(uint256 _disputeId) { _checkDisputeExists(_disputeId); _; } /** * @dev Ensure a dispute round exists * @param _disputeId Identification number of the dispute to be ensured * @param _roundId Identification number of the dispute round to be ensured */ modifier roundExists(uint256 _disputeId, uint256 _roundId) { _checkRoundExists(_disputeId, _roundId); _; } /** * @dev Constructor function * @param _controller Address of the controller * @param _maxJurorsPerDraftBatch Max number of jurors to be drafted per batch * @param _skippedDisputes Number of disputes to be skipped */ constructor(Controller _controller, uint64 _maxJurorsPerDraftBatch, uint256 _skippedDisputes) ControlledRecoverable(_controller) public { // No need to explicitly call `Controlled` constructor since `ControlledRecoverable` is already doing it _setMaxJurorsPerDraftBatch(_maxJurorsPerDraftBatch); _skipDisputes(_skippedDisputes); } /** * @notice Create a dispute over `_subject` with `_possibleRulings` possible rulings * @param _subject Arbitrable instance creating the dispute * @param _possibleRulings Number of possible rulings allowed for the drafted jurors to vote on the dispute * @param _metadata Optional metadata that can be used to provide additional information on the dispute to be created * @return Dispute identification number */ function createDispute(IArbitrable _subject, uint8 _possibleRulings, bytes calldata _metadata) external onlyController returns (uint256) { uint64 termId = _ensureCurrentTerm(); Config memory config = _getConfigAt(termId); require(_possibleRulings >= MIN_RULING_OPTIONS && _possibleRulings <= config.disputes.maxRulingOptions, ERROR_INVALID_RULING_OPTIONS); // Create the dispute uint256 disputeId = disputes.length++; Dispute storage dispute = disputes[disputeId]; dispute.subject = _subject; dispute.possibleRulings = _possibleRulings; dispute.createTermId = termId; uint64 jurorsNumber = config.disputes.firstRoundJurorsNumber; uint64 draftTermId = termId.add(config.disputes.evidenceTerms); emit NewDispute(disputeId, _subject, draftTermId, jurorsNumber, _metadata); // Create first adjudication round of the dispute (ERC20 feeToken, uint256 jurorFees, uint256 totalFees) = _getRegularRoundFees(config.fees, jurorsNumber); _createRound(disputeId, DisputeState.PreDraft, draftTermId, jurorsNumber, jurorFees); // Pay round fees and return dispute id _depositAmount(address(_subject), feeToken, totalFees); return disputeId; } /** * @notice Submit evidence for a dispute #`_disputeId` * @param _subject Arbitrable instance submitting the dispute * @param _disputeId Identification number of the dispute receiving new evidence * @param _submitter Address of the account submitting the evidence * @param _evidence Data submitted for the evidence of the dispute */ function submitEvidence(IArbitrable _subject, uint256 _disputeId, address _submitter, bytes calldata _evidence) external onlyController disputeExists(_disputeId) { Dispute storage dispute = disputes[_disputeId]; require(dispute.subject == _subject, ERROR_SUBJECT_NOT_DISPUTE_SUBJECT); emit EvidenceSubmitted(_disputeId, _submitter, _evidence); } /** * @notice Close the evidence period of dispute #`_disputeId` * @param _subject IArbitrable instance requesting to close the evidence submission period * @param _disputeId Identification number of the dispute to close its evidence submitting period */ function closeEvidencePeriod(IArbitrable _subject, uint256 _disputeId) external onlyController roundExists(_disputeId, 0) { Dispute storage dispute = disputes[_disputeId]; AdjudicationRound storage round = dispute.rounds[0]; require(dispute.subject == _subject, ERROR_SUBJECT_NOT_DISPUTE_SUBJECT); // Check current term is within the evidence submission period uint64 termId = _ensureCurrentTerm(); uint64 newDraftTermId = termId.add(1); require(newDraftTermId < round.draftTermId, ERROR_EVIDENCE_PERIOD_IS_CLOSED); // Update the draft term of the first round to the next term round.draftTermId = newDraftTermId; emit EvidencePeriodClosed(_disputeId, termId); } /** * @notice Draft jurors for the next round of dispute #`_disputeId` * @param _disputeId Identification number of the dispute to be drafted */ function draft(uint256 _disputeId) external disputeExists(_disputeId) { // Drafts can only be computed when the Court is up-to-date. Note that forcing a term transition won't work since the term randomness // is always based on the next term which means it won't be available anyway. IClock clock = _clock(); uint64 requiredTransitions = _clock().getNeededTermTransitions(); require(uint256(requiredTransitions) == 0, ERROR_TERM_OUTDATED); uint64 currentTermId = _getLastEnsuredTermId(); // Ensure dispute has not been drafted yet Dispute storage dispute = disputes[_disputeId]; require(dispute.state == DisputeState.PreDraft, ERROR_ROUND_ALREADY_DRAFTED); // Ensure draft term randomness can be computed for the current block number uint256 roundId = dispute.rounds.length - 1; AdjudicationRound storage round = dispute.rounds[roundId]; uint64 draftTermId = round.draftTermId; require(draftTermId <= currentTermId, ERROR_DRAFT_TERM_NOT_REACHED); bytes32 draftTermRandomness = clock.ensureCurrentTermRandomness(); // Draft jurors for the given dispute and reimburse fees DraftConfig memory config = _getDraftConfig(draftTermId); bool draftEnded = _draft(round, _buildDraftParams(_disputeId, roundId, currentTermId, draftTermRandomness, config)); // If the drafting is over, update its state if (draftEnded) { // No need for SafeMath: we ensured `currentTermId` is greater than or equal to `draftTermId` above round.delayedTerms = currentTermId - draftTermId; dispute.state = DisputeState.Adjudicating; emit DisputeStateChanged(_disputeId, DisputeState.Adjudicating); } } /** * @notice Appeal round #`_roundId` of dispute #`_disputeId` in favor of ruling `_ruling` * @param _disputeId Identification number of the dispute being appealed * @param _roundId Identification number of the dispute round being appealed * @param _ruling Ruling appealing a dispute round in favor of */ function createAppeal(uint256 _disputeId, uint256 _roundId, uint8 _ruling) external roundExists(_disputeId, _roundId) { // Ensure current term and check that the given round can be appealed. // Note that if there was a final appeal the adjudication state will be 'Ended'. Dispute storage dispute = disputes[_disputeId]; Config memory config = _getDisputeConfig(dispute); _ensureAdjudicationState(dispute, _roundId, AdjudicationState.Appealing, config.disputes); // Ensure that the ruling being appealed in favor of is valid and different from the current winning ruling ICRVoting voting = _voting(); uint256 voteId = _getVoteId(_disputeId, _roundId); uint8 roundWinningRuling = voting.getWinningOutcome(voteId); require(roundWinningRuling != _ruling && voting.isValidOutcome(voteId, _ruling), ERROR_INVALID_APPEAL_RULING); // Update round appeal state AdjudicationRound storage round = dispute.rounds[_roundId]; Appeal storage appeal = round.appeal; appeal.maker = msg.sender; appeal.appealedRuling = _ruling; emit RulingAppealed(_disputeId, _roundId, _ruling); // Pay appeal deposit NextRoundDetails memory nextRound = _getNextRoundDetails(round, _roundId, config); _depositAmount(msg.sender, nextRound.feeToken, nextRound.appealDeposit); } /** * @notice Confirm appeal for round #`_roundId` of dispute #`_disputeId` in favor of ruling `_ruling` * @param _disputeId Identification number of the dispute confirming an appeal of * @param _roundId Identification number of the dispute round confirming an appeal of * @param _ruling Ruling being confirmed against a dispute round appeal */ function confirmAppeal(uint256 _disputeId, uint256 _roundId, uint8 _ruling) external roundExists(_disputeId, _roundId) { // Ensure current term and check that the given round is appealed and can be confirmed. // Note that if there was a final appeal the adjudication state will be 'Ended'. Dispute storage dispute = disputes[_disputeId]; Config memory config = _getDisputeConfig(dispute); _ensureAdjudicationState(dispute, _roundId, AdjudicationState.ConfirmingAppeal, config.disputes); // Ensure that the ruling being confirmed in favor of is valid and different from the appealed ruling AdjudicationRound storage round = dispute.rounds[_roundId]; Appeal storage appeal = round.appeal; uint256 voteId = _getVoteId(_disputeId, _roundId); require(appeal.appealedRuling != _ruling && _voting().isValidOutcome(voteId, _ruling), ERROR_INVALID_APPEAL_RULING); // Create a new adjudication round for the dispute NextRoundDetails memory nextRound = _getNextRoundDetails(round, _roundId, config); DisputeState newDisputeState = nextRound.newDisputeState; uint256 newRoundId = _createRound(_disputeId, newDisputeState, nextRound.startTerm, nextRound.jurorsNumber, nextRound.jurorFees); // Update previous round appeal state appeal.taker = msg.sender; appeal.opposedRuling = _ruling; emit RulingAppealConfirmed(_disputeId, newRoundId, nextRound.startTerm, nextRound.jurorsNumber); // Pay appeal confirm deposit _depositAmount(msg.sender, nextRound.feeToken, nextRound.confirmAppealDeposit); } /** * @notice Compute the final ruling for dispute #`_disputeId` * @param _disputeId Identification number of the dispute to compute its final ruling * @return subject Arbitrable instance associated to the dispute * @return finalRuling Final ruling decided for the given dispute */ function computeRuling(uint256 _disputeId) external disputeExists(_disputeId) returns (IArbitrable subject, uint8 finalRuling) { Dispute storage dispute = disputes[_disputeId]; subject = dispute.subject; Config memory config = _getDisputeConfig(dispute); finalRuling = _ensureFinalRuling(dispute, _disputeId, config); if (dispute.state != DisputeState.Ruled) { dispute.state = DisputeState.Ruled; emit RulingComputed(_disputeId, finalRuling); } } /** * @notice Settle penalties for round #`_roundId` of dispute #`_disputeId` * @dev In case of a regular round, all the drafted jurors that didn't vote in favor of the final ruling of the given dispute will be slashed. * In case of a final round, jurors are slashed when voting, thus it is considered these rounds settled at once. Rewards have to be * manually claimed through `settleReward` which will return pre-slashed tokens for the winning jurors of a final round as well. * @param _disputeId Identification number of the dispute to settle penalties for * @param _roundId Identification number of the dispute round to settle penalties for * @param _jurorsToSettle Maximum number of jurors to be slashed in this call. It can be set to zero to slash all the losing jurors of the * given round. This argument is only used when settling regular rounds. */ function settlePenalties(uint256 _disputeId, uint256 _roundId, uint256 _jurorsToSettle) external roundExists(_disputeId, _roundId) { // Enforce that rounds are settled in order to avoid one round without incentive to settle. Even if there is a settle fee // it may not be big enough and all jurors in the round could be slashed. Dispute storage dispute = disputes[_disputeId]; require(_roundId == 0 || dispute.rounds[_roundId - 1].settledPenalties, ERROR_PREV_ROUND_NOT_SETTLED); // Ensure given round has not been fully settled yet AdjudicationRound storage round = dispute.rounds[_roundId]; require(!round.settledPenalties, ERROR_ROUND_ALREADY_SETTLED); // Ensure the final ruling of the given dispute is already computed Config memory config = _getDisputeConfig(dispute); uint8 finalRuling = _ensureFinalRuling(dispute, _disputeId, config); // Set the number of jurors that voted in favor of the final ruling if we haven't started settling yet uint256 voteId = _getVoteId(_disputeId, _roundId); if (round.settledJurors == 0) { // Note that we are safe to cast the tally of a ruling to uint64 since the highest value a ruling can have is equal to the jurors // number for regular rounds or to the total active balance of the registry for final rounds, and both are ensured to fit in uint64. ICRVoting voting = _voting(); round.coherentJurors = uint64(voting.getOutcomeTally(voteId, finalRuling)); } ITreasury treasury = _treasury(); ERC20 feeToken = config.fees.token; if (_isRegularRound(_roundId, config)) { // For regular appeal rounds we compute the amount of locked tokens that needs to get burned in batches. // The callers of this function will get rewarded in this case. uint256 jurorsSettled = _settleRegularRoundPenalties(round, voteId, finalRuling, config.disputes.penaltyPct, _jurorsToSettle, config.jurors.minActiveBalance); treasury.assign(feeToken, msg.sender, config.fees.settleFee.mul(jurorsSettled)); } else { // For the final appeal round, there is no need to settle in batches since, to guarantee scalability, // all the tokens are collected from jurors when they vote, and those jurors who // voted in favor of the winning ruling can claim their collected tokens back along with their reward. // Note that the caller of this function is not being reimbursed. round.settledPenalties = true; } if (round.settledPenalties) { uint256 collectedTokens = round.collectedTokens; emit PenaltiesSettled(_disputeId, _roundId, collectedTokens); _burnCollectedTokensIfNecessary(dispute, round, _roundId, treasury, feeToken, collectedTokens); } } /** * @notice Claim reward for round #`_roundId` of dispute #`_disputeId` for juror `_juror` * @dev For regular rounds, it will only reward winning jurors * @param _disputeId Identification number of the dispute to settle rewards for * @param _roundId Identification number of the dispute round to settle rewards for * @param _juror Address of the juror to settle their rewards */ function settleReward(uint256 _disputeId, uint256 _roundId, address _juror) external roundExists(_disputeId, _roundId) { // Ensure dispute round penalties are settled first Dispute storage dispute = disputes[_disputeId]; AdjudicationRound storage round = dispute.rounds[_roundId]; require(round.settledPenalties, ERROR_ROUND_NOT_SETTLED); // Ensure given juror was not rewarded yet and was drafted for the given round JurorState storage jurorState = round.jurorsStates[_juror]; require(!jurorState.rewarded, ERROR_JUROR_ALREADY_REWARDED); require(uint256(jurorState.weight) > 0, ERROR_WONT_REWARD_NON_VOTER_JUROR); jurorState.rewarded = true; // Check if the given juror has voted in favor of the final ruling of the dispute in this round ICRVoting voting = _voting(); uint256 voteId = _getVoteId(_disputeId, _roundId); require(voting.hasVotedInFavorOf(voteId, dispute.finalRuling, _juror), ERROR_WONT_REWARD_INCOHERENT_JUROR); uint256 collectedTokens = round.collectedTokens; IJurorsRegistry jurorsRegistry = _jurorsRegistry(); // Distribute the collected tokens of the jurors that were slashed weighted by the winning jurors. Note that we are penalizing jurors // that refused intentionally their vote for the final round. uint256 rewardTokens; if (collectedTokens > 0) { // Note that the number of coherent jurors has to be greater than zero since we already ensured the juror has voted in favor of the // final ruling, therefore there will be at least one coherent juror and divisions below are safe. rewardTokens = _getRoundWeightedAmount(round, jurorState, collectedTokens); jurorsRegistry.assignTokens(_juror, rewardTokens); } // Reward the winning juror with fees Config memory config = _getDisputeConfig(dispute); // Note that the number of coherent jurors has to be greater than zero since we already ensured the juror has voted in favor of the // final ruling, therefore there will be at least one coherent juror and divisions below are safe. uint256 rewardFees = _getRoundWeightedAmount(round, jurorState, round.jurorFees); _treasury().assign(config.fees.token, _juror, rewardFees); // Set the lock for final round if (!_isRegularRound(_roundId, config)) { // Round end term ID (as it's final there's no draft delay nor appeal) plus the lock period DisputesConfig memory disputesConfig = config.disputes; jurorsRegistry.lockWithdrawals( _juror, round.draftTermId + disputesConfig.commitTerms + disputesConfig.revealTerms + disputesConfig.finalRoundLockTerms ); } emit RewardSettled(_disputeId, _roundId, _juror, rewardTokens, rewardFees); } /** * @notice Settle appeal deposits for round #`_roundId` of dispute #`_disputeId` * @param _disputeId Identification number of the dispute to settle appeal deposits for * @param _roundId Identification number of the dispute round to settle appeal deposits for */ function settleAppealDeposit(uint256 _disputeId, uint256 _roundId) external roundExists(_disputeId, _roundId) { // Ensure dispute round penalties are settled first Dispute storage dispute = disputes[_disputeId]; AdjudicationRound storage round = dispute.rounds[_roundId]; require(round.settledPenalties, ERROR_ROUND_NOT_SETTLED); // Ensure given round was appealed and has not been settled yet Appeal storage appeal = round.appeal; require(_existsAppeal(appeal), ERROR_ROUND_NOT_APPEALED); require(!appeal.settled, ERROR_ROUND_APPEAL_ALREADY_SETTLED); appeal.settled = true; emit AppealDepositSettled(_disputeId, _roundId); // Load next round details Config memory config = _getDisputeConfig(dispute); NextRoundDetails memory nextRound = _getNextRoundDetails(round, _roundId, config); ERC20 feeToken = nextRound.feeToken; uint256 totalFees = nextRound.totalFees; uint256 appealDeposit = nextRound.appealDeposit; uint256 confirmAppealDeposit = nextRound.confirmAppealDeposit; // If the appeal wasn't confirmed, return the entire deposit to appeal maker ITreasury treasury = _treasury(); if (!_isAppealConfirmed(appeal)) { treasury.assign(feeToken, appeal.maker, appealDeposit); return; } // If the appeal was confirmed and there is a winner, we transfer the total deposit to that party. Otherwise, if the final ruling wasn't // selected by any of the appealing parties or no juror voted in the in favor of the possible outcomes, we split it between both parties. // Note that we are safe to access the dispute final ruling, since we already ensured that round penalties were settled. uint8 finalRuling = dispute.finalRuling; uint256 totalDeposit = appealDeposit.add(confirmAppealDeposit); if (appeal.appealedRuling == finalRuling) { treasury.assign(feeToken, appeal.maker, totalDeposit.sub(totalFees)); } else if (appeal.opposedRuling == finalRuling) { treasury.assign(feeToken, appeal.taker, totalDeposit.sub(totalFees)); } else { uint256 feesRefund = totalFees / 2; treasury.assign(feeToken, appeal.maker, appealDeposit.sub(feesRefund)); treasury.assign(feeToken, appeal.taker, confirmAppealDeposit.sub(feesRefund)); } } /** * @notice Ensure votes can be committed for vote #`_voteId`, revert otherwise * @dev This function will ensure the current term of the Court and revert in case votes cannot still be committed * @param _voteId ID of the vote instance to request the weight of a voter for */ function ensureCanCommit(uint256 _voteId) external { (Dispute storage dispute, uint256 roundId) = _decodeVoteId(_voteId); Config memory config = _getDisputeConfig(dispute); // Ensure current term and check that votes can still be committed for the given round _ensureAdjudicationState(dispute, roundId, AdjudicationState.Committing, config.disputes); } /** * @notice Ensure `voter` can commit votes for vote #`_voteId`, revert otherwise * @dev This function will ensure the current term of the Court and revert in case the given voter is not allowed to commit votes * @param _voteId ID of the vote instance to request the weight of a voter for * @param _voter Address of the voter querying the weight of */ function ensureCanCommit(uint256 _voteId, address _voter) external onlyVoting { (Dispute storage dispute, uint256 roundId) = _decodeVoteId(_voteId); Config memory config = _getDisputeConfig(dispute); // Ensure current term and check that votes can still be committed for the given round _ensureAdjudicationState(dispute, roundId, AdjudicationState.Committing, config.disputes); uint64 weight = _computeJurorWeight(dispute, roundId, _voter, config); require(weight > 0, ERROR_VOTER_WEIGHT_ZERO); } /** * @notice Ensure `voter` can reveal votes for vote #`_voteId`, revert otherwise * @dev This function will ensure the current term of the Court and revert in case votes cannot still be revealed * @param _voteId ID of the vote instance to request the weight of a voter for * @param _voter Address of the voter querying the weight of * @return Weight of the requested juror for the requested dispute's round */ function ensureCanReveal(uint256 _voteId, address _voter) external returns (uint64) { (Dispute storage dispute, uint256 roundId) = _decodeVoteId(_voteId); Config memory config = _getDisputeConfig(dispute); // Ensure current term and check that votes can still be revealed for the given round _ensureAdjudicationState(dispute, roundId, AdjudicationState.Revealing, config.disputes); AdjudicationRound storage round = dispute.rounds[roundId]; return _getJurorWeight(round, _voter); } /** * @notice Sets the global configuration for the max number of jurors to be drafted per batch to `_maxJurorsPerDraftBatch` * @param _maxJurorsPerDraftBatch Max number of jurors to be drafted per batch */ function setMaxJurorsPerDraftBatch(uint64 _maxJurorsPerDraftBatch) external onlyConfigGovernor { _setMaxJurorsPerDraftBatch(_maxJurorsPerDraftBatch); } /** * @dev Tell the amount of token fees required to create a dispute * @return feeToken ERC20 token used for the fees * @return totalFees Total amount of fees for a regular round at the given term */ function getDisputeFees() external view returns (ERC20 feeToken, uint256 totalFees) { uint64 currentTermId = _getCurrentTermId(); Config memory config = _getConfigAt(currentTermId); (feeToken,, totalFees) = _getRegularRoundFees(config.fees, config.disputes.firstRoundJurorsNumber); } /** * @dev Tell information of a certain dispute * @param _disputeId Identification number of the dispute being queried * @return subject Arbitrable subject being disputed * @return possibleRulings Number of possible rulings allowed for the drafted jurors to vote on the dispute * @return state Current state of the dispute being queried: pre-draft, adjudicating, or ruled * @return finalRuling The winning ruling in case the dispute is finished * @return lastRoundId Identification number of the last round created for the dispute * @return createTermId Identification number of the term when the dispute was created */ function getDispute(uint256 _disputeId) external view disputeExists(_disputeId) returns (IArbitrable subject, uint8 possibleRulings, DisputeState state, uint8 finalRuling, uint256 lastRoundId, uint64 createTermId) { Dispute storage dispute = disputes[_disputeId]; subject = dispute.subject; possibleRulings = dispute.possibleRulings; state = dispute.state; finalRuling = dispute.finalRuling; createTermId = dispute.createTermId; // If a dispute exists, it has at least one round lastRoundId = dispute.rounds.length - 1; } /** * @dev Tell information of a certain adjudication round * @param _disputeId Identification number of the dispute being queried * @param _roundId Identification number of the round being queried * @return draftTerm Term from which the requested round can be drafted * @return delayedTerms Number of terms the given round was delayed based on its requested draft term id * @return jurorsNumber Number of jurors requested for the round * @return selectedJurors Number of jurors already selected for the requested round * @return settledPenalties Whether or not penalties have been settled for the requested round * @return collectedTokens Amount of juror tokens that were collected from slashed jurors for the requested round * @return coherentJurors Number of jurors that voted in favor of the final ruling in the requested round * @return state Adjudication state of the requested round */ function getRound(uint256 _disputeId, uint256 _roundId) external view roundExists(_disputeId, _roundId) returns ( uint64 draftTerm, uint64 delayedTerms, uint64 jurorsNumber, uint64 selectedJurors, uint256 jurorFees, bool settledPenalties, uint256 collectedTokens, uint64 coherentJurors, AdjudicationState state ) { Dispute storage dispute = disputes[_disputeId]; state = _adjudicationStateAt(dispute, _roundId, _getCurrentTermId(), _getDisputeConfig(dispute).disputes); AdjudicationRound storage round = dispute.rounds[_roundId]; draftTerm = round.draftTermId; delayedTerms = round.delayedTerms; jurorsNumber = round.jurorsNumber; selectedJurors = round.selectedJurors; jurorFees = round.jurorFees; settledPenalties = round.settledPenalties; coherentJurors = round.coherentJurors; collectedTokens = round.collectedTokens; } /** * @dev Tell appeal-related information of a certain adjudication round * @param _disputeId Identification number of the dispute being queried * @param _roundId Identification number of the round being queried * @return maker Address of the account appealing the given round * @return appealedRuling Ruling confirmed by the appealer of the given round * @return taker Address of the account confirming the appeal of the given round * @return opposedRuling Ruling confirmed by the appeal taker of the given round */ function getAppeal(uint256 _disputeId, uint256 _roundId) external view roundExists(_disputeId, _roundId) returns (address maker, uint64 appealedRuling, address taker, uint64 opposedRuling) { Appeal storage appeal = disputes[_disputeId].rounds[_roundId].appeal; maker = appeal.maker; appealedRuling = appeal.appealedRuling; taker = appeal.taker; opposedRuling = appeal.opposedRuling; } /** * @dev Tell information related to the next round due to an appeal of a certain round given. * @param _disputeId Identification number of the dispute being queried * @param _roundId Identification number of the round requesting the appeal details of * @return nextRoundStartTerm Term ID from which the next round will start * @return nextRoundJurorsNumber Jurors number for the next round * @return newDisputeState New state for the dispute associated to the given round after the appeal * @return feeToken ERC20 token used for the next round fees * @return jurorFees Total amount of fees to be distributed between the winning jurors of the next round * @return totalFees Total amount of fees for a regular round at the given term * @return appealDeposit Amount to be deposit of fees for a regular round at the given term * @return confirmAppealDeposit Total amount of fees for a regular round at the given term */ function getNextRoundDetails(uint256 _disputeId, uint256 _roundId) external view returns ( uint64 nextRoundStartTerm, uint64 nextRoundJurorsNumber, DisputeState newDisputeState, ERC20 feeToken, uint256 totalFees, uint256 jurorFees, uint256 appealDeposit, uint256 confirmAppealDeposit ) { _checkRoundExists(_disputeId, _roundId); Dispute storage dispute = disputes[_disputeId]; Config memory config = _getDisputeConfig(dispute); require(_isRegularRound(_roundId, config), ERROR_ROUND_IS_FINAL); AdjudicationRound storage round = dispute.rounds[_roundId]; NextRoundDetails memory nextRound = _getNextRoundDetails(round, _roundId, config); return ( nextRound.startTerm, nextRound.jurorsNumber, nextRound.newDisputeState, nextRound.feeToken, nextRound.totalFees, nextRound.jurorFees, nextRound.appealDeposit, nextRound.confirmAppealDeposit ); } /** * @dev Tell juror-related information of a certain adjudication round * @param _disputeId Identification number of the dispute being queried * @param _roundId Identification number of the round being queried * @param _juror Address of the juror being queried * @return weight Juror weight drafted for the requested round * @return rewarded Whether or not the given juror was rewarded based on the requested round */ function getJuror(uint256 _disputeId, uint256 _roundId, address _juror) external view roundExists(_disputeId, _roundId) returns (uint64 weight, bool rewarded) { Dispute storage dispute = disputes[_disputeId]; AdjudicationRound storage round = dispute.rounds[_roundId]; Config memory config = _getDisputeConfig(dispute); if (_isRegularRound(_roundId, config)) { weight = _getJurorWeight(round, _juror); } else { IJurorsRegistry jurorsRegistry = _jurorsRegistry(); uint256 activeBalance = jurorsRegistry.activeBalanceOfAt(_juror, round.draftTermId); weight = _getMinActiveBalanceMultiple(activeBalance, config.jurors.minActiveBalance); } rewarded = round.jurorsStates[_juror].rewarded; } /** * @dev Internal function to create a new round for a given dispute * @param _disputeId Identification number of the dispute to create a new round for * @param _disputeState New state for the dispute to be changed * @param _draftTermId Term ID when the jurors for the new round will be drafted * @param _jurorsNumber Number of jurors to be drafted for the new round * @param _jurorFees Total amount of fees to be shared between the winning jurors of the new round * @return Identification number of the new dispute round */ function _createRound(uint256 _disputeId, DisputeState _disputeState, uint64 _draftTermId, uint64 _jurorsNumber, uint256 _jurorFees) internal returns (uint256) { // Update dispute state Dispute storage dispute = disputes[_disputeId]; dispute.state = _disputeState; // Create new requested round uint256 roundId = dispute.rounds.length++; AdjudicationRound storage round = dispute.rounds[roundId]; round.draftTermId = _draftTermId; round.jurorsNumber = _jurorsNumber; round.jurorFees = _jurorFees; // Create new vote for the new round ICRVoting voting = _voting(); uint256 voteId = _getVoteId(_disputeId, roundId); voting.create(voteId, dispute.possibleRulings); return roundId; } /** * @dev Internal function to ensure the adjudication state of a certain dispute round. This function will make sure the court term is updated. * This function assumes the given round exists. * @param _dispute Dispute to be checked * @param _roundId Identification number of the dispute round to be checked * @param _state Expected adjudication state for the given dispute round * @param _config Config at the draft term ID of the given dispute */ function _ensureAdjudicationState(Dispute storage _dispute, uint256 _roundId, AdjudicationState _state, DisputesConfig memory _config) internal { uint64 termId = _ensureCurrentTerm(); AdjudicationState roundState = _adjudicationStateAt(_dispute, _roundId, termId, _config); require(roundState == _state, ERROR_INVALID_ADJUDICATION_STATE); } /** * @dev Internal function to ensure the final ruling of a dispute. It will compute it only if missing. * @param _dispute Dispute to ensure its final ruling * @param _disputeId Identification number of the dispute to ensure its final ruling * @param _config Config at the draft term ID of the given dispute * @return Number of the final ruling ensured for the given dispute */ function _ensureFinalRuling(Dispute storage _dispute, uint256 _disputeId, Config memory _config) internal returns (uint8) { // Check if there was a final ruling already cached if (uint256(_dispute.finalRuling) > 0) { return _dispute.finalRuling; } // Ensure current term and check that the last adjudication round has ended. // Note that there will always be at least one round. uint256 lastRoundId = _dispute.rounds.length - 1; _ensureAdjudicationState(_dispute, lastRoundId, AdjudicationState.Ended, _config.disputes); // If the last adjudication round was appealed but no-one confirmed it, the final ruling is the outcome the // appealer vouched for. Otherwise, fetch the winning outcome from the voting app of the last round. AdjudicationRound storage lastRound = _dispute.rounds[lastRoundId]; Appeal storage lastAppeal = lastRound.appeal; bool isRoundAppealedAndNotConfirmed = _existsAppeal(lastAppeal) && !_isAppealConfirmed(lastAppeal); uint8 finalRuling = isRoundAppealedAndNotConfirmed ? lastAppeal.appealedRuling : _voting().getWinningOutcome(_getVoteId(_disputeId, lastRoundId)); // Store the winning ruling as the final decision for the given dispute _dispute.finalRuling = finalRuling; return finalRuling; } /** * @dev Internal function to slash all the jurors drafted for a round that didn't vote in favor of the final ruling of a dispute. Note that * the slashing can be batched handling the maximum number of jurors to be slashed on each call. * @param _round Round to slash the non-winning jurors of * @param _voteId Identification number of the voting associated to the given round * @param _finalRuling Winning ruling of the dispute corresponding to the given round * @param _penaltyPct Per ten thousand of the minimum active balance of a juror to be slashed * @param _jurorsToSettle Maximum number of jurors to be slashed in this call. It can be set to zero to slash all the losing jurors of the round. * @param _minActiveBalance Minimum amount of juror tokens that can be activated * @return Number of jurors slashed for the given round */ function _settleRegularRoundPenalties( AdjudicationRound storage _round, uint256 _voteId, uint8 _finalRuling, uint16 _penaltyPct, uint256 _jurorsToSettle, uint256 _minActiveBalance ) internal returns (uint256) { uint64 termId = _ensureCurrentTerm(); // The batch starts where the previous one ended, stored in _round.settledJurors uint256 roundSettledJurors = _round.settledJurors; // Compute the amount of jurors that are going to be settled in this batch, which is returned by the function for fees calculation // Initially we try to reach the end of the jurors array uint256 batchSettledJurors = _round.jurors.length.sub(roundSettledJurors); // If the requested amount of jurors is not zero and it is lower that the remaining number of jurors to be settled for the given round, // we cap the number of jurors that are going to be settled in this batch to the requested amount. If not, we know we have reached the // last batch and we are safe to mark round penalties as settled. if (_jurorsToSettle > 0 && batchSettledJurors > _jurorsToSettle) { batchSettledJurors = _jurorsToSettle; } else { _round.settledPenalties = true; } // Update the number of round settled jurors. _round.settledJurors = uint64(roundSettledJurors.add(batchSettledJurors)); // Prepare the list of jurors and penalties to either be slashed or returned based on their votes for the given round IJurorsRegistry jurorsRegistry = _jurorsRegistry(); address[] memory jurors = new address[](batchSettledJurors); uint256[] memory penalties = new uint256[](batchSettledJurors); for (uint256 i = 0; i < batchSettledJurors; i++) { address juror = _round.jurors[roundSettledJurors + i]; jurors[i] = juror; penalties[i] = _minActiveBalance.pct(_penaltyPct).mul(_round.jurorsStates[juror].weight); } // Check which of the jurors voted in favor of the final ruling of the dispute in this round. Ask the registry to slash or unlocked the // locked active tokens of each juror depending on their vote, and finally store the total amount of slashed tokens. bool[] memory jurorsInFavor = _voting().getVotersInFavorOf(_voteId, _finalRuling, jurors); _round.collectedTokens = _round.collectedTokens.add(jurorsRegistry.slashOrUnlock(termId, jurors, penalties, jurorsInFavor)); return batchSettledJurors; } /** * @dev Internal function to compute the juror weight for a dispute's round * @param _dispute Dispute to calculate the juror's weight of * @param _roundId ID of the dispute's round to calculate the juror's weight of * @param _juror Address of the juror to calculate the weight of * @param _config Config at the draft term ID of the given dispute * @return Computed weight of the requested juror for the final round of the given dispute */ function _computeJurorWeight(Dispute storage _dispute, uint256 _roundId, address _juror, Config memory _config) internal returns (uint64) { AdjudicationRound storage round = _dispute.rounds[_roundId]; return _isRegularRound(_roundId, _config) ? _getJurorWeight(round, _juror) : _computeJurorWeightForFinalRound(_config, round, _juror); } /** * @dev Internal function to compute the juror weight for the final round. Note that for a final round the weight of * each juror is equal to the number of times the min active balance the juror has. This function will try to * collect said amount from the active balance of a juror, acting as a lock to allow them to vote. * @param _config Court config to calculate the juror's weight * @param _round Dispute round to calculate the juror's weight for * @param _juror Address of the juror to calculate the weight of * @return Weight of the requested juror for the final round of the given dispute */ function _computeJurorWeightForFinalRound(Config memory _config, AdjudicationRound storage _round, address _juror) internal returns (uint64) { // Fetch active balance and multiples of the min active balance from the registry IJurorsRegistry jurorsRegistry = _jurorsRegistry(); uint256 activeBalance = jurorsRegistry.activeBalanceOfAt(_juror, _round.draftTermId); uint64 weight = _getMinActiveBalanceMultiple(activeBalance, _config.jurors.minActiveBalance); // If the juror weight for the last round is zero, return zero if (weight == 0) { return uint64(0); } // To guarantee scalability of the final round, since all jurors may vote, we try to collect the amount of // active tokens that needs to be locked for each juror when they try to commit their vote. uint256 weightedPenalty = activeBalance.pct(_config.disputes.penaltyPct); // If it was not possible to collect the amount to be locked, return 0 to prevent juror from voting if (!jurorsRegistry.collectTokens(_juror, weightedPenalty, _getLastEnsuredTermId())) { return uint64(0); } // If it was possible to collect the amount of active tokens to be locked, update the final round state _round.jurorsStates[_juror].weight = weight; _round.collectedTokens = _round.collectedTokens.add(weightedPenalty); return weight; } /** * @dev Sets the global configuration for the max number of jurors to be drafted per batch * @param _maxJurorsPerDraftBatch Max number of jurors to be drafted per batch */ function _setMaxJurorsPerDraftBatch(uint64 _maxJurorsPerDraftBatch) internal { require(_maxJurorsPerDraftBatch > 0, ERROR_BAD_MAX_DRAFT_BATCH_SIZE); emit MaxJurorsPerDraftBatchChanged(maxJurorsPerDraftBatch, _maxJurorsPerDraftBatch); maxJurorsPerDraftBatch = _maxJurorsPerDraftBatch; } /** * @dev Internal function to execute a deposit of tokens from an account to the Court treasury contract * @param _from Address transferring the amount of tokens * @param _token ERC20 token to execute a transfer from * @param _amount Amount of tokens to be transferred from the address transferring the funds to the Court treasury */ function _depositAmount(address _from, ERC20 _token, uint256 _amount) internal { if (_amount > 0) { ITreasury treasury = _treasury(); require(_token.safeTransferFrom(_from, address(treasury), _amount), ERROR_DEPOSIT_FAILED); } } /** * @dev Internal function to get the stored juror weight for a round. Note that the weight of a juror is: * - For a regular round: the number of times a juror was picked for the round round. * - For a final round: the relative active stake of a juror's state over the total active tokens, only set after the juror has voted. * @param _round Dispute round to calculate the juror's weight of * @param _juror Address of the juror to calculate the weight of * @return Weight of the requested juror for the given round */ function _getJurorWeight(AdjudicationRound storage _round, address _juror) internal view returns (uint64) { return _round.jurorsStates[_juror].weight; } /** * @dev Internal function to tell information related to the next round due to an appeal of a certain round given. This function assumes * given round can be appealed and that the given round ID corresponds to the given round pointer. * @param _round Round requesting the appeal details of * @param _roundId Identification number of the round requesting the appeal details of * @param _config Config at the draft term of the given dispute * @return Next round details */ function _getNextRoundDetails(AdjudicationRound storage _round, uint256 _roundId, Config memory _config) internal view returns (NextRoundDetails memory) { NextRoundDetails memory nextRound; DisputesConfig memory disputesConfig = _config.disputes; // Next round start term is current round end term uint64 delayedDraftTerm = _round.draftTermId.add(_round.delayedTerms); uint64 currentRoundAppealStartTerm = delayedDraftTerm.add(disputesConfig.commitTerms).add(disputesConfig.revealTerms); nextRound.startTerm = currentRoundAppealStartTerm.add(disputesConfig.appealTerms).add(disputesConfig.appealConfirmTerms); // Compute next round settings depending on if it will be the final round or not if (_roundId >= disputesConfig.maxRegularAppealRounds.sub(1)) { // If the next round is the final round, no draft is needed. nextRound.newDisputeState = DisputeState.Adjudicating; // The number of jurors will be the number of times the minimum stake is held in the registry, // multiplied by a precision factor to help with division rounding. // Total active balance is guaranteed to never be greater than `2^64 * minActiveBalance / FINAL_ROUND_WEIGHT_PRECISION`. // Thus, the jurors number for a final round will always fit in uint64. IJurorsRegistry jurorsRegistry = _jurorsRegistry(); uint256 totalActiveBalance = jurorsRegistry.totalActiveBalanceAt(nextRound.startTerm); uint64 jurorsNumber = _getMinActiveBalanceMultiple(totalActiveBalance, _config.jurors.minActiveBalance); nextRound.jurorsNumber = jurorsNumber; // Calculate fees for the final round using the appeal start term of the current round (nextRound.feeToken, nextRound.jurorFees, nextRound.totalFees) = _getFinalRoundFees(_config.fees, jurorsNumber); } else { // For a new regular rounds we need to draft jurors nextRound.newDisputeState = DisputeState.PreDraft; // The number of jurors will be the number of jurors of the current round multiplied by an appeal factor nextRound.jurorsNumber = _getNextRegularRoundJurorsNumber(_round, disputesConfig); // Calculate fees for the next regular round using the appeal start term of the current round (nextRound.feeToken, nextRound.jurorFees, nextRound.totalFees) = _getRegularRoundFees(_config.fees, nextRound.jurorsNumber); } // Calculate appeal collateral nextRound.appealDeposit = nextRound.totalFees.pct256(disputesConfig.appealCollateralFactor); nextRound.confirmAppealDeposit = nextRound.totalFees.pct256(disputesConfig.appealConfirmCollateralFactor); return nextRound; } /** * @dev Internal function to calculate the jurors number for the next regular round of a given round. This function assumes Court term is * up-to-date, that the next round of the one given is regular, and the given config corresponds to the draft term of the given round. * @param _round Round querying the jurors number of its next round * @param _config Disputes config at the draft term of the first round of the dispute * @return Jurors number for the next regular round of the given round */ function _getNextRegularRoundJurorsNumber(AdjudicationRound storage _round, DisputesConfig memory _config) internal view returns (uint64) { // Jurors number are increased by a step factor on each appeal uint64 jurorsNumber = _round.jurorsNumber.mul(_config.appealStepFactor); // Make sure it's odd to enforce avoiding a tie. Note that it can happen if any of the jurors don't vote anyway. if (uint256(jurorsNumber) % 2 == 0) { jurorsNumber++; } return jurorsNumber; } /** * @dev Internal function to tell adjudication state of a round at a certain term. This function assumes the given round exists. * @param _dispute Dispute querying the adjudication round of * @param _roundId Identification number of the dispute round querying the adjudication round of * @param _termId Identification number of the term to be used for the different round phases durations * @param _config Disputes config at the draft term ID of the given dispute * @return Adjudication state of the requested dispute round for the given term */ function _adjudicationStateAt(Dispute storage _dispute, uint256 _roundId, uint64 _termId, DisputesConfig memory _config) internal view returns (AdjudicationState) { AdjudicationRound storage round = _dispute.rounds[_roundId]; // If the dispute is ruled or the given round is not the last one, we consider it ended uint256 numberOfRounds = _dispute.rounds.length; if (_dispute.state == DisputeState.Ruled || _roundId < numberOfRounds.sub(1)) { return AdjudicationState.Ended; } // If given term is before the actual term when the last round was finally drafted, then the last round adjudication state is invalid uint64 draftFinishedTermId = round.draftTermId.add(round.delayedTerms); if (_dispute.state == DisputeState.PreDraft || _termId < draftFinishedTermId) { return AdjudicationState.Invalid; } // If given term is before the reveal start term of the last round, then jurors are still allowed to commit votes for the last round uint64 revealStartTerm = draftFinishedTermId.add(_config.commitTerms); if (_termId < revealStartTerm) { return AdjudicationState.Committing; } // If given term is before the appeal start term of the last round, then jurors are still allowed to reveal votes for the last round uint64 appealStartTerm = revealStartTerm.add(_config.revealTerms); if (_termId < appealStartTerm) { return AdjudicationState.Revealing; } // If the max number of appeals has been reached, then the last round is the final round and can be considered ended bool maxAppealReached = numberOfRounds > _config.maxRegularAppealRounds; if (maxAppealReached) { return AdjudicationState.Ended; } // If the last round was not appealed yet, check if the confirmation period has started or not bool isLastRoundAppealed = _existsAppeal(round.appeal); uint64 appealConfirmationStartTerm = appealStartTerm.add(_config.appealTerms); if (!isLastRoundAppealed) { // If given term is before the appeal confirmation start term, then the last round can still be appealed. Otherwise, it is ended. if (_termId < appealConfirmationStartTerm) { return AdjudicationState.Appealing; } else { return AdjudicationState.Ended; } } // If the last round was appealed and the given term is before the appeal confirmation end term, then the last round appeal can still be // confirmed. Note that if the round being checked was already appealed and confirmed, it won't be the last round, thus it will be caught // above by the first check and considered 'Ended'. uint64 appealConfirmationEndTerm = appealConfirmationStartTerm.add(_config.appealConfirmTerms); if (_termId < appealConfirmationEndTerm) { return AdjudicationState.ConfirmingAppeal; } // If non of the above conditions have been met, the last round is considered ended return AdjudicationState.Ended; } /** * @dev Internal function to get the Court config used for a dispute * @param _dispute Dispute querying the Court config of * @return Court config used for the given dispute */ function _getDisputeConfig(Dispute storage _dispute) internal view returns (Config memory) { // Note that it is safe to access a Court config directly for a past term return _getConfigAt(_dispute.createTermId); } /** * @dev Internal function to check if a certain appeal exists * @param _appeal Appeal to be checked * @return True if the given appeal has a maker address associated to it, false otherwise */ function _existsAppeal(Appeal storage _appeal) internal view returns (bool) { return _appeal.maker != address(0); } /** * @dev Internal function to check if a certain appeal has been confirmed * @param _appeal Appeal to be checked * @return True if the given appeal was confirmed, false otherwise */ function _isAppealConfirmed(Appeal storage _appeal) internal view returns (bool) { return _appeal.taker != address(0); } /** * @dev Internal function to check if a certain dispute exists, it reverts if it doesn't * @param _disputeId Identification number of the dispute to be checked */ function _checkDisputeExists(uint256 _disputeId) internal view { require(_disputeId < disputes.length, ERROR_DISPUTE_DOES_NOT_EXIST); } /** * @dev Internal function to check if a certain dispute round exists, it reverts if it doesn't * @param _disputeId Identification number of the dispute to be checked * @param _roundId Identification number of the dispute round to be checked */ function _checkRoundExists(uint256 _disputeId, uint256 _roundId) internal view { _checkDisputeExists(_disputeId); require(_roundId < disputes[_disputeId].rounds.length, ERROR_ROUND_DOES_NOT_EXIST); } /** * @dev Internal function to get the dispute round of a certain vote identification number * @param _voteId Identification number of the vote querying the dispute round of * @return dispute Dispute for the given vote * @return roundId Identification number of the dispute round for the given vote */ function _decodeVoteId(uint256 _voteId) internal view returns (Dispute storage dispute, uint256 roundId) { uint256 disputeId = _voteId >> 128; roundId = _voteId & VOTE_ID_MASK; _checkRoundExists(disputeId, roundId); dispute = disputes[disputeId]; } /** * @dev Internal function to get the identification number of the vote of a certain dispute round * @param _disputeId Identification number of the dispute querying the vote ID of * @param _roundId Identification number of the dispute round querying the vote ID of * @return Identification number of the vote of the requested dispute round */ function _getVoteId(uint256 _disputeId, uint256 _roundId) internal pure returns (uint256) { return (_disputeId << 128) + _roundId; } /** * @dev Assumes round.coherentJurors is greater than zero * @param _round Round which the weighted amount is computed for * @param _jurorState Juror with state which the weighted amount is computed for * @param _amount Amount to be weighted * @return Weighted amount for a juror in a round in relation to total amount of coherent jurors */ function _getRoundWeightedAmount( AdjudicationRound storage _round, JurorState storage _jurorState, uint256 _amount ) internal view returns (uint256) { return _amount.mul(_jurorState.weight) / _round.coherentJurors; } /** * @dev Internal function to get fees information for regular rounds for a certain term. This function assumes Court term is up-to-date. * @param _config Court config to use in order to get fees * @param _jurorsNumber Number of jurors participating in the round being queried * @return feeToken ERC20 token used for the fees * @return jurorFees Total amount of fees to be distributed between the winning jurors of a round * @return totalFees Total amount of fees for a regular round at the given term */ function _getRegularRoundFees(FeesConfig memory _config, uint64 _jurorsNumber) internal pure returns (ERC20 feeToken, uint256 jurorFees, uint256 totalFees) { feeToken = _config.token; // For regular rounds the fees for each juror is constant and given by the config of the round jurorFees = uint256(_jurorsNumber).mul(_config.jurorFee); // The total fees for regular rounds also considers the number of drafts and settles uint256 draftAndSettleFees = (_config.draftFee.add(_config.settleFee)).mul(uint256(_jurorsNumber)); totalFees = jurorFees.add(draftAndSettleFees); } /** * @dev Internal function to get fees information for final rounds for a certain term. This function assumes Court term is up-to-date. * @param _config Court config to use in order to get fees * @param _jurorsNumber Number of jurors participating in the round being queried * @return feeToken ERC20 token used for the fees * @return jurorFees Total amount of fees corresponding to the jurors at the given term * @return totalFees Total amount of fees for a final round at the given term */ function _getFinalRoundFees(FeesConfig memory _config, uint64 _jurorsNumber) internal pure returns (ERC20 feeToken, uint256 jurorFees, uint256 totalFees) { feeToken = _config.token; // For final rounds, the jurors number is computed as the number of times the registry's minimum active balance is held in the registry // itself, multiplied by a precision factor. To avoid requesting a huge amount of fees, a final round discount is applied for each juror. jurorFees = (uint256(_jurorsNumber).mul(_config.jurorFee) / FINAL_ROUND_WEIGHT_PRECISION).pct(_config.finalRoundReduction); // There is no draft and no extra settle fees considered for final rounds totalFees = jurorFees; } /** * @dev Internal function to tell whether a round is regular or final. This function assumes the given round exists. * @param _roundId Identification number of the round to be checked * @param _config Court config to use in order to check if the given round is regular or final * @return True if the given round is regular, false in case its a final round */ function _isRegularRound(uint256 _roundId, Config memory _config) internal pure returns (bool) { return _roundId < _config.disputes.maxRegularAppealRounds; } /** * @dev Calculate the number of times that an amount contains the min active balance (multiplied by precision). * Used to get the juror weight for the final round. Note that for the final round the weight of * each juror is equal to the number of times the min active balance the juror has, multiplied by a precision * factor to deal with division rounding. * @param _activeBalance Juror's or total active balance * @param _minActiveBalance Minimum amount of juror tokens that can be activated * @return Number of times that the active balance contains the min active balance (multiplied by precision) */ function _getMinActiveBalanceMultiple(uint256 _activeBalance, uint256 _minActiveBalance) internal pure returns (uint64) { // Note that jurors may not reach the minimum active balance since some might have been slashed. If that occurs, // these jurors cannot vote in the final round. if (_activeBalance < _minActiveBalance) { return 0; } // Otherwise, return the times the active balance of the juror fits in the min active balance, multiplying // it by a round factor to ensure a better precision rounding. return (FINAL_ROUND_WEIGHT_PRECISION.mul(_activeBalance) / _minActiveBalance).toUint64(); } /** * @dev Private function to build params to call for a draft. It assumes the given data is correct. * @param _disputeId Identification number of the dispute to be drafted * @param _roundId Identification number of the round to be drafted * @param _termId Identification number of the current term of the Court * @param _draftTermRandomness Randomness of the term in which the dispute was requested to be drafted * @param _config Draft config of the Court at the draft term * @return Draft params object */ function _buildDraftParams(uint256 _disputeId, uint256 _roundId, uint64 _termId, bytes32 _draftTermRandomness, DraftConfig memory _config) private pure returns (DraftParams memory) { return DraftParams({ disputeId: _disputeId, roundId: _roundId, termId: _termId, draftTermRandomness: _draftTermRandomness, config: _config }); } /** * @dev Private function to draft jurors for a given dispute and round. It assumes the given data is correct. * @param _round Round of the dispute to be drafted * @param _draftParams Draft params to be used for the draft * @return True if all the requested jurors for the given round were drafted, false otherwise */ function _draft(AdjudicationRound storage _round, DraftParams memory _draftParams) private returns (bool) { uint64 jurorsNumber = _round.jurorsNumber; uint64 selectedJurors = _round.selectedJurors; uint64 maxJurorsPerBatch = maxJurorsPerDraftBatch; uint64 jurorsToBeDrafted = jurorsNumber.sub(selectedJurors); // Draft the min number of jurors between the one requested by the sender and the one requested by the sender uint64 requestedJurors = jurorsToBeDrafted < maxJurorsPerBatch ? jurorsToBeDrafted : maxJurorsPerBatch; // Pack draft params uint256[7] memory params = [ uint256(_draftParams.draftTermRandomness), _draftParams.disputeId, uint256(_draftParams.termId), uint256(selectedJurors), uint256(requestedJurors), uint256(jurorsNumber), uint256(_draftParams.config.penaltyPct) ]; // Draft jurors for the requested round IJurorsRegistry jurorsRegistry = _jurorsRegistry(); (address[] memory jurors, uint256 draftedJurors) = jurorsRegistry.draft(params); // Update round with drafted jurors information uint64 newSelectedJurors = selectedJurors.add(uint64(draftedJurors)); _round.selectedJurors = newSelectedJurors; _updateRoundDraftedJurors(_draftParams.disputeId, _draftParams.roundId, _round, jurors, draftedJurors); bool draftEnded = newSelectedJurors == jurorsNumber; // Transfer fees corresponding to the actual number of drafted jurors uint256 draftFees = _draftParams.config.draftFee.mul(draftedJurors); _treasury().assign(_draftParams.config.feeToken, msg.sender, draftFees); return draftEnded; } /** * @dev Private function to update the drafted jurors' weight for the given round * @param _disputeId Identification number of the dispute being drafted * @param _roundId Identification number of the round being drafted * @param _round Adjudication round that was drafted * @param _jurors List of jurors addresses that were drafted for the given round * @param _draftedJurors Number of jurors that were drafted for the given round. Note that this number may not necessarily be equal to the * given list of jurors since the draft could potentially return less jurors than the requested amount. */ function _updateRoundDraftedJurors( uint256 _disputeId, uint256 _roundId, AdjudicationRound storage _round, address[] memory _jurors, uint256 _draftedJurors ) private { for (uint256 i = 0; i < _draftedJurors; i++) { address juror = _jurors[i]; JurorState storage jurorState = _round.jurorsStates[juror]; // If the juror was already registered in the list, then don't add it twice if (uint256(jurorState.weight) == 0) { _round.jurors.push(juror); } jurorState.weight = jurorState.weight.add(1); emit JurorDrafted(_disputeId, _roundId, juror); } } /** * @dev Private function to burn the collected for a certain round in case there were no coherent jurors * @param _dispute Dispute to settle penalties for * @param _round Dispute round to settle penalties for * @param _roundId Identification number of the dispute round to settle penalties for * @param _courtTreasury Treasury module to refund the corresponding juror fees * @param _feeToken ERC20 token to be used for the fees corresponding to the draft term of the given dispute round * @param _collectedTokens Amount of tokens collected during the given dispute round */ function _burnCollectedTokensIfNecessary( Dispute storage _dispute, AdjudicationRound storage _round, uint256 _roundId, ITreasury _courtTreasury, ERC20 _feeToken, uint256 _collectedTokens ) private { // If there was at least one juror voting in favor of the winning ruling, return if (_round.coherentJurors > 0) { return; } // Burn all the collected tokens of the jurors to be slashed. Note that this will happen only when there were no jurors voting // in favor of the final winning outcome. Otherwise, these will be re-distributed between the winning jurors in `settleReward` // instead of being burned. if (_collectedTokens > 0) { IJurorsRegistry jurorsRegistry = _jurorsRegistry(); jurorsRegistry.burnTokens(_collectedTokens); } // Reimburse juror fees to the Arbtirable subject for round 0 or to the previous appeal parties for other rounds. // Note that if the given round is not the first round, we can ensure there was an appeal in the previous round. if (_roundId == 0) { _courtTreasury.assign(_feeToken, address(_dispute.subject), _round.jurorFees); } else { uint256 refundFees = _round.jurorFees / 2; Appeal storage triggeringAppeal = _dispute.rounds[_roundId - 1].appeal; _courtTreasury.assign(_feeToken, triggeringAppeal.maker, refundFees); _courtTreasury.assign(_feeToken, triggeringAppeal.taker, refundFees); } } /** * @dev Private function only used in the constructor to skip a given number of disputes * @param _skippedDisputes Number of disputes to be skipped */ function _skipDisputes(uint256 _skippedDisputes) private { assert(disputes.length == 0); disputes.length = _skippedDisputes; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":false,"inputs":[{"name":"_maxJurorsPerDraftBatch","type":"uint64"}],"name":"setMaxJurorsPerDraftBatch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_voteId","type":"uint256"},{"name":"_voter","type":"address"}],"name":"ensureCanCommit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"},{"name":"_ruling","type":"uint8"}],"name":"createAppeal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_voteId","type":"uint256"}],"name":"ensureCanCommit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_subject","type":"address"},{"name":"_possibleRulings","type":"uint8"},{"name":"_metadata","type":"bytes"}],"name":"createDispute","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_to","type":"address"}],"name":"recoverFunds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getController","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxJurorsPerDraftBatch","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"}],"name":"getRound","outputs":[{"name":"draftTerm","type":"uint64"},{"name":"delayedTerms","type":"uint64"},{"name":"jurorsNumber","type":"uint64"},{"name":"selectedJurors","type":"uint64"},{"name":"jurorFees","type":"uint256"},{"name":"settledPenalties","type":"bool"},{"name":"collectedTokens","type":"uint256"},{"name":"coherentJurors","type":"uint64"},{"name":"state","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"},{"name":"_juror","type":"address"}],"name":"getJuror","outputs":[{"name":"weight","type":"uint64"},{"name":"rewarded","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_subject","type":"address"},{"name":"_disputeId","type":"uint256"},{"name":"_submitter","type":"address"},{"name":"_evidence","type":"bytes"}],"name":"submitEvidence","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"}],"name":"draft","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"}],"name":"getAppeal","outputs":[{"name":"maker","type":"address"},{"name":"appealedRuling","type":"uint64"},{"name":"taker","type":"address"},{"name":"opposedRuling","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getDisputeFees","outputs":[{"name":"feeToken","type":"address"},{"name":"totalFees","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"},{"name":"_juror","type":"address"}],"name":"settleReward","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"},{"name":"_jurorsToSettle","type":"uint256"}],"name":"settlePenalties","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"},{"name":"_ruling","type":"uint8"}],"name":"confirmAppeal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"}],"name":"computeRuling","outputs":[{"name":"subject","type":"address"},{"name":"finalRuling","type":"uint8"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_voteId","type":"uint256"},{"name":"_voter","type":"address"}],"name":"ensureCanReveal","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_subject","type":"address"},{"name":"_disputeId","type":"uint256"}],"name":"closeEvidencePeriod","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"}],"name":"getNextRoundDetails","outputs":[{"name":"nextRoundStartTerm","type":"uint64"},{"name":"nextRoundJurorsNumber","type":"uint64"},{"name":"newDisputeState","type":"uint8"},{"name":"feeToken","type":"address"},{"name":"totalFees","type":"uint256"},{"name":"jurorFees","type":"uint256"},{"name":"appealDeposit","type":"uint256"},{"name":"confirmAppealDeposit","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_disputeId","type":"uint256"}],"name":"getDispute","outputs":[{"name":"subject","type":"address"},{"name":"possibleRulings","type":"uint8"},{"name":"state","type":"uint8"},{"name":"finalRuling","type":"uint8"},{"name":"lastRoundId","type":"uint256"},{"name":"createTermId","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_disputeId","type":"uint256"},{"name":"_roundId","type":"uint256"}],"name":"settleAppealDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_controller","type":"address"},{"name":"_maxJurorsPerDraftBatch","type":"uint64"},{"name":"_skippedDisputes","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"state","type":"uint8"}],"name":"DisputeStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"submitter","type":"address"},{"indexed":false,"name":"evidence","type":"bytes"}],"name":"EvidenceSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"termId","type":"uint64"}],"name":"EvidencePeriodClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"subject","type":"address"},{"indexed":true,"name":"draftTermId","type":"uint64"},{"indexed":false,"name":"jurorsNumber","type":"uint64"},{"indexed":false,"name":"metadata","type":"bytes"}],"name":"NewDispute","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"roundId","type":"uint256"},{"indexed":true,"name":"juror","type":"address"}],"name":"JurorDrafted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"roundId","type":"uint256"},{"indexed":false,"name":"ruling","type":"uint8"}],"name":"RulingAppealed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"roundId","type":"uint256"},{"indexed":true,"name":"draftTermId","type":"uint64"},{"indexed":false,"name":"jurorsNumber","type":"uint256"}],"name":"RulingAppealConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"ruling","type":"uint8"}],"name":"RulingComputed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"roundId","type":"uint256"},{"indexed":false,"name":"collectedTokens","type":"uint256"}],"name":"PenaltiesSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"roundId","type":"uint256"},{"indexed":false,"name":"juror","type":"address"},{"indexed":false,"name":"tokens","type":"uint256"},{"indexed":false,"name":"fees","type":"uint256"}],"name":"RewardSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"disputeId","type":"uint256"},{"indexed":true,"name":"roundId","type":"uint256"}],"name":"AppealDepositSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousMaxJurorsPerDraftBatch","type":"uint64"},{"indexed":false,"name":"currentMaxJurorsPerDraftBatch","type":"uint64"}],"name":"MaxJurorsPerDraftBatchChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"recipient","type":"address"},{"indexed":false,"name":"balance","type":"uint256"}],"name":"RecoverFunds","type":"event"}]
Contract Creation Code
60806040523480156200001157600080fd5b50604051606080620063e7833981018060405260608110156200003357600080fd5b50805160208083015160409093015191929190839081906200005b90829062000186811b901c565b6040518060400160405280601b81526020017f4354445f434f4e54524f4c4c45525f4e4f545f434f4e545241435400000000008152509062000138576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620000fc578181015183820152602001620000e2565b50505050905090810190601f1680156200012a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600080546001600160a01b0319166001600160a01b0392909216919091179055506200016c82620001ab602090811b901c565b6200017d81620002ef60201b60201c565b50505062000467565b60006001600160a01b038216620001a057506000620001a6565b50803b15155b919050565b60408051808201909152601b81527f444d5f4241445f4d41585f44524146545f42415443485f53495a45000000000060208201526001600160401b03821662000251576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315620000fc578181015183820152602001620000e2565b50600054604080516001600160401b037401000000000000000000000000000000000000000090930483168152918316602083015280517fed22db0c227e21d249167e5f9d39415fd9386958f122075463fef70fd46c95c49281900390910190a1600080546001600160401b039092167401000000000000000000000000000000000000000002600160a01b600160e01b0319909216919091179055565b60015415620002fa57fe5b80620003086001826200030c565b5050565b8154818355818111156200033b576002028160020283600052602060002091820191016200033b919062000340565b505050565b6200039591905b80821115620003915780547fff00000000000000000000000000000000000000000000000000000000000000168155600062000387600183018262000398565b5060020162000347565b5090565b90565b5080546000825560080290600052602060002090810190620003bb9190620003be565b50565b6200039591905b80821115620003915780546001600160881b0319168155600060018201819055620003f4600283018262000430565b5060006004820181905560058201556006810180546001600160a81b03191690556007810180546001600160b01b0319169055600801620003c5565b5080546000825590600052602060002090810190620003bb91906200039591905b8082111562000391576000815560010162000451565b615f7080620004776000396000f3fe608060405234801561001057600080fd5b506004361061017c5760003560e01c8063710cf1ed116100e3578063bd881e531161008c578063cd604ada11610066578063cd604ada14610674578063e3a96cbd146106fe578063eed04b801461077a5761017c565b8063bd881e53146105da578063c1361a7c1461061c578063c39c83d1146106485761017c565b806382a8b3b0116100bd57806382a8b3b014610553578063859ba187146105855780639c0065f7146105ae5761017c565b8063710cf1ed146104ab5780637263bf2a146104c85780637b751b9e146105285761017c565b806324ae6a271161014557806339ec68a31161011f57806339ec68a31461032e5780634b4acfd3146103c75780635bdaf9d81461041c5761017c565b806324ae6a27146102b85780633018205f146102e65780633238f8f41461030a5761017c565b80629230a51461018157806306349cfa146101a95780630d03d126146101d557806315fe5268146102015780631d2fa1fb1461021e575b600080fd5b6101a76004803603602081101561019757600080fd5b50356001600160401b031661079d565b005b6101a7600480360360408110156101bf57600080fd5b50803590602001356001600160a01b0316610888565b6101a7600480360360608110156101eb57600080fd5b508035906020810135906040013560ff16610a04565b6101a76004803603602081101561021757600080fd5b5035610ced565b6102a66004803603606081101561023457600080fd5b6001600160a01b038235169160ff6020820135169181019060608101604082013564010000000081111561026757600080fd5b82018360208201111561027957600080fd5b8035906020019184600183028401116401000000008311171561029b57600080fd5b509092509050610d27565b60408051918252519081900360200190f35b6101a7600480360360408110156102ce57600080fd5b506001600160a01b038135811691602001351661102f565b6102ee61133c565b604080516001600160a01b039092168252519081900360200190f35b61031261134c565b604080516001600160401b039092168252519081900360200190f35b6103516004803603604081101561034457600080fd5b5080359060200135611362565b604080516001600160401b03808c1682528a811660208301528981169282019290925287821660608201526080810187905285151560a082015260c0810185905290831660e082015261010081018260058111156103ab57fe5b60ff168152602001995050505050505050505060405180910390f35b6103f9600480360360608110156103dd57600080fd5b50803590602081013590604001356001600160a01b0316611492565b604080516001600160401b03909316835290151560208301528051918290030190f35b6101a76004803603608081101561043257600080fd5b6001600160a01b03823581169260208101359260408201359092169181019060808101606082013564010000000081111561046c57600080fd5b82018360208201111561047e57600080fd5b803590602001918460018302840111640100000000831117156104a057600080fd5b509092509050611600565b6101a7600480360360208110156104c157600080fd5b50356117c9565b6104eb600480360360408110156104de57600080fd5b5080359060200135611b7d565b604080516001600160a01b0395861681526001600160401b0394851660208201529290941682850152909116606082015290519081900360800190f35b610530611c06565b604080516001600160a01b03909316835260208301919091528051918290030190f35b6101a76004803603606081101561056957600080fd5b50803590602081013590604001356001600160a01b0316611c4b565b6101a76004803603606081101561059b57600080fd5b508035906020810135906040013561226f565b6101a7600480360360608110156105c457600080fd5b508035906020810135906040013560ff1661267e565b6105f7600480360360208110156105f057600080fd5b503561290e565b604080516001600160a01b03909316835260ff90911660208301528051918290030190f35b6103126004803603604081101561063257600080fd5b50803590602001356001600160a01b03166129d4565b6101a76004803603604081101561065e57600080fd5b506001600160a01b038135169060200135612a42565b6106976004803603604081101561068a57600080fd5b5080359060200135612cd1565b604080516001600160401b03808b168252891660208201529081018760028111156106be57fe5b60ff1681526001600160a01b039096166020870152506040808601949094526060850192909252608084015260a0830152519081900360c0019350915050f35b61071b6004803603602081101561071457600080fd5b5035612e28565b604080516001600160a01b038816815260ff8716602082015290810185600281111561074357fe5b60ff9081168252949094166020850152506040808401929092526001600160401b0316606083015251908190036080019350915050f35b6101a76004803603604081101561079057600080fd5b5080359060200135612eb2565b6107a561342e565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f434f4e4649475f474f5645524e4f5200008152509061087b57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610840578181015183820152602001610828565b50505050905090810190601f16801561086d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50610885816134ae565b50565b60006108926135cb565b60408051808201909152601481527f444d5f53454e4445525f4e4f545f564f54494e470000000000000000000000006020820152909150336001600160a01b0383161461092357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000806109308561361a565b9150915061093c615b71565b61094583613661565b9050610958838360018460200151613684565b600061096684848885613747565b90506000816001600160401b0316116040518060400160405280601481526020017f444d5f564f5445525f5745494748545f5a45524f000000000000000000000000815250906109fa57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050505050505050565b8282610a10828261379b565b600060018681548110610a1f57fe5b90600052602060002090600202019050610a37615b71565b610a4082613661565b9050610a53828760038460200151613684565b6000610a5d6135cb565b90506000610a6b8989613852565b90506000826001600160a01b031663084d72f4836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610ab357600080fd5b505afa158015610ac7573d6000803e3d6000fd5b505050506040513d6020811015610add57600080fd5b5051905060ff80821690891614801590610b885750604080517fe2e7ed9f0000000000000000000000000000000000000000000000000000000081526004810184905260ff8a16602482015290516001600160a01b0385169163e2e7ed9f916044808301926020929190829003018186803b158015610b5b57600080fd5b505afa158015610b6f573d6000803e3d6000fd5b505050506040513d6020811015610b8557600080fd5b50515b6040518060400160405280601881526020017f444d5f494e56414c49445f41505045414c5f52554c494e47000000000000000081525090610c0d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000856001018a81548110610c1f57fe5b6000918252602091829020600891909102016006810180543373ffffffffffffffffffffffffffffffffffffffff199091161774ff00000000000000000000000000000000000000001916600160a01b60ff8e16908102919091178255604080519182525192945090928d928f927f57dc4548648c602e9f394f905942ffeba7a2041a6a704128b3a75e5b0efa11a792908290030190a3610cbe615ba4565b610cc9838d8961385c565b9050610cde3382606001518360c00151613ab5565b50505050505050505050505050565b600080610cf98361361a565b91509150610d05615b71565b610d0e83613661565b9050610d21838360018460200151613684565b50505050565b6000805460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b03163314610db957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000610dc4613b6e565b9050610dce615b71565b610dd782613bc6565b9050600260ff871610801590610dfb575080602001516000015160ff168660ff1611155b6040518060400160405280601981526020017f444d5f494e56414c49445f52554c494e475f4f5054494f4e530000000000000081525090610e8057604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060018054600091610e9490828101615bf2565b9050600060018281548110610ea557fe5b90600052602060002090600202019050888160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508781600001601c6101000a81548160ff021916908360ff160217905550838160000160146101000a8154816001600160401b0302191690836001600160401b031602179055506000836020015160e0015190506000610f57856020015160200151876001600160401b0316613ee590919063ffffffff16565b9050806001600160401b03168b6001600160a01b0316857fd4784fc5a2aef689d6639d09cb5b543abfeabd597519d01b93f4ffef74d10396858d8d60405180846001600160401b03166001600160401b03168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a46000806000610ffb886000015186613f86565b92509250925061100f876000868886614000565b5061101b8e8483613ab5565b50949750505050505050505b949350505050565b6000809054906101000a90046001600160a01b03166001600160a01b0316633c28e88b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561107c57600080fd5b505afa158015611090573d6000803e3d6000fd5b505050506040513d60208110156110a657600080fd5b505160408051808201909152601d81527f4354445f53454e4445525f4e4f545f46554e44535f474f5645524e4f520000006020820152906001600160a01b0316331461113657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000916001600160a01b038516916370a0823191602480820192602092909190829003018186803b15801561119a57600080fd5b505afa1580156111ae573d6000803e3d6000fd5b505050506040513d60208110156111c457600080fd5b505160408051808201909152601e81527f4354445f494e53554646494349454e545f5245434f5645525f46554e4453000060208201529091508161124c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506112676001600160a01b038416838363ffffffff61417816565b6040518060400160405280601e81526020017f4354445f5245434f5645525f544f4b454e5f46554e44535f4641494c45440000815250906112ec57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50604080516001600160a01b0380861682528416602082015280820183905290517f724139fea3954691c2c1ee02b3be6be1763b32ec84841f1acad6d3a18695ba0d9181900360600190a1505050565b6000546001600160a01b03165b90565b600054600160a01b90046001600160401b031681565b60008060008060008060008060008a8a61137c828261379b565b600060018e8154811061138b57fe5b906000526020600020906002020190506113ba818e6113a86141ee565b6113b185613661565b60200151614230565b93506000816001018e815481106113cd57fe5b906000526020600020906008020190508060000160009054906101000a90046001600160401b03169c508060040160009054906101000a90046001600160401b03169b508060000160089054906101000a90046001600160401b03169a508060040160089054906101000a90046001600160401b03169950806001015498508060000160109054906101000a900460ff1697508060040160109054906101000a90046001600160401b0316955080600501549650505050509295985092959850929598565b60008084846114a1828261379b565b6000600188815481106114b057fe5b9060005260206000209060020201905060008160010188815481106114d157fe5b906000526020600020906008020190506114e9615b71565b6114f283613661565b90506114fe8982614499565b156115145761150d82896144a6565b96506115c8565b600061151e6144ce565b835460408051600160e01b63e9e67d670281526001600160a01b038d811660048301526001600160401b03909316602482015290519293506000929184169163e9e67d6791604480820192602092909190829003018186803b15801561158357600080fd5b505afa158015611597573d6000803e3d6000fd5b505050506040513d60208110156115ad57600080fd5b50516040840151519091506115c390829061451d565b985050505b506001600160a01b03969096166000908152600390960160205250506040909320549195600160401b90920460ff1694509092505050565b60005460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b0316331461169157604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b508361169c81614552565b6000600186815481106116ab57fe5b6000918252602091829020600290910201805460408051808201909152601e81527f444d5f5355424a4543545f4e4f545f444953505554455f5355424a4543540000938101939093529092506001600160a01b039081169089161461175457604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50846001600160a01b0316867fd25027d3faf6af10da1a82e9d4df3c98b93cb0481f9acaf87718a548fad0abce868660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a350505050505050565b806117d381614552565b60006117dd61133c565b905060006117e961133c565b6001600160a01b03166350c365806040518163ffffffff1660e01b815260040160206040518083038186803b15801561182157600080fd5b505afa158015611835573d6000803e3d6000fd5b505050506040513d602081101561184b57600080fd5b505160408051808201909152601081527f444d5f5445524d5f4f555444415445440000000000000000000000000000000060208201529091506001600160401b038216156118dd57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060006118e86145de565b90506000600186815481106118f957fe5b60009182526020822060029091020191508154600160f01b900460ff16600281111561192157fe5b146040518060400160405280601881526020017f444d5f524f554e445f414c52454144595f445241465445440000000000000000815250906119a757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600181018054600019810191600091839081106119c157fe5b6000918252602091829020600890910201805460408051808201909152601981527f444d5f44524146545f5445524d5f4e4f545f5245414348454400000000000000938101939093529092506001600160401b0390811691908616821115611a6d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000876001600160a01b0316637d1f24c96040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611aab57600080fd5b505af1158015611abf573d6000803e3d6000fd5b505050506040513d6020811015611ad557600080fd5b50519050611ae1615c1e565b611aea83614620565b90506000611b0485611aff8e898c88886146f3565b614733565b90508015611b6f5760048501805467ffffffffffffffff1916858a036001600160401b03161790558654600160f01b60ff021916600160f01b1787556040516001908d907f9bfdc20780e4912d62e8c31a73ffad5cbd841d7f76d114aa9f302ceca2d8258590600090a35b505050505050505050505050565b6000806000808585611b8f828261379b565b600060018981548110611b9e57fe5b90600052602060002090600202016001018881548110611bba57fe5b600091825260209091206006600890920201908101546007909101546001600160a01b038083169c60ff600160a01b9485900481169d509183169b509290910416975095505050505050565b6000806000611c136141ee565b9050611c1d615b71565b611c2682613bc6565b9050611c3e8160000151826020015160e00151613f86565b9196919550909350505050565b8282611c57828261379b565b600060018681548110611c6657fe5b906000526020600020906002020190506000816001018681548110611c8757fe5b906000526020600020906008020190508060000160109054906101000a900460ff166040518060400160405280601e81526020017f444d5f524f554e445f50454e414c544945535f4e4f545f534554544c4544000081525090611d2e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506001600160a01b038516600090815260038201602090815260409182902080548351808501909452601984527f444d5f4a55524f525f414c52454144595f524557415244454400000000000000928401929092529190600160401b900460ff1615611dde57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50805460408051808201909152601e81527f444d5f574f4e545f5245574152445f4e4f4e5f564f5445525f4a55524f5200006020820152906001600160401b0316611e6d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50805468ff00000000000000001916600160401b1781556000611e8e6135cb565b90506000611e9c8a8a613852565b8554604080517fcfa558ba00000000000000000000000000000000000000000000000000000000815260048101849052600160e81b90920460ff1660248301526001600160a01b038b81166044840152905192935084169163cfa558ba91606480820192602092909190829003018186803b158015611f1a57600080fd5b505afa158015611f2e573d6000803e3d6000fd5b505050506040513d6020811015611f4457600080fd5b505160408051808201909152601f81527f444d5f574f4e545f5245574152445f494e434f484552454e545f4a55524f5200602082015290611fc957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060058401546000611fd96144ce565b90506000821561206957611fee878785614a49565b9050816001600160a01b0316634d7edc158c836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b505050505b612071615b71565b61207a89613661565b9050600061208d89898b60010154614a49565b9050612097614a88565b6001600160a01b0316635f52d44e8360000151600001518f846040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b15801561211857600080fd5b505af115801561212c573d6000803e3d6000fd5b5050505061213a8e83614499565b61220357612146615c3e565b82602001519050846001600160a01b031663af8b9d0f8f836101200151846060015185604001518f60000160009054906101000a90046001600160401b03160101016040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b03168152602001826001600160401b03166001600160401b0316815260200192505050600060405180830381600087803b1580156121e957600080fd5b505af11580156121fd573d6000803e3d6000fd5b50505050505b8d8f7f3aea41188dba0e19aa929ada5527b70c76ba34b22bb672818cf2ed788c3c9e778f868560405180846001600160a01b03166001600160a01b03168152602001838152602001828152602001935050505060405180910390a3505050505050505050505050505050565b828261227b828261379b565b60006001868154811061228a57fe5b9060005260206000209060020201905084600014806122d257508060010160018603815481106122b657fe5b6000918252602090912060089091020154600160801b900460ff165b6040518060400160405280601d81526020017f444d5f50524556494f55535f524f554e445f4e4f545f534554544c45440000008152509061235757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600081600101868154811061236957fe5b906000526020600020906008020190508060000160109054906101000a900460ff16156040518060400160405280601881526020017f444d5f524f554e445f414c52454144595f534554544c454400000000000000008152509061241157604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5061241a615b71565b61242383613661565b90506000612432848a84614ad7565b905060006124408a8a613852565b6004850154909150600160c01b90046001600160401b03166125295760006124666135cb565b9050806001600160a01b03166385dbcf7983856040518363ffffffff1660e01b8152600401808381526020018260ff1660ff1681526020019250505060206040518083038186803b1580156124ba57600080fd5b505afa1580156124ce573d6000803e3d6000fd5b505050506040513d60208110156124e457600080fd5b50516004860180546001600160401b03909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909216919091179055505b6000612533614a88565b8451519091506125438b86614499565b15612604576000612568878587896020015160c001518f8b6040015160000151614c39565b9050826001600160a01b0316635f52d44e8333612596858b60000151608001516150f990919063ffffffff16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b1580156125e657600080fd5b505af11580156125fa573d6000803e3d6000fd5b5050505050612623565b855470ff000000000000000000000000000000001916600160801b1786555b8554600160801b900460ff1615611b6f5760058601546040805182815290518d918f917f2f643ff79db9be434873df2e7b4cc272c517e58b5712ea5a20c5d7bfc482f5539181900360200190a3610cde88888e86868661519c565b828261268a828261379b565b60006001868154811061269957fe5b906000526020600020906002020190506126b1615b71565b6126ba82613661565b90506126cd828760048460200151613684565b60008260010187815481106126de57fe5b600091825260208220600890910201915060068201906126fe8a8a613852565b825490915060ff898116600160a01b90920416148015906127a057506127226135cb565b6001600160a01b031663e2e7ed9f828a6040518363ffffffff1660e01b8152600401808381526020018260ff1660ff1681526020019250505060206040518083038186803b15801561277357600080fd5b505afa158015612787573d6000803e3d6000fd5b505050506040513d602081101561279d57600080fd5b50515b6040518060400160405280601881526020017f444d5f494e56414c49445f41505045414c5f52554c494e4700000000000000008152509061282557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5061282e615ba4565b612839848b8761385c565b9050600081604001519050600061285f8d83856000015186602001518760a00151614000565b9050338560010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a8560010160146101000a81548160ff021916908360ff16021790555082600001516001600160401b0316818e7f06c05c98f79e14aad019b270fad6f7d1bcb11dc267667ed908d78e4d5ec9a3eb866020015160405180826001600160401b0316815260200191505060405180910390a4610cde3384606001518560e00151613ab5565b6000808261291b81614552565b60006001858154811061292a57fe5b6000918252602090912060029091020180546001600160a01b031694509050612951615b71565b61295a82613661565b9050612967828783614ad7565b935060028254600160f01b900460ff16600281111561298257fe5b146129cc578154600160f01b60ff021916600160f11b17825560405160ff85169087907f33ebf61f1f1800f29578208d33c8618cf5a27602cd0c4c1978a60651eb531d3b90600090a35b505050915091565b60008060006129e28561361a565b915091506129ee615b71565b6129f783613661565b9050612a0a838360028460200151613684565b6000836001018381548110612a1b57fe5b90600052602060002090600802019050612a3581876144a6565b9450505050505b92915050565b60005460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b03163314612ad357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50806000612ae1828261379b565b600060018481548110612af057fe5b90600052602060002090600202019050600081600101600081548110612b1257fe5b6000918252602091829020845460408051808201909152601e81527f444d5f5355424a4543545f4e4f545f444953505554455f5355424a45435400009481019490945260089092020192506001600160a01b0390811690881614612bba57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000612bc5613b6e565b90506000612be36001600160401b038316600163ffffffff613ee516565b835460408051808201909152601c81527f444d5f45564944454e43455f504552494f445f49535f434c4f5345440000000060208201529192506001600160401b0390811690831610612c7957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50825467ffffffffffffffff19166001600160401b038281169190911784556040519083169088907f1384c9abcdf1fa5a2a50953bad79f58ea7b2999fae7783b5b1e2edff339b8d1c90600090a35050505050505050565b600080600080600080600080612ce78a8a61379b565b600060018b81548110612cf657fe5b90600052602060002090600202019050612d0e615b71565b612d1782613661565b9050612d238b82614499565b6040518060400160405280601181526020017f444d5f524f554e445f49535f46494e414c00000000000000000000000000000081525090612da857604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000826001018c81548110612dba57fe5b90600052602060002090600802019050612dd2615ba4565b612ddd828e8561385c565b9050806000015181602001518260400151836060015184608001518560a001518660c001518760e001519b509b509b509b509b509b509b509b50505050509295985092959890939650565b60008060008060008086612e3b81614552565b600060018981548110612e4a57fe5b6000918252602090912060029091020180546001909101546001600160a01b0382169b600160e01b830460ff9081169c50600160f01b840481169b50600160e81b84041699506000199091019750600160a01b9091046001600160401b031695509350505050565b8181612ebe828261379b565b600060018581548110612ecd57fe5b906000526020600020906002020190506000816001018581548110612eee57fe5b906000526020600020906008020190508060000160109054906101000a900460ff166040518060400160405280601e81526020017f444d5f524f554e445f50454e414c544945535f4e4f545f534554544c4544000081525090612f9557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060068101612fa3816153dd565b6040518060400160405280601581526020017f444d5f524f554e445f4e4f545f41505045414c454400000000000000000000008152509061302857604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600181015460408051808201909152601981527f444d5f41505045414c5f414c52454144595f534554544c454400000000000000602082015290600160a81b900460ff16156130bc57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060018101805475ff0000000000000000000000000000000000000000001916600160a81b179055604051869088907f28d5bc8b3a7bef24e784872d5b3b9069cf63ae040039bcc6040bd0b7af32d2f290600090a3613119615b71565b61312284613661565b905061312c615ba4565b61313784898461385c565b6060810151608082015160c083015160e08401519394509192909190600061315d614a88565b9050613168886153ec565b6131f257875460408051600160e11b632fa96a270281526001600160a01b038881166004830152928316602482015260448101869052905191831691635f52d44e9160648082019260009290919082900301818387803b1580156131cb57600080fd5b505af11580156131df573d6000803e3d6000fd5b5050505050505050505050505050610d21565b8954600160e81b900460ff16600061320a85856153fe565b8a5490915060ff838116600160a01b9092041614156132b75789546001600160a01b0380851691635f52d44e918a911661324a858b63ffffffff61548b16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561329a57600080fd5b505af11580156132ae573d6000803e3d6000fd5b5050505061341c565b60018a015460ff838116600160a01b9092041614156132fa5760018a01546001600160a01b0380851691635f52d44e918a911661324a858b63ffffffff61548b16565b895460028704906001600160a01b0385811691635f52d44e918b91166133208a8661548b565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561337057600080fd5b505af1158015613384573d6000803e3d6000fd5b50505060018c01546001600160a01b038087169250635f52d44e918b91166133b2898663ffffffff61548b16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561340257600080fd5b505af1158015613416573d6000803e3d6000fd5b50505050505b50505050505050505050505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166397023f816040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b505afa158015613491573d6000803e3d6000fd5b505050506040513d60208110156134a757600080fd5b5051905090565b60408051808201909152601b81527f444d5f4241445f4d41585f44524146545f42415443485f53495a45000000000060208201526001600160401b03821661353a57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600054604080516001600160401b03600160a01b90930483168152918316602083015280517fed22db0c227e21d249167e5f9d39415fd9386958f122075463fef70fd46c95c49281900390910190a1600080546001600160401b03909216600160a01b027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60008060009054906101000a90046001600160a01b03166001600160a01b0316631986d3766040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b60006fffffffffffffffffffffffffffffffff8216608083901c61363e818361379b565b6001818154811061364b57fe5b9060005260206000209060020201925050915091565b613669615b71565b8154612a3c90600160a01b90046001600160401b0316613bc6565b600061368e613b6e565b9050600061369e86868486614230565b90508360058111156136ac57fe5b8160058111156136b857fe5b146040518060400160405280601d81526020017f444d5f494e56414c49445f41444a554449434154494f4e5f53544154450000008152509061373e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50505050505050565b60008085600101858154811061375957fe5b906000526020600020906008020190506137738584614499565b6137875761378283828661551d565b613791565b61379181856144a6565b9695505050505050565b6137a482614552565b600182815481106137b157fe5b90600052602060002090600202016001018054905081106040518060400160405280601781526020017f444d5f524f554e445f444f45535f4e4f545f45584953540000000000000000008152509061384d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b505050565b60809190911b0190565b613864615ba4565b61386c615ba4565b613874615c3e565b506020830151600486015486546000916138a0916001600160401b03908116911663ffffffff613ee516565b905060006138e183606001516138cc8560400151856001600160401b0316613ee590919063ffffffff16565b6001600160401b03169063ffffffff613ee516565b905061390b8360a001516138cc8560800151846001600160401b0316613ee590919063ffffffff16565b6001600160401b0316845261014083015161392d90600163ffffffff61548b16565b8710613a24576001604085015260006139446144ce565b90506000816001600160a01b0316638e12779387600001516040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b0316815260200191505060206040518083038186803b1580156139a257600080fd5b505afa1580156139b6573d6000803e3d6000fd5b505050506040513d60208110156139cc57600080fd5b50516040890151519091506000906139e590839061451d565b6001600160401b03811660208901528951909150613a03908261570d565b60808a015260a08901526001600160a01b0316606088015250613a69915050565b60006040850152613a358884615761565b6001600160401b0316602085018190528651613a5091613f86565b608087015260a08601526001600160a01b031660608501525b6101608301516080850151613a839163ffffffff61579d16565b60c08501526101808301516080850151613aa29163ffffffff61579d16565b60e08501525091925050505b9392505050565b801561384d576000613ac5614a88565b9050613ae26001600160a01b03841685838563ffffffff6157c116565b6040518060400160405280601181526020017f444d5f4445504f5349545f4641494c454400000000000000000000000000000081525090613b6757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050505050565b6000613b7861133c565b6001600160a01b0316633f33bf866040518163ffffffff1660e01b8152600401602060405180830381600087803b158015613bb257600080fd5b505af1158015613491573d6000803e3d6000fd5b613bce615b71565b6000613bd8615caa565b6000613be2615cc8565b613bea615ce7565b613bf2615ce7565b613bfa615d05565b613c0261133c565b6001600160a01b031663e008cb628a6040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b031681526020019150506102c06040518083038186803b158015613c5857600080fd5b505afa158015613c6c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506102c0811015613c9257600080fd5b5080516080820151909850602082019750955060a0810194506101c08101935061020081019250610240019050613cc7615b71565b6040805160a0810182526001600160a01b038a16815260208681015161ffff168183015289518284015289810151606083015289830151608083015290835281516101a08101835260ff8916815287516001600160401b03169181019190915290810186600160200201516001600160401b0316815260200186600260098110613d4d57fe5b60200201516001600160401b0316815260200186600360098110613d6d57fe5b60200201516001600160401b0316815260200186600460098110613d8d57fe5b60200201516001600160401b0316815260200185600060028110613dad57fe5b602002015161ffff16815260200186600560098110613dc857fe5b60200201516001600160401b0316815260200186600660098110613de857fe5b60200201516001600160401b0316815260200186600860098110613e0857fe5b60200201516001600160401b0316815260200186600760098110613e2857fe5b60200201516001600160401b0316815260200184600060028110613e4857fe5b6020020151815260200184600160028110613e5f57fe5b60200201518152508160200181905250604051806080016040528083600060048110613e8757fe5b6020020151815260200183600160048110613e9e57fe5b6020020151815260200183600260048110613eb557fe5b6020020151815260200183600360048110613ecc57fe5b6020020151905260408201529998505050505050505050565b60408051808201909152601381527f4d41544836345f4144445f4f564552464c4f57000000000000000000000000006020820152600090838301906001600160401b038086169083161015613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b509392505050565b815160408301516000908190613fac906001600160401b0386169063ffffffff6150f916565b91506000613fe4856001600160401b0316613fd8886080015189606001516153fe90919063ffffffff16565b9063ffffffff6150f916565b9050613ff6838263ffffffff6153fe16565b9150509250925092565b6000806001878154811061401057fe5b906000526020600020906002020190508581600001601e6101000a81548160ff0219169083600281111561404057fe5b0217905550600081600101805480919060010161405d9190615d23565b9050600082600101828154811061407057fe5b60009182526020822060089091020180546001600160401b03898116600160401b026fffffffffffffffff000000000000000019918c1667ffffffffffffffff1990931692909217161781556001810187905591506140cd6135cb565b905060006140db8b85613852565b8554604080517ffaf172f700000000000000000000000000000000000000000000000000000000815260048101849052600160e01b90920460ff166024830152519192506001600160a01b0384169163faf172f79160448082019260009290919082900301818387803b15801561415157600080fd5b505af1158015614165573d6000803e3d6000fd5b50959d9c50505050505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b03167fa9059cbb000000000000000000000000000000000000000000000000000000001790526000906141e58582615832565b95945050505050565b60006141f861133c565b6001600160a01b03166308135a936040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b60008085600101858154811061424257fe5b600091825260209091206001880154600890920201915060028754600160f01b900460ff16600281111561427257fe5b148061428d575061428a81600163ffffffff61548b16565b86105b1561429d57600592505050611027565b600482015482546000916142c3916001600160401b03908116911663ffffffff613ee516565b905060008854600160f01b900460ff1660028111156142de57fe5b14806142fb5750806001600160401b0316866001600160401b0316105b1561430c5760009350505050611027565b600061432e8660400151836001600160401b0316613ee590919063ffffffff16565b9050806001600160401b0316876001600160401b03161015614357576001945050505050611027565b60006143798760600151836001600160401b0316613ee590919063ffffffff16565b9050806001600160401b0316886001600160401b031610156143a357600295505050505050611027565b610140870151841180156143c05760059650505050505050611027565b60006143ce876006016153dd565b905060006143f28a60800151856001600160401b0316613ee590919063ffffffff16565b90508161443557806001600160401b03168b6001600160401b0316101561442457600398505050505050505050611027565b600598505050505050505050611027565b60006144578b60a00151836001600160401b0316613ee590919063ffffffff16565b9050806001600160401b03168c6001600160401b031610156144855760049950505050505050505050611027565b5060059d9c50505050505050505050505050565b6020015161014001511190565b6001600160a01b0316600090815260039190910160205260409020546001600160401b031690565b60008060009054906101000a90046001600160a01b03166001600160a01b031663953e46a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b60008183101561452f57506000612a3c565b613aae826145456103e88663ffffffff6150f916565b8161454c57fe5b0461587d565b60015460408051808201909152601981527f444d5f444953505554455f444f45535f4e4f545f45584953540000000000000060208201529082106145da57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050565b60006145e861133c565b6001600160a01b031663f7fe57896040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b614628615c1e565b600080600061463561133c565b6001600160a01b03166369667005866040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b0316815260200191505060606040518083038186803b15801561468a57600080fd5b505afa15801561469e573d6000803e3d6000fd5b505050506040513d60608110156146b457600080fd5b50805160208083015160409384015184516060810186526001600160a01b03909416845261ffff16918301919091529181019190915295945050505050565b6146fb615d4f565b506040805160a08101825295865260208601949094526001600160401b03909216928401929092526060830191909152608082015290565b815460048301546000805490926001600160401b03600160401b9182900481169391909104811691600160a01b90041683614774848463ffffffff61591416565b90506000826001600160401b0316826001600160401b0316106147975782614799565b815b90506147a3615d8a565b6040518060e00160405280896060015160001c81526020018960000151815260200189604001516001600160401b03168152602001866001600160401b03168152602001836001600160401b03168152602001876001600160401b0316815260200189608001516020015161ffff16815250905060006148216144ce565b905060606000826001600160a01b031663d903bcf4856040518263ffffffff1660e01b81526004018082600760200280838360005b8381101561486e578181015183820152602001614856565b50505050905001915050600060405180830381600087803b15801561489257600080fd5b505af11580156148a6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160409081528110156148cf57600080fd5b8101908080516401000000008111156148e757600080fd5b820160208101848111156148fa57600080fd5b815185602082028301116401000000008211171561491757600080fd5b505060209091015190945092506000915061494390506001600160401b038a168363ffffffff613ee516565b60048e0180546fffffffffffffffff00000000000000001916600160401b6001600160401b038416021790558c5160208e0151919250614985918f86866159b1565b60808c0151604001516001600160401b03828116908c1614906000906149b1908563ffffffff6150f916565b90506149bb614a88565b60808f01515160408051600160e11b632fa96a270281526001600160a01b0392831660048201523360248201526044810185905290519290911691635f52d44e9160648082019260009290919082900301818387803b158015614a1d57600080fd5b505af1158015614a31573d6000803e3d6000fd5b50939e50505050505050505050505050505092915050565b600483015482546000916001600160401b03600160801b909104811691614a789185911663ffffffff6150f916565b81614a7f57fe5b04949350505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316633b19e84a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b8254600090600160e81b900460ff1615614afd57508254600160e81b900460ff16613aae565b600060018560010180549050039050614b1d858260058660200151613684565b6000856001018281548110614b2e57fe5b60009182526020822060089091020191506006820190614b4d826153dd565b8015614b5f5750614b5d826153ec565b155b9050600081614bed57614b706135cb565b6001600160a01b031663084d72f4614b888a88613852565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015614bbc57600080fd5b505afa158015614bd0573d6000803e3d6000fd5b505050506040513d6020811015614be657600080fd5b5051614bfa565b8254600160a01b900460ff165b89547fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160e81b60ff831602179099555096979650505050505050565b600080614c44613b6e565b600489015460028a0154919250600160c01b90046001600160401b031690600090614c6f908361548b565b9050600086118015614c8057508581115b15614c8c575084614cab565b895470ff000000000000000000000000000000001916600160801b178a555b614cbb828263ffffffff6153fe16565b8a60040160186101000a8154816001600160401b0302191690836001600160401b031602179055506000614ced6144ce565b9050606082604051908082528060200260200182016040528015614d1b578160200160208202803883390190505b509050606083604051908082528060200260200182016040528015614d4a578160200160208202803883390190505b50905060005b84811015614e355760008e60020182880181548110614d6b57fe5b9060005260206000200160009054906101000a90046001600160a01b0316905080848381518110614d9857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050614e158f6003016000836001600160a01b03166001600160a01b0316815260200190815260200160002060000160009054906101000a90046001600160401b03166001600160401b0316613fd88e8d615abc90919063ffffffff16565b838381518110614e2157fe5b602090810291909101015250600101614d50565b506060614e406135cb565b6001600160a01b03166318ce8f568e8e866040518463ffffffff1660e01b8152600401808481526020018360ff1660ff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b83811015614eb2578181015183820152602001614e9a565b5050505090500194505050505060006040518083038186803b158015614ed757600080fd5b505afa158015614eeb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015614f1457600080fd5b810190808051640100000000811115614f2c57600080fd5b82016020810184811115614f3f57600080fd5b8151856020820283011164010000000082111715614f5c57600080fd5b505092919050505090506150e1846001600160a01b031663c67106f5898686866040518563ffffffff1660e01b815260040180856001600160401b03166001600160401b03168152602001806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b83811015614feb578181015183820152602001614fd3565b50505050905001848103835286818151815260200191508051906020019060200280838360005b8381101561502a578181015183820152602001615012565b50505050905001848103825285818151815260200191508051906020019060200280838360005b83811015615069578181015183820152602001615051565b50505050905001975050505050505050602060405180830381600087803b15801561509357600080fd5b505af11580156150a7573d6000803e3d6000fd5b505050506040513d60208110156150bd57600080fd5b81019080805190602001909291905050508f600501546153fe90919063ffffffff16565b60058f01555092955050505050509695505050505050565b60008261510857506000612a3c565b8282028284828161511557fe5b04146040518060400160405280601181526020017f4d4154485f4d554c5f4f564552464c4f5700000000000000000000000000000081525090613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b6004850154600160801b90046001600160401b0316156151bb576153d5565b801561522d5760006151cb6144ce565b9050806001600160a01b0316636d1b229d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561521357600080fd5b505af1158015615227573d6000803e3d6000fd5b50505050505b836152b3578554600186015460408051600160e11b632fa96a270281526001600160a01b038681166004830152938416602482015260448101929092525191851691635f52d44e9160648082019260009290919082900301818387803b15801561529657600080fd5b505af11580156152aa573d6000803e3d6000fd5b505050506153d5565b600060028660010154816152c357fe5b04905060008760010160018703815481106152da57fe5b600091825260208220600660089092020101805460408051600160e11b632fa96a270281526001600160a01b038981166004830152928316602482015260448101879052905192945090881692635f52d44e9260648084019382900301818387803b15801561534857600080fd5b505af115801561535c573d6000803e3d6000fd5b505050600182015460408051600160e11b632fa96a270281526001600160a01b03888116600483015292831660248201526044810186905290519188169250635f52d44e91606480830192600092919082900301818387803b1580156153c157600080fd5b505af1158015611b6f573d6000803e3d6000fd5b505050505050565b546001600160a01b0316151590565b600101546001600160a01b0316151590565b60408051808201909152601181527f4d4154485f4144445f4f564552464c4f5700000000000000000000000000000060208201526000908383019084821015613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b6000828211156040518060400160405280601281526020017f4d4154485f5355425f554e444552464c4f5700000000000000000000000000008152509061551657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050900390565b6000806155286144ce565b845460408051600160e01b63e9e67d670281526001600160a01b0387811660048301526001600160401b03909316602482015290519293506000929184169163e9e67d6791604480820192602092909190829003018186803b15801561558d57600080fd5b505afa1580156155a1573d6000803e3d6000fd5b505050506040513d60208110156155b757600080fd5b50516040870151519091506000906155d090839061451d565b90506001600160401b0381166155ec5760009350505050613aae565b6000615609886020015160c0015184615abc90919063ffffffff16565b9050836001600160a01b031663605da1b287836156246145de565b6040805163ffffffff861660e01b81526001600160a01b03909416600485015260248401929092526001600160401b031660448301525160648083019260209291908290030181600087803b15801561567c57600080fd5b505af1158015615690573d6000803e3d6000fd5b505050506040513d60208110156156a657600080fd5b50516156b9576000945050505050613aae565b6001600160a01b03861660009081526003880160205260409020805467ffffffffffffffff19166001600160401b03841617905560058701546156fc90826153fe565b600588015550925050509392505050565b815160208301516040840151600091829161575591906103e890615741906001600160401b0389169063ffffffff6150f916565b8161574857fe5b049063ffffffff615abc16565b91508190509250925092565b6101008101518254600091829161578991600160401b9091046001600160401b031690615ad5565b905060018116613aae576001019392505050565b60006127106157b2848463ffffffff6150f916565b816157b957fe5b049392505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03167f23b872dd0000000000000000000000000000000000000000000000000000000017905260009061379186825b6000806040516020818551602087016000895af18015615873573d8015615860576020811461586957615871565b60019350615871565b600183511493505b505b5090949350505050565b60408051808201909152601581527f55494e5436345f4e554d4245525f544f4f5f424947000000000000000000000060208201526000906001600160401b0383111561590d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5090919050565b6000826001600160401b0316826001600160401b031611156040518060400160405280601481526020017f4d41544836345f5355425f554e444552464c4f570000000000000000000000008152509061551657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b60005b818110156153d55760008382815181106159ca57fe5b6020908102919091018101516001600160a01b03811660009081526003880190925260409091208054919250906001600160401b0316615a42576002860180546001810182556000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384161790555b8054615a5e906001600160401b0316600163ffffffff613ee516565b815467ffffffffffffffff19166001600160401b03919091161781556040516001600160a01b0383169088908a907fbfd1b785c517ac3c709db5d7c9904052346df35e7069c1cb80f3dd966579d52290600090a450506001016159b4565b60006127106157b28461ffff851663ffffffff6150f916565b60408051808201909152601381527f4d41544836345f4d554c5f4f564552464c4f570000000000000000000000000060208201526000906001600160401b038481169084160290600160401b8210613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b604051806102c00160405280615b85615da8565b8152602001615b92615c3e565b8152602001615b9f615de4565b905290565b60408051610100810182526000808252602082018190529091820190815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b81548183558181111561384d5760020281600202836000526020600020918201910161384d9190615e0c565b604080516060810182526000808252602082018190529181019190915290565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081019190915290565b60405180606001604052806003906020820280388339509192915050565b6040518061012001604052806009906020820280388339509192915050565b60405180604001604052806002906020820280388339509192915050565b60405180608001604052806004906020820280388339509192915050565b81548183558181111561384d5760080281600802836000526020600020918201910161384d9190615e5c565b6040518060e00160405280600081526020016000815260200160006001600160401b0316815260200160008019168152602001615b9f615c1e565b6040518060e001604052806007906020820280388339509192915050565b6040518060a0016040528060006001600160a01b03168152602001600061ffff1681526020016000815260200160008152602001600081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b61134991905b80821115615e585780547fff000000000000000000000000000000000000000000000000000000000000001681556000615e4f6001830182615ef0565b50600201615e12565b5090565b61134991905b80821115615e5857805470ffffffffffffffffffffffffffffffffff19168155600060018201819055615e986002830182615f11565b50600060048201819055600582015560068101805474ffffffffffffffffffffffffffffffffffffffffff1916905560078101805475ffffffffffffffffffffffffffffffffffffffffffff19169055600801615e62565b50805460008255600802906000526020600020908101906108859190615e5c565b5080546000825590600052602060002090810190610885919061134991905b80821115615e585760008155600101615f3056fea165627a7a7230582020c137edb6f0f5f0da0d0d361d22809d8f4b8382642960f9058207418aaf2b340029000000000000000000000000f0c8376065fadfacb706cafbaac96b321069c01500000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061017c5760003560e01c8063710cf1ed116100e3578063bd881e531161008c578063cd604ada11610066578063cd604ada14610674578063e3a96cbd146106fe578063eed04b801461077a5761017c565b8063bd881e53146105da578063c1361a7c1461061c578063c39c83d1146106485761017c565b806382a8b3b0116100bd57806382a8b3b014610553578063859ba187146105855780639c0065f7146105ae5761017c565b8063710cf1ed146104ab5780637263bf2a146104c85780637b751b9e146105285761017c565b806324ae6a271161014557806339ec68a31161011f57806339ec68a31461032e5780634b4acfd3146103c75780635bdaf9d81461041c5761017c565b806324ae6a27146102b85780633018205f146102e65780633238f8f41461030a5761017c565b80629230a51461018157806306349cfa146101a95780630d03d126146101d557806315fe5268146102015780631d2fa1fb1461021e575b600080fd5b6101a76004803603602081101561019757600080fd5b50356001600160401b031661079d565b005b6101a7600480360360408110156101bf57600080fd5b50803590602001356001600160a01b0316610888565b6101a7600480360360608110156101eb57600080fd5b508035906020810135906040013560ff16610a04565b6101a76004803603602081101561021757600080fd5b5035610ced565b6102a66004803603606081101561023457600080fd5b6001600160a01b038235169160ff6020820135169181019060608101604082013564010000000081111561026757600080fd5b82018360208201111561027957600080fd5b8035906020019184600183028401116401000000008311171561029b57600080fd5b509092509050610d27565b60408051918252519081900360200190f35b6101a7600480360360408110156102ce57600080fd5b506001600160a01b038135811691602001351661102f565b6102ee61133c565b604080516001600160a01b039092168252519081900360200190f35b61031261134c565b604080516001600160401b039092168252519081900360200190f35b6103516004803603604081101561034457600080fd5b5080359060200135611362565b604080516001600160401b03808c1682528a811660208301528981169282019290925287821660608201526080810187905285151560a082015260c0810185905290831660e082015261010081018260058111156103ab57fe5b60ff168152602001995050505050505050505060405180910390f35b6103f9600480360360608110156103dd57600080fd5b50803590602081013590604001356001600160a01b0316611492565b604080516001600160401b03909316835290151560208301528051918290030190f35b6101a76004803603608081101561043257600080fd5b6001600160a01b03823581169260208101359260408201359092169181019060808101606082013564010000000081111561046c57600080fd5b82018360208201111561047e57600080fd5b803590602001918460018302840111640100000000831117156104a057600080fd5b509092509050611600565b6101a7600480360360208110156104c157600080fd5b50356117c9565b6104eb600480360360408110156104de57600080fd5b5080359060200135611b7d565b604080516001600160a01b0395861681526001600160401b0394851660208201529290941682850152909116606082015290519081900360800190f35b610530611c06565b604080516001600160a01b03909316835260208301919091528051918290030190f35b6101a76004803603606081101561056957600080fd5b50803590602081013590604001356001600160a01b0316611c4b565b6101a76004803603606081101561059b57600080fd5b508035906020810135906040013561226f565b6101a7600480360360608110156105c457600080fd5b508035906020810135906040013560ff1661267e565b6105f7600480360360208110156105f057600080fd5b503561290e565b604080516001600160a01b03909316835260ff90911660208301528051918290030190f35b6103126004803603604081101561063257600080fd5b50803590602001356001600160a01b03166129d4565b6101a76004803603604081101561065e57600080fd5b506001600160a01b038135169060200135612a42565b6106976004803603604081101561068a57600080fd5b5080359060200135612cd1565b604080516001600160401b03808b168252891660208201529081018760028111156106be57fe5b60ff1681526001600160a01b039096166020870152506040808601949094526060850192909252608084015260a0830152519081900360c0019350915050f35b61071b6004803603602081101561071457600080fd5b5035612e28565b604080516001600160a01b038816815260ff8716602082015290810185600281111561074357fe5b60ff9081168252949094166020850152506040808401929092526001600160401b0316606083015251908190036080019350915050f35b6101a76004803603604081101561079057600080fd5b5080359060200135612eb2565b6107a561342e565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f434f4e4649475f474f5645524e4f5200008152509061087b57604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610840578181015183820152602001610828565b50505050905090810190601f16801561086d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50610885816134ae565b50565b60006108926135cb565b60408051808201909152601481527f444d5f53454e4445525f4e4f545f564f54494e470000000000000000000000006020820152909150336001600160a01b0383161461092357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000806109308561361a565b9150915061093c615b71565b61094583613661565b9050610958838360018460200151613684565b600061096684848885613747565b90506000816001600160401b0316116040518060400160405280601481526020017f444d5f564f5445525f5745494748545f5a45524f000000000000000000000000815250906109fa57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050505050505050565b8282610a10828261379b565b600060018681548110610a1f57fe5b90600052602060002090600202019050610a37615b71565b610a4082613661565b9050610a53828760038460200151613684565b6000610a5d6135cb565b90506000610a6b8989613852565b90506000826001600160a01b031663084d72f4836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610ab357600080fd5b505afa158015610ac7573d6000803e3d6000fd5b505050506040513d6020811015610add57600080fd5b5051905060ff80821690891614801590610b885750604080517fe2e7ed9f0000000000000000000000000000000000000000000000000000000081526004810184905260ff8a16602482015290516001600160a01b0385169163e2e7ed9f916044808301926020929190829003018186803b158015610b5b57600080fd5b505afa158015610b6f573d6000803e3d6000fd5b505050506040513d6020811015610b8557600080fd5b50515b6040518060400160405280601881526020017f444d5f494e56414c49445f41505045414c5f52554c494e47000000000000000081525090610c0d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000856001018a81548110610c1f57fe5b6000918252602091829020600891909102016006810180543373ffffffffffffffffffffffffffffffffffffffff199091161774ff00000000000000000000000000000000000000001916600160a01b60ff8e16908102919091178255604080519182525192945090928d928f927f57dc4548648c602e9f394f905942ffeba7a2041a6a704128b3a75e5b0efa11a792908290030190a3610cbe615ba4565b610cc9838d8961385c565b9050610cde3382606001518360c00151613ab5565b50505050505050505050505050565b600080610cf98361361a565b91509150610d05615b71565b610d0e83613661565b9050610d21838360018460200151613684565b50505050565b6000805460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b03163314610db957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000610dc4613b6e565b9050610dce615b71565b610dd782613bc6565b9050600260ff871610801590610dfb575080602001516000015160ff168660ff1611155b6040518060400160405280601981526020017f444d5f494e56414c49445f52554c494e475f4f5054494f4e530000000000000081525090610e8057604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060018054600091610e9490828101615bf2565b9050600060018281548110610ea557fe5b90600052602060002090600202019050888160000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508781600001601c6101000a81548160ff021916908360ff160217905550838160000160146101000a8154816001600160401b0302191690836001600160401b031602179055506000836020015160e0015190506000610f57856020015160200151876001600160401b0316613ee590919063ffffffff16565b9050806001600160401b03168b6001600160a01b0316857fd4784fc5a2aef689d6639d09cb5b543abfeabd597519d01b93f4ffef74d10396858d8d60405180846001600160401b03166001600160401b03168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a46000806000610ffb886000015186613f86565b92509250925061100f876000868886614000565b5061101b8e8483613ab5565b50949750505050505050505b949350505050565b6000809054906101000a90046001600160a01b03166001600160a01b0316633c28e88b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561107c57600080fd5b505afa158015611090573d6000803e3d6000fd5b505050506040513d60208110156110a657600080fd5b505160408051808201909152601d81527f4354445f53454e4445525f4e4f545f46554e44535f474f5645524e4f520000006020820152906001600160a01b0316331461113657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000916001600160a01b038516916370a0823191602480820192602092909190829003018186803b15801561119a57600080fd5b505afa1580156111ae573d6000803e3d6000fd5b505050506040513d60208110156111c457600080fd5b505160408051808201909152601e81527f4354445f494e53554646494349454e545f5245434f5645525f46554e4453000060208201529091508161124c57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506112676001600160a01b038416838363ffffffff61417816565b6040518060400160405280601e81526020017f4354445f5245434f5645525f544f4b454e5f46554e44535f4641494c45440000815250906112ec57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50604080516001600160a01b0380861682528416602082015280820183905290517f724139fea3954691c2c1ee02b3be6be1763b32ec84841f1acad6d3a18695ba0d9181900360600190a1505050565b6000546001600160a01b03165b90565b600054600160a01b90046001600160401b031681565b60008060008060008060008060008a8a61137c828261379b565b600060018e8154811061138b57fe5b906000526020600020906002020190506113ba818e6113a86141ee565b6113b185613661565b60200151614230565b93506000816001018e815481106113cd57fe5b906000526020600020906008020190508060000160009054906101000a90046001600160401b03169c508060040160009054906101000a90046001600160401b03169b508060000160089054906101000a90046001600160401b03169a508060040160089054906101000a90046001600160401b03169950806001015498508060000160109054906101000a900460ff1697508060040160109054906101000a90046001600160401b0316955080600501549650505050509295985092959850929598565b60008084846114a1828261379b565b6000600188815481106114b057fe5b9060005260206000209060020201905060008160010188815481106114d157fe5b906000526020600020906008020190506114e9615b71565b6114f283613661565b90506114fe8982614499565b156115145761150d82896144a6565b96506115c8565b600061151e6144ce565b835460408051600160e01b63e9e67d670281526001600160a01b038d811660048301526001600160401b03909316602482015290519293506000929184169163e9e67d6791604480820192602092909190829003018186803b15801561158357600080fd5b505afa158015611597573d6000803e3d6000fd5b505050506040513d60208110156115ad57600080fd5b50516040840151519091506115c390829061451d565b985050505b506001600160a01b03969096166000908152600390960160205250506040909320549195600160401b90920460ff1694509092505050565b60005460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b0316331461169157604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b508361169c81614552565b6000600186815481106116ab57fe5b6000918252602091829020600290910201805460408051808201909152601e81527f444d5f5355424a4543545f4e4f545f444953505554455f5355424a4543540000938101939093529092506001600160a01b039081169089161461175457604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50846001600160a01b0316867fd25027d3faf6af10da1a82e9d4df3c98b93cb0481f9acaf87718a548fad0abce868660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a350505050505050565b806117d381614552565b60006117dd61133c565b905060006117e961133c565b6001600160a01b03166350c365806040518163ffffffff1660e01b815260040160206040518083038186803b15801561182157600080fd5b505afa158015611835573d6000803e3d6000fd5b505050506040513d602081101561184b57600080fd5b505160408051808201909152601081527f444d5f5445524d5f4f555444415445440000000000000000000000000000000060208201529091506001600160401b038216156118dd57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060006118e86145de565b90506000600186815481106118f957fe5b60009182526020822060029091020191508154600160f01b900460ff16600281111561192157fe5b146040518060400160405280601881526020017f444d5f524f554e445f414c52454144595f445241465445440000000000000000815250906119a757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600181018054600019810191600091839081106119c157fe5b6000918252602091829020600890910201805460408051808201909152601981527f444d5f44524146545f5445524d5f4e4f545f5245414348454400000000000000938101939093529092506001600160401b0390811691908616821115611a6d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000876001600160a01b0316637d1f24c96040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611aab57600080fd5b505af1158015611abf573d6000803e3d6000fd5b505050506040513d6020811015611ad557600080fd5b50519050611ae1615c1e565b611aea83614620565b90506000611b0485611aff8e898c88886146f3565b614733565b90508015611b6f5760048501805467ffffffffffffffff1916858a036001600160401b03161790558654600160f01b60ff021916600160f01b1787556040516001908d907f9bfdc20780e4912d62e8c31a73ffad5cbd841d7f76d114aa9f302ceca2d8258590600090a35b505050505050505050505050565b6000806000808585611b8f828261379b565b600060018981548110611b9e57fe5b90600052602060002090600202016001018881548110611bba57fe5b600091825260209091206006600890920201908101546007909101546001600160a01b038083169c60ff600160a01b9485900481169d509183169b509290910416975095505050505050565b6000806000611c136141ee565b9050611c1d615b71565b611c2682613bc6565b9050611c3e8160000151826020015160e00151613f86565b9196919550909350505050565b8282611c57828261379b565b600060018681548110611c6657fe5b906000526020600020906002020190506000816001018681548110611c8757fe5b906000526020600020906008020190508060000160109054906101000a900460ff166040518060400160405280601e81526020017f444d5f524f554e445f50454e414c544945535f4e4f545f534554544c4544000081525090611d2e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506001600160a01b038516600090815260038201602090815260409182902080548351808501909452601984527f444d5f4a55524f525f414c52454144595f524557415244454400000000000000928401929092529190600160401b900460ff1615611dde57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50805460408051808201909152601e81527f444d5f574f4e545f5245574152445f4e4f4e5f564f5445525f4a55524f5200006020820152906001600160401b0316611e6d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50805468ff00000000000000001916600160401b1781556000611e8e6135cb565b90506000611e9c8a8a613852565b8554604080517fcfa558ba00000000000000000000000000000000000000000000000000000000815260048101849052600160e81b90920460ff1660248301526001600160a01b038b81166044840152905192935084169163cfa558ba91606480820192602092909190829003018186803b158015611f1a57600080fd5b505afa158015611f2e573d6000803e3d6000fd5b505050506040513d6020811015611f4457600080fd5b505160408051808201909152601f81527f444d5f574f4e545f5245574152445f494e434f484552454e545f4a55524f5200602082015290611fc957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060058401546000611fd96144ce565b90506000821561206957611fee878785614a49565b9050816001600160a01b0316634d7edc158c836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561205057600080fd5b505af1158015612064573d6000803e3d6000fd5b505050505b612071615b71565b61207a89613661565b9050600061208d89898b60010154614a49565b9050612097614a88565b6001600160a01b0316635f52d44e8360000151600001518f846040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b15801561211857600080fd5b505af115801561212c573d6000803e3d6000fd5b5050505061213a8e83614499565b61220357612146615c3e565b82602001519050846001600160a01b031663af8b9d0f8f836101200151846060015185604001518f60000160009054906101000a90046001600160401b03160101016040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b03168152602001826001600160401b03166001600160401b0316815260200192505050600060405180830381600087803b1580156121e957600080fd5b505af11580156121fd573d6000803e3d6000fd5b50505050505b8d8f7f3aea41188dba0e19aa929ada5527b70c76ba34b22bb672818cf2ed788c3c9e778f868560405180846001600160a01b03166001600160a01b03168152602001838152602001828152602001935050505060405180910390a3505050505050505050505050505050565b828261227b828261379b565b60006001868154811061228a57fe5b9060005260206000209060020201905084600014806122d257508060010160018603815481106122b657fe5b6000918252602090912060089091020154600160801b900460ff165b6040518060400160405280601d81526020017f444d5f50524556494f55535f524f554e445f4e4f545f534554544c45440000008152509061235757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600081600101868154811061236957fe5b906000526020600020906008020190508060000160109054906101000a900460ff16156040518060400160405280601881526020017f444d5f524f554e445f414c52454144595f534554544c454400000000000000008152509061241157604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5061241a615b71565b61242383613661565b90506000612432848a84614ad7565b905060006124408a8a613852565b6004850154909150600160c01b90046001600160401b03166125295760006124666135cb565b9050806001600160a01b03166385dbcf7983856040518363ffffffff1660e01b8152600401808381526020018260ff1660ff1681526020019250505060206040518083038186803b1580156124ba57600080fd5b505afa1580156124ce573d6000803e3d6000fd5b505050506040513d60208110156124e457600080fd5b50516004860180546001600160401b03909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909216919091179055505b6000612533614a88565b8451519091506125438b86614499565b15612604576000612568878587896020015160c001518f8b6040015160000151614c39565b9050826001600160a01b0316635f52d44e8333612596858b60000151608001516150f990919063ffffffff16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b1580156125e657600080fd5b505af11580156125fa573d6000803e3d6000fd5b5050505050612623565b855470ff000000000000000000000000000000001916600160801b1786555b8554600160801b900460ff1615611b6f5760058601546040805182815290518d918f917f2f643ff79db9be434873df2e7b4cc272c517e58b5712ea5a20c5d7bfc482f5539181900360200190a3610cde88888e86868661519c565b828261268a828261379b565b60006001868154811061269957fe5b906000526020600020906002020190506126b1615b71565b6126ba82613661565b90506126cd828760048460200151613684565b60008260010187815481106126de57fe5b600091825260208220600890910201915060068201906126fe8a8a613852565b825490915060ff898116600160a01b90920416148015906127a057506127226135cb565b6001600160a01b031663e2e7ed9f828a6040518363ffffffff1660e01b8152600401808381526020018260ff1660ff1681526020019250505060206040518083038186803b15801561277357600080fd5b505afa158015612787573d6000803e3d6000fd5b505050506040513d602081101561279d57600080fd5b50515b6040518060400160405280601881526020017f444d5f494e56414c49445f41505045414c5f52554c494e4700000000000000008152509061282557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5061282e615ba4565b612839848b8761385c565b9050600081604001519050600061285f8d83856000015186602001518760a00151614000565b9050338560010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a8560010160146101000a81548160ff021916908360ff16021790555082600001516001600160401b0316818e7f06c05c98f79e14aad019b270fad6f7d1bcb11dc267667ed908d78e4d5ec9a3eb866020015160405180826001600160401b0316815260200191505060405180910390a4610cde3384606001518560e00151613ab5565b6000808261291b81614552565b60006001858154811061292a57fe5b6000918252602090912060029091020180546001600160a01b031694509050612951615b71565b61295a82613661565b9050612967828783614ad7565b935060028254600160f01b900460ff16600281111561298257fe5b146129cc578154600160f01b60ff021916600160f11b17825560405160ff85169087907f33ebf61f1f1800f29578208d33c8618cf5a27602cd0c4c1978a60651eb531d3b90600090a35b505050915091565b60008060006129e28561361a565b915091506129ee615b71565b6129f783613661565b9050612a0a838360028460200151613684565b6000836001018381548110612a1b57fe5b90600052602060002090600802019050612a3581876144a6565b9450505050505b92915050565b60005460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b03163314612ad357604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50806000612ae1828261379b565b600060018481548110612af057fe5b90600052602060002090600202019050600081600101600081548110612b1257fe5b6000918252602091829020845460408051808201909152601e81527f444d5f5355424a4543545f4e4f545f444953505554455f5355424a45435400009481019490945260089092020192506001600160a01b0390811690881614612bba57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000612bc5613b6e565b90506000612be36001600160401b038316600163ffffffff613ee516565b835460408051808201909152601c81527f444d5f45564944454e43455f504552494f445f49535f434c4f5345440000000060208201529192506001600160401b0390811690831610612c7957604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50825467ffffffffffffffff19166001600160401b038281169190911784556040519083169088907f1384c9abcdf1fa5a2a50953bad79f58ea7b2999fae7783b5b1e2edff339b8d1c90600090a35050505050505050565b600080600080600080600080612ce78a8a61379b565b600060018b81548110612cf657fe5b90600052602060002090600202019050612d0e615b71565b612d1782613661565b9050612d238b82614499565b6040518060400160405280601181526020017f444d5f524f554e445f49535f46494e414c00000000000000000000000000000081525090612da857604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b506000826001018c81548110612dba57fe5b90600052602060002090600802019050612dd2615ba4565b612ddd828e8561385c565b9050806000015181602001518260400151836060015184608001518560a001518660c001518760e001519b509b509b509b509b509b509b509b50505050509295985092959890939650565b60008060008060008086612e3b81614552565b600060018981548110612e4a57fe5b6000918252602090912060029091020180546001909101546001600160a01b0382169b600160e01b830460ff9081169c50600160f01b840481169b50600160e81b84041699506000199091019750600160a01b9091046001600160401b031695509350505050565b8181612ebe828261379b565b600060018581548110612ecd57fe5b906000526020600020906002020190506000816001018581548110612eee57fe5b906000526020600020906008020190508060000160109054906101000a900460ff166040518060400160405280601e81526020017f444d5f524f554e445f50454e414c544945535f4e4f545f534554544c4544000081525090612f9557604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060068101612fa3816153dd565b6040518060400160405280601581526020017f444d5f524f554e445f4e4f545f41505045414c454400000000000000000000008152509061302857604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600181015460408051808201909152601981527f444d5f41505045414c5f414c52454144595f534554544c454400000000000000602082015290600160a81b900460ff16156130bc57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5060018101805475ff0000000000000000000000000000000000000000001916600160a81b179055604051869088907f28d5bc8b3a7bef24e784872d5b3b9069cf63ae040039bcc6040bd0b7af32d2f290600090a3613119615b71565b61312284613661565b905061312c615ba4565b61313784898461385c565b6060810151608082015160c083015160e08401519394509192909190600061315d614a88565b9050613168886153ec565b6131f257875460408051600160e11b632fa96a270281526001600160a01b038881166004830152928316602482015260448101869052905191831691635f52d44e9160648082019260009290919082900301818387803b1580156131cb57600080fd5b505af11580156131df573d6000803e3d6000fd5b5050505050505050505050505050610d21565b8954600160e81b900460ff16600061320a85856153fe565b8a5490915060ff838116600160a01b9092041614156132b75789546001600160a01b0380851691635f52d44e918a911661324a858b63ffffffff61548b16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561329a57600080fd5b505af11580156132ae573d6000803e3d6000fd5b5050505061341c565b60018a015460ff838116600160a01b9092041614156132fa5760018a01546001600160a01b0380851691635f52d44e918a911661324a858b63ffffffff61548b16565b895460028704906001600160a01b0385811691635f52d44e918b91166133208a8661548b565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561337057600080fd5b505af1158015613384573d6000803e3d6000fd5b50505060018c01546001600160a01b038087169250635f52d44e918b91166133b2898663ffffffff61548b16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561340257600080fd5b505af1158015613416573d6000803e3d6000fd5b50505050505b50505050505050505050505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166397023f816040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b505afa158015613491573d6000803e3d6000fd5b505050506040513d60208110156134a757600080fd5b5051905090565b60408051808201909152601b81527f444d5f4241445f4d41585f44524146545f42415443485f53495a45000000000060208201526001600160401b03821661353a57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50600054604080516001600160401b03600160a01b90930483168152918316602083015280517fed22db0c227e21d249167e5f9d39415fd9386958f122075463fef70fd46c95c49281900390910190a1600080546001600160401b03909216600160a01b027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60008060009054906101000a90046001600160a01b03166001600160a01b0316631986d3766040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b60006fffffffffffffffffffffffffffffffff8216608083901c61363e818361379b565b6001818154811061364b57fe5b9060005260206000209060020201925050915091565b613669615b71565b8154612a3c90600160a01b90046001600160401b0316613bc6565b600061368e613b6e565b9050600061369e86868486614230565b90508360058111156136ac57fe5b8160058111156136b857fe5b146040518060400160405280601d81526020017f444d5f494e56414c49445f41444a554449434154494f4e5f53544154450000008152509061373e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b50505050505050565b60008085600101858154811061375957fe5b906000526020600020906008020190506137738584614499565b6137875761378283828661551d565b613791565b61379181856144a6565b9695505050505050565b6137a482614552565b600182815481106137b157fe5b90600052602060002090600202016001018054905081106040518060400160405280601781526020017f444d5f524f554e445f444f45535f4e4f545f45584953540000000000000000008152509061384d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b505050565b60809190911b0190565b613864615ba4565b61386c615ba4565b613874615c3e565b506020830151600486015486546000916138a0916001600160401b03908116911663ffffffff613ee516565b905060006138e183606001516138cc8560400151856001600160401b0316613ee590919063ffffffff16565b6001600160401b03169063ffffffff613ee516565b905061390b8360a001516138cc8560800151846001600160401b0316613ee590919063ffffffff16565b6001600160401b0316845261014083015161392d90600163ffffffff61548b16565b8710613a24576001604085015260006139446144ce565b90506000816001600160a01b0316638e12779387600001516040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b0316815260200191505060206040518083038186803b1580156139a257600080fd5b505afa1580156139b6573d6000803e3d6000fd5b505050506040513d60208110156139cc57600080fd5b50516040890151519091506000906139e590839061451d565b6001600160401b03811660208901528951909150613a03908261570d565b60808a015260a08901526001600160a01b0316606088015250613a69915050565b60006040850152613a358884615761565b6001600160401b0316602085018190528651613a5091613f86565b608087015260a08601526001600160a01b031660608501525b6101608301516080850151613a839163ffffffff61579d16565b60c08501526101808301516080850151613aa29163ffffffff61579d16565b60e08501525091925050505b9392505050565b801561384d576000613ac5614a88565b9050613ae26001600160a01b03841685838563ffffffff6157c116565b6040518060400160405280601181526020017f444d5f4445504f5349545f4641494c454400000000000000000000000000000081525090613b6757604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050505050565b6000613b7861133c565b6001600160a01b0316633f33bf866040518163ffffffff1660e01b8152600401602060405180830381600087803b158015613bb257600080fd5b505af1158015613491573d6000803e3d6000fd5b613bce615b71565b6000613bd8615caa565b6000613be2615cc8565b613bea615ce7565b613bf2615ce7565b613bfa615d05565b613c0261133c565b6001600160a01b031663e008cb628a6040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b031681526020019150506102c06040518083038186803b158015613c5857600080fd5b505afa158015613c6c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506102c0811015613c9257600080fd5b5080516080820151909850602082019750955060a0810194506101c08101935061020081019250610240019050613cc7615b71565b6040805160a0810182526001600160a01b038a16815260208681015161ffff168183015289518284015289810151606083015289830151608083015290835281516101a08101835260ff8916815287516001600160401b03169181019190915290810186600160200201516001600160401b0316815260200186600260098110613d4d57fe5b60200201516001600160401b0316815260200186600360098110613d6d57fe5b60200201516001600160401b0316815260200186600460098110613d8d57fe5b60200201516001600160401b0316815260200185600060028110613dad57fe5b602002015161ffff16815260200186600560098110613dc857fe5b60200201516001600160401b0316815260200186600660098110613de857fe5b60200201516001600160401b0316815260200186600860098110613e0857fe5b60200201516001600160401b0316815260200186600760098110613e2857fe5b60200201516001600160401b0316815260200184600060028110613e4857fe5b6020020151815260200184600160028110613e5f57fe5b60200201518152508160200181905250604051806080016040528083600060048110613e8757fe5b6020020151815260200183600160048110613e9e57fe5b6020020151815260200183600260048110613eb557fe5b6020020151815260200183600360048110613ecc57fe5b6020020151905260408201529998505050505050505050565b60408051808201909152601381527f4d41544836345f4144445f4f564552464c4f57000000000000000000000000006020820152600090838301906001600160401b038086169083161015613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b509392505050565b815160408301516000908190613fac906001600160401b0386169063ffffffff6150f916565b91506000613fe4856001600160401b0316613fd8886080015189606001516153fe90919063ffffffff16565b9063ffffffff6150f916565b9050613ff6838263ffffffff6153fe16565b9150509250925092565b6000806001878154811061401057fe5b906000526020600020906002020190508581600001601e6101000a81548160ff0219169083600281111561404057fe5b0217905550600081600101805480919060010161405d9190615d23565b9050600082600101828154811061407057fe5b60009182526020822060089091020180546001600160401b03898116600160401b026fffffffffffffffff000000000000000019918c1667ffffffffffffffff1990931692909217161781556001810187905591506140cd6135cb565b905060006140db8b85613852565b8554604080517ffaf172f700000000000000000000000000000000000000000000000000000000815260048101849052600160e01b90920460ff166024830152519192506001600160a01b0384169163faf172f79160448082019260009290919082900301818387803b15801561415157600080fd5b505af1158015614165573d6000803e3d6000fd5b50959d9c50505050505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b03167fa9059cbb000000000000000000000000000000000000000000000000000000001790526000906141e58582615832565b95945050505050565b60006141f861133c565b6001600160a01b03166308135a936040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b60008085600101858154811061424257fe5b600091825260209091206001880154600890920201915060028754600160f01b900460ff16600281111561427257fe5b148061428d575061428a81600163ffffffff61548b16565b86105b1561429d57600592505050611027565b600482015482546000916142c3916001600160401b03908116911663ffffffff613ee516565b905060008854600160f01b900460ff1660028111156142de57fe5b14806142fb5750806001600160401b0316866001600160401b0316105b1561430c5760009350505050611027565b600061432e8660400151836001600160401b0316613ee590919063ffffffff16565b9050806001600160401b0316876001600160401b03161015614357576001945050505050611027565b60006143798760600151836001600160401b0316613ee590919063ffffffff16565b9050806001600160401b0316886001600160401b031610156143a357600295505050505050611027565b610140870151841180156143c05760059650505050505050611027565b60006143ce876006016153dd565b905060006143f28a60800151856001600160401b0316613ee590919063ffffffff16565b90508161443557806001600160401b03168b6001600160401b0316101561442457600398505050505050505050611027565b600598505050505050505050611027565b60006144578b60a00151836001600160401b0316613ee590919063ffffffff16565b9050806001600160401b03168c6001600160401b031610156144855760049950505050505050505050611027565b5060059d9c50505050505050505050505050565b6020015161014001511190565b6001600160a01b0316600090815260039190910160205260409020546001600160401b031690565b60008060009054906101000a90046001600160a01b03166001600160a01b031663953e46a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b60008183101561452f57506000612a3c565b613aae826145456103e88663ffffffff6150f916565b8161454c57fe5b0461587d565b60015460408051808201909152601981527f444d5f444953505554455f444f45535f4e4f545f45584953540000000000000060208201529082106145da57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050565b60006145e861133c565b6001600160a01b031663f7fe57896040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b614628615c1e565b600080600061463561133c565b6001600160a01b03166369667005866040518263ffffffff1660e01b815260040180826001600160401b03166001600160401b0316815260200191505060606040518083038186803b15801561468a57600080fd5b505afa15801561469e573d6000803e3d6000fd5b505050506040513d60608110156146b457600080fd5b50805160208083015160409384015184516060810186526001600160a01b03909416845261ffff16918301919091529181019190915295945050505050565b6146fb615d4f565b506040805160a08101825295865260208601949094526001600160401b03909216928401929092526060830191909152608082015290565b815460048301546000805490926001600160401b03600160401b9182900481169391909104811691600160a01b90041683614774848463ffffffff61591416565b90506000826001600160401b0316826001600160401b0316106147975782614799565b815b90506147a3615d8a565b6040518060e00160405280896060015160001c81526020018960000151815260200189604001516001600160401b03168152602001866001600160401b03168152602001836001600160401b03168152602001876001600160401b0316815260200189608001516020015161ffff16815250905060006148216144ce565b905060606000826001600160a01b031663d903bcf4856040518263ffffffff1660e01b81526004018082600760200280838360005b8381101561486e578181015183820152602001614856565b50505050905001915050600060405180830381600087803b15801561489257600080fd5b505af11580156148a6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160409081528110156148cf57600080fd5b8101908080516401000000008111156148e757600080fd5b820160208101848111156148fa57600080fd5b815185602082028301116401000000008211171561491757600080fd5b505060209091015190945092506000915061494390506001600160401b038a168363ffffffff613ee516565b60048e0180546fffffffffffffffff00000000000000001916600160401b6001600160401b038416021790558c5160208e0151919250614985918f86866159b1565b60808c0151604001516001600160401b03828116908c1614906000906149b1908563ffffffff6150f916565b90506149bb614a88565b60808f01515160408051600160e11b632fa96a270281526001600160a01b0392831660048201523360248201526044810185905290519290911691635f52d44e9160648082019260009290919082900301818387803b158015614a1d57600080fd5b505af1158015614a31573d6000803e3d6000fd5b50939e50505050505050505050505050505092915050565b600483015482546000916001600160401b03600160801b909104811691614a789185911663ffffffff6150f916565b81614a7f57fe5b04949350505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316633b19e84a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561347d57600080fd5b8254600090600160e81b900460ff1615614afd57508254600160e81b900460ff16613aae565b600060018560010180549050039050614b1d858260058660200151613684565b6000856001018281548110614b2e57fe5b60009182526020822060089091020191506006820190614b4d826153dd565b8015614b5f5750614b5d826153ec565b155b9050600081614bed57614b706135cb565b6001600160a01b031663084d72f4614b888a88613852565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015614bbc57600080fd5b505afa158015614bd0573d6000803e3d6000fd5b505050506040513d6020811015614be657600080fd5b5051614bfa565b8254600160a01b900460ff165b89547fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160e81b60ff831602179099555096979650505050505050565b600080614c44613b6e565b600489015460028a0154919250600160c01b90046001600160401b031690600090614c6f908361548b565b9050600086118015614c8057508581115b15614c8c575084614cab565b895470ff000000000000000000000000000000001916600160801b178a555b614cbb828263ffffffff6153fe16565b8a60040160186101000a8154816001600160401b0302191690836001600160401b031602179055506000614ced6144ce565b9050606082604051908082528060200260200182016040528015614d1b578160200160208202803883390190505b509050606083604051908082528060200260200182016040528015614d4a578160200160208202803883390190505b50905060005b84811015614e355760008e60020182880181548110614d6b57fe5b9060005260206000200160009054906101000a90046001600160a01b0316905080848381518110614d9857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050614e158f6003016000836001600160a01b03166001600160a01b0316815260200190815260200160002060000160009054906101000a90046001600160401b03166001600160401b0316613fd88e8d615abc90919063ffffffff16565b838381518110614e2157fe5b602090810291909101015250600101614d50565b506060614e406135cb565b6001600160a01b03166318ce8f568e8e866040518463ffffffff1660e01b8152600401808481526020018360ff1660ff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b83811015614eb2578181015183820152602001614e9a565b5050505090500194505050505060006040518083038186803b158015614ed757600080fd5b505afa158015614eeb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015614f1457600080fd5b810190808051640100000000811115614f2c57600080fd5b82016020810184811115614f3f57600080fd5b8151856020820283011164010000000082111715614f5c57600080fd5b505092919050505090506150e1846001600160a01b031663c67106f5898686866040518563ffffffff1660e01b815260040180856001600160401b03166001600160401b03168152602001806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b83811015614feb578181015183820152602001614fd3565b50505050905001848103835286818151815260200191508051906020019060200280838360005b8381101561502a578181015183820152602001615012565b50505050905001848103825285818151815260200191508051906020019060200280838360005b83811015615069578181015183820152602001615051565b50505050905001975050505050505050602060405180830381600087803b15801561509357600080fd5b505af11580156150a7573d6000803e3d6000fd5b505050506040513d60208110156150bd57600080fd5b81019080805190602001909291905050508f600501546153fe90919063ffffffff16565b60058f01555092955050505050509695505050505050565b60008261510857506000612a3c565b8282028284828161511557fe5b04146040518060400160405280601181526020017f4d4154485f4d554c5f4f564552464c4f5700000000000000000000000000000081525090613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b6004850154600160801b90046001600160401b0316156151bb576153d5565b801561522d5760006151cb6144ce565b9050806001600160a01b0316636d1b229d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561521357600080fd5b505af1158015615227573d6000803e3d6000fd5b50505050505b836152b3578554600186015460408051600160e11b632fa96a270281526001600160a01b038681166004830152938416602482015260448101929092525191851691635f52d44e9160648082019260009290919082900301818387803b15801561529657600080fd5b505af11580156152aa573d6000803e3d6000fd5b505050506153d5565b600060028660010154816152c357fe5b04905060008760010160018703815481106152da57fe5b600091825260208220600660089092020101805460408051600160e11b632fa96a270281526001600160a01b038981166004830152928316602482015260448101879052905192945090881692635f52d44e9260648084019382900301818387803b15801561534857600080fd5b505af115801561535c573d6000803e3d6000fd5b505050600182015460408051600160e11b632fa96a270281526001600160a01b03888116600483015292831660248201526044810186905290519188169250635f52d44e91606480830192600092919082900301818387803b1580156153c157600080fd5b505af1158015611b6f573d6000803e3d6000fd5b505050505050565b546001600160a01b0316151590565b600101546001600160a01b0316151590565b60408051808201909152601181527f4d4154485f4144445f4f564552464c4f5700000000000000000000000000000060208201526000908383019084821015613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b6000828211156040518060400160405280601281526020017f4d4154485f5355425f554e444552464c4f5700000000000000000000000000008152509061551657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5050900390565b6000806155286144ce565b845460408051600160e01b63e9e67d670281526001600160a01b0387811660048301526001600160401b03909316602482015290519293506000929184169163e9e67d6791604480820192602092909190829003018186803b15801561558d57600080fd5b505afa1580156155a1573d6000803e3d6000fd5b505050506040513d60208110156155b757600080fd5b50516040870151519091506000906155d090839061451d565b90506001600160401b0381166155ec5760009350505050613aae565b6000615609886020015160c0015184615abc90919063ffffffff16565b9050836001600160a01b031663605da1b287836156246145de565b6040805163ffffffff861660e01b81526001600160a01b03909416600485015260248401929092526001600160401b031660448301525160648083019260209291908290030181600087803b15801561567c57600080fd5b505af1158015615690573d6000803e3d6000fd5b505050506040513d60208110156156a657600080fd5b50516156b9576000945050505050613aae565b6001600160a01b03861660009081526003880160205260409020805467ffffffffffffffff19166001600160401b03841617905560058701546156fc90826153fe565b600588015550925050509392505050565b815160208301516040840151600091829161575591906103e890615741906001600160401b0389169063ffffffff6150f916565b8161574857fe5b049063ffffffff615abc16565b91508190509250925092565b6101008101518254600091829161578991600160401b9091046001600160401b031690615ad5565b905060018116613aae576001019392505050565b60006127106157b2848463ffffffff6150f916565b816157b957fe5b049392505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03167f23b872dd0000000000000000000000000000000000000000000000000000000017905260009061379186825b6000806040516020818551602087016000895af18015615873573d8015615860576020811461586957615871565b60019350615871565b600183511493505b505b5090949350505050565b60408051808201909152601581527f55494e5436345f4e554d4245525f544f4f5f424947000000000000000000000060208201526000906001600160401b0383111561590d57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b5090919050565b6000826001600160401b0316826001600160401b031611156040518060400160405280601481526020017f4d41544836345f5355425f554e444552464c4f570000000000000000000000008152509061551657604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b60005b818110156153d55760008382815181106159ca57fe5b6020908102919091018101516001600160a01b03811660009081526003880190925260409091208054919250906001600160401b0316615a42576002860180546001810182556000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384161790555b8054615a5e906001600160401b0316600163ffffffff613ee516565b815467ffffffffffffffff19166001600160401b03919091161781556040516001600160a01b0383169088908a907fbfd1b785c517ac3c709db5d7c9904052346df35e7069c1cb80f3dd966579d52290600090a450506001016159b4565b60006127106157b28461ffff851663ffffffff6150f916565b60408051808201909152601381527f4d41544836345f4d554c5f4f564552464c4f570000000000000000000000000060208201526000906001600160401b038481169084160290600160401b8210613f7e57604051600160e51b62461bcd028152602060048201818152835160248401528351909283926044909101919085019080838360008315610840578181015183820152602001610828565b604051806102c00160405280615b85615da8565b8152602001615b92615c3e565b8152602001615b9f615de4565b905290565b60408051610100810182526000808252602082018190529091820190815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b81548183558181111561384d5760020281600202836000526020600020918201910161384d9190615e0c565b604080516060810182526000808252602082018190529181019190915290565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081019190915290565b60405180606001604052806003906020820280388339509192915050565b6040518061012001604052806009906020820280388339509192915050565b60405180604001604052806002906020820280388339509192915050565b60405180608001604052806004906020820280388339509192915050565b81548183558181111561384d5760080281600802836000526020600020918201910161384d9190615e5c565b6040518060e00160405280600081526020016000815260200160006001600160401b0316815260200160008019168152602001615b9f615c1e565b6040518060e001604052806007906020820280388339509192915050565b6040518060a0016040528060006001600160a01b03168152602001600061ffff1681526020016000815260200160008152602001600081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b61134991905b80821115615e585780547fff000000000000000000000000000000000000000000000000000000000000001681556000615e4f6001830182615ef0565b50600201615e12565b5090565b61134991905b80821115615e5857805470ffffffffffffffffffffffffffffffffff19168155600060018201819055615e986002830182615f11565b50600060048201819055600582015560068101805474ffffffffffffffffffffffffffffffffffffffffff1916905560078101805475ffffffffffffffffffffffffffffffffffffffffffff19169055600801615e62565b50805460008255600802906000526020600020908101906108859190615e5c565b5080546000825590600052602060002090810190610885919061134991905b80821115615e585760008155600101615f3056fea165627a7a7230582020c137edb6f0f5f0da0d0d361d22809d8f4b8382642960f9058207418aaf2b340029
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f0c8376065fadfacb706cafbaac96b321069c01500000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _controller (address): 0xf0C8376065fadfACB706caFbaaC96B321069C015
Arg [1] : _maxJurorsPerDraftBatch (uint64): 81
Arg [2] : _skippedDisputes (uint256): 1
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000f0c8376065fadfacb706cafbaac96b321069c015
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000051
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode Sourcemap
125219:77809:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;125219:77809:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158158:165;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;158158:165:0;-1:-1:-1;;;;;158158:165:0;;:::i;:::-;;156369:557;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;156369:557:0;;;;;;-1:-1:-1;;;;;156369:557:0;;:::i;140840:1423::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140840:1423:0;;;;;;;;;;;;;;:::i;155582:395::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;155582:395:0;;:::i;135366:1302::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;135366:1302:0;;;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;135366:1302:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;135366:1302:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;135366:1302:0;;-1:-1:-1;135366:1302:0;-1:-1:-1;135366:1302:0;:::i;:::-;;;;;;;;;;;;;;;;124761:346;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;124761:346:0;;;;;;;;;;:::i;119841:96::-;;;:::i;:::-;;;;-1:-1:-1;;;;;119841:96:0;;;;;;;;;;;;;;132077:36;;;:::i;:::-;;;;-1:-1:-1;;;;;132077:36:0;;;;;;;;;;;;;;161131:1069;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;161131:1069:0;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;161131:1069:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;165833:823;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;165833:823:0;;;;;;;;;;;-1:-1:-1;;;;;165833:823:0;;:::i;:::-;;;;-1:-1:-1;;;;;165833:823:0;;;;;;;;;;;;;;;;;;;;;137046:391;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;137046:391:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;137046:391:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;137046:391:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;137046:391:0;;-1:-1:-1;137046:391:0;-1:-1:-1;137046:391:0;:::i;138672:1824::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;138672:1824:0;;:::i;162771:450::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;162771:450:0;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;162771:450:0;;;;;-1:-1:-1;;;;;162771:450:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158557:315;;;:::i;:::-;;;;-1:-1:-1;;;;;158557:315:0;;;;;;;;;;;;;;;;;;;;;149500:2979;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;149500:2979:0;;;;;;;;;;;-1:-1:-1;;;;;149500:2979:0;;:::i;146109:2967::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;146109:2967:0;;;;;;;;;;;;:::i;142646:1675::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;142646:1675:0;;;;;;;;;;;;;;:::i;144641:535::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;144641:535:0;;:::i;:::-;;;;-1:-1:-1;;;;;144641:535:0;;;;;;;;;;;;;;;;;;;;;;157381:542;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;157381:542:0;;;;;;-1:-1:-1;;;;;157381:542:0;;:::i;137725:774::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;137725:774:0;;;;;;;;:::i;164213:1152::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;164213:1152:0;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;164213:1152:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;164213:1152:0;;;;;;;-1:-1:-1;164213:1152:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;164213:1152:0;-1:-1:-1;;164213:1152:0;159551:614;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;159551:614:0;;:::i;:::-;;;;-1:-1:-1;;;;;159551:614:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;159551:614:0;;;;;;;;-1:-1:-1;;;;;159551:614:0;;;;;;;;;;;;;-1:-1:-1;159551:614:0;-1:-1:-1;;159551:614:0;152777:2495;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;152777:2495:0;;;;;;;:::i;158158:165::-;118940:17;:15;:17::i;:::-;-1:-1:-1;;;;;118926:31:0;:10;-1:-1:-1;;;;;118926:31:0;;118959:32;;;;;;;;;;;;;;;;;118918:74;;;;;-1:-1:-1;;;;;118918:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;118918:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158264:51;158291:23;158264:26;:51::i;:::-;158158:165;:::o;156369:557::-;133574:16;133593:9;:7;:9::i;:::-;133652:23;;;;;;;;;;;;;;;;;133574:28;;-1:-1:-1;133621:10:0;-1:-1:-1;;;;;133621:29:0;;;133613:63;;;;-1:-1:-1;;;;;133613:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;133613:63:0;;156459:23;156484:15;156503:22;156517:7;156503:13;:22::i;:::-;156458:67;;;;156536:20;;:::i;:::-;156559:26;156577:7;156559:17;:26::i;:::-;156536:49;;156694:89;156719:7;156728;156737:28;156767:6;:15;;;156694:24;:89::i;:::-;156794:13;156810:53;156830:7;156839;156848:6;156856;156810:19;:53::i;:::-;156794:69;;156891:1;156882:6;-1:-1:-1;;;;;156882:10:0;;156894:23;;;;;;;;;;;;;;;;;156874:44;;;;;-1:-1:-1;;;;;156874:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;156874:44:0;;133687:1;;;;156369:557;;;:::o;140840:1423::-;140936:10;140948:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;141139:23;141165:8;141174:10;141165:20;;;;;;;;;;;;;;;;;;141139:46;;141196:20;;:::i;:::-;141219:26;141237:7;141219:17;:26::i;:::-;141196:49;;141256:89;141281:7;141290:8;141300:27;141329:6;:15;;;141256:24;:89::i;:::-;141475:16;141494:9;:7;:9::i;:::-;141475:28;;141514:14;141531:32;141542:10;141554:8;141531:10;:32::i;:::-;141514:49;;141574:24;141601:6;-1:-1:-1;;;;;141601:24:0;;141626:6;141601:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;141601:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;141601:32:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;141601:32:0;;-1:-1:-1;141652:29:0;;;;;;;;;;;:71;;-1:-1:-1;141685:38:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;141685:21:0;;;;;:38;;;;;;;;;;;;;;:21;:38;;;5:2:-1;;;;30:1;27;20:12;5:2;141685:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;141685:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;141685:38:0;141652:71;141725:27;;;;;;;;;;;;;;;;;141644:109;;;;;-1:-1:-1;;;;;141644:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;141644:109:0;;141804:31;141838:7;:14;;141853:8;141838:24;;;;;;;;;;;;;;;;;;;;;;;141897:12;;;141920:25;;141935:10;-1:-1:-1;;141920:25:0;;;;-1:-1:-1;;141956:31:0;-1:-1:-1;;;141956:31:0;;;;;;;;;;;;142003:45;;;;;;;141838:24;;-1:-1:-1;141897:12:0;;142030:8;;142018:10;;142003:45;;;;;;;;;142092:33;;:::i;:::-;142128:45;142149:5;142156:8;142166:6;142128:20;:45::i;:::-;142092:81;;142184:71;142199:10;142211:9;:18;;;142231:9;:23;;;142184:14;:71::i;:::-;134281:1;;;;;;;;140840:1423;;;;;:::o;155582:395::-;155645:23;155670:15;155689:22;155703:7;155689:13;:22::i;:::-;155644:67;;;;155722:20;;:::i;:::-;155745:26;155763:7;155745:17;:26::i;:::-;155722:49;;155880:89;155905:7;155914;155923:28;155953:6;:15;;;155880:24;:89::i;:::-;155582:395;;;;:::o;135366:1302::-;135494:7;119156:10;;119169:27;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;119156:10:0;119134;:33;119126:71;;;;-1:-1:-1;;;;;119126:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;119126:71:0;;135514:13;135530:20;:18;:20::i;:::-;135514:36;;135561:20;;:::i;:::-;135584;135597:6;135584:12;:20::i;:::-;135561:43;-1:-1:-1;127761:1:0;135623:38;;;;;;;:94;;;135685:6;:15;;;:32;;;135665:52;;:16;:52;;;;135623:94;135719:28;;;;;;;;;;;;;;;;;135615:133;;;;;-1:-1:-1;;;;;135615:133:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;135615:133:0;-1:-1:-1;135812:8:0;:17;;135792;;135812;;;;;;:::i;:::-;135792:37;;135840:23;135866:8;135875:9;135866:19;;;;;;;;;;;;;;;;;;135840:45;;135914:8;135896:7;:15;;;:26;;;;;-1:-1:-1;;;;;135896:26:0;;;;;-1:-1:-1;;;;;135896:26:0;;;;;;135959:16;135933:7;:23;;;:42;;;;;;;;;;;;;;;;;;136009:6;135986:7;:20;;;:29;;;;;-1:-1:-1;;;;;135986:29:0;;;;;-1:-1:-1;;;;;135986:29:0;;;;;;136028:19;136050:6;:15;;;:38;;;136028:60;;136099:18;136120:41;136131:6;:15;;;:29;;;136120:6;-1:-1:-1;;;;;136120:10:0;;;:41;;;;:::i;:::-;136099:62;;136209:11;-1:-1:-1;;;;;136177:69:0;136199:8;-1:-1:-1;;;;;136177:69:0;136188:9;136177:69;136222:12;136236:9;;136177:69;;;;-1:-1:-1;;;;;136177:69:0;-1:-1:-1;;;;;136177:69:0;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;;74:27;136177:69:0;;137:4:-1;117:14;;;-1:-1;;113:30;157:16;;;136177:69:0;;;;-1:-1:-1;136177:69:0;;-1:-1:-1;;;;;136177:69:0;136319:14;136335:17;136354;136375:47;136396:6;:11;;;136409:12;136375:20;:47::i;:::-;136318:104;;;;;;136433:84;136446:9;136457:21;136480:11;136493:12;136507:9;136433:12;:84::i;:::-;;136579:54;136602:8;136613;136623:9;136579:14;:54::i;:::-;-1:-1:-1;136651:9:0;;-1:-1:-1;;;;;;;;119208:1:0;135366:1302;;;;;;:::o;124761:346::-;124208:10;;;;;;;;;-1:-1:-1;;;;;124208:10:0;-1:-1:-1;;;;;124208:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;124208:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;124208:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;124208:29:0;124239:31;;;;;;;;;;;;;124208:29;124239:31;;;;-1:-1:-1;;;;;124194:43:0;:10;:43;124186:85;;;;-1:-1:-1;;;;;124186:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;124186:85:0;-1:-1:-1;124866:31:0;;;;;;124891:4;124866:31;;;;;;124848:15;;-1:-1:-1;;;;;124866:16:0;;;;;:31;;;;;;;;;;;;;;;:16;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;124866:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;124866:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;124866:31:0;124929:32;;;;;;;;;;;;;124866:31;124929:32;;;124866:31;;-1:-1:-1;124916:11:0;124908:54;;;;-1:-1:-1;;;;;124908:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;124908:54:0;-1:-1:-1;124981:33:0;-1:-1:-1;;;;;124981:19:0;;125001:3;125006:7;124981:33;:19;:33;:::i;:::-;125016:32;;;;;;;;;;;;;;;;;124973:76;;;;;-1:-1:-1;;;;;124973:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;124973:76:0;-1:-1:-1;125065:34:0;;;-1:-1:-1;;;;;125065:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;124282:1;124761:346;;:::o;119841:96::-;119889:10;119919;-1:-1:-1;;;;;119919:10:0;119841:96;;:::o;132077:36::-;;;-1:-1:-1;;;132077:36:0;;-1:-1:-1;;;;;132077:36:0;;:::o;161131:1069::-;161267:16;161298:19;161332;161366:21;161402:17;161434:21;161470:23;161508:21;161544:23;161213:10;161225:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;161595:23;161621:8;161630:10;161621:20;;;;;;;;;;;;;;;;;;161595:46;;161660:97;161681:7;161690:8;161700:19;:17;:19::i;:::-;161721:26;161739:7;161721:17;:26::i;:::-;:35;;;161660:20;:97::i;:::-;161652:105;;161770:31;161804:7;:14;;161819:8;161804:24;;;;;;;;;;;;;;;;;;161770:58;;161851:5;:17;;;;;;;;;;-1:-1:-1;;;;;161851:17:0;161839:29;;161894:5;:18;;;;;;;;;;-1:-1:-1;;;;;161894:18:0;161879:33;;161938:5;:18;;;;;;;;;;-1:-1:-1;;;;;161938:18:0;161923:33;;161984:5;:20;;;;;;;;;;-1:-1:-1;;;;;161984:20:0;161967:37;;162027:5;:15;;;162015:27;;162072:5;:22;;;;;;;;;;;;162053:41;;162122:5;:20;;;;;;;;;;-1:-1:-1;;;;;162122:20:0;162105:37;;162171:5;:21;;;162153:39;;134281:1;;161131:1069;;;;;;;;;;;;;:::o;165833:823::-;165971:13;165986;165931:10;165943:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;166017:23;166043:8;166052:10;166043:20;;;;;;;;;;;;;;;;;;166017:46;;166074:31;166108:7;:14;;166123:8;166108:24;;;;;;;;;;;;;;;;;;166074:58;;166143:20;;:::i;:::-;166166:26;166184:7;166166:17;:26::i;:::-;166143:49;;166209:33;166225:8;166235:6;166209:15;:33::i;:::-;166205:385;;;166268:30;166284:5;166291:6;166268:15;:30::i;:::-;166259:39;;166205:385;;;166331:30;166364:17;:15;:17::i;:::-;166461;;166420:59;;;-1:-1:-1;;;;;166420:59:0;;-1:-1:-1;;;;;166420:59:0;;;;;;;-1:-1:-1;;;;;166461:17:0;;;166420:59;;;;;;166331:50;;-1:-1:-1;166396:21:0;;166420:32;;;;;;:59;;;;;;;;;;;;;;;:32;:59;;;5:2:-1;;;;30:1;27;20:12;5:2;166420:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;166420:59:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;166420:59:0;166547:13;;;;:30;166420:59;;-1:-1:-1;166503:75:0;;166420:59;;166503:28;:75::i;:::-;166494:84;;166205:385;;;-1:-1:-1;;;;;;166613:26:0;;;;;;;;:18;;;;:26;;-1:-1:-1;;166613:26:0;;;;:35;165833:823;;-1:-1:-1;;;166613:35:0;;;;;;-1:-1:-1;165833:823:0;;-1:-1:-1;;;165833:823:0:o;137046:391::-;119156:10;;119169:27;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;119156:10:0;119134;:33;119126:71;;;;-1:-1:-1;;;;;119126:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;119126:71:0;;137205:10;133887:31;133907:10;133887:19;:31::i;:::-;137233:23;137259:8;137268:10;137259:20;;;;;;;;;;;;;;;;;;;;;;137298:15;;137327:33;;;;;;;;;;;;;;;;;;;;137259:20;;-1:-1:-1;;;;;;137298:15:0;;;:27;;;;137290:71;;;;-1:-1:-1;;;;;137290:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;137290:71:0;;137407:10;-1:-1:-1;;;;;137377:52:0;137395:10;137377:52;137419:9;;137377:52;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;;74:27;137377:52:0;;137:4:-1;117:14;;;-1:-1;;113:30;157:16;;;137377:52:0;;;;-1:-1:-1;137377:52:0;;-1:-1:-1;;;;137377:52:0;133929:1;119208;137046:391;;;;;:::o;138672:1824::-;138730:10;133887:31;133907:10;133887:19;:31::i;:::-;138983:12;138998:8;:6;:8::i;:::-;138983:23;;139017:26;139046:8;:6;:8::i;:::-;-1:-1:-1;;;;;139046:33:0;;:35;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;139046:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;139046:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;139046:35:0;139135:19;;;;;;;;;;;;;139046:35;139135:19;;;139046:35;;-1:-1:-1;;;;;;139100:28:0;;:33;139092:63;;;;-1:-1:-1;;;;;139092:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;139092:63:0;;139166:20;139189:23;:21;:23::i;:::-;139166:46;;139277:23;139303:8;139312:10;139303:20;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;139342:13:0;;-1:-1:-1;;;139342:13:0;;;;:38;;;;;;;;;139382:27;;;;;;;;;;;;;;;;;139334:76;;;;;-1:-1:-1;;;;;139334:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;139334:76:0;-1:-1:-1;139551:1:0;139527:14;;:21;;-1:-1:-1;;139527:25:0;;;139509:15;;139527:25;;139597:23;;;;;;;;;;;;;;;;;;;;139652:17;;139718:28;;;;;;;;;;;;;;;;;;;;139597:23;;-1:-1:-1;;;;;;139652:17:0;;;;139718:28;139688;;;;;139680:67;;;;-1:-1:-1;;;;;139680:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;139680:67:0;;139758:27;139788:5;-1:-1:-1;;;;;139788:33:0;;:35;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;139788:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;139788:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;139788:35:0;;-1:-1:-1;139902:25:0;;:::i;:::-;139930:28;139946:11;139930:15;:28::i;:::-;139902:56;;139969:15;139987:97;139994:5;140001:82;140019:10;140031:7;140040:13;140055:19;140076:6;140001:17;:82::i;:::-;139987:6;:97::i;:::-;139969:115;;140155:10;140151:338;;;140295:18;;;:48;;-1:-1:-1;;140295:48:0;140316:27;;;-1:-1:-1;;;;;140295:48:0;;;;140358:41;;-1:-1:-1;;;;;;140358:41:0;-1:-1:-1;;;140358:41:0;;;140419:58;;-1:-1:-1;;140439:10:0;;140419:58;;-1:-1:-1;;140419:58:0;140151:338;133929:1;;;;;;;;;;138672:1824;;:::o;162771:450::-;162894:13;162909:21;162932:13;162947:20;162854:10;162866:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;162985:21;163009:8;163018:10;163009:20;;;;;;;;;;;;;;;;;;:27;;163037:8;163009:37;;;;;;;;;;;;;;;;:44;:37;;;;;:44;;;163074:12;163154;;;;;-1:-1:-1;;;;;163074:12:0;;;;163114:21;-1:-1:-1;;;163114:21:0;;;;;;;-1:-1:-1;163154:12:0;;;;-1:-1:-1;163193:20:0;;;;;;-1:-1:-1;162771:450:0;-1:-1:-1;;;;;;162771:450:0:o;158557:315::-;158606:14;158622:17;158652:20;158675:19;:17;:19::i;:::-;158652:42;;158705:20;;:::i;:::-;158728:27;158741:13;158728:12;:27::i;:::-;158705:50;;158791:73;158812:6;:11;;;158825:6;:15;;;:38;;;158791:20;:73::i;:::-;158766:98;;;;-1:-1:-1;158557:315:0;;-1:-1:-1;;;;158557:315:0:o;149500:2979::-;149597:10;149609:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;149691:23;149717:8;149726:10;149717:20;;;;;;;;;;;;;;;;;;149691:46;;149748:31;149782:7;:14;;149797:8;149782:24;;;;;;;;;;;;;;;;;;149748:58;;149825:5;:22;;;;;;;;;;;;149849:23;;;;;;;;;;;;;;;;;149817:56;;;;;-1:-1:-1;;;;;149817:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;149817:56:0;-1:-1:-1;;;;;;150006:26:0;;149974:29;150006:26;;;:18;;;:26;;;;;;;;;150052:19;;150073:28;;;;;;;;;;;;;;;;;;;150006:26;150073:28;-1:-1:-1;;;150052:19:0;;;;150051:20;150043:59;;;;-1:-1:-1;;;;;150043:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;150043:59:0;-1:-1:-1;150129:17:0;;150153:33;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;150129:17:0;150113:74;;;;-1:-1:-1;;;;;150113:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;150113:74:0;-1:-1:-1;150198:26:0;;-1:-1:-1;;150198:26:0;-1:-1:-1;;;150198:26:0;;;:19;150361:9;:7;:9::i;:::-;150342:28;;150381:14;150398:32;150409:10;150421:8;150398:10;:32::i;:::-;150482:19;;150449:61;;;;;;;;;;;;-1:-1:-1;;;150482:19:0;;;;;150449:61;;;;-1:-1:-1;;;;;150449:61:0;;;;;;;;;;;-1:-1:-1;150449:24:0;;;;;:61;;;;;;;;;;;;;;;:24;:61;;;5:2:-1;;;;30:1;27;20:12;5:2;150449:61:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;150449:61:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;150449:61:0;150512:34;;;;;;;;;;;;;150449:61;150512:34;;;;150441:106;;;;-1:-1:-1;;;;;150441:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;150441:106:0;-1:-1:-1;150586:21:0;;;;150560:23;150651:17;:15;:17::i;:::-;150618:50;-1:-1:-1;150895:20:0;150930:19;;150926:447;;151238:59;151262:5;151269:10;151281:15;151238:23;:59::i;:::-;151223:74;;151312:14;-1:-1:-1;;;;;151312:27:0;;151340:6;151348:12;151312:49;;;;;;;;;;;;;-1:-1:-1;;;;;151312:49:0;-1:-1:-1;;;;;151312:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;151312:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;151312:49:0;;;;150926:447;151432:20;;:::i;:::-;151455:26;151473:7;151455:17;:26::i;:::-;151432:49;;151741:18;151762:59;151786:5;151793:10;151805:5;:15;;;151762:23;:59::i;:::-;151741:80;;151832:11;:9;:11::i;:::-;-1:-1:-1;;;;;151832:18:0;;151851:6;:11;;;:17;;;151870:6;151878:10;151832:57;;;;;;;;;;;;;-1:-1:-1;;;;;151832:57:0;-1:-1:-1;;;;;151832:57:0;;;;;;-1:-1:-1;;;;;151832:57:0;-1:-1:-1;;;;;151832:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;151832:57:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;151832:57:0;;;;151948:33;151964:8;151974:6;151948:15;:33::i;:::-;151943:442;;152103:36;;:::i;:::-;152142:6;:15;;;152103:54;;152172:14;-1:-1:-1;;;;;152172:30:0;;152221:6;152324:14;:34;;;152295:14;:26;;;152266:14;:26;;;152246:5;:17;;;;;;;;;;-1:-1:-1;;;;;152246:17:0;:46;:75;:112;152172:201;;;;;;;;;;;;;-1:-1:-1;;;;;152172:201:0;-1:-1:-1;;;;;152172:201:0;;;;;;-1:-1:-1;;;;;152172:201:0;-1:-1:-1;;;;;152172:201:0;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;152172:201:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;152172:201:0;;;;151943:442;;152428:8;152416:10;152402:69;152438:6;152446:12;152460:10;152402:69;;;;-1:-1:-1;;;;;152402:69:0;-1:-1:-1;;;;;152402:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;134281:1;;;;;;;;;;149500:2979;;;;;:::o;146109:2967::-;146218:10;146230:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;146465:23;146491:8;146500:10;146491:20;;;;;;;;;;;;;;;;;;146465:46;;146530:8;146542:1;146530:13;:62;;;;146547:7;:14;;146573:1;146562:8;:12;146547:28;;;;;;;;;;;;;;;;;;;;;:45;-1:-1:-1;;;146547:45:0;;;;146530:62;146594:28;;;;;;;;;;;;;;;;;146522:101;;;;;-1:-1:-1;;;;;146522:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;146522:101:0;;146698:31;146732:7;:14;;146747:8;146732:24;;;;;;;;;;;;;;;;;;146698:58;;146776:5;:22;;;;;;;;;;;;146775:23;146800:27;;;;;;;;;;;;;;;;;146767:61;;;;;-1:-1:-1;;;;;146767:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;146767:61:0;;146918:20;;:::i;:::-;146941:26;146959:7;146941:17;:26::i;:::-;146918:49;;146978:17;146998:47;147017:7;147026:10;147038:6;146998:18;:47::i;:::-;146978:67;;147170:14;147187:32;147198:10;147210:8;147187:10;:32::i;:::-;147234:19;;;;147170:49;;-1:-1:-1;;;;147234:19:0;;-1:-1:-1;;;;;147234:19:0;147230:463;;147564:16;147583:9;:7;:9::i;:::-;147564:28;;147637:6;-1:-1:-1;;;;;147637:22:0;;147660:6;147668:11;147637:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;147637:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;147637:43:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;147637:43:0;147607:20;;;:74;;-1:-1:-1;;;;;147607:74:0;;;-1:-1:-1;;;147607:74:0;;;;;;;;;;;-1:-1:-1;147230:463:0;147705:18;147726:11;:9;:11::i;:::-;147765;;:17;147705:32;;-1:-1:-1;147797:33:0;147813:8;147765:6;147797:15;:33::i;:::-;147793:978;;;148042:21;148066:133;148095:5;148102:6;148110:11;148123:6;:15;;;:26;;;148151:15;148168:6;:13;;;:30;;;148066:28;:133::i;:::-;148042:157;;148214:8;-1:-1:-1;;;;;148214:15:0;;148230:8;148240:10;148252:40;148278:13;148252:6;:11;;;:21;;;:25;;:40;;;;:::i;:::-;148214:79;;;;;;;;;;-1:-1:-1;;;;;148214:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;148214:79:0;;;;;;;-1:-1:-1;148214:79:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;148214:79:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;148214:79:0;;;;147793:978;;;;148730:29;;-1:-1:-1;;148730:29:0;-1:-1:-1;;;148730:29:0;;;147793:978;148787:22;;-1:-1:-1;;;148787:22:0;;;;148783:286;;;148852:21;;;;148893:55;;;;;;;;148922:8;;148910:10;;148893:55;;;;;;;;;148963:94;148995:7;149004:5;149011:8;149021;149031;149041:15;148963:31;:94::i;142646:1675::-;142743:10;142755:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;142963:23;142989:8;142998:10;142989:20;;;;;;;;;;;;;;;;;;142963:46;;143020:20;;:::i;:::-;143043:26;143061:7;143043:17;:26::i;:::-;143020:49;;143080:96;143105:7;143114:8;143124:34;143160:6;:15;;;143080:24;:96::i;:::-;143300:31;143334:7;:14;;143349:8;143334:24;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;143393:12:0;;;;143433:32;143444:10;143456:8;143433:10;:32::i;:::-;143484:21;;143416:49;;-1:-1:-1;143484:32:0;;;;-1:-1:-1;;;143484:21:0;;;;:32;;;;:77;;;143520:9;:7;:9::i;:::-;-1:-1:-1;;;;;143520:24:0;;143545:6;143553:7;143520:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;143520:41:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;143520:41:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;143520:41:0;143484:77;143563:27;;;;;;;;;;;;;;;;;143476:115;;;;;-1:-1:-1;;;;;143476:115:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;143476:115:0;;143664:33;;:::i;:::-;143700:45;143721:5;143728:8;143738:6;143700:20;:45::i;:::-;143664:81;;143756:28;143787:9;:25;;;143756:56;;143823:18;143844:107;143857:10;143869:15;143886:9;:19;;;143907:9;:22;;;143931:9;:19;;;143844:12;:107::i;:::-;143823:128;;144026:10;144011:6;:12;;;:25;;;;;-1:-1:-1;;;;;144011:25:0;;;;;-1:-1:-1;;;;;144011:25:0;;;;;;144070:7;144047:6;:20;;;:30;;;;;;;;;;;;;;;;;;144139:9;:19;;;-1:-1:-1;;;;;144093:90:0;144127:10;144115;144093:90;144160:9;:22;;;144093:90;;;;-1:-1:-1;;;;;144093:90:0;;;;;;;;;;;;;;;144235:78;144250:10;144262:9;:18;;;144282:9;:30;;;144235:14;:78::i;144641:535::-;144728:19;144749:17;144707:10;133887:31;133907:10;133887:19;:31::i;:::-;144779:23;144805:8;144814:10;144805:20;;;;;;;;;;;;;;;;;;;;;144846:15;;-1:-1:-1;;;;;144846:15:0;;-1:-1:-1;144805:20:0;-1:-1:-1;144874:20:0;;:::i;:::-;144897:26;144915:7;144897:17;:26::i;:::-;144874:49;;144948:47;144967:7;144976:10;144988:6;144948:18;:47::i;:::-;144934:61;-1:-1:-1;145029:18:0;145012:13;;-1:-1:-1;;;145012:13:0;;;;:35;;;;;;;;;145008:161;;145064:34;;-1:-1:-1;;;;;;145064:34:0;-1:-1:-1;;;145064:34:0;;;145118:39;;;;;;145133:10;;145118:39;;-1:-1:-1;;145118:39:0;145008:161;133929:1;;144641:535;;;;:::o;157381:542::-;157457:6;157477:23;157502:15;157521:22;157535:7;157521:13;:22::i;:::-;157476:67;;;;157554:20;;:::i;:::-;157577:26;157595:7;157577:17;:26::i;:::-;157554:49;;157711:88;157736:7;157745;157754:27;157783:6;:15;;;157711:24;:88::i;:::-;157810:31;157844:7;:14;;157859:7;157844:23;;;;;;;;;;;;;;;;;;157810:57;;157885:30;157901:5;157908:6;157885:15;:30::i;:::-;157878:37;;;;;;157381:542;;;;;:::o;137725:774::-;119156:10;;119169:27;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;119156:10:0;119134;:33;119126:71;;;;-1:-1:-1;;;;;119126:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;119126:71:0;;137841:10;137853:1;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;137872:23;137898:8;137907:10;137898:20;;;;;;;;;;;;;;;;;;137872:46;;137929:31;137963:7;:14;;137978:1;137963:17;;;;;;;;;;;;;;;;;137999:15;;138028:33;;;;;;;;;;;;;;;;;;;;137963:17;;;;;;-1:-1:-1;;;;;;137999:15:0;;;:27;;;;137991:71;;;;-1:-1:-1;;;;;137991:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;137991:71:0;;138147:13;138163:20;:18;:20::i;:::-;138147:36;-1:-1:-1;138194:21:0;138218:13;-1:-1:-1;;;;;138218:10:0;;138229:1;138218:13;:10;:13;:::i;:::-;138267:17;;138286:31;;;;;;;;;;;;;;;;;138194:37;;-1:-1:-1;;;;;;138267:17:0;;;138250:34;;;;138242:76;;;;-1:-1:-1;;;;;138242:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;138242:76:0;-1:-1:-1;138401:34:0;;-1:-1:-1;;138401:34:0;-1:-1:-1;;;;;138401:34:0;;;;;;;;;138451:40;;;;;;138472:10;;138451:40;;-1:-1:-1;;138451:40:0;134281:1;;;;119208;;137725:774;;:::o;164213:1152::-;164326:25;164366:28;164409;164452:14;164481:17;164513;164545:21;164581:28;164637:39;164655:10;164667:8;164637:17;:39::i;:::-;164689:23;164715:8;164724:10;164715:20;;;;;;;;;;;;;;;;;;164689:46;;164746:20;;:::i;:::-;164769:26;164787:7;164769:17;:26::i;:::-;164746:49;;164814:33;164830:8;164840:6;164814:15;:33::i;:::-;164849:20;;;;;;;;;;;;;;;;;164806:64;;;;;-1:-1:-1;;;;;164806:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;164806:64:0;;164883:31;164917:7;:14;;164932:8;164917:24;;;;;;;;;;;;;;;;;;164883:58;;164952:33;;:::i;:::-;164988:45;165009:5;165016:8;165026:6;164988:20;:45::i;:::-;164952:81;;165066:9;:19;;;165100:9;:22;;;165137:9;:25;;;165177:9;:18;;;165210:9;:19;;;165244:9;:19;;;165278:9;:23;;;165316:9;:30;;;165044:313;;;;;;;;;;;;;;;;;;;;164213:1152;;;;;;;;;;;:::o;159551:614::-;159649:19;159670:21;159693:18;159713:17;159732:19;159753;159619:10;133887:31;133907:10;133887:19;:31::i;:::-;159790:23;159816:8;159825:10;159816:20;;;;;;;;;;;;;;;;;;;;;159859:15;;;160132:14;;;:21;-1:-1:-1;;;;;159859:15:0;;;-1:-1:-1;;;159903:23:0;;;;;;;-1:-1:-1;;;;159945:13:0;;;;;-1:-1:-1;;;;159983:19:0;;;;-1:-1:-1;;;160132:25:0;;;;-1:-1:-1;;;;160028:20:0;;;-1:-1:-1;;;;;160028:20:0;;-1:-1:-1;159859:15:0;-1:-1:-1;;;;159551:614:0:o;152777:2495::-;152865:10;152877:8;134231:39;134249:10;134261:8;134231:17;:39::i;:::-;152959:23;152985:8;152994:10;152985:20;;;;;;;;;;;;;;;;;;152959:46;;153016:31;153050:7;:14;;153065:8;153050:24;;;;;;;;;;;;;;;;;;153016:58;;153093:5;:22;;;;;;;;;;;;153117:23;;;;;;;;;;;;;;;;;153085:56;;;;;-1:-1:-1;;;;;153085:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;153085:56:0;-1:-1:-1;153251:12:0;;;153282:21;153251:12;153282:13;:21::i;:::-;153305:24;;;;;;;;;;;;;;;;;153274:56;;;;;-1:-1:-1;;;;;153274:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;153274:56:0;-1:-1:-1;153350:14:0;;;;153366:34;;;;;;;;;;;;;;;;;;-1:-1:-1;;;153350:14:0;;;;153349:15;153341:60;;;;-1:-1:-1;;;;;153341:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;153341:60:0;-1:-1:-1;153429:4:0;153412:14;;:21;;-1:-1:-1;;153412:21:0;-1:-1:-1;;;153412:21:0;;;153449:42;;153482:8;;153470:10;;153449:42;;153412:21;;153449:42;153540:20;;:::i;:::-;153563:26;153581:7;153563:17;:26::i;:::-;153540:49;;153600:33;;:::i;:::-;153636:45;153657:5;153664:8;153674:6;153636:20;:45::i;:::-;153709:18;;;;153758:19;;;;153812:23;;;;153877:30;;;;153600:81;;-1:-1:-1;153709:18:0;;153758:19;;153812:23;153692:14;154027:11;:9;:11::i;:::-;154006:32;;154054:26;154073:6;154054:18;:26::i;:::-;154049:135;;154123:12;;154097:54;;;-1:-1:-1;;;;;154097:54:0;;-1:-1:-1;;;;;154097:54:0;;;;;;;154123:12;;;154097:54;;;;;;;;;;;;:15;;;;;;:54;;;;;154123:12;;154097:54;;;;;;;;154123:12;154097:15;:54;;;5:2:-1;;;;30:1;27;20:12;5:2;154097:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;154097:54:0;;;;154166:7;;;;;;;;;;;;154049:135;154639:19;;-1:-1:-1;;;154639:19:0;;;;154619:17;154692:39;:13;154710:20;154692:17;:39::i;:::-;154746:21;;154669:62;;-1:-1:-1;154746:36:0;;;;-1:-1:-1;;;154746:21:0;;;;:36;154742:523;;;154825:12;;-1:-1:-1;;;;;154799:15:0;;;;;;154815:8;;154825:12;154839:27;:12;154856:9;154839:27;:16;:27;:::i;:::-;154799:68;;;;;;;;;;-1:-1:-1;;;;;154799:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;154799:68:0;;;;;;;-1:-1:-1;154799:68:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;154799:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;154799:68:0;;;;154742:523;;;154889:20;;;;:35;;;;-1:-1:-1;;;154889:20:0;;;;:35;154885:380;;;154967:12;;;;-1:-1:-1;;;;;154941:15:0;;;;;;154957:8;;154967:12;154981:27;:12;154998:9;154981:27;:16;:27;:::i;154885:380::-;155117:12;;155075:1;155063:13;;;-1:-1:-1;;;;;155091:15:0;;;;;;155107:8;;155117:12;155131:29;:13;155063;155131:17;:29::i;:::-;155091:70;;;;;;;;;;-1:-1:-1;;;;;155091:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;155091:70:0;;;;;;;-1:-1:-1;155091:70:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;155091:70:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;155202:12:0;;;;-1:-1:-1;;;;;155176:15:0;;;;-1:-1:-1;155176:15:0;;155192:8;;155202:12;155216:36;:20;155241:10;155216:36;:24;:36;:::i;:::-;155176:77;;;;;;;;;;-1:-1:-1;;;;;155176:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;155176:77:0;;;;;;;-1:-1:-1;155176:77:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;155176:77:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;155176:77:0;;;;154885:380;;134281:1;;;;;;;;;;;;152777:2495;;;;:::o;120943:115::-;120993:7;121020:10;;;;;;;;;-1:-1:-1;;;;;121020:10:0;-1:-1:-1;;;;;121020:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;121020:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;121020:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;121020:30:0;;-1:-1:-1;120943:115:0;:::o;177571:317::-;177696:30;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;177667:27:0;;177659:68;;;;-1:-1:-1;;;;;177659:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;177659:68:0;-1:-1:-1;177773:22:0;;177743:78;;;-1:-1:-1;;;;;;;;177773:22:0;;;;;177743:78;;;;;;;;;;;;;;;;;;;;;177832:22;:48;;-1:-1:-1;;;;;177832:48:0;;;-1:-1:-1;;;177832:48:0;;;;;;;;;;;177571:317::o;121877:112::-;121919:9;121958:10;;;;;;;;;-1:-1:-1;;;;;121958:10:0;-1:-1:-1;;;;;121958:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;189943:289:0;190006:23;128012:66;190114:22;;190090:3;190079:14;;;190147:37;190079:14;190114:22;190147:17;:37::i;:::-;190205:8;190214:9;190205:19;;;;;;;;;;;;;;;;;;190195:29;;189943:289;;;;:::o;187814:235::-;187890:13;;:::i;:::-;188019:21;;188006:35;;-1:-1:-1;;;188019:21:0;;-1:-1:-1;;;;;188019:21:0;188006:12;:35::i;168567:386::-;168736:13;168752:20;:18;:20::i;:::-;168736:36;;168783:28;168814:57;168835:8;168845;168855:6;168863:7;168814:20;:57::i;:::-;168783:88;;168904:6;168890:20;;;;;;;;:10;:20;;;;;;;;;168912:32;;;;;;;;;;;;;;;;;168882:63;;;;;-1:-1:-1;;;;;168882:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;168882:63:0;;168567:386;;;;;;:::o;174832:388::-;174962:6;174981:31;175015:8;:15;;175031:8;175015:25;;;;;;;;;;;;;;;;;;174981:59;;175060:34;175076:8;175086:7;175060:15;:34::i;:::-;:152;;175156:56;175189:7;175198:5;175205:6;175156:32;:56::i;:::-;175060:152;;;175110:30;175126:5;175133:6;175110:15;:30::i;:::-;175053:159;174832:388;-1:-1:-1;;;;;;174832:388:0:o;189380:222::-;189470:31;189490:10;189470:19;:31::i;:::-;189531:8;189540:10;189531:20;;;;;;;;;;;;;;;;;;:27;;:34;;;;189520:8;:45;189567:26;;;;;;;;;;;;;;;;;189512:82;;;;;-1:-1:-1;;;;;189512:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;189512:82:0;;189380:222;;:::o;190615:146::-;190738:3;190724:17;;;;190723:30;;190615:146::o;179810:2866::-;179947:23;;:::i;:::-;179988:33;;:::i;:::-;180032:36;;:::i;:::-;-1:-1:-1;180071:16:0;;;;180209:19;;;;180186:18;;180160:23;;180186:43;;-1:-1:-1;;;;;180186:18:0;;;;180209:19;180186:43;:22;:43;:::i;:::-;180160:69;;180240:34;180277:80;180330:14;:26;;;180277:48;180298:14;:26;;;180277:16;-1:-1:-1;;;;;180277:20:0;;;:48;;;;:::i;:::-;-1:-1:-1;;;;;180277:52:0;;:80;:52;:80;:::i;:::-;180240:117;;180390:98;180454:14;:33;;;180390:59;180422:14;:26;;;180390:27;-1:-1:-1;;;;;180390:31:0;;;:59;;;;:::i;:98::-;-1:-1:-1;;;;;180368:120:0;;;180607:37;;;;:44;;180649:1;180607:44;:41;:44;:::i;:::-;180595:8;:56;180591:1791;;180770:25;180742;;;:53;181218:30;181251:17;:15;:17::i;:::-;181218:50;;181283:26;181312:14;-1:-1:-1;;;;;181312:35:0;;181348:9;:19;;;181312:56;;;;;;;;;;;;;-1:-1:-1;;;;;181312:56:0;-1:-1:-1;;;;;181312:56:0;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;181312:56:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;181312:56:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;181312:56:0;181454:14;;;;:31;181312:56;;-1:-1:-1;181383:19:0;;181405:81;;181312:56;;181405:28;:81::i;:::-;-1:-1:-1;;;;;181501:37:0;;:22;;;:37;181737:12;;181383:103;;-1:-1:-1;181718:46:0;;181383:103;181718:18;:46::i;:::-;181695:19;;;181653:111;181674:19;;;181653:111;-1:-1:-1;;;;;181653:111:0;181654:18;;;181653:111;-1:-1:-1;180591:1791:0;;-1:-1:-1;;180591:1791:0;;181890:21;181862:25;;;:49;182069:56;182102:6;182110:14;182069:32;:56::i;:::-;-1:-1:-1;;;;;182044:81:0;:22;;;:81;;;182333:12;;182312:58;;:20;:58::i;:::-;182289:19;;;182247:123;182268:19;;;182247:123;-1:-1:-1;;;;;182247:123:0;182248:18;;;182247:123;180591:1791;182487:37;;;;182460:19;;;;:65;;;:26;:65;:::i;:::-;182434:23;;;:91;182596:44;;;;182569:19;;;;:72;;;:26;:72;:::i;:::-;182536:30;;;:105;-1:-1:-1;182536:9:0;;-1:-1:-1;;;179810:2866:0;;;;;;:::o;178262:277::-;178356:11;;178352:180;;178384:18;178405:11;:9;:11::i;:::-;178384:32;-1:-1:-1;178439:58:0;-1:-1:-1;;;;;178439:23:0;;178463:5;178384:32;178489:7;178439:58;:23;:58;:::i;:::-;178499:20;;;;;;;;;;;;;;;;;178431:89;;;;;-1:-1:-1;;;;;178431:89:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;178431:89:0;;178352:180;178262:277;;;:::o;120127:110::-;120175:6;120201:8;:6;:8::i;:::-;-1:-1:-1;;;;;120201:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;120201:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;115238:1637:0;115299:13;;:::i;:::-;115326:15;115352:23;;:::i;:::-;115386:22;115419:29;;:::i;:::-;115459:22;;:::i;:::-;115492:41;;:::i;:::-;115544:31;;:::i;:::-;115579:14;:12;:14::i;:::-;-1:-1:-1;;;;;115579:24:0;;115604:7;115579:33;;;;;;;;;;;;;-1:-1:-1;;;;;115579:33:0;-1:-1:-1;;;;;115579:33:0;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;115579:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;115579:33:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;13:3;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;115579:33:0;;;;;;;;-1:-1:-1;115579:33:0;;;;-1:-1:-1;115579:33:0;-1:-1:-1;115579:33:0;;;;-1:-1:-1;115579:33:0;;;;-1:-1:-1;115579:33:0;;;;-1:-1:-1;115579:33:0;;;-1:-1:-1;115625:20:0;;:::i;:::-;115672:198;;;;;;;;-1:-1:-1;;;;;115672:198:0;;;;;115850:8;;;;115672:198;;;;;;115739:8;;115672:198;;;;115772:8;;;;115672:198;;;;115806:8;;;;115672:198;;;;115658:212;;;115901:679;;;;;;;;;;;;115995:15;;-1:-1:-1;;;;;115901:679:0;;;;;;;;;;;115995:12;116051:1;116038:15;;;;-1:-1:-1;;;;;115901:679:0;;;;;116081:12;116094:1;116081:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116124:12;116137:1;116124:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116174:12;116187:1;116174:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116216:5;116222:1;116216:8;;;;;;;;;;;115901:679;;;;;;116263:12;116276:1;116263:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116311:12;116324:1;116311:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116416:12;116429:1;116416:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116365:12;116378:1;116365:15;;;;;;;;;;;-1:-1:-1;;;;;115901:679:0;;;;;116470:23;116494:1;116470:26;;;;;;;;;;;115901:679;;;;116542:23;116566:1;116542:26;;;;;;;;;;;115901:679;;;115883:6;:15;;:697;;;;116609:232;;;;;;;;116655:13;116669:1;116655:16;;;;;;;;;;;116609:232;;;;116708:13;116722:1;116708:16;;;;;;;;;;;116609:232;;;;116761:13;116775:1;116761:16;;;;;;;;;;;116609:232;;;;116813:13;116827:1;116813:16;;;;;;;;;;;116609:232;;116593:13;;;:248;:13;115238:1637;-1:-1:-1;;;;;;;;;115238:1637:0:o;8678:171::-;8801:18;;;;;;;;;;;;;;;;;8736:6;;8766:7;;;;-1:-1:-1;;;;;8792:7:0;;;;;;;;8784:36;;;;-1:-1:-1;;;;;8784:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;8784:36:0;-1:-1:-1;8840:1:0;8678:171;-1:-1:-1;;;8678:171:0:o;191997:643::-;192189:13;;192356:16;;;;192108:14;;;;192329:44;;-1:-1:-1;;;;;192329:22:0;;;:44;:26;:44;:::i;:::-;192317:56;;192478:26;192507:69;192561:13;-1:-1:-1;;;;;192553:22:0;192508:39;192529:7;:17;;;192508:7;:16;;;:20;;:39;;;;:::i;:::-;192507:45;:69;:45;:69;:::i;:::-;192478:98;-1:-1:-1;192599:33:0;:9;192478:98;192599:33;:13;:33;:::i;:::-;192587:45;;191997:643;;;;;;:::o;167236:828::-;167396:7;167454:23;167480:8;167489:10;167480:20;;;;;;;;;;;;;;;;;;167454:46;;167527:13;167511:7;:13;;;:29;;;;;;;;;;;;;;;;;;;;;;;;167592:15;167610:7;:14;;:23;;;;;;;;;;;:::i;:::-;167592:41;;167644:31;167678:7;:14;;167693:7;167678:23;;;;;;;;;;;;;;;;;;;;167712:32;;-1:-1:-1;;;;;167755:34:0;;;-1:-1:-1;;;167755:34:0;-1:-1:-1;;167712:32:0;;;-1:-1:-1;;167712:32:0;;;;;;;167755:34;;;;167712:32;167800:15;;:28;;;167678:23;-1:-1:-1;167906:9:0;:7;:9::i;:::-;167887:28;;167926:14;167943:31;167954:10;167966:7;167943:10;:31::i;:::-;168007:23;;167985:46;;;;;;;;;;;;-1:-1:-1;;;168007:23:0;;;;;167985:46;;;;;;;-1:-1:-1;;;;;;167985:13:0;;;;;:46;;;;;-1:-1:-1;;167985:46:0;;;;;;;;-1:-1:-1;167985:13:0;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;167985:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;168049:7:0;;167236:828;-1:-1:-1;;;;;;;;;;;;;167236:828:0:o;1663:320::-;1796:105;;;-1:-1:-1;;;;;1796:105:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;1796:105:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;1833:17:0;179:29:-1;160:49;;1747:4:0;;1919:56;1949:6;1796:105;1919:21;:56::i;:::-;1912:63;1663:320;-1:-1:-1;;;;;1663:320:0:o;120681:113::-;120733:6;120759:8;:6;:8::i;:::-;-1:-1:-1;;;;;120759:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;184360:3241:0;184513:17;184548:31;184582:8;:15;;184598:8;184582:25;;;;;;;;;;;;;;;;184742:15;;;:22;184582:25;;;;;;-1:-1:-1;184797:18:0;184779:14;;-1:-1:-1;;;184779:14:0;;;;:36;;;;;;;;;:72;;;-1:-1:-1;184830:21:0;:14;184849:1;184830:21;:18;:21;:::i;:::-;184819:8;:32;184779:72;184775:135;;;184875:23;184868:30;;;;;;184775:135;185116:18;;;;185094:17;;185065:26;;185094:41;;-1:-1:-1;;;;;185094:17:0;;;;185116:18;185094:41;:21;:41;:::i;:::-;185065:70;-1:-1:-1;185168:21:0;185150:14;;-1:-1:-1;;;185150:14:0;;;;:39;;;;;;;;;:72;;;;185203:19;-1:-1:-1;;;;;185193:29:0;:7;-1:-1:-1;;;;;185193:29:0;;185150:72;185146:137;;;185246:25;185239:32;;;;;;;185146:137;185437:22;185462:44;185486:7;:19;;;185462;-1:-1:-1;;;;;185462:23:0;;;:44;;;;:::i;:::-;185437:69;;185531:15;-1:-1:-1;;;;;185521:25:0;:7;-1:-1:-1;;;;;185521:25:0;;185517:93;;;185570:28;185563:35;;;;;;;;185517:93;185764:22;185789:40;185809:7;:19;;;185789:15;-1:-1:-1;;;;;185789:19:0;;;:40;;;;:::i;:::-;185764:65;;185854:15;-1:-1:-1;;;;;185844:25:0;:7;-1:-1:-1;;;;;185844:25:0;;185840:92;;;185893:27;185886:34;;;;;;;;;185840:92;186111:30;;;;186094:47;;186152:79;;;;186196:23;186189:30;;;;;;;;;;186152:79;186347:24;186374:27;186388:5;:12;;186374:13;:27::i;:::-;186347:54;;186412:34;186449:40;186469:7;:19;;;186449:15;-1:-1:-1;;;;;186449:19:0;;;:40;;;;:::i;:::-;186412:77;;186505:19;186500:378;;186698:27;-1:-1:-1;;;;;186688:37:0;:7;-1:-1:-1;;;;;186688:37:0;;186684:183;;;186753:27;186746:34;;;;;;;;;;;;186684:183;186828:23;186821:30;;;;;;;;;;;;186684:183;187244:32;187279:59;187311:7;:26;;;187279:27;-1:-1:-1;;;;;187279:31:0;;;:59;;;;:::i;:::-;187244:94;;187363:25;-1:-1:-1;;;;;187353:35:0;:7;-1:-1:-1;;;;;187353:35:0;;187349:109;;;187412:34;187405:41;;;;;;;;;;;;;187349:109;-1:-1:-1;187570:23:0;;184360:3241;-1:-1:-1;;;;;;;;;;;;;184360:3241:0:o;194332:171::-;194456:16;;;:39;;;-1:-1:-1;194445:50:0;194332:171::o;179117:166::-;-1:-1:-1;;;;;179241:27:0;179215:6;179241:27;;;:19;;;;;:27;;;;;:34;-1:-1:-1;;;;;179241:34:0;;179117:166::o;122498:140::-;122548:15;122599:10;;;;;;;;;-1:-1:-1;;;;;122599:10:0;-1:-1:-1;;;;;122599:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;195179:681:0;195291:6;195510:17;195493:14;:34;195489:75;;;-1:-1:-1;195551:1:0;195544:8;;195489:75;195771:81;195823:17;195772:48;127921:4;195805:14;195772:48;:32;:48;:::i;:::-;:68;;;;;;195771:79;:81::i;188951:149::-;189046:8;:15;189063:28;;;;;;;;;;;;;;;;;;189033;;189025:67;;;;-1:-1:-1;;;;;189025:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;189025:67:0;;188951:149;:::o;120401:121::-;120457:6;120483:8;:6;:8::i;:::-;-1:-1:-1;;;;;120483:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;117103:294:0;117167:18;;:::i;:::-;117199:14;117215:16;117233:17;117254:14;:12;:14::i;:::-;-1:-1:-1;;;;;117254:29:0;;117284:7;117254:38;;;;;;;;;;;;;-1:-1:-1;;;;;117254:38:0;-1:-1:-1;;;;;117254:38:0;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;117254:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;117254:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;117254:38:0;;;;;;;;;;;;117310:79;;117254:38;117310:79;;;;-1:-1:-1;;;;;117310:79:0;;;;;;;;;;;;;;;;;;;;;;117103:294;-1:-1:-1;;;;;117103:294:0:o;196422:447::-;196610:18;;:::i;:::-;-1:-1:-1;196653:208:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;196653:208:0;;;;;;;;;;;;;;;;;;;;;;196422:447::o;197227:1804::-;197366:19;;197420:21;;;;197327:4;197479:22;;197327:4;;-1:-1:-1;;;;;;;;197366:19:0;;;;;;;197420:21;;;;;;;-1:-1:-1;;;197479:22:0;;;197327:4;197539:32;197366:19;197420:21;197539:32;:16;:32;:::i;:::-;197512:59;;197701:22;197746:17;-1:-1:-1;;;;;197726:37:0;:17;-1:-1:-1;;;;;197726:37:0;;:77;;197786:17;197726:77;;;197766:17;197726:77;197701:102;;197846:24;;:::i;:::-;:341;;;;;;;;197896:12;:32;;;197888:41;;197846:341;;;;197944:12;:22;;;197846:341;;;;197989:12;:19;;;-1:-1:-1;;;;;197981:28:0;197846:341;;;;198032:14;-1:-1:-1;;;;;198024:23:0;197846:341;;;;198070:15;-1:-1:-1;;;;;198062:24:0;197846:341;;;;198109:12;-1:-1:-1;;;;;198101:21:0;197846:341;;;;198145:12;:19;;;:30;;;198137:39;;197846:341;;;;;198249:30;198282:17;:15;:17::i;:::-;198249:50;;198311:23;198336:21;198361:14;-1:-1:-1;;;;;198361:20:0;;198382:6;198361:28;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;198361:28:0;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;198361:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;198361:28:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;198361:28:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;;;5:11;;2:2;;;29:1;26;19:12;2:2;198361:28:0;;;;;;19:11:-1;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;261:11;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;-1:-1;;198361:28:0;;;;;;;-1:-1:-1;198361:28:0;-1:-1:-1;198459:24:0;;-1:-1:-1;198486:41:0;;-1:-1:-1;;;;;;198486:18:0;;198361:28;198486:41;:18;:41;:::i;:::-;198538:21;;;:41;;-1:-1:-1;;198538:41:0;-1:-1:-1;;;;;;;;198538:41:0;;;;;;198616:22;;198640:20;;;;198538:41;;-1:-1:-1;198590:102:0;;198538:21;198670:6;198678:13;198590:25;:102::i;:::-;198866:19;;;;:28;;;-1:-1:-1;;;;;198721:33:0;;;;;;;;198703:15;;198866:47;;198899:13;198866:47;:32;:47;:::i;:::-;198846:67;;198924:11;:9;:11::i;:::-;198943:19;;;;:28;198924:71;;;-1:-1:-1;;;;;198924:71:0;;-1:-1:-1;;;;;198924:71:0;;;;;;;198973:10;198924:71;;;;;;;;;;;;:18;;;;;;;:71;;;;;198943:28;;198924:71;;;;;;;;198943:28;198924:18;:71;;;5:2:-1;;;;30:1;27;20:12;5:2;198924:71:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;199013:10:0;;-1:-1:-1;;;;;;;;;;;;;;;197227:1804:0;;;;:::o;191147:295::-;191413:21;;;;191391:18;;191347:7;;-1:-1:-1;;;;;;;;191413:21:0;;;;;;191379:31;;:7;;191391:18;191379:31;:11;:31;:::i;:::-;:55;;;;;;;191147:295;-1:-1:-1;;;;191147:295:0:o;121570:116::-;121614:9;121653:10;;;;;;;;;-1:-1:-1;;;;;121653:10:0;-1:-1:-1;;;;;121653:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;169375:1414:0;169581:20;;169490:5;;-1:-1:-1;;;169581:20:0;;;;169573:33;169569:93;;-1:-1:-1;169630:20:0;;-1:-1:-1;;;169630:20:0;;;;169623:27;;169569:93;169823:19;169870:1;169845:8;:15;;:22;;;;:26;169823:48;;169882:90;169907:8;169917:11;169930:23;169955:7;:16;;;169882:24;:90::i;:::-;170212:35;170250:8;:15;;170266:11;170250:28;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;170317:16:0;;;;170382:25;170317:16;170382:13;:25::i;:::-;:60;;;;;170412:30;170431:10;170412:18;:30::i;:::-;170411:31;170382:60;170344:98;;170453:17;170473:30;:151;;170560:9;:7;:9::i;:::-;-1:-1:-1;;;;;170560:27:0;;170588:35;170599:10;170611:11;170588:10;:35::i;:::-;170560:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;170560:64:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;170560:64:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;170560:64:0;170473:151;;;170519:25;;-1:-1:-1;;;170519:25:0;;;;170473:151;170718:34;;;;-1:-1:-1;;;170718:34:0;;;;;;;;-1:-1:-1;170718:34:0;;169375:1414;-1:-1:-1;;;;;;;169375:1414:0:o;171697:2645::-;171975:7;172000:13;172016:20;:18;:20::i;:::-;172166;;;;172432:13;;;:20;172000:36;;-1:-1:-1;;;;172166:20:0;;-1:-1:-1;;;;;172166:20:0;;172137:26;;172432:44;;172166:20;172432:24;:44::i;:::-;172403:73;;172875:1;172857:15;:19;:59;;;;;172901:15;172880:18;:36;172857:59;172853:191;;;-1:-1:-1;172954:15:0;172853:191;;;173002:30;;-1:-1:-1;;173002:30:0;-1:-1:-1;;;173002:30:0;;;172853:191;173141:42;:18;173164;173141:42;:22;:42;:::i;:::-;173111:6;:20;;;:73;;;;;-1:-1:-1;;;;;173111:73:0;;;;;-1:-1:-1;;;;;173111:73:0;;;;;;173324:30;173357:17;:15;:17::i;:::-;173324:50;;173385:23;173425:18;173411:33;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;173411:33:0;;173385:59;;173455:26;173498:18;173484:33;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;173484:33:0;-1:-1:-1;173455:62:0;-1:-1:-1;173533:9:0;173528:264;173552:18;173548:1;:22;173528:264;;;173592:13;173608:6;:13;;173643:1;173622:18;:22;173608:37;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;173608:37:0;173592:53;;173672:5;173660:6;173667:1;173660:9;;;;;;;;;;;;;:17;-1:-1:-1;;;;;173660:17:0;;;-1:-1:-1;;;;;173660:17:0;;;;;173707:73;173746:6;:19;;:26;173766:5;-1:-1:-1;;;;;173746:26:0;-1:-1:-1;;;;;173746:26:0;;;;;;;;;;;;:33;;;;;;;;;;-1:-1:-1;;;;;173746:33:0;-1:-1:-1;;;;;173707:73:0;:34;173729:11;173707:17;:21;;:34;;;;:::i;:73::-;173692:9;173702:1;173692:12;;;;;;;;;;;;;;;;;:88;-1:-1:-1;173572:3:0;;173528:264;;;;174075:27;174105:9;:7;:9::i;:::-;-1:-1:-1;;;;;174105:28:0;;174134:7;174143:12;174157:6;174105:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;174105:59:0;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;174105:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;174105:59:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;174105:59:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;174105:59:0;;;;;;19:11:-1;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;261:11;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;0:373;;174105:59:0;;;;;;174075:89;;174200:98;174227:14;-1:-1:-1;;;;;174227:28:0;;174256:6;174264;174272:9;174283:13;174227:70;;;;;;;;;;;;;-1:-1:-1;;;;;174227:70:0;-1:-1:-1;;;;;174227:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;174227:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;174227:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;174227:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;174227:70:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;174227:70:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;174227:70:0;;;;;;;;;;;;;;;;174200:6;:22;;;:26;;:98;;;;:::i;:::-;174175:22;;;:123;-1:-1:-1;174316:18:0;;-1:-1:-1;;;;;;171697:2645:0;;;;;;;;:::o;5139:460::-;5199:7;5443;5439:48;;-1:-1:-1;5474:1:0;5467:8;;5439:48;5511:7;;;5516:2;5511;:7;:2;5537:6;;;;;:12;5551:18;;;;;;;;;;;;;;;;;5529:41;;;;;-1:-1:-1;;;;;5529:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;201064:1630:0;201440:21;;;;-1:-1:-1;;;201440:21:0;;-1:-1:-1;;;;;201440:21:0;:25;201436:64;;201482:7;;201436:64;201825:20;;201821:161;;201862:30;201895:17;:15;:17::i;:::-;201862:50;;201927:14;-1:-1:-1;;;;;201927:25:0;;201953:16;201927:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;201927:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;201927:43:0;;;;201821:161;;202243:13;202239:448;;202314:16;;;202333;;;202273:77;;;-1:-1:-1;;;;;202273:77:0;;-1:-1:-1;;;;;202273:77:0;;;;;;;202314:16;;;202273:77;;;;;;;;;;;;:21;;;;;;:77;;;;;202314:16;;202273:77;;;;;;;;202314:16;202273:21;:77;;;5:2:-1;;;;30:1;27;20:12;5:2;202273:77:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;202273:77:0;;;;202239:448;;;202383:18;202423:1;202404:6;:16;;;:20;;;;;;202383:41;;202439:31;202473:8;:15;;202500:1;202489:8;:12;202473:29;;;;;;;;;;;;;;;:36;:29;;;;;:36;202557:22;;202524:68;;;-1:-1:-1;;;;;202524:68:0;;-1:-1:-1;;;;;202524:68:0;;;;;;;202557:22;;;202524:68;;;;;;;;;;;;202473:36;;-1:-1:-1;202524:21:0;;;;;;:68;;;;;;;;;;202473:29;202524:21;:68;;;5:2:-1;;;;30:1;27;20:12;5:2;202524:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;202640:22:0;;;;202607:68;;;-1:-1:-1;;;;;202607:68:0;;-1:-1:-1;;;;;202607:68:0;;;;;;;202640:22;;;202607:68;;;;;;;;;;;;:21;;;;-1:-1:-1;202607:21:0;;:68;;;;;202640:22;;202607:68;;;;;;;202640:22;202607:21;:68;;;5:2:-1;;;;30:1;27;20:12;5:2;202607:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;202239:448:0;201064:1630;;;;;;:::o;188277:129::-;188371:13;-1:-1:-1;;;;;188371:13:0;:27;;;188277:129::o;188623:134::-;188722:13;;;-1:-1:-1;;;;;188722:13:0;:27;;;188623:134::o;6420:175::-;6547:18;;;;;;;;;;;;;;;;;6480:7;;6512;;;;6538;;;;6530:36;;;;-1:-1:-1;;;;;6530:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;6167:177:0;6227:7;6261:2;6255;:8;;6265:19;;;;;;;;;;;;;;;;;6247:38;;;;;-1:-1:-1;;;;;6247:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;6247:38:0;-1:-1:-1;;6308:7:0;;;6167:177::o;175886:1482::-;176028:6;176143:30;176176:17;:15;:17::i;:::-;176269:18;;176228:60;;;-1:-1:-1;;;;;176228:60:0;;-1:-1:-1;;;;;176228:60:0;;;;;;;-1:-1:-1;;;;;176269:18:0;;;176228:60;;;;;;176143:50;;-1:-1:-1;176204:21:0;;176228:32;;;;;;:60;;;;;;;;;;;;;;;:32;:60;;;5:2:-1;;;;30:1;27;20:12;5:2;176228:60:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;176228:60:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;176228:60:0;176359:14;;;;:31;176228:60;;-1:-1:-1;176299:13:0;;176315:76;;176228:60;;176315:28;:76::i;:::-;176299:92;-1:-1:-1;;;;;;176480:11:0;;176476:60;;176522:1;176508:16;;;;;;;176476:60;176765:23;176791:46;176809:7;:16;;;:27;;;176791:13;:17;;:46;;;;:::i;:::-;176765:72;;176964:14;-1:-1:-1;;;;;176964:28:0;;176993:6;177001:15;177018:23;:21;:23::i;:::-;176964:78;;;;;;;;;;-1:-1:-1;;;;;176964:78:0;;;;;;;;;;;;;;-1:-1:-1;;;;;176964:78:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;176964:78:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;176964:78:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;176964:78:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;176964:78:0;176959:128;;177073:1;177059:16;;;;;;;;176959:128;-1:-1:-1;;;;;177212:27:0;;;;;;:19;;;:27;;;;;:43;;-1:-1:-1;;177212:43:0;-1:-1:-1;;;;;177212:43:0;;;;;177291:22;;;;:43;;177318:15;177291:26;:43::i;:::-;177266:22;;;:68;-1:-1:-1;177354:6:0;-1:-1:-1;;;175886:1482:0;;;;;:::o;193181:751::-;193371:13;;193781:27;;;;193727:16;;;;193290:14;;;;193699:110;;193781:27;127921:4;;193700:44;;-1:-1:-1;;;;;193700:22:0;;;:44;:26;:44;:::i;:::-;:75;;;;;;;193699:110;:81;:110;:::i;:::-;193687:122;;193915:9;193903:21;;193181:751;;;;;:::o;183224:539::-;183491:24;;;;183467:19;;183354:6;;;;183467:49;;-1:-1:-1;;;183467:19:0;;;-1:-1:-1;;;;;183467:19:0;;:23;:49::i;:::-;183445:71;-1:-1:-1;183653:25:0;;;183649:77;;183700:14;;183743:12;183224:539;-1:-1:-1;;;183224:539:0:o;22939:127::-;23006:7;22447:5;23033:14;:4;23042;23033:14;:8;:14;:::i;:::-;:25;;;;;;;22939:127;-1:-1:-1;;;22939:127:0:o;2171:378::-;2327:136;;;-1:-1:-1;;;;;2327:136:0;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;2327:136:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;2364:28:0;179:29:-1;160:49;;2274:4:0;;2481:60;2364:6;2327:136;3073:1346;3160:4;3177:8;3237:4;3231:11;3668:4;3596:3;3544:9;3538:16;3496:4;3485:9;3481:20;3430:1;3380:5;3322:3;3299:423;3741:14;;3738:2;;3853:14;3941:57;;;;4080:4;4075:189;;;;3846:519;;3941:57;3978:1;3971:8;;3941:57;;4075:189;4243:1;4237:3;4231:10;4228:17;4221:24;;3846:519;;3738:2;-1:-1:-1;4408:3:0;;3073:1346;-1:-1:-1;;;;3073:1346:0:o;9852:159::-;9948:27;;;;;;;;;;;;;;;;;9904:6;;-1:-1:-1;;;;;9931:15:0;;;9923:53;;;;-1:-1:-1;;;;;9923:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;9923:53:0;-1:-1:-1;10001:1:0;;9852:159;-1:-1:-1;9852:159:0:o;8429:173::-;8487:6;8520:2;-1:-1:-1;;;;;8514:8:0;:2;-1:-1:-1;;;;;8514:8:0;;;8524:19;;;;;;;;;;;;;;;;;8506:38;;;;;-1:-1:-1;;;;;8506:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;199690:744:0;199937:9;199932:495;199956:14;199952:1;:18;199932:495;;;199992:13;200008:7;200016:1;200008:10;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;200065:26:0;;200033:29;200065:26;;;:19;;;:26;;;;;;;200209:17;;200008:10;;-1:-1:-1;200065:26:0;-1:-1:-1;;;;;200209:17:0;200197:97;;200253:13;;;27:10:-1;;39:1;23:18;;45:23;;-1:-1;200253:25:0;;;;;;;;;;-1:-1:-1;;200253:25:0;-1:-1:-1;;;;;200253:25:0;;;;;200197:97;200330:17;;:24;;-1:-1:-1;;;;;200330:17:0;200352:1;200330:24;:21;:24;:::i;:::-;200310:44;;-1:-1:-1;;200310:44:0;-1:-1:-1;;;;;200310:44:0;;;;;;;200374:41;;-1:-1:-1;;;;;200374:41:0;;;200399:8;;200387:10;;200374:41;;-1:-1:-1;;200374:41:0;-1:-1:-1;;199972:3:0;;199932:495;;22799:132;22862:7;22447:5;22889:23;:4;22898:13;;;22889:23;:8;:23;:::i;7621:244::-;7780:18;;;;;;;;;;;;;;;;;7679:6;;-1:-1:-1;;;;;7710:11:0;;;7724;;;7710:25;;-1:-1:-1;;;7754:24:0;;7746:53;;;;-1:-1:-1;;;;;7746:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;125219:77809:0;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;-1:-1:-1;125219:77809:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;125219:77809:0;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;125219:77809:0;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;-1:-1:-1;125219:77809:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;125219:77809:0;;;-1:-1:-1;;125219:77809:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;125219:77809:0;;;-1:-1:-1;;125219:77809:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;125219:77809:0;;;-1:-1:-1;;125219:77809:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;125219:77809:0;;;-1:-1:-1;;125219:77809:0:o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;125219:77809:0;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;125219:77809:0;;;-1:-1:-1;;125219:77809:0:o;:::-;;;;;;;;;;-1:-1:-1;;;;;125219:77809:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;125219:77809:0;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;125219:77809:0;;;;;;;;;;;;;;;;-1:-1:-1;;125219:77809:0;;;;;;;;-1:-1:-1;;125219:77809:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Swarm Source
bzzr://20c137edb6f0f5f0da0d0d361d22809d8f4b8382642960f9058207418aaf2b34
Loading...
Loading
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.