Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 118 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Settle Reward | 11273745 | 1381 days ago | IN | 0 ETH | 0.0058203 | ||||
Settle Reward | 11273745 | 1381 days ago | IN | 0 ETH | 0.0073203 | ||||
Settle Reward | 10869836 | 1444 days ago | IN | 0 ETH | 0.01175821 | ||||
Settle Reward | 10869833 | 1444 days ago | IN | 0 ETH | 0.01175821 | ||||
Settle Reward | 10869831 | 1444 days ago | IN | 0 ETH | 0.01478821 | ||||
Settle Penalties | 10869825 | 1444 days ago | IN | 0 ETH | 0.03863805 | ||||
Settle Appeal De... | 10869823 | 1444 days ago | IN | 0 ETH | 0.00956884 | ||||
Settle Reward | 10869822 | 1444 days ago | IN | 0 ETH | 0.014787 | ||||
Settle Reward | 10869821 | 1444 days ago | IN | 0 ETH | 0.014787 | ||||
Settle Penalties | 10869819 | 1444 days ago | IN | 0 ETH | 0.02408486 | ||||
Settle Reward | 10869814 | 1444 days ago | IN | 0 ETH | 0.01175821 | ||||
Settle Reward | 10869810 | 1444 days ago | IN | 0 ETH | 0.01478821 | ||||
Settle Reward | 10869808 | 1444 days ago | IN | 0 ETH | 0.01478821 | ||||
Settle Penalties | 10869807 | 1444 days ago | IN | 0 ETH | 0.03824203 | ||||
Settle Appeal De... | 10869805 | 1444 days ago | IN | 0 ETH | 0.01108384 | ||||
Settle Reward | 10869804 | 1444 days ago | IN | 0 ETH | 0.014787 | ||||
Settle Penalties | 10869802 | 1444 days ago | IN | 0 ETH | 0.03743514 | ||||
Draft | 10832262 | 1449 days ago | IN | 0 ETH | 0.1317162 | ||||
Draft | 10832252 | 1449 days ago | IN | 0 ETH | 0.144 | ||||
Draft | 10831356 | 1449 days ago | IN | 0 ETH | 0.1272 | ||||
Draft | 10830899 | 1450 days ago | IN | 0 ETH | 0.1188 | ||||
Draft | 10830889 | 1450 days ago | IN | 0 ETH | 0.1128 | ||||
Draft | 10830876 | 1450 days ago | IN | 0 ETH | 0.10081818 | ||||
Draft | 10830171 | 1450 days ago | IN | 0 ETH | 0.00394868 | ||||
Draft | 10829585 | 1450 days ago | IN | 0 ETH | 0.00373639 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
DisputeManager
Compiler Version
v0.5.8+commit.23d335f2
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-03-16 */ /** * Commit sha: d04b668834b9f05058f4f4e8f9b799a5e26463a1 * GitHub repository: https://github.com/aragon/aragon-court * Tool used for the deploy: https://github.com/aragon/aragon-network-deploy **/ // File: contracts/lib/os/ERC20.sol // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/lib/token/ERC20.sol // Adapted to use pragma ^0.5.8 and satisfy our linter rules pragma solidity ^0.5.8; /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ contract ERC20 { function totalSupply() public view returns (uint256); function balanceOf(address _who) public view returns (uint256); function allowance(address _owner, address _spender) public view returns (uint256); function transfer(address _to, uint256 _value) public returns (bool); function approve(address _spender, uint256 _value) public returns (bool); function transferFrom(address _from, address _to, uint256 _value) public returns (bool); event Transfer( address indexed from, address indexed to, uint256 value ); event Approval( address indexed owner, address indexed spender, uint256 value ); } // File: contracts/lib/os/SafeERC20.sol // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/common/SafeERC20.sol // Adapted to use pragma ^0.5.8 and satisfy our linter rules pragma solidity ^0.5.8; library SafeERC20 { // Before 0.5, solidity has a mismatch between `address.transfer()` and `token.transfer()`: // https://github.com/ethereum/solidity/issues/3544 bytes4 private constant TRANSFER_SELECTOR = 0xa9059cbb; /** * @dev Same as a standards-compliant ERC20.transfer() that never reverts (returns false). * Note that this makes an external call to the token. */ function safeTransfer(ERC20 _token, address _to, uint256 _amount) internal returns (bool) { bytes memory transferCallData = abi.encodeWithSelector( TRANSFER_SELECTOR, _to, _amount ); return invokeAndCheckSuccess(address(_token), transferCallData); } /** * @dev Same as a standards-compliant ERC20.transferFrom() that never reverts (returns false). * Note that this makes an external call to the token. */ function safeTransferFrom(ERC20 _token, address _from, address _to, uint256 _amount) internal returns (bool) { bytes memory transferFromCallData = abi.encodeWithSelector( _token.transferFrom.selector, _from, _to, _amount ); return invokeAndCheckSuccess(address(_token), transferFromCallData); } /** * @dev Same as a standards-compliant ERC20.approve() that never reverts (returns false). * Note that this makes an external call to the token. */ function safeApprove(ERC20 _token, address _spender, uint256 _amount) internal returns (bool) { bytes memory approveCallData = abi.encodeWithSelector( _token.approve.selector, _spender, _amount ); return invokeAndCheckSuccess(address(_token), approveCallData); } function invokeAndCheckSuccess(address _addr, bytes memory _calldata) private returns (bool) { bool ret; assembly { let ptr := mload(0x40) // free memory pointer let success := call( gas, // forward all gas _addr, // address 0, // no value add(_calldata, 0x20), // calldata start mload(_calldata), // calldata length ptr, // write output over free memory 0x20 // uint256 return ) if gt(success, 0) { // Check number of bytes returned from last function call switch returndatasize // No bytes returned: assume success case 0 { ret := 1 } // 32 bytes returned: check if non-zero case 0x20 { // Only return success if returned data was true // Already have output in ptr ret := eq(mload(ptr), 1) } // Not sure what was returned: don't mark as success default { } } } return ret; } } // File: contracts/lib/os/SafeMath.sol // Brought from https://github.com/aragon/aragonOS/blob/v4.3.0/contracts/lib/math/SafeMath.sol // Adapted to use pragma ^0.5.8 and satisfy our linter rules pragma solidity >=0.4.24 <0.6.0; /** * @title SafeMath * @dev Math operations with safety checks that revert on error */ library SafeMath { string private constant ERROR_ADD_OVERFLOW = "MATH_ADD_OVERFLOW"; string private constant ERROR_SUB_UNDERFLOW = "MATH_SUB_UNDERFLOW"; string private constant ERROR_MUL_OVERFLOW = "MATH_MUL_OVERFLOW"; string private constant ERROR_DIV_ZERO = "MATH_DIV_ZERO"; /** * @dev Multiplies two numbers, reverts on overflow. */ function mul(uint256 _a, uint256 _b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (_a == 0) { return 0; } uint256 c = _a * _b; require(c / _a == _b, ERROR_MUL_OVERFLOW); return c; } /** * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. */ function div(uint256 _a, uint256 _b) internal pure returns (uint256) { require(_b > 0, ERROR_DIV_ZERO); // Solidity only automatically asserts when dividing by 0 uint256 c = _a / _b; // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold return c; } /** * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 _a, uint256 _b) internal pure returns (uint256) { require(_b <= _a, ERROR_SUB_UNDERFLOW); uint256 c = _a - _b; return c; } /** * @dev Adds two numbers, reverts on overflow. */ function add(uint256 _a, uint256 _b) internal pure returns (uint256) { uint256 c = _a + _b; require(c >= _a, ERROR_ADD_OVERFLOW); return c; } /** * @dev Divides two numbers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, ERROR_DIV_ZERO); return a % b; } } // File: contracts/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 Close the evidence period of a dispute * @param _disputeId Identification number of the dispute to close its evidence submitting period */ function closeEvidencePeriod(uint256 _disputeId) external; /** * @dev Execute the Arbitrable associated to a dispute based on its final ruling * @param _disputeId Identification number of the dispute to be executed */ function executeRuling(uint256 _disputeId) external; /** * @dev Tell the dispute fees information to create a dispute * @return recipient Address where the corresponding dispute fees must be transferred to * @return feeToken ERC20 token used for the fees * @return feeAmount Total amount of fees that must be allowed to the recipient */ function getDisputeFees() external view returns (address recipient, ERC20 feeToken, uint256 feeAmount); /** * @dev Tell the subscription fees information for a subscriber to be up-to-date * @param _subscriber Address of the account paying the subscription fees for * @return recipient Address where the corresponding subscriptions fees must be transferred to * @return feeToken ERC20 token used for the subscription fees * @return feeAmount Total amount of fees that must be allowed to the recipient */ function getSubscriptionFees(address _subscriber) external view returns (address recipient, ERC20 feeToken, uint256 feeAmount); } // File: contracts/standards/ERC165.sol pragma solidity ^0.5.8; interface ERC165 { /** * @dev Query if a contract implements a certain interface * @param _interfaceId The interface identifier being queried, as specified in ERC-165 * @return True if the contract implements the requested interface and if its not 0xffffffff, false otherwise */ function supportsInterface(bytes4 _interfaceId) external pure returns (bool); } // File: contracts/arbitration/IArbitrable.sol pragma solidity ^0.5.8; contract IArbitrable is ERC165 { bytes4 internal constant ERC165_INTERFACE_ID = bytes4(0x01ffc9a7); bytes4 internal constant ARBITRABLE_INTERFACE_ID = bytes4(0x88f3ee69); /** * @dev Emitted when an IArbitrable instance's dispute is ruled by an IArbitrator * @param arbitrator IArbitrator instance ruling the dispute * @param disputeId Identification number of the dispute being ruled by the arbitrator * @param ruling Ruling given by the arbitrator */ event Ruled(IArbitrator indexed arbitrator, uint256 indexed disputeId, uint256 ruling); /** * @dev Emitted when new evidence is submitted for the IArbitrable instance's dispute * @param disputeId Identification number of the dispute receiving new evidence * @param submitter Address of the account submitting the evidence * @param evidence Data submitted for the evidence of the dispute * @param finished Whether or not the submitter has finished submitting evidence */ event EvidenceSubmitted(uint256 indexed disputeId, address indexed submitter, bytes evidence, bool finished); /** * @dev Submit evidence for a dispute * @param _disputeId Id of the dispute in the Court * @param _evidence Data submitted for the evidence related to the dispute * @param _finished Whether or not the submitter has finished submitting evidence */ function submitEvidence(uint256 _disputeId, bytes calldata _evidence, bool _finished) external; /** * @dev Give a ruling for a certain dispute, the account calling it must have rights to rule on the contract * @param _disputeId Identification number of the dispute to be ruled * @param _ruling Ruling given by the arbitrator, where 0 is reserved for "refused to make a decision" */ function rule(uint256 _disputeId, uint256 _ruling) external; /** * @dev ERC165 - Query if a contract implements a certain interface * @param _interfaceId The interface identifier being queried, as specified in ERC-165 * @return True if this contract supports the given interface, false otherwise */ function supportsInterface(bytes4 _interfaceId) external pure returns (bool) { return _interfaceId == ARBITRABLE_INTERFACE_ID || _interfaceId == ERC165_INTERFACE_ID; } } // File: contracts/disputes/IDisputeManager.sol pragma solidity ^0.5.8; interface IDisputeManager { enum DisputeState { PreDraft, Adjudicating, Ruled } enum AdjudicationState { Invalid, Committing, Revealing, Appealing, ConfirmingAppeal, Ended } /** * @dev Create a dispute to be drafted in a future term * @param _subject Arbitrable instance creating the dispute * @param _possibleRulings Number of possible rulings allowed for the drafted jurors to vote on the dispute * @param _metadata Optional metadata that can be used to provide additional information on the dispute to be created * @return Dispute identification number */ function createDispute(IArbitrable _subject, uint8 _possibleRulings, bytes calldata _metadata) external returns (uint256); /** * @dev Close the evidence period of a dispute * @param _subject IArbitrable instance requesting to close the evidence submission period * @param _disputeId Identification number of the dispute to close its evidence submitting period */ function closeEvidencePeriod(IArbitrable _subject, uint256 _disputeId) external; /** * @dev Draft jurors for the next round of a dispute * @param _disputeId Identification number of the dispute to be drafted */ function draft(uint256 _disputeId) external; /** * @dev Appeal round of a dispute in favor of a certain ruling * @param _disputeId Identification number of the dispute being appealed * @param _roundId Identification number of the dispute round being appealed * @param _ruling Ruling appealing a dispute round in favor of */ function createAppeal(uint256 _disputeId, uint256 _roundId, uint8 _ruling) external; /** * @dev Confirm appeal for a round of a dispute in favor of a ruling * @param _disputeId Identification number of the dispute confirming an appeal of * @param _roundId Identification number of the dispute round confirming an appeal of * @param _ruling Ruling being confirmed against a dispute round appeal */ function confirmAppeal(uint256 _disputeId, uint256 _roundId, uint8 _ruling) external; /** * @dev Compute the final ruling for a dispute * @param _disputeId Identification number of the dispute to compute its final ruling * @return subject Arbitrable instance associated to the dispute * @return finalRuling Final ruling decided for the given dispute */ function computeRuling(uint256 _disputeId) external returns (IArbitrable subject, uint8 finalRuling); /** * @dev Settle penalties for a round of a dispute * @param _disputeId Identification number of the dispute to settle penalties for * @param _roundId Identification number of the dispute round to settle penalties for * @param _jurorsToSettle Maximum number of jurors to be slashed in this call */ function settlePenalties(uint256 _disputeId, uint256 _roundId, uint256 _jurorsToSettle) external; /** * @dev Claim rewards for a round of a dispute for juror * @dev For regular rounds, it will only reward winning jurors * @param _disputeId Identification number of the dispute to settle rewards for * @param _roundId Identification number of the dispute round to settle rewards for * @param _juror Address of the juror to settle their rewards */ function settleReward(uint256 _disputeId, uint256 _roundId, address _juror) external; /** * @dev Settle appeal deposits for a round of a dispute * @param _disputeId Identification number of the dispute to settle appeal deposits for * @param _roundId Identification number of the dispute round to settle appeal deposits for */ function settleAppealDeposit(uint256 _disputeId, uint256 _roundId) external; /** * @dev Tell the amount of token fees required to create a dispute * @return feeToken ERC20 token used for the fees * @return feeAmount Total amount of fees to be paid for a dispute at the given term */ function getDisputeFees() external view returns (ERC20 feeToken, uint256 feeAmount); /** * @dev Tell information of a certain dispute * @param _disputeId Identification number of the dispute being queried * @return subject Arbitrable subject being disputed * @return possibleRulings Number of possible rulings allowed for the drafted jurors to vote on the dispute * @return state Current state of the dispute being queried: pre-draft, adjudicating, or ruled * @return finalRuling The winning ruling in case the dispute is finished * @return lastRoundId Identification number of the last round created for the dispute * @return createTermId Identification number of the term when the dispute was created */ function getDispute(uint256 _disputeId) external view returns (IArbitrable subject, uint8 possibleRulings, DisputeState state, uint8 finalRuling, uint256 lastRoundId, uint64 createTermId); /** * @dev Tell information of a certain adjudication round * @param _disputeId Identification number of the dispute being queried * @param _roundId Identification number of the round being queried * @return draftTerm Term from which the requested round can be drafted * @return delayedTerms Number of terms the given round was delayed based on its requested draft term id * @return jurorsNumber Number of jurors requested for the round * @return selectedJurors Number of jurors already selected for the requested round * @return settledPenalties Whether or not penalties have been settled for the requested round * @return collectedTokens Amount of juror tokens that were collected from slashed jurors for the requested round * @return coherentJurors Number of jurors that voted in favor of the final ruling in the requested round * @return state Adjudication state of the requested round */ function getRound(uint256 _disputeId, uint256 _roundId) external view returns ( uint64 draftTerm, uint64 delayedTerms, uint64 jurorsNumber, uint64 selectedJurors, uint256 jurorFees, bool settledPenalties, uint256 collectedTokens, uint64 coherentJurors, AdjudicationState state ); /** * @dev Tell appeal-related information of a certain adjudication round * @param _disputeId Identification number of the dispute being queried * @param _roundId Identification number of the round being queried * @return maker Address of the account appealing the given round * @return appealedRuling Ruling confirmed by the appealer of the given round * @return taker Address of the account confirming the appeal of the given round * @return opposedRuling Ruling confirmed by the appeal taker of the given round */ function getAppeal(uint256 _disputeId, uint256 _roundId) external view returns (address maker, uint64 appealedRuling, address taker, uint64 opposedRuling); /** * @dev Tell information related to the next round due to an appeal of a certain round given. * @param _disputeId Identification number of the dispute being queried * @param _roundId Identification number of the round requesting the appeal details of * @return nextRoundStartTerm Term ID from which the next round will start * @return nextRoundJurorsNumber Jurors number for the next round * @return newDisputeState New state for the dispute associated to the given round after the appeal * @return feeToken ERC20 token used for the next round fees * @return jurorFees Total amount of fees to be distributed between the winning jurors of the next round * @return totalFees Total amount of fees for a regular round at the given term * @return appealDeposit Amount to be deposit of fees for a regular round at the given term * @return confirmAppealDeposit Total amount of fees for a regular round at the given term */ function getNextRoundDetails(uint256 _disputeId, uint256 _roundId) external view returns ( uint64 nextRoundStartTerm, uint64 nextRoundJurorsNumber, DisputeState newDisputeState, ERC20 feeToken, uint256 totalFees, uint256 jurorFees, uint256 appealDeposit, uint256 confirmAppealDeposit ); /** * @dev Tell juror-related information of a certain adjudication round * @param _disputeId Identification number of the dispute being queried * @param _roundId Identification number of the round being queried * @param _juror Address of the juror being queried * @return weight Juror weight drafted for the requested round * @return rewarded Whether or not the given juror was rewarded based on the requested round */ function getJuror(uint256 _disputeId, uint256 _roundId, address _juror) external view returns (uint64 weight, bool rewarded); } // File: contracts/lib/PctHelpers.sol pragma solidity ^0.5.8; library PctHelpers { using SafeMath for uint256; uint256 internal constant PCT_BASE = 10000; // ‱ (1 / 10,000) function isValid(uint16 _pct) internal pure returns (bool) { return _pct <= PCT_BASE; } function pct(uint256 self, uint16 _pct) internal pure returns (uint256) { return self.mul(uint256(_pct)) / PCT_BASE; } function pct256(uint256 self, uint256 _pct) internal pure returns (uint256) { return self.mul(_pct) / PCT_BASE; } function pctIncrease(uint256 self, uint16 _pct) internal pure returns (uint256) { // No need for SafeMath: for addition note that `PCT_BASE` is lower than (2^256 - 2^16) return self.mul(PCT_BASE + uint256(_pct)) / PCT_BASE; } } // File: contracts/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/subscriptions/ISubscriptions.sol pragma solidity ^0.5.8; interface ISubscriptions { /** * @dev Tell whether a certain subscriber has paid all the fees up to current period or not * @param _subscriber Address of subscriber being checked * @return True if subscriber has paid all the fees up to current period, false otherwise */ function isUpToDate(address _subscriber) external view returns (bool); /** * @dev Tell the minimum amount of fees to pay and resulting last paid period for a given subscriber in order to be up-to-date * @param _subscriber Address of the subscriber willing to pay * @return feeToken ERC20 token used for the subscription fees * @return amountToPay Amount of subscription fee tokens to be paid * @return newLastPeriodId Identification number of the resulting last paid period */ function getOwedFeesDetails(address _subscriber) external view returns (ERC20, uint256, uint256); } // File: contracts/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 */ function getTerm(uint64 _termId) external view returns (uint64 startTime, uint64 randomnessBN, bytes32 randomness); /** * @dev Tell the randomness of a term even if it wasn't computed yet * @param _termId Identification number of the term being queried * @return Randomness of the requested term */ function getTermRandomness(uint64 _termId) external view returns (bytes32); } // File: contracts/court/clock/CourtClock.sol pragma solidity ^0.5.8; contract CourtClock is IClock, TimeHelpers { using SafeMath64 for uint64; string private constant ERROR_TERM_DOES_NOT_EXIST = "CLK_TERM_DOES_NOT_EXIST"; string private constant ERROR_TERM_DURATION_TOO_LONG = "CLK_TERM_DURATION_TOO_LONG"; string private constant ERROR_TERM_RANDOMNESS_NOT_YET = "CLK_TERM_RANDOMNESS_NOT_YET"; string private constant ERROR_TERM_RANDOMNESS_UNAVAILABLE = "CLK_TERM_RANDOMNESS_UNAVAILABLE"; string private constant ERROR_BAD_FIRST_TERM_START_TIME = "CLK_BAD_FIRST_TERM_START_TIME"; string private constant ERROR_TOO_MANY_TRANSITIONS = "CLK_TOO_MANY_TRANSITIONS"; string private constant ERROR_INVALID_TRANSITION_TERMS = "CLK_INVALID_TRANSITION_TERMS"; string private constant ERROR_CANNOT_DELAY_STARTED_COURT = "CLK_CANNOT_DELAY_STARTED_COURT"; string private constant ERROR_CANNOT_DELAY_PAST_START_TIME = "CLK_CANNOT_DELAY_PAST_START_TIME"; // Maximum number of term transitions a callee may have to assume in order to call certain functions that require the Court being up-to-date uint64 internal constant MAX_AUTO_TERM_TRANSITIONS_ALLOWED = 1; // Max duration in seconds that a term can last uint64 internal constant MAX_TERM_DURATION = 365 days; // Max time until first term starts since contract is deployed uint64 internal constant MAX_FIRST_TERM_DELAY_PERIOD = 2 * MAX_TERM_DURATION; struct Term { uint64 startTime; // Timestamp when the term started uint64 randomnessBN; // Block number for entropy bytes32 randomness; // Entropy from randomnessBN block hash } // Duration in seconds for each term of the Court uint64 private termDuration; // Last ensured term id uint64 private termId; // List of Court terms indexed by id mapping (uint64 => Term) private terms; event Heartbeat(uint64 previousTermId, uint64 currentTermId); event StartTimeDelayed(uint64 previousStartTime, uint64 currentStartTime); /** * @dev Ensure a certain term has already been processed * @param _termId Identification number of the term to be checked */ modifier termExists(uint64 _termId) { require(_termId <= termId, ERROR_TERM_DOES_NOT_EXIST); _; } /** * @dev Constructor function * @param _termParams Array containing: * 0. _termDuration Duration in seconds per term * 1. _firstTermStartTime Timestamp in seconds when the court will open (to give time for juror on-boarding) */ constructor(uint64[2] memory _termParams) public { uint64 _termDuration = _termParams[0]; uint64 _firstTermStartTime = _termParams[1]; require(_termDuration < MAX_TERM_DURATION, ERROR_TERM_DURATION_TOO_LONG); require(_firstTermStartTime >= getTimestamp64() + _termDuration, ERROR_BAD_FIRST_TERM_START_TIME); require(_firstTermStartTime <= getTimestamp64() + MAX_FIRST_TERM_DELAY_PERIOD, ERROR_BAD_FIRST_TERM_START_TIME); termDuration = _termDuration; // No need for SafeMath: we already checked values above terms[0].startTime = _firstTermStartTime - _termDuration; } /** * @notice Ensure that the current term of the Court is up-to-date. If the Court is outdated by more than `MAX_AUTO_TERM_TRANSITIONS_ALLOWED` * terms, the heartbeat function must be called manually instead. * @return Identification number of the current term */ function ensureCurrentTerm() external returns (uint64) { return _ensureCurrentTerm(); } /** * @notice Transition up to `_maxRequestedTransitions` terms * @param _maxRequestedTransitions Max number of term transitions allowed by the sender * @return Identification number of the term ID after executing the heartbeat transitions */ function heartbeat(uint64 _maxRequestedTransitions) external returns (uint64) { return _heartbeat(_maxRequestedTransitions); } /** * @notice Ensure that a certain term has its randomness set. As we allow to draft disputes requested for previous terms, if there * were mined more than 256 blocks for the current term, the blockhash of its randomness BN is no longer available, given * round will be able to be drafted in the following term. * @return Randomness of the current term */ function ensureCurrentTermRandomness() external returns (bytes32) { // If the randomness for the given term was already computed, return uint64 currentTermId = termId; Term storage term = terms[currentTermId]; bytes32 termRandomness = term.randomness; if (termRandomness != bytes32(0)) { return termRandomness; } // Compute term randomness bytes32 newRandomness = _computeTermRandomness(currentTermId); require(newRandomness != bytes32(0), ERROR_TERM_RANDOMNESS_UNAVAILABLE); term.randomness = newRandomness; return newRandomness; } /** * @dev Tell the term duration of the Court * @return Duration in seconds of the Court term */ function getTermDuration() external view returns (uint64) { return termDuration; } /** * @dev Tell the last ensured term identification number * @return Identification number of the last ensured term */ function getLastEnsuredTermId() external view returns (uint64) { return _lastEnsuredTermId(); } /** * @dev Tell the current term identification number. Note that there may be pending term transitions. * @return Identification number of the current term */ function getCurrentTermId() external view returns (uint64) { return _currentTermId(); } /** * @dev Tell the number of terms the Court should transition to be up-to-date * @return Number of terms the Court should transition to be up-to-date */ function getNeededTermTransitions() external view returns (uint64) { return _neededTermTransitions(); } /** * @dev Tell the information related to a term based on its ID. Note that if the term has not been reached, the * information returned won't be computed yet. This function allows querying future terms that were not computed yet. * @param _termId ID of the term being queried * @return startTime Term start time * @return randomnessBN Block number used for randomness in the requested term * @return randomness Randomness computed for the requested term */ function getTerm(uint64 _termId) external view returns (uint64 startTime, uint64 randomnessBN, bytes32 randomness) { Term storage term = terms[_termId]; return (term.startTime, term.randomnessBN, term.randomness); } /** * @dev Tell the randomness of a term even if it wasn't computed yet * @param _termId Identification number of the term being queried * @return Randomness of the requested term */ function getTermRandomness(uint64 _termId) external view termExists(_termId) returns (bytes32) { return _computeTermRandomness(_termId); } /** * @dev Internal function to ensure that the current term of the Court is up-to-date. If the Court is outdated by more than * `MAX_AUTO_TERM_TRANSITIONS_ALLOWED` terms, the heartbeat function must be called manually. * @return Identification number of the resultant term ID after executing the corresponding transitions */ function _ensureCurrentTerm() internal returns (uint64) { // Check the required number of transitions does not exceeds the max allowed number to be processed automatically uint64 requiredTransitions = _neededTermTransitions(); require(requiredTransitions <= MAX_AUTO_TERM_TRANSITIONS_ALLOWED, ERROR_TOO_MANY_TRANSITIONS); // If there are no transitions pending, return the last ensured term id if (uint256(requiredTransitions) == 0) { return termId; } // Process transition if there is at least one pending return _heartbeat(requiredTransitions); } /** * @dev Internal function to transition the Court terms up to a requested number of terms * @param _maxRequestedTransitions Max number of term transitions allowed by the sender * @return Identification number of the resultant term ID after executing the requested transitions */ function _heartbeat(uint64 _maxRequestedTransitions) internal returns (uint64) { // Transition the minimum number of terms between the amount requested and the amount actually needed uint64 neededTransitions = _neededTermTransitions(); uint256 transitions = uint256(_maxRequestedTransitions < neededTransitions ? _maxRequestedTransitions : neededTransitions); require(transitions > 0, ERROR_INVALID_TRANSITION_TERMS); uint64 blockNumber = getBlockNumber64(); uint64 previousTermId = termId; uint64 currentTermId = previousTermId; for (uint256 transition = 1; transition <= transitions; transition++) { // Term IDs are incremented by one based on the number of time periods since the Court started. Since time is represented in uint64, // even if we chose the minimum duration possible for a term (1 second), we can ensure terms will never reach 2^64 since time is // already assumed to fit in uint64. Term storage previousTerm = terms[currentTermId++]; Term storage currentTerm = terms[currentTermId]; _onTermTransitioned(currentTermId); // Set the start time of the new term. Note that we are using a constant term duration value to guarantee // equally long terms, regardless of heartbeats. currentTerm.startTime = previousTerm.startTime.add(termDuration); // In order to draft a random number of jurors in a term, we use a randomness factor for each term based on a // block number that is set once the term has started. Note that this information could not be known beforehand. currentTerm.randomnessBN = blockNumber + 1; } termId = currentTermId; emit Heartbeat(previousTermId, currentTermId); return currentTermId; } /** * @dev Internal function to delay the first term start time only if it wasn't reached yet * @param _newFirstTermStartTime New timestamp in seconds when the court will open */ function _delayStartTime(uint64 _newFirstTermStartTime) internal { require(_currentTermId() == 0, ERROR_CANNOT_DELAY_STARTED_COURT); Term storage term = terms[0]; uint64 currentFirstTermStartTime = term.startTime.add(termDuration); require(_newFirstTermStartTime > currentFirstTermStartTime, ERROR_CANNOT_DELAY_PAST_START_TIME); // No need for SafeMath: we already checked above that `_newFirstTermStartTime` > `currentFirstTermStartTime` >= `termDuration` term.startTime = _newFirstTermStartTime - termDuration; emit StartTimeDelayed(currentFirstTermStartTime, _newFirstTermStartTime); } /** * @dev Internal function to notify when a term has been transitioned. This function must be overridden to provide custom behavior. * @param _termId Identification number of the new current term that has been transitioned */ function _onTermTransitioned(uint64 _termId) internal; /** * @dev Internal function to tell the last ensured term identification number * @return Identification number of the last ensured term */ function _lastEnsuredTermId() internal view returns (uint64) { return termId; } /** * @dev Internal function to tell the current term identification number. Note that there may be pending term transitions. * @return Identification number of the current term */ function _currentTermId() internal view returns (uint64) { return termId.add(_neededTermTransitions()); } /** * @dev Internal function to tell the number of terms the Court should transition to be up-to-date * @return Number of terms the Court should transition to be up-to-date */ function _neededTermTransitions() internal view returns (uint64) { // Note that the Court is always initialized providing a start time for the first-term in the future. If that's the case, // no term transitions are required. uint64 currentTermStartTime = terms[termId].startTime; if (getTimestamp64() < currentTermStartTime) { return uint64(0); } // No need for SafeMath: we already know that the start time of the current term is in the past return (getTimestamp64() - currentTermStartTime) / termDuration; } /** * @dev Internal function to compute the randomness that will be used to draft jurors for the given term. This * function assumes the given term exists. To determine the randomness factor for a term we use the hash of a * block number that is set once the term has started to ensure it cannot be known beforehand. Note that the * hash function being used only works for the 256 most recent block numbers. * @param _termId Identification number of the term being queried * @return Randomness computed for the given term */ function _computeTermRandomness(uint64 _termId) internal view returns (bytes32) { Term storage term = terms[_termId]; require(getBlockNumber64() > term.randomnessBN, ERROR_TERM_RANDOMNESS_NOT_YET); return blockhash(term.randomnessBN); } } // File: contracts/court/config/IConfig.sol pragma solidity ^0.5.8; interface IConfig { /** * @dev Tell the full Court configuration parameters at a certain term * @param _termId Identification number of the term querying the Court config of * @return token Address of the token used to pay for fees * @return fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @return roundStateDurations Array containing the durations in terms of the different phases of a dispute: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * @return pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @return roundParams Array containing params for rounds: * 0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * @return appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal * @return minActiveBalance Minimum amount of tokens jurors have to activate to participate in the Court */ function getConfig(uint64 _termId) external view returns ( ERC20 feeToken, uint256[3] memory fees, uint64[5] memory roundStateDurations, uint16[2] memory pcts, uint64[4] memory roundParams, uint256[2] memory appealCollateralParams, uint256 minActiveBalance ); /** * @dev Tell the draft config at a certain term * @param _termId Identification number of the term querying the draft config of * @return feeToken Address of the token used to pay for fees * @return draftFee Amount of fee tokens per juror to cover the drafting cost * @return penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) */ function getDraftConfig(uint64 _termId) external view returns (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct); /** * @dev Tell the min active balance config at a certain term * @param _termId Term querying the min active balance config of * @return Minimum amount of tokens jurors have to activate to participate in the Court */ function getMinActiveBalance(uint64 _termId) external view returns (uint256); /** * @dev Tell whether a certain holder accepts automatic withdrawals of tokens or not * @return True if the given holder accepts automatic withdrawals of their tokens, false otherwise */ function areWithdrawalsAllowedFor(address _holder) external view returns (bool); } // File: contracts/court/config/CourtConfigData.sol pragma solidity ^0.5.8; contract CourtConfigData { struct Config { FeesConfig fees; // Full fees-related config DisputesConfig disputes; // Full disputes-related config uint256 minActiveBalance; // Minimum amount of tokens jurors have to activate to participate in the Court } struct FeesConfig { ERC20 token; // ERC20 token to be used for the fees of the Court uint16 finalRoundReduction; // Permyriad of fees reduction applied for final appeal round (‱ - 1/10,000) uint256 jurorFee; // Amount of tokens paid to draft a juror to adjudicate a dispute uint256 draftFee; // Amount of tokens paid per round to cover the costs of drafting jurors uint256 settleFee; // Amount of tokens paid per round to cover the costs of slashing jurors } struct DisputesConfig { uint64 evidenceTerms; // Max submitting evidence period duration in terms uint64 commitTerms; // Committing period duration in terms uint64 revealTerms; // Revealing period duration in terms uint64 appealTerms; // Appealing period duration in terms uint64 appealConfirmTerms; // Confirmation appeal period duration in terms uint16 penaltyPct; // Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) uint64 firstRoundJurorsNumber; // Number of jurors drafted on first round uint64 appealStepFactor; // Factor in which the jurors number is increased on each appeal uint64 finalRoundLockTerms; // Period a coherent juror in the final round will remain locked uint256 maxRegularAppealRounds; // Before the final appeal uint256 appealCollateralFactor; // Permyriad multiple of dispute fees required to appeal a preliminary ruling (‱ - 1/10,000) uint256 appealConfirmCollateralFactor; // Permyriad multiple of dispute fees required to confirm appeal (‱ - 1/10,000) } struct DraftConfig { ERC20 feeToken; // ERC20 token to be used for the fees of the Court uint16 penaltyPct; // Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) uint256 draftFee; // Amount of tokens paid per round to cover the costs of drafting jurors } } // File: contracts/court/config/CourtConfig.sol pragma solidity ^0.5.8; contract CourtConfig is IConfig, CourtConfigData { using SafeMath64 for uint64; using PctHelpers for uint256; string private constant ERROR_TOO_OLD_TERM = "CONF_TOO_OLD_TERM"; string private constant ERROR_INVALID_PENALTY_PCT = "CONF_INVALID_PENALTY_PCT"; string private constant ERROR_INVALID_FINAL_ROUND_REDUCTION_PCT = "CONF_INVALID_FINAL_ROUND_RED_PCT"; string private constant ERROR_INVALID_MAX_APPEAL_ROUNDS = "CONF_INVALID_MAX_APPEAL_ROUNDS"; string private constant ERROR_LARGE_ROUND_PHASE_DURATION = "CONF_LARGE_ROUND_PHASE_DURATION"; string private constant ERROR_BAD_INITIAL_JURORS_NUMBER = "CONF_BAD_INITIAL_JURORS_NUMBER"; string private constant ERROR_BAD_APPEAL_STEP_FACTOR = "CONF_BAD_APPEAL_STEP_FACTOR"; string private constant ERROR_ZERO_COLLATERAL_FACTOR = "CONF_ZERO_COLLATERAL_FACTOR"; string private constant ERROR_ZERO_MIN_ACTIVE_BALANCE = "CONF_ZERO_MIN_ACTIVE_BALANCE"; // Max number of terms that each of the different adjudication states can last (if lasted 1h, this would be a year) uint64 internal constant MAX_ADJ_STATE_DURATION = 8670; // Cap the max number of regular appeal rounds uint256 internal constant MAX_REGULAR_APPEAL_ROUNDS_LIMIT = 10; // Future term ID in which a config change has been scheduled uint64 private configChangeTermId; // List of all the configs used in the Court Config[] private configs; // List of configs indexed by id mapping (uint64 => uint256) private configIdByTerm; // Holders opt-in config for automatic withdrawals mapping (address => bool) private withdrawalsAllowed; event NewConfig(uint64 fromTermId, uint64 courtConfigId); event AutomaticWithdrawalsAllowedChanged(address indexed holder, bool allowed); /** * @dev Constructor function * @param _feeToken Address of the token contract that is used to pay for fees * @param _fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @param _roundStateDurations Array containing the durations in terms of the different phases of a dispute: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * @param _pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @param _roundParams Array containing params for rounds: * 0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 3. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @param _appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal * @param _minActiveBalance Minimum amount of juror tokens that can be activated */ constructor( ERC20 _feeToken, uint256[3] memory _fees, uint64[5] memory _roundStateDurations, uint16[2] memory _pcts, uint64[4] memory _roundParams, uint256[2] memory _appealCollateralParams, uint256 _minActiveBalance ) public { // Leave config at index 0 empty for non-scheduled config changes configs.length = 1; _setConfig( 0, 0, _feeToken, _fees, _roundStateDurations, _pcts, _roundParams, _appealCollateralParams, _minActiveBalance ); } /** * @notice Set the automatic withdrawals config for the sender to `_allowed` * @param _allowed Whether or not the automatic withdrawals are allowed by the sender */ function setAutomaticWithdrawals(bool _allowed) external { withdrawalsAllowed[msg.sender] = _allowed; emit AutomaticWithdrawalsAllowedChanged(msg.sender, _allowed); } /** * @dev Tell the full Court configuration parameters at a certain term * @param _termId Identification number of the term querying the Court config of * @return token Address of the token used to pay for fees * @return fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @return roundStateDurations Array containing the durations in terms of the different phases of a dispute: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * @return pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @return roundParams Array containing params for rounds: * 0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * @return appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal * @return minActiveBalance Minimum amount of tokens jurors have to activate to participate in the Court */ function getConfig(uint64 _termId) external view returns ( ERC20 feeToken, uint256[3] memory fees, uint64[5] memory roundStateDurations, uint16[2] memory pcts, uint64[4] memory roundParams, uint256[2] memory appealCollateralParams, uint256 minActiveBalance ); /** * @dev Tell the draft config at a certain term * @param _termId Identification number of the term querying the draft config of * @return feeToken Address of the token used to pay for fees * @return draftFee Amount of fee tokens per juror to cover the drafting cost * @return penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) */ function getDraftConfig(uint64 _termId) external view returns (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct); /** * @dev Tell the min active balance config at a certain term * @param _termId Term querying the min active balance config of * @return Minimum amount of tokens jurors have to activate to participate in the Court */ function getMinActiveBalance(uint64 _termId) external view returns (uint256); /** * @dev Tell whether a certain holder accepts automatic withdrawals of tokens or not * @param _holder Address of the token holder querying if withdrawals are allowed for * @return True if the given holder accepts automatic withdrawals of their tokens, false otherwise */ function areWithdrawalsAllowedFor(address _holder) external view returns (bool) { return withdrawalsAllowed[_holder]; } /** * @dev Tell the term identification number of the next scheduled config change * @return Term identification number of the next scheduled config change */ function getConfigChangeTermId() external view returns (uint64) { return configChangeTermId; } /** * @dev Internal to make sure to set a config for the new term, it will copy the previous term config if none * @param _termId Identification number of the new current term that has been transitioned */ function _ensureTermConfig(uint64 _termId) internal { // If the term being transitioned had no config change scheduled, keep the previous one uint256 currentConfigId = configIdByTerm[_termId]; if (currentConfigId == 0) { uint256 previousConfigId = configIdByTerm[_termId.sub(1)]; configIdByTerm[_termId] = previousConfigId; } } /** * @dev Assumes that sender it's allowed (either it's from governor or it's on init) * @param _termId Identification number of the current Court term * @param _fromTermId Identification number of the term in which the config will be effective at * @param _feeToken Address of the token contract that is used to pay for fees. * @param _fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @param _roundStateDurations Array containing the durations in terms of the different phases of a dispute: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * @param _pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @param _roundParams Array containing params for rounds: * 0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 3. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @param _appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal * @param _minActiveBalance Minimum amount of juror tokens that can be activated */ function _setConfig( uint64 _termId, uint64 _fromTermId, ERC20 _feeToken, uint256[3] memory _fees, uint64[5] memory _roundStateDurations, uint16[2] memory _pcts, uint64[4] memory _roundParams, uint256[2] memory _appealCollateralParams, uint256 _minActiveBalance ) internal { // If the current term is not zero, changes must be scheduled at least after the current period. // No need to ensure delays for on-going disputes since these already use their creation term for that. require(_termId == 0 || _fromTermId > _termId, ERROR_TOO_OLD_TERM); // Make sure appeal collateral factors are greater than zero require(_appealCollateralParams[0] > 0 && _appealCollateralParams[1] > 0, ERROR_ZERO_COLLATERAL_FACTOR); // Make sure the given penalty and final round reduction pcts are not greater than 100% require(PctHelpers.isValid(_pcts[0]), ERROR_INVALID_PENALTY_PCT); require(PctHelpers.isValid(_pcts[1]), ERROR_INVALID_FINAL_ROUND_REDUCTION_PCT); // Disputes must request at least one juror to be drafted initially require(_roundParams[0] > 0, ERROR_BAD_INITIAL_JURORS_NUMBER); // Prevent that further rounds have zero jurors require(_roundParams[1] > 0, ERROR_BAD_APPEAL_STEP_FACTOR); // Make sure the max number of appeals allowed does not reach the limit uint256 _maxRegularAppealRounds = _roundParams[2]; bool isMaxAppealRoundsValid = _maxRegularAppealRounds > 0 && _maxRegularAppealRounds <= MAX_REGULAR_APPEAL_ROUNDS_LIMIT; require(isMaxAppealRoundsValid, ERROR_INVALID_MAX_APPEAL_ROUNDS); // Make sure each adjudication round phase duration is valid for (uint i = 0; i < _roundStateDurations.length; i++) { require(_roundStateDurations[i] > 0 && _roundStateDurations[i] < MAX_ADJ_STATE_DURATION, ERROR_LARGE_ROUND_PHASE_DURATION); } // Make sure min active balance is not zero require(_minActiveBalance > 0, ERROR_ZERO_MIN_ACTIVE_BALANCE); // If there was a config change already scheduled, reset it (in that case we will overwrite last array item). // Otherwise, schedule a new config. if (configChangeTermId > _termId) { configIdByTerm[configChangeTermId] = 0; } else { configs.length++; } uint64 courtConfigId = uint64(configs.length - 1); Config storage config = configs[courtConfigId]; config.fees = FeesConfig({ token: _feeToken, jurorFee: _fees[0], draftFee: _fees[1], settleFee: _fees[2], finalRoundReduction: _pcts[1] }); config.disputes = DisputesConfig({ evidenceTerms: _roundStateDurations[0], commitTerms: _roundStateDurations[1], revealTerms: _roundStateDurations[2], appealTerms: _roundStateDurations[3], appealConfirmTerms: _roundStateDurations[4], penaltyPct: _pcts[0], firstRoundJurorsNumber: _roundParams[0], appealStepFactor: _roundParams[1], maxRegularAppealRounds: _maxRegularAppealRounds, finalRoundLockTerms: _roundParams[3], appealCollateralFactor: _appealCollateralParams[0], appealConfirmCollateralFactor: _appealCollateralParams[1] }); config.minActiveBalance = _minActiveBalance; configIdByTerm[_fromTermId] = courtConfigId; configChangeTermId = _fromTermId; emit NewConfig(_fromTermId, courtConfigId); } /** * @dev Internal function to get the Court config for a given term * @param _termId Identification number of the term querying the Court config of * @param _lastEnsuredTermId Identification number of the last ensured term of the Court * @return token Address of the token used to pay for fees * @return fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @return roundStateDurations Array containing the durations in terms of the different phases of a dispute: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * @return pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @return roundParams Array containing params for rounds: * 0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 3. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @return appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal * @return minActiveBalance Minimum amount of juror tokens that can be activated */ function _getConfigAt(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns ( ERC20 feeToken, uint256[3] memory fees, uint64[5] memory roundStateDurations, uint16[2] memory pcts, uint64[4] memory roundParams, uint256[2] memory appealCollateralParams, uint256 minActiveBalance ) { Config storage config = _getConfigFor(_termId, _lastEnsuredTermId); FeesConfig storage feesConfig = config.fees; feeToken = feesConfig.token; fees = [feesConfig.jurorFee, feesConfig.draftFee, feesConfig.settleFee]; DisputesConfig storage disputesConfig = config.disputes; roundStateDurations = [ disputesConfig.evidenceTerms, disputesConfig.commitTerms, disputesConfig.revealTerms, disputesConfig.appealTerms, disputesConfig.appealConfirmTerms ]; pcts = [disputesConfig.penaltyPct, feesConfig.finalRoundReduction]; roundParams = [ disputesConfig.firstRoundJurorsNumber, disputesConfig.appealStepFactor, uint64(disputesConfig.maxRegularAppealRounds), disputesConfig.finalRoundLockTerms ]; appealCollateralParams = [disputesConfig.appealCollateralFactor, disputesConfig.appealConfirmCollateralFactor]; minActiveBalance = config.minActiveBalance; } /** * @dev Tell the draft config at a certain term * @param _termId Identification number of the term querying the draft config of * @param _lastEnsuredTermId Identification number of the last ensured term of the Court * @return feeToken Address of the token used to pay for fees * @return draftFee Amount of fee tokens per juror to cover the drafting cost * @return penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) */ function _getDraftConfig(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct) { Config storage config = _getConfigFor(_termId, _lastEnsuredTermId); return (config.fees.token, config.fees.draftFee, config.disputes.penaltyPct); } /** * @dev Internal function to get the min active balance config for a given term * @param _termId Identification number of the term querying the min active balance config of * @param _lastEnsuredTermId Identification number of the last ensured term of the Court * @return Minimum amount of juror tokens that can be activated at the given term */ function _getMinActiveBalance(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns (uint256) { Config storage config = _getConfigFor(_termId, _lastEnsuredTermId); return config.minActiveBalance; } /** * @dev Internal function to get the Court config for a given term * @param _termId Identification number of the term querying the min active balance config of * @param _lastEnsuredTermId Identification number of the last ensured term of the Court * @return Court config for the given term */ function _getConfigFor(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns (Config storage) { uint256 id = _getConfigIdFor(_termId, _lastEnsuredTermId); return configs[id]; } /** * @dev Internal function to get the Court config ID for a given term * @param _termId Identification number of the term querying the Court config of * @param _lastEnsuredTermId Identification number of the last ensured term of the Court * @return Identification number of the config for the given terms */ function _getConfigIdFor(uint64 _termId, uint64 _lastEnsuredTermId) internal view returns (uint256) { // If the given term is lower or equal to the last ensured Court term, it is safe to use a past Court config if (_termId <= _lastEnsuredTermId) { return configIdByTerm[_termId]; } // If the given term is in the future but there is a config change scheduled before it, use the incoming config uint64 scheduledChangeTermId = configChangeTermId; if (scheduledChangeTermId <= _termId) { return configIdByTerm[scheduledChangeTermId]; } // If no changes are scheduled, use the Court config of the last ensured term return configIdByTerm[_lastEnsuredTermId]; } } // File: contracts/court/controller/Controller.sol pragma solidity ^0.5.8; contract Controller is IsContract, CourtClock, CourtConfig { string private constant ERROR_SENDER_NOT_GOVERNOR = "CTR_SENDER_NOT_GOVERNOR"; string private constant ERROR_INVALID_GOVERNOR_ADDRESS = "CTR_INVALID_GOVERNOR_ADDRESS"; string private constant ERROR_IMPLEMENTATION_NOT_CONTRACT = "CTR_IMPLEMENTATION_NOT_CONTRACT"; string private constant ERROR_INVALID_IMPLS_INPUT_LENGTH = "CTR_INVALID_IMPLS_INPUT_LENGTH"; address private constant ZERO_ADDRESS = address(0); // DisputeManager module ID - keccak256(abi.encodePacked("DISPUTE_MANAGER")) bytes32 internal constant DISPUTE_MANAGER = 0x14a6c70f0f6d449c014c7bbc9e68e31e79e8474fb03b7194df83109a2d888ae6; // Treasury module ID - keccak256(abi.encodePacked("TREASURY")) bytes32 internal constant TREASURY = 0x06aa03964db1f7257357ef09714a5f0ca3633723df419e97015e0c7a3e83edb7; // Voting module ID - keccak256(abi.encodePacked("VOTING")) bytes32 internal constant VOTING = 0x7cbb12e82a6d63ff16fe43977f43e3e2b247ecd4e62c0e340da8800a48c67346; // JurorsRegistry module ID - keccak256(abi.encodePacked("JURORS_REGISTRY")) bytes32 internal constant JURORS_REGISTRY = 0x3b21d36b36308c830e6c4053fb40a3b6d79dde78947fbf6b0accd30720ab5370; // Subscriptions module ID - keccak256(abi.encodePacked("SUBSCRIPTIONS")) bytes32 internal constant SUBSCRIPTIONS = 0x2bfa3327fe52344390da94c32a346eeb1b65a8b583e4335a419b9471e88c1365; /** * @dev Governor of the whole system. Set of three addresses to recover funds, change configuration settings and setup modules */ struct Governor { address funds; // This address can be unset at any time. It is allowed to recover funds from the ControlledRecoverable modules address config; // This address is meant not to be unset. It is allowed to change the different configurations of the whole system address modules; // This address can be unset at any time. It is allowed to plug/unplug modules from the system } // Governor addresses of the system Governor private governor; // List of modules registered for the system indexed by ID mapping (bytes32 => address) internal modules; event ModuleSet(bytes32 id, address addr); event FundsGovernorChanged(address previousGovernor, address currentGovernor); event ConfigGovernorChanged(address previousGovernor, address currentGovernor); event ModulesGovernorChanged(address previousGovernor, address currentGovernor); /** * @dev Ensure the msg.sender is the funds governor */ modifier onlyFundsGovernor { require(msg.sender == governor.funds, ERROR_SENDER_NOT_GOVERNOR); _; } /** * @dev Ensure the msg.sender is the modules governor */ modifier onlyConfigGovernor { require(msg.sender == governor.config, ERROR_SENDER_NOT_GOVERNOR); _; } /** * @dev Ensure the msg.sender is the modules governor */ modifier onlyModulesGovernor { require(msg.sender == governor.modules, ERROR_SENDER_NOT_GOVERNOR); _; } /** * @dev Constructor function * @param _termParams Array containing: * 0. _termDuration Duration in seconds per term * 1. _firstTermStartTime Timestamp in seconds when the court will open (to give time for juror on-boarding) * @param _governors Array containing: * 0. _fundsGovernor Address of the funds governor * 1. _configGovernor Address of the config governor * 2. _modulesGovernor Address of the modules governor * @param _feeToken Address of the token contract that is used to pay for fees * @param _fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @param _roundStateDurations Array containing the durations in terms of the different phases of a dispute: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * @param _pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked to each drafted jurors (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @param _roundParams Array containing params for rounds: * 0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 3. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @param _appealCollateralParams Array containing params for appeal collateral: * 1. appealCollateralFactor Permyriad multiple of dispute fees required to appeal a preliminary ruling * 2. appealConfirmCollateralFactor Permyriad multiple of dispute fees required to confirm appeal * @param _minActiveBalance Minimum amount of juror tokens that can be activated */ constructor( uint64[2] memory _termParams, address[3] memory _governors, ERC20 _feeToken, uint256[3] memory _fees, uint64[5] memory _roundStateDurations, uint16[2] memory _pcts, uint64[4] memory _roundParams, uint256[2] memory _appealCollateralParams, uint256 _minActiveBalance ) public CourtClock(_termParams) CourtConfig(_feeToken, _fees, _roundStateDurations, _pcts, _roundParams, _appealCollateralParams, _minActiveBalance) { _setFundsGovernor(_governors[0]); _setConfigGovernor(_governors[1]); _setModulesGovernor(_governors[2]); } /** * @notice Change Court configuration params * @param _fromTermId Identification number of the term in which the config will be effective at * @param _feeToken Address of the token contract that is used to pay for fees * @param _fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @param _roundStateDurations Array containing the durations in terms of the different phases of a dispute: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * @param _pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked to each drafted jurors (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @param _roundParams Array containing params for rounds: * 0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 3. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @param _appealCollateralParams Array containing params for appeal collateral: * 1. appealCollateralFactor Permyriad multiple of dispute fees required to appeal a preliminary ruling * 2. appealConfirmCollateralFactor Permyriad multiple of dispute fees required to confirm appeal * @param _minActiveBalance Minimum amount of juror tokens that can be activated */ function setConfig( uint64 _fromTermId, ERC20 _feeToken, uint256[3] calldata _fees, uint64[5] calldata _roundStateDurations, uint16[2] calldata _pcts, uint64[4] calldata _roundParams, uint256[2] calldata _appealCollateralParams, uint256 _minActiveBalance ) external onlyConfigGovernor { uint64 currentTermId = _ensureCurrentTerm(); _setConfig( currentTermId, _fromTermId, _feeToken, _fees, _roundStateDurations, _pcts, _roundParams, _appealCollateralParams, _minActiveBalance ); } /** * @notice Delay the Court start time to `_newFirstTermStartTime` * @param _newFirstTermStartTime New timestamp in seconds when the court will open */ function delayStartTime(uint64 _newFirstTermStartTime) external onlyConfigGovernor { _delayStartTime(_newFirstTermStartTime); } /** * @notice Change funds governor address to `_newFundsGovernor` * @param _newFundsGovernor Address of the new funds governor to be set */ function changeFundsGovernor(address _newFundsGovernor) external onlyFundsGovernor { require(_newFundsGovernor != ZERO_ADDRESS, ERROR_INVALID_GOVERNOR_ADDRESS); _setFundsGovernor(_newFundsGovernor); } /** * @notice Change config governor address to `_newConfigGovernor` * @param _newConfigGovernor Address of the new config governor to be set */ function changeConfigGovernor(address _newConfigGovernor) external onlyConfigGovernor { require(_newConfigGovernor != ZERO_ADDRESS, ERROR_INVALID_GOVERNOR_ADDRESS); _setConfigGovernor(_newConfigGovernor); } /** * @notice Change modules governor address to `_newModulesGovernor` * @param _newModulesGovernor Address of the new governor to be set */ function changeModulesGovernor(address _newModulesGovernor) external onlyModulesGovernor { require(_newModulesGovernor != ZERO_ADDRESS, ERROR_INVALID_GOVERNOR_ADDRESS); _setModulesGovernor(_newModulesGovernor); } /** * @notice Remove the funds governor. Set the funds governor to the zero address. * @dev This action cannot be rolled back, once the funds governor has been unset, funds cannot be recovered from recoverable modules anymore */ function ejectFundsGovernor() external onlyFundsGovernor { _setFundsGovernor(ZERO_ADDRESS); } /** * @notice Remove the modules governor. Set the modules governor to the zero address. * @dev This action cannot be rolled back, once the modules governor has been unset, system modules cannot be changed anymore */ function ejectModulesGovernor() external onlyModulesGovernor { _setModulesGovernor(ZERO_ADDRESS); } /** * @notice Set module `_id` to `_addr` * @param _id ID of the module to be set * @param _addr Address of the module to be set */ function setModule(bytes32 _id, address _addr) external onlyModulesGovernor { _setModule(_id, _addr); } /** * @notice Set many modules at once * @param _ids List of ids of each module to be set * @param _addresses List of addressed of each the module to be set */ function setModules(bytes32[] calldata _ids, address[] calldata _addresses) external onlyModulesGovernor { require(_ids.length == _addresses.length, ERROR_INVALID_IMPLS_INPUT_LENGTH); for (uint256 i = 0; i < _ids.length; i++) { _setModule(_ids[i], _addresses[i]); } } /** * @dev Tell the full Court configuration parameters at a certain term * @param _termId Identification number of the term querying the Court config of * @return token Address of the token used to pay for fees * @return fees Array containing: * 0. jurorFee Amount of fee tokens that is paid per juror per dispute * 1. draftFee Amount of fee tokens per juror to cover the drafting cost * 2. settleFee Amount of fee tokens per juror to cover round settlement cost * @return roundStateDurations Array containing the durations in terms of the different phases of a dispute: * 0. evidenceTerms Max submitting evidence period duration in terms * 1. commitTerms Commit period duration in terms * 2. revealTerms Reveal period duration in terms * 3. appealTerms Appeal period duration in terms * 4. appealConfirmationTerms Appeal confirmation period duration in terms * @return pcts Array containing: * 0. penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) * 1. finalRoundReduction Permyriad of fee reduction for the last appeal round (‱ - 1/10,000) * @return roundParams Array containing params for rounds: * 0. firstRoundJurorsNumber Number of jurors to be drafted for the first round of disputes * 1. appealStepFactor Increasing factor for the number of jurors of each round of a dispute * 2. maxRegularAppealRounds Number of regular appeal rounds before the final round is triggered * 3. finalRoundLockTerms Number of terms that a coherent juror in a final round is disallowed to withdraw (to prevent 51% attacks) * @return appealCollateralParams Array containing params for appeal collateral: * 0. appealCollateralFactor Multiple of dispute fees required to appeal a preliminary ruling * 1. appealConfirmCollateralFactor Multiple of dispute fees required to confirm appeal */ function getConfig(uint64 _termId) external view returns ( ERC20 feeToken, uint256[3] memory fees, uint64[5] memory roundStateDurations, uint16[2] memory pcts, uint64[4] memory roundParams, uint256[2] memory appealCollateralParams, uint256 minActiveBalance ) { uint64 lastEnsuredTermId = _lastEnsuredTermId(); return _getConfigAt(_termId, lastEnsuredTermId); } /** * @dev Tell the draft config at a certain term * @param _termId Identification number of the term querying the draft config of * @return feeToken Address of the token used to pay for fees * @return draftFee Amount of fee tokens per juror to cover the drafting cost * @return penaltyPct Permyriad of min active tokens balance to be locked for each drafted juror (‱ - 1/10,000) */ function getDraftConfig(uint64 _termId) external view returns (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct) { uint64 lastEnsuredTermId = _lastEnsuredTermId(); return _getDraftConfig(_termId, lastEnsuredTermId); } /** * @dev Tell the min active balance config at a certain term * @param _termId Identification number of the term querying the min active balance config of * @return Minimum amount of tokens jurors have to activate to participate in the Court */ function getMinActiveBalance(uint64 _termId) external view returns (uint256) { uint64 lastEnsuredTermId = _lastEnsuredTermId(); return _getMinActiveBalance(_termId, lastEnsuredTermId); } /** * @dev Tell the address of the funds governor * @return Address of the funds governor */ function getFundsGovernor() external view returns (address) { return governor.funds; } /** * @dev Tell the address of the config governor * @return Address of the config governor */ function getConfigGovernor() external view returns (address) { return governor.config; } /** * @dev Tell the address of the modules governor * @return Address of the modules governor */ function getModulesGovernor() external view returns (address) { return governor.modules; } /** * @dev Tell address of a module based on a given ID * @param _id ID of the module being queried * @return Address of the requested module */ function getModule(bytes32 _id) external view returns (address) { return _getModule(_id); } /** * @dev Tell the address of the DisputeManager module * @return Address of the DisputeManager module */ function getDisputeManager() external view returns (address) { return _getDisputeManager(); } /** * @dev Tell the address of the Treasury module * @return Address of the Treasury module */ function getTreasury() external view returns (address) { return _getModule(TREASURY); } /** * @dev Tell the address of the Voting module * @return Address of the Voting module */ function getVoting() external view returns (address) { return _getModule(VOTING); } /** * @dev Tell the address of the JurorsRegistry module * @return Address of the JurorsRegistry module */ function getJurorsRegistry() external view returns (address) { return _getModule(JURORS_REGISTRY); } /** * @dev Tell the address of the Subscriptions module * @return Address of the Subscriptions module */ function getSubscriptions() external view returns (address) { return _getSubscriptions(); } /** * @dev Internal function to set the address of the funds governor * @param _newFundsGovernor Address of the new config governor to be set */ function _setFundsGovernor(address _newFundsGovernor) internal { emit FundsGovernorChanged(governor.funds, _newFundsGovernor); governor.funds = _newFundsGovernor; } /** * @dev Internal function to set the address of the config governor * @param _newConfigGovernor Address of the new config governor to be set */ function _setConfigGovernor(address _newConfigGovernor) internal { emit ConfigGovernorChanged(governor.config, _newConfigGovernor); governor.config = _newConfigGovernor; } /** * @dev Internal function to set the address of the modules governor * @param _newModulesGovernor Address of the new modules governor to be set */ function _setModulesGovernor(address _newModulesGovernor) internal { emit ModulesGovernorChanged(governor.modules, _newModulesGovernor); governor.modules = _newModulesGovernor; } /** * @dev Internal function to set a module * @param _id Id of the module to be set * @param _addr Address of the module to be set */ function _setModule(bytes32 _id, address _addr) internal { require(isContract(_addr), ERROR_IMPLEMENTATION_NOT_CONTRACT); modules[_id] = _addr; emit ModuleSet(_id, _addr); } /** * @dev Internal function to notify when a term has been transitioned * @param _termId Identification number of the new current term that has been transitioned */ function _onTermTransitioned(uint64 _termId) internal { _ensureTermConfig(_termId); } /** * @dev Internal function to tell the address of the DisputeManager module * @return Address of the DisputeManager module */ function _getDisputeManager() internal view returns (address) { return _getModule(DISPUTE_MANAGER); } /** * @dev Internal function to tell the address of the Subscriptions module * @return Address of the Subscriptions module */ function _getSubscriptions() internal view returns (address) { return _getModule(SUBSCRIPTIONS); } /** * @dev Internal function to tell address of a module based on a given ID * @param _id ID of the module being queried * @return Address of the requested module */ function _getModule(bytes32 _id) internal view returns (address) { return modules[_id]; } } // File: contracts/court/config/ConfigConsumer.sol pragma solidity ^0.5.8; contract ConfigConsumer is CourtConfigData { /** * @dev Internal function to fetch the address of the Config module from the controller * @return Address of the Config module */ function _courtConfig() internal view returns (IConfig); /** * @dev Internal function to get the Court config for a certain term * @param _termId Identification number of the term querying the Court config of * @return Court config for the given term */ function _getConfigAt(uint64 _termId) internal view returns (Config memory) { (ERC20 _feeToken, uint256[3] memory _fees, uint64[5] memory _roundStateDurations, uint16[2] memory _pcts, uint64[4] memory _roundParams, uint256[2] memory _appealCollateralParams, uint256 _minActiveBalance) = _courtConfig().getConfig(_termId); Config memory config; config.fees = FeesConfig({ token: _feeToken, jurorFee: _fees[0], draftFee: _fees[1], settleFee: _fees[2], finalRoundReduction: _pcts[1] }); config.disputes = DisputesConfig({ evidenceTerms: _roundStateDurations[0], commitTerms: _roundStateDurations[1], revealTerms: _roundStateDurations[2], appealTerms: _roundStateDurations[3], appealConfirmTerms: _roundStateDurations[4], penaltyPct: _pcts[0], firstRoundJurorsNumber: _roundParams[0], appealStepFactor: _roundParams[1], maxRegularAppealRounds: _roundParams[2], finalRoundLockTerms: _roundParams[3], appealCollateralFactor: _appealCollateralParams[0], appealConfirmCollateralFactor: _appealCollateralParams[1] }); config.minActiveBalance = _minActiveBalance; return config; } /** * @dev Internal function to get the draft config for a given term * @param _termId Identification number of the term querying the draft config of * @return Draft config for the given term */ function _getDraftConfig(uint64 _termId) internal view returns (DraftConfig memory) { (ERC20 feeToken, uint256 draftFee, uint16 penaltyPct) = _courtConfig().getDraftConfig(_termId); return DraftConfig({ feeToken: feeToken, draftFee: draftFee, penaltyPct: penaltyPct }); } /** * @dev Internal function to get the min active balance config for a given term * @param _termId Identification number of the term querying the min active balance config of * @return Minimum amount of juror tokens that can be activated */ function _getMinActiveBalance(uint64 _termId) internal view returns (uint256) { return _courtConfig().getMinActiveBalance(_termId); } } // File: contracts/court/controller/Controlled.sol pragma solidity ^0.5.8; contract Controlled is IsContract, ConfigConsumer { string private constant ERROR_CONTROLLER_NOT_CONTRACT = "CTD_CONTROLLER_NOT_CONTRACT"; string private constant ERROR_SENDER_NOT_CONTROLLER = "CTD_SENDER_NOT_CONTROLLER"; string private constant ERROR_SENDER_NOT_CONFIG_GOVERNOR = "CTD_SENDER_NOT_CONFIG_GOVERNOR"; string private constant ERROR_SENDER_NOT_DISPUTES_MODULE = "CTD_SENDER_NOT_DISPUTES_MODULE"; // Address of the controller Controller internal controller; /** * @dev Ensure the msg.sender is the controller's config governor */ modifier onlyConfigGovernor { require(msg.sender == _configGovernor(), ERROR_SENDER_NOT_CONFIG_GOVERNOR); _; } /** * @dev Ensure the msg.sender is the controller */ modifier onlyController() { require(msg.sender == address(controller), ERROR_SENDER_NOT_CONTROLLER); _; } /** * @dev Ensure the msg.sender is the DisputeManager module */ modifier onlyDisputeManager() { require(msg.sender == address(_disputeManager()), ERROR_SENDER_NOT_DISPUTES_MODULE); _; } /** * @dev Constructor function * @param _controller Address of the controller */ constructor(Controller _controller) public { require(isContract(address(_controller)), ERROR_CONTROLLER_NOT_CONTRACT); controller = _controller; } /** * @dev Tell the address of the controller * @return Address of the controller */ function getController() external view returns (Controller) { return controller; } /** * @dev Internal function to ensure the Court term is up-to-date, it will try to update it if not * @return Identification number of the current Court term */ function _ensureCurrentTerm() internal returns (uint64) { return _clock().ensureCurrentTerm(); } /** * @dev Internal function to fetch the last ensured term ID of the Court * @return Identification number of the last ensured term */ function _getLastEnsuredTermId() internal view returns (uint64) { return _clock().getLastEnsuredTermId(); } /** * @dev Internal function to tell the current term identification number * @return Identification number of the current term */ function _getCurrentTermId() internal view returns (uint64) { return _clock().getCurrentTermId(); } /** * @dev Internal function to fetch the controller's config governor * @return Address of the controller's governor */ function _configGovernor() internal view returns (address) { return controller.getConfigGovernor(); } /** * @dev Internal function to fetch the address of the DisputeManager module from the controller * @return Address of the DisputeManager module */ function _disputeManager() internal view returns (IDisputeManager) { return IDisputeManager(controller.getDisputeManager()); } /** * @dev Internal function to fetch the address of the Treasury module implementation from the controller * @return Address of the Treasury module implementation */ function _treasury() internal view returns (ITreasury) { return ITreasury(controller.getTreasury()); } /** * @dev Internal function to fetch the address of the Voting module implementation from the controller * @return Address of the Voting module implementation */ function _voting() internal view returns (ICRVoting) { return ICRVoting(controller.getVoting()); } /** * @dev Internal function to fetch the address of the Voting module owner from the controller * @return Address of the Voting module owner */ function _votingOwner() internal view returns (ICRVotingOwner) { return ICRVotingOwner(address(_disputeManager())); } /** * @dev Internal function to fetch the address of the JurorRegistry module implementation from the controller * @return Address of the JurorRegistry module implementation */ function _jurorsRegistry() internal view returns (IJurorsRegistry) { return IJurorsRegistry(controller.getJurorsRegistry()); } /** * @dev Internal function to fetch the address of the Subscriptions module implementation from the controller * @return Address of the Subscriptions module implementation */ function _subscriptions() internal view returns (ISubscriptions) { return ISubscriptions(controller.getSubscriptions()); } /** * @dev Internal function to fetch the address of the Clock module from the controller * @return Address of the Clock module */ function _clock() internal view returns (IClock) { return IClock(controller); } /** * @dev Internal function to fetch the address of the Config module from the controller * @return Address of the Config module */ function _courtConfig() internal view returns (IConfig) { return IConfig(controller); } } // File: contracts/court/controller/ControlledRecoverable.sol pragma solidity ^0.5.8; contract ControlledRecoverable is Controlled { using SafeERC20 for ERC20; string private constant ERROR_SENDER_NOT_FUNDS_GOVERNOR = "CTD_SENDER_NOT_FUNDS_GOVERNOR"; string private constant ERROR_INSUFFICIENT_RECOVER_FUNDS = "CTD_INSUFFICIENT_RECOVER_FUNDS"; string private constant ERROR_RECOVER_TOKEN_FUNDS_FAILED = "CTD_RECOVER_TOKEN_FUNDS_FAILED"; event RecoverFunds(ERC20 token, address recipient, uint256 balance); /** * @dev Ensure the msg.sender is the controller's funds governor */ modifier onlyFundsGovernor { require(msg.sender == controller.getFundsGovernor(), ERROR_SENDER_NOT_FUNDS_GOVERNOR); _; } /** * @dev Constructor function * @param _controller Address of the controller */ constructor(Controller _controller) Controlled(_controller) public { // solium-disable-previous-line no-empty-blocks } /** * @notice Transfer all `_token` tokens to `_to` * @param _token ERC20 token to be recovered * @param _to Address of the recipient that will be receive all the funds of the requested token */ function recoverFunds(ERC20 _token, address _to) external onlyFundsGovernor { uint256 balance = _token.balanceOf(address(this)); require(balance > 0, ERROR_INSUFFICIENT_RECOVER_FUNDS); require(_token.safeTransfer(_to, balance), ERROR_RECOVER_TOKEN_FUNDS_FAILED); emit RecoverFunds(_token, _to, balance); } } // File: contracts/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_SENDER_NOT_DISPUTE_SUBJECT = "DM_SENDER_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_SUBSCRIPTION_NOT_PAID = "DM_SUBSCRIPTION_NOT_PAID"; 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; // Maximum possible rulings for a dispute, equal to minimum limit uint8 internal constant MAX_RULING_OPTIONS = MIN_RULING_OPTIONS; // 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 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(); require(_possibleRulings >= MIN_RULING_OPTIONS && _possibleRulings <= MAX_RULING_OPTIONS, 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; Config memory config = _getConfigAt(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 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_SENDER_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.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.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.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.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":"_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":"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
60806040523480156200001157600080fd5b50604051606080620063cd833981018060405260608110156200003357600080fd5b50805160208083015160409093015191929190839081906200005b90829062000186811b901c565b6040518060400160405280601b81526020017f4354445f434f4e54524f4c4c45525f4e4f545f434f4e545241435400000000008152509062000138576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620000fc578181015183820152602001620000e2565b50505050905090810190601f1680156200012a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600080546001600160a01b0319166001600160a01b0392909216919091179055506200016c82620001ab602090811b901c565b6200017d81620002ef60201b60201c565b50505062000467565b60006001600160a01b038216620001a057506000620001a6565b50803b15155b919050565b60408051808201909152601b81527f444d5f4241445f4d41585f44524146545f42415443485f53495a45000000000060208201526001600160401b03821662000251576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315620000fc578181015183820152602001620000e2565b50600054604080516001600160401b037401000000000000000000000000000000000000000090930483168152918316602083015280517fed22db0c227e21d249167e5f9d39415fd9386958f122075463fef70fd46c95c49281900390910190a1600080546001600160401b039092167401000000000000000000000000000000000000000002600160a01b600160e01b0319909216919091179055565b60015415620002fa57fe5b80620003086001826200030c565b5050565b8154818355818111156200033b576002028160020283600052602060002091820191016200033b919062000340565b505050565b6200039591905b80821115620003915780547fff00000000000000000000000000000000000000000000000000000000000000168155600062000387600183018262000398565b5060020162000347565b5090565b90565b5080546000825560080290600052602060002090810190620003bb9190620003be565b50565b6200039591905b80821115620003915780546001600160881b0319168155600060018201819055620003f4600283018262000430565b5060006004820181905560058201556006810180546001600160a81b03191690556007810180546001600160b01b0319169055600801620003c5565b5080546000825590600052602060002090810190620003bb91906200039591905b8082111562000391576000815560010162000451565b615f5680620004776000396000f3fe608060405234801561001057600080fd5b50600436106101815760003560e01c80637263bf2a116100d8578063bd881e531161008c578063cd604ada11610066578063cd604ada146105ef578063e3a96cbd1461067a578063eed04b80146106f757610181565b8063bd881e5314610555578063c1361a7c14610597578063c39c83d1146105c357610181565b806382a8b3b0116100bd57806382a8b3b0146104ce578063859ba187146105005780639c0065f71461052957610181565b80637263bf2a146104425780637b751b9e146104a357610181565b806324ae6a271161013a57806339ec68a31161011457806339ec68a3146103355780634b4acfd3146103cf578063710cf1ed1461042557610181565b806324ae6a27146102be5780633018205f146102ec5780633238f8f41461031057610181565b80630d03d1261161016b5780630d03d126146101db57806315fe5268146102075780631d2fa1fb1461022457610181565b80629230a51461018657806306349cfa146101af575b600080fd5b6101ad6004803603602081101561019c57600080fd5b503567ffffffffffffffff1661071a565b005b6101ad600480360360408110156101c557600080fd5b50803590602001356001600160a01b0316610805565b6101ad600480360360608110156101f157600080fd5b508035906020810135906040013560ff16610982565b6101ad6004803603602081101561021d57600080fd5b5035610c80565b6102ac6004803603606081101561023a57600080fd5b6001600160a01b038235169160ff6020820135169181019060608101604082013564010000000081111561026d57600080fd5b82018360208201111561027f57600080fd5b803590602001918460018302840111640100000000831117156102a157600080fd5b509092509050610cba565b60408051918252519081900360200190f35b6101ad600480360360408110156102d457600080fd5b506001600160a01b0381358116916020013516610ff2565b6102f46112ff565b604080516001600160a01b039092168252519081900360200190f35b61031861130f565b6040805167ffffffffffffffff9092168252519081900360200190f35b6103586004803603604081101561034b57600080fd5b5080359060200135611326565b6040805167ffffffffffffffff808c1682528a811660208301528981169282019290925287821660608201526080810187905285151560a082015260c0810185905290831660e082015261010081018260058111156103b357fe5b60ff168152602001995050505050505050505060405180910390f35b610401600480360360608110156103e557600080fd5b50803590602081013590604001356001600160a01b031661145b565b6040805167ffffffffffffffff909316835290151560208301528051918290030190f35b6101ad6004803603602081101561043b57600080fd5b50356115e4565b6104656004803603604081101561045857600080fd5b50803590602001356119b3565b604080516001600160a01b03958616815267ffffffffffffffff94851660208201529290941682850152909116606082015290519081900360800190f35b6104ab611a3c565b604080516001600160a01b03909316835260208301919091528051918290030190f35b6101ad600480360360608110156104e457600080fd5b50803590602081013590604001356001600160a01b0316611a81565b6101ad6004803603606081101561051657600080fd5b50803590602081013590604001356120c9565b6101ad6004803603606081101561053f57600080fd5b508035906020810135906040013560ff166124f9565b6105726004803603602081101561056b57600080fd5b503561278b565b604080516001600160a01b03909316835260ff90911660208301528051918290030190f35b610318600480360360408110156105ad57600080fd5b50803590602001356001600160a01b0316612884565b6101ad600480360360408110156105d957600080fd5b506001600160a01b0381351690602001356128f2565b6106126004803603604081101561060557600080fd5b5080359060200135612b84565b6040805167ffffffffffffffff808b1682528916602082015290810187600281111561063a57fe5b60ff1681526001600160a01b039096166020870152506040808601949094526060850192909252608084015260a0830152519081900360c0019350915050f35b6106976004803603602081101561069057600080fd5b5035612cdb565b604080516001600160a01b038816815260ff871660208201529081018560028111156106bf57fe5b60ff90811682529490941660208501525060408084019290925267ffffffffffffffff16606083015251908190036080019350915050f35b6101ad6004803603604081101561070d57600080fd5b5080359060200135612d7f565b61072261333e565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f434f4e4649475f474f5645524e4f520000815250906107f857604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b838110156107bd5781810151838201526020016107a5565b50505050905090810190601f1680156107ea5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50610802816133be565b50565b600061080f6134de565b60408051808201909152601481527f444d5f53454e4445525f4e4f545f564f54494e470000000000000000000000006020820152909150336001600160a01b038316146108a057604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000806108ad8561352d565b915091506108b9615b66565b6108c283613574565b90506108d5838360018460200151613598565b60006108e38484888561365b565b905060008167ffffffffffffffff16116040518060400160405280601481526020017f444d5f564f5445525f5745494748545f5a45524f0000000000000000000000008152509061097857604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5050505050505050565b828261098e82826136af565b60006001868154811061099d57fe5b906000526020600020906002020190506109b5615b66565b6109be82613574565b90506109d1828760038460200151613598565b60006109db6134de565b905060006109e98989613766565b90506000826001600160a01b031663084d72f4836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a3157600080fd5b505afa158015610a45573d6000803e3d6000fd5b505050506040513d6020811015610a5b57600080fd5b5051905060ff80821690891614801590610b065750604080517fe2e7ed9f0000000000000000000000000000000000000000000000000000000081526004810184905260ff8a16602482015290516001600160a01b0385169163e2e7ed9f916044808301926020929190829003018186803b158015610ad957600080fd5b505afa158015610aed573d6000803e3d6000fd5b505050506040513d6020811015610b0357600080fd5b50515b6040518060400160405280601881526020017f444d5f494e56414c49445f41505045414c5f52554c494e47000000000000000081525090610b8b57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000856001018a81548110610b9d57fe5b600091825260209182902060089190910201600681018054337fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b60ff8e16908102919091178255604080519182525192945090928d928f927f57dc4548648c602e9f394f905942ffeba7a2041a6a704128b3a75e5b0efa11a792908290030190a3610c51615b94565b610c5c838d89613770565b9050610c713382606001518360c001516139d1565b50505050505050505050505050565b600080610c8c8361352d565b91509150610c98615b66565b610ca183613574565b9050610cb4838360018460200151613598565b50505050565b6000805460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b03163314610d4c57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000610d57613a8a565b9050600260ff861610801590610d715750600260ff861611155b6040518060400160405280601981526020017f444d5f494e56414c49445f52554c494e475f4f5054494f4e530000000000000081525090610df657604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5060018054600091610e0a90828101615be2565b9050600060018281548110610e1b57fe5b6000918252602090912060029091020180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038a16177fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000060ff8a1602177fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff16600160a01b67ffffffffffffffff8616021781559050610ee0615b66565b610ee984613ae2565b602081015160c0810151905191925090600090610f179067ffffffffffffffff88169063ffffffff613d8f16565b90508067ffffffffffffffff168b6001600160a01b0316867fd4784fc5a2aef689d6639d09cb5b543abfeabd597519d01b93f4ffef74d10396858d8d604051808467ffffffffffffffff1667ffffffffffffffff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a46000806000610fbe866000015186613e31565b925092509250610fd2886000868886613ead565b50610fde8e84836139d1565b50959750505050505050505b949350505050565b6000809054906101000a90046001600160a01b03166001600160a01b0316633c28e88b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561103f57600080fd5b505afa158015611053573d6000803e3d6000fd5b505050506040513d602081101561106957600080fd5b505160408051808201909152601d81527f4354445f53454e4445525f4e4f545f46554e44535f474f5645524e4f520000006020820152906001600160a01b031633146110f957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000916001600160a01b038516916370a0823191602480820192602092909190829003018186803b15801561115d57600080fd5b505afa158015611171573d6000803e3d6000fd5b505050506040513d602081101561118757600080fd5b505160408051808201909152601e81527f4354445f494e53554646494349454e545f5245434f5645525f46554e4453000060208201529091508161120f57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5061122a6001600160a01b038416838363ffffffff61405316565b6040518060400160405280601e81526020017f4354445f5245434f5645525f544f4b454e5f46554e44535f4641494c45440000815250906112af57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50604080516001600160a01b0380861682528416602082015280820183905290517f724139fea3954691c2c1ee02b3be6be1763b32ec84841f1acad6d3a18695ba0d9181900360600190a1505050565b6000546001600160a01b03165b90565b600054600160a01b900467ffffffffffffffff1681565b60008060008060008060008060008a8a61134082826136af565b600060018e8154811061134f57fe5b9060005260206000209060020201905061137e818e61136c6140de565b61137585613574565b60200151614120565b93506000816001018e8154811061139157fe5b906000526020600020906008020190508060000160009054906101000a900467ffffffffffffffff169c508060040160009054906101000a900467ffffffffffffffff169b508060000160089054906101000a900467ffffffffffffffff169a508060040160089054906101000a900467ffffffffffffffff169950806001015498508060000160109054906101000a900460ff1697508060040160109054906101000a900467ffffffffffffffff16955080600501549650505050509295985092959850929598565b600080848461146a82826136af565b60006001888154811061147957fe5b90600052602060002090600202019050600081600101888154811061149a57fe5b906000526020600020906008020190506114b2615b66565b6114bb83613574565b90506114c78982614398565b156114dd576114d682896143a5565b96506115a7565b60006114e76143ce565b8354604080517fe9e67d670000000000000000000000000000000000000000000000000000000081526001600160a01b038d8116600483015267ffffffffffffffff909316602482015290519293506000929184169163e9e67d6791604480820192602092909190829003018186803b15801561156357600080fd5b505afa158015611577573d6000803e3d6000fd5b505050506040513d602081101561158d57600080fd5b505160408401519091506115a290829061441d565b985050505b506001600160a01b039690961660009081526003909601602052505060409093205491956801000000000000000090920460ff1694509092505050565b806115ee81614452565b60006115f86112ff565b905060006116046112ff565b6001600160a01b03166350c365806040518163ffffffff1660e01b815260040160206040518083038186803b15801561163c57600080fd5b505afa158015611650573d6000803e3d6000fd5b505050506040513d602081101561166657600080fd5b505160408051808201909152601081527f444d5f5445524d5f4f5554444154454400000000000000000000000000000000602082015290915067ffffffffffffffff8216156116f957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5060006117046144de565b905060006001868154811061171557fe5b60009182526020822060029091020191508154600160f01b900460ff16600281111561173d57fe5b146040518060400160405280601881526020017f444d5f524f554e445f414c52454144595f445241465445440000000000000000815250906117c357604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50600181018054600019810191600091839081106117dd57fe5b6000918252602091829020600890910201805460408051808201909152601981527f444d5f44524146545f5445524d5f4e4f545f52454143484544000000000000009381019390935290925067ffffffffffffffff9081169190861682111561188a57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000876001600160a01b0316637d1f24c96040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156118c857600080fd5b505af11580156118dc573d6000803e3d6000fd5b505050506040513d60208110156118f257600080fd5b505190506118fe615c0e565b61190783614520565b905060006119218561191c8e898c88886145f5565b614636565b905080156119a55760048501805467ffffffffffffffff1916858a0367ffffffffffffffff1617905586547fff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f01b1787556040516001908d907f9bfdc20780e4912d62e8c31a73ffad5cbd841d7f76d114aa9f302ceca2d8258590600090a35b505050505050505050505050565b60008060008085856119c582826136af565b6000600189815481106119d457fe5b906000526020600020906002020160010188815481106119f057fe5b600091825260209091206006600890920201908101546007909101546001600160a01b038083169c60ff600160a01b9485900481169d509183169b509290910416975095505050505050565b6000806000611a496140de565b9050611a53615b66565b611a5c82613ae2565b9050611a748160000151826020015160c00151613e31565b9196919550909350505050565b8282611a8d82826136af565b600060018681548110611a9c57fe5b906000526020600020906002020190506000816001018681548110611abd57fe5b906000526020600020906008020190508060000160109054906101000a900460ff166040518060400160405280601e81526020017f444d5f524f554e445f50454e414c544945535f4e4f545f534554544c4544000081525090611b6457604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506001600160a01b038516600090815260038201602090815260409182902080548351808501909452601984527f444d5f4a55524f525f414c52454144595f52455741524445440000000000000092840192909252919068010000000000000000900460ff1615611c1957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50805460408051808201909152601e81527f444d5f574f4e545f5245574152445f4e4f4e5f564f5445525f4a55524f52000060208201529067ffffffffffffffff16611ca957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5080547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001781556000611ce56134de565b90506000611cf38a8a613766565b8554604080517fcfa558ba00000000000000000000000000000000000000000000000000000000815260048101849052600160e81b90920460ff1660248301526001600160a01b038b81166044840152905192935084169163cfa558ba91606480820192602092909190829003018186803b158015611d7157600080fd5b505afa158015611d85573d6000803e3d6000fd5b505050506040513d6020811015611d9b57600080fd5b505160408051808201909152601f81527f444d5f574f4e545f5245574152445f494e434f484552454e545f4a55524f5200602082015290611e2057604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5060058401546000611e306143ce565b905060008215611ec057611e45878785614985565b9050816001600160a01b0316634d7edc158c836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611ea757600080fd5b505af1158015611ebb573d6000803e3d6000fd5b505050505b611ec8615b66565b611ed189613574565b90506000611ee489898b60010154614985565b9050611eee6149c5565b6001600160a01b0316635f52d44e8360000151600001518f846040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015611f6f57600080fd5b505af1158015611f83573d6000803e3d6000fd5b50505050611f918e83614398565b61205d57611f9d615c2e565b82602001519050846001600160a01b031663af8b9d0f8f836101000151846040015185602001518f60000160009054906101000a900467ffffffffffffffff160101016040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018267ffffffffffffffff1667ffffffffffffffff16815260200192505050600060405180830381600087803b15801561204357600080fd5b505af1158015612057573d6000803e3d6000fd5b50505050505b8d8f7f3aea41188dba0e19aa929ada5527b70c76ba34b22bb672818cf2ed788c3c9e778f868560405180846001600160a01b03166001600160a01b03168152602001838152602001828152602001935050505060405180910390a3505050505050505050505050505050565b82826120d582826136af565b6000600186815481106120e457fe5b90600052602060002090600202019050846000148061212c575080600101600186038154811061211057fe5b6000918252602090912060089091020154600160801b900460ff165b6040518060400160405280601d81526020017f444d5f50524556494f55535f524f554e445f4e4f545f534554544c4544000000815250906121b157604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5060008160010186815481106121c357fe5b906000526020600020906008020190508060000160109054906101000a900460ff16156040518060400160405280601881526020017f444d5f524f554e445f414c52454144595f534554544c454400000000000000008152509061226b57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50612274615b66565b61227d83613574565b9050600061228c848a84614a14565b9050600061229a8a8a613766565b60048501549091507801000000000000000000000000000000000000000000000000900467ffffffffffffffff1661239a5760006122d66134de565b9050806001600160a01b03166385dbcf7983856040518363ffffffff1660e01b8152600401808381526020018260ff1660ff1681526020019250505060206040518083038186803b15801561232a57600080fd5b505afa15801561233e573d6000803e3d6000fd5b505050506040513d602081101561235457600080fd5b505160048601805467ffffffffffffffff909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909216919091179055505b60006123a46149c5565b8451519091506123b48b86614398565b156124715760006123d5878587896020015160a001518f8b60400151614b76565b9050826001600160a01b0316635f52d44e8333612403858b600001516080015161506090919063ffffffff16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561245357600080fd5b505af1158015612467573d6000803e3d6000fd5b505050505061249e565b85547fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff16600160801b1786555b8554600160801b900460ff16156119a55760058601546040805182815290518d918f917f2f643ff79db9be434873df2e7b4cc272c517e58b5712ea5a20c5d7bfc482f5539181900360200190a3610c7188888e868686615103565b828261250582826136af565b60006001868154811061251457fe5b9060005260206000209060020201905061252c615b66565b61253582613574565b9050612548828760048460200151613598565b600082600101878154811061255957fe5b600091825260208220600890910201915060068201906125798a8a613766565b825490915060ff898116600160a01b909204161480159061261b575061259d6134de565b6001600160a01b031663e2e7ed9f828a6040518363ffffffff1660e01b8152600401808381526020018260ff1660ff1681526020019250505060206040518083038186803b1580156125ee57600080fd5b505afa158015612602573d6000803e3d6000fd5b505050506040513d602081101561261857600080fd5b50515b6040518060400160405280601881526020017f444d5f494e56414c49445f41505045414c5f52554c494e470000000000000000815250906126a057604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506126a9615b94565b6126b4848b87613770565b905060008160400151905060006126da8d83856000015186602001518760a00151613ead565b9050338560010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a8560010160146101000a81548160ff021916908360ff160217905550826000015167ffffffffffffffff16818e7f06c05c98f79e14aad019b270fad6f7d1bcb11dc267667ed908d78e4d5ec9a3eb8660200151604051808267ffffffffffffffff16815260200191505060405180910390a4610c713384606001518560e001516139d1565b6000808261279881614452565b6000600185815481106127a757fe5b6000918252602090912060029091020180546001600160a01b0316945090506127ce615b66565b6127d782613574565b90506127e4828783614a14565b935060028254600160f01b900460ff1660028111156127ff57fe5b1461287c5781547fff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0200000000000000000000000000000000000000000000000000000000000017825560405160ff85169087907f33ebf61f1f1800f29578208d33c8618cf5a27602cd0c4c1978a60651eb531d3b90600090a35b505050915091565b60008060006128928561352d565b9150915061289e615b66565b6128a783613574565b90506128ba838360028460200151613598565b60008360010183815481106128cb57fe5b906000526020600020906008020190506128e581876143a5565b9450505050505b92915050565b60005460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b0316331461298357604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5080600061299182826136af565b6000600184815481106129a057fe5b906000526020600020906002020190506000816001016000815481106129c257fe5b6000918252602091829020845460408051808201909152601d81527f444d5f53454e4445525f4e4f545f444953505554455f5355424a4543540000009481019490945260089092020192506001600160a01b0390811690881614612a6a57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000612a75613a8a565b90506000612a9467ffffffffffffffff8316600163ffffffff613d8f16565b835460408051808201909152601c81527f444d5f45564944454e43455f504552494f445f49535f434c4f53454400000000602082015291925067ffffffffffffffff90811690831610612b2b57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50825467ffffffffffffffff191667ffffffffffffffff8281169190911784556040519083169088907f1384c9abcdf1fa5a2a50953bad79f58ea7b2999fae7783b5b1e2edff339b8d1c90600090a35050505050505050565b600080600080600080600080612b9a8a8a6136af565b600060018b81548110612ba957fe5b90600052602060002090600202019050612bc1615b66565b612bca82613574565b9050612bd68b82614398565b6040518060400160405280601181526020017f444d5f524f554e445f49535f46494e414c00000000000000000000000000000081525090612c5b57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000826001018c81548110612c6d57fe5b90600052602060002090600802019050612c85615b94565b612c90828e85613770565b9050806000015181602001518260400151836060015184608001518560a001518660c001518760e001519b509b509b509b509b509b509b509b50505050509295985092959890939650565b60008060008060008086612cee81614452565b600060018981548110612cfd57fe5b6000918252602090912060029091020180546001909101546001600160a01b0382169b7c0100000000000000000000000000000000000000000000000000000000830460ff9081169c50600160f01b840481169b50600160e81b84041699506000199091019750600160a01b90910467ffffffffffffffff1695509350505050565b8181612d8b82826136af565b600060018581548110612d9a57fe5b906000526020600020906002020190506000816001018581548110612dbb57fe5b906000526020600020906008020190508060000160109054906101000a900460ff166040518060400160405280601e81526020017f444d5f524f554e445f50454e414c544945535f4e4f545f534554544c4544000081525090612e6257604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5060068101612e7081615387565b6040518060400160405280601581526020017f444d5f524f554e445f4e4f545f41505045414c4544000000000000000000000081525090612ef557604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50600181015460408051808201909152601981527f444d5f41505045414c5f414c52454144595f534554544c4544000000000000006020820152907501000000000000000000000000000000000000000000900460ff1615612f9b57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506001810180547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055604051869088907f28d5bc8b3a7bef24e784872d5b3b9069cf63ae040039bcc6040bd0b7af32d2f290600090a3613013615b66565b61301c84613574565b9050613026615b94565b613031848984613770565b6060810151608082015160c083015160e0840151939450919290919060006130576149c5565b905061306288615396565b613102578754604080517f5f52d44e0000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152928316602482015260448101869052905191831691635f52d44e9160648082019260009290919082900301818387803b1580156130db57600080fd5b505af11580156130ef573d6000803e3d6000fd5b5050505050505050505050505050610cb4565b8954600160e81b900460ff16600061311a85856153a8565b8a5490915060ff838116600160a01b9092041614156131c75789546001600160a01b0380851691635f52d44e918a911661315a858b63ffffffff61543516565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b1580156131aa57600080fd5b505af11580156131be573d6000803e3d6000fd5b5050505061332c565b60018a015460ff838116600160a01b90920416141561320a5760018a01546001600160a01b0380851691635f52d44e918a911661315a858b63ffffffff61543516565b895460028704906001600160a01b0385811691635f52d44e918b91166132308a86615435565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561328057600080fd5b505af1158015613294573d6000803e3d6000fd5b50505060018c01546001600160a01b038087169250635f52d44e918b91166132c2898663ffffffff61543516565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561331257600080fd5b505af1158015613326573d6000803e3d6000fd5b50505050505b50505050505050505050505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166397023f816040518163ffffffff1660e01b815260040160206040518083038186803b15801561338d57600080fd5b505afa1580156133a1573d6000803e3d6000fd5b505050506040513d60208110156133b757600080fd5b5051905090565b60408051808201909152601b81527f444d5f4241445f4d41585f44524146545f42415443485f53495a450000000000602082015267ffffffffffffffff821661344b57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000546040805167ffffffffffffffff600160a01b90930483168152918316602083015280517fed22db0c227e21d249167e5f9d39415fd9386958f122075463fef70fd46c95c49281900390910190a16000805467ffffffffffffffff909216600160a01b027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60008060009054906101000a90046001600160a01b03166001600160a01b0316631986d3766040518163ffffffff1660e01b815260040160206040518083038186803b15801561338d57600080fd5b60006fffffffffffffffffffffffffffffffff8216608083901c61355181836136af565b6001818154811061355e57fe5b9060005260206000209060020201925050915091565b61357c615b66565b81546128ec90600160a01b900467ffffffffffffffff16613ae2565b60006135a2613a8a565b905060006135b286868486614120565b90508360058111156135c057fe5b8160058111156135cc57fe5b146040518060400160405280601d81526020017f444d5f494e56414c49445f41444a554449434154494f4e5f53544154450000008152509061365257604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50505050505050565b60008085600101858154811061366d57fe5b906000526020600020906008020190506136878584614398565b61369b576136968382866154c7565b6136a5565b6136a581856143a5565b9695505050505050565b6136b882614452565b600182815481106136c557fe5b90600052602060002090600202016001018054905081106040518060400160405280601781526020017f444d5f524f554e445f444f45535f4e4f545f45584953540000000000000000008152509061376157604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b505050565b60809190911b0190565b613778615b94565b613780615b94565b613788615c2e565b506020830151600486015486546000916137b59167ffffffffffffffff908116911663ffffffff613d8f16565b905060006137f883604001516137e285602001518567ffffffffffffffff16613d8f90919063ffffffff16565b67ffffffffffffffff169063ffffffff613d8f16565b905061382383608001516137e285606001518467ffffffffffffffff16613d8f90919063ffffffff16565b67ffffffffffffffff16845261012083015161384690600163ffffffff61543516565b871061393f5760016040850152600061385d6143ce565b90506000816001600160a01b0316638e12779387600001516040518263ffffffff1660e01b8152600401808267ffffffffffffffff1667ffffffffffffffff16815260200191505060206040518083038186803b1580156138bd57600080fd5b505afa1580156138d1573d6000803e3d6000fd5b505050506040513d60208110156138e757600080fd5b505160408901519091506000906138ff90839061441d565b67ffffffffffffffff81166020890152895190915061391e90826156d0565b60808a015260a08901526001600160a01b0316606088015250613985915050565b600060408501526139508884615725565b67ffffffffffffffff1660208501819052865161396c91613e31565b608087015260a08601526001600160a01b031660608501525b610140830151608085015161399f9163ffffffff61576616565b60c085015261016083015160808501516139be9163ffffffff61576616565b60e08501525091925050505b9392505050565b80156137615760006139e16149c5565b90506139fe6001600160a01b03841685838563ffffffff61578a16565b6040518060400160405280601181526020017f444d5f4445504f5349545f4641494c454400000000000000000000000000000081525090613a8357604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5050505050565b6000613a946112ff565b6001600160a01b0316633f33bf866040518163ffffffff1660e01b8152600401602060405180830381600087803b158015613ace57600080fd5b505af11580156133a1573d6000803e3d6000fd5b613aea615b66565b6000613af4615c92565b613afc615cb0565b613b04615cce565b613b0c615cec565b613b14615cce565b6000613b1e6112ff565b6001600160a01b031663e008cb628a6040518263ffffffff1660e01b8152600401808267ffffffffffffffff1667ffffffffffffffff1681526020019150506102406040518083038186803b158015613b7657600080fd5b505afa158015613b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610240811015613bb057600080fd5b50805161022082015190985060208201975060808201965061012082019550610160820194506101e090910192509050613be8615b66565b6040805160a0810182526001600160a01b038a16815260208781015161ffff1681830152895182840152898101516060830152898301516080830152908352815161018081018352885167ffffffffffffffff9081168252898301511691810191909152908101876002602002015167ffffffffffffffff16815260200187600360058110613c7357fe5b602002015167ffffffffffffffff16815260200187600460058110613c9457fe5b602002015167ffffffffffffffff16815260200186600060028110613cb557fe5b602002015161ffff16815260200185600060048110613cd057fe5b602002015167ffffffffffffffff16815260200185600160048110613cf157fe5b602002015167ffffffffffffffff16815260200185600360048110613d1257fe5b602002015167ffffffffffffffff16815260200185600260048110613d3357fe5b602002015167ffffffffffffffff16815260200184600060028110613d5457fe5b6020020151815260200184600160028110613d6b57fe5b60209081029190910151909152820152604081019190915298975050505050505050565b60408051808201909152601381527f4d41544836345f4144445f4f564552464c4f570000000000000000000000000060208201526000908383019067ffffffffffffffff8086169083161015613e2957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b509392505050565b815160408301516000908190613e589067ffffffffffffffff86169063ffffffff61506016565b91506000613e918567ffffffffffffffff16613e85886080015189606001516153a890919063ffffffff16565b9063ffffffff61506016565b9050613ea3838263ffffffff6153a816565b9150509250925092565b60008060018781548110613ebd57fe5b906000526020600020906002020190508581600001601e6101000a81548160ff02191690836002811115613eed57fe5b02179055506000816001018054809190600101613f0a9190615d0a565b90506000826001018281548110613f1d57fe5b600091825260208220600890910201805467ffffffffffffffff89811668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff918c1667ffffffffffffffff199093169290921716178155600181018790559150613f8f6134de565b90506000613f9d8b85613766565b8554604080517ffaf172f7000000000000000000000000000000000000000000000000000000008152600481018490527c010000000000000000000000000000000000000000000000000000000090920460ff166024830152519192506001600160a01b0384169163faf172f79160448082019260009290919082900301818387803b15801561402c57600080fd5b505af1158015614040573d6000803e3d6000fd5b50959d9c50505050505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526000906140d58582615810565b95945050505050565b60006140e86112ff565b6001600160a01b03166308135a936040518163ffffffff1660e01b815260040160206040518083038186803b15801561338d57600080fd5b60008085600101858154811061413257fe5b600091825260209091206001880154600890920201915060028754600160f01b900460ff16600281111561416257fe5b148061417d575061417a81600163ffffffff61543516565b86105b1561418d57600592505050610fea565b600482015482546000916141b49167ffffffffffffffff908116911663ffffffff613d8f16565b905060008854600160f01b900460ff1660028111156141cf57fe5b14806141ee57508067ffffffffffffffff168667ffffffffffffffff16105b156141ff5760009350505050610fea565b600061422286602001518367ffffffffffffffff16613d8f90919063ffffffff16565b90508067ffffffffffffffff168767ffffffffffffffff16101561424d576001945050505050610fea565b600061427087604001518367ffffffffffffffff16613d8f90919063ffffffff16565b90508067ffffffffffffffff168867ffffffffffffffff16101561429c57600295505050505050610fea565b610120870151841180156142b95760059650505050505050610fea565b60006142c787600601615387565b905060006142ec8a606001518567ffffffffffffffff16613d8f90919063ffffffff16565b905081614331578067ffffffffffffffff168b67ffffffffffffffff16101561432057600398505050505050505050610fea565b600598505050505050505050610fea565b60006143548b608001518367ffffffffffffffff16613d8f90919063ffffffff16565b90508067ffffffffffffffff168c67ffffffffffffffff1610156143845760049950505050505050505050610fea565b5060059d9c50505050505050505050505050565b6020015161012001511190565b6001600160a01b03166000908152600391909101602052604090205467ffffffffffffffff1690565b60008060009054906101000a90046001600160a01b03166001600160a01b031663953e46a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561338d57600080fd5b60008183101561442f575060006128ec565b6139ca826144456103e88663ffffffff61506016565b8161444c57fe5b0461585b565b60015460408051808201909152601981527f444d5f444953505554455f444f45535f4e4f545f45584953540000000000000060208201529082106144da57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5050565b60006144e86112ff565b6001600160a01b031663f7fe57896040518163ffffffff1660e01b815260040160206040518083038186803b15801561338d57600080fd5b614528615c0e565b60008060006145356112ff565b6001600160a01b03166369667005866040518263ffffffff1660e01b8152600401808267ffffffffffffffff1667ffffffffffffffff16815260200191505060606040518083038186803b15801561458c57600080fd5b505afa1580156145a0573d6000803e3d6000fd5b505050506040513d60608110156145b657600080fd5b50805160208083015160409384015184516060810186526001600160a01b03909416845261ffff16918301919091529181019190915295945050505050565b6145fd615d36565b506040805160a081018252958652602086019490945267ffffffffffffffff909216928401929092526060830191909152608082015290565b8154600483015460008054909267ffffffffffffffff680100000000000000009182900481169391909104811691600160a01b9004168361467d848463ffffffff6158f316565b905060008267ffffffffffffffff168267ffffffffffffffff16106146a257826146a4565b815b90506146ae615d77565b6040518060e00160405280896060015160001c815260200189600001518152602001896040015167ffffffffffffffff1681526020018667ffffffffffffffff1681526020018367ffffffffffffffff1681526020018767ffffffffffffffff16815260200189608001516020015161ffff16815250905060006147306143ce565b905060606000826001600160a01b031663d903bcf4856040518263ffffffff1660e01b81526004018082600760200280838360005b8381101561477d578181015183820152602001614765565b50505050905001915050600060405180830381600087803b1580156147a157600080fd5b505af11580156147b5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160409081528110156147de57600080fd5b8101908080516401000000008111156147f657600080fd5b8201602081018481111561480957600080fd5b815185602082028301116401000000008211171561482657600080fd5b5050602090910151909450925060009150614853905067ffffffffffffffff8a168363ffffffff613d8f16565b60048e0180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8416021790558c5160208e01519192506148aa918f8686615992565b60808c01516040015167ffffffffffffffff828116908c1614906000906148d7908563ffffffff61506016565b90506148e16149c5565b60808f015151604080517f5f52d44e0000000000000000000000000000000000000000000000000000000081526001600160a01b0392831660048201523360248201526044810185905290519290911691635f52d44e9160648082019260009290919082900301818387803b15801561495957600080fd5b505af115801561496d573d6000803e3d6000fd5b50939e50505050505050505050505050505092915050565b6004830154825460009167ffffffffffffffff600160801b9091048116916149b59185911663ffffffff61506016565b816149bc57fe5b04949350505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316633b19e84a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561338d57600080fd5b8254600090600160e81b900460ff1615614a3a57508254600160e81b900460ff166139ca565b600060018560010180549050039050614a5a858260058660200151613598565b6000856001018281548110614a6b57fe5b60009182526020822060089091020191506006820190614a8a82615387565b8015614a9c5750614a9a82615396565b155b9050600081614b2a57614aad6134de565b6001600160a01b031663084d72f4614ac58a88613766565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015614af957600080fd5b505afa158015614b0d573d6000803e3d6000fd5b505050506040513d6020811015614b2357600080fd5b5051614b37565b8254600160a01b900460ff165b89547fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160e81b60ff831602179099555096979650505050505050565b600080614b81613a8a565b600489015460028a01549192507801000000000000000000000000000000000000000000000000900467ffffffffffffffff1690600090614bc29083615435565b9050600086118015614bd357508581115b15614bdf575084614c0c565b89547fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff16600160801b178a555b614c1c828263ffffffff6153a816565b8a60040160186101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000614c506143ce565b9050606082604051908082528060200260200182016040528015614c7e578160200160208202803883390190505b509050606083604051908082528060200260200182016040528015614cad578160200160208202803883390190505b50905060005b84811015614d9a5760008e60020182880181548110614cce57fe5b9060005260206000200160009054906101000a90046001600160a01b0316905080848381518110614cfb57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050614d7a8f6003016000836001600160a01b03166001600160a01b0316815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff16613e858e8d615aab90919063ffffffff16565b838381518110614d8657fe5b602090810291909101015250600101614cb3565b506060614da56134de565b6001600160a01b03166318ce8f568e8e866040518463ffffffff1660e01b8152600401808481526020018360ff1660ff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b83811015614e17578181015183820152602001614dff565b5050505090500194505050505060006040518083038186803b158015614e3c57600080fd5b505afa158015614e50573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015614e7957600080fd5b810190808051640100000000811115614e9157600080fd5b82016020810184811115614ea457600080fd5b8151856020820283011164010000000082111715614ec157600080fd5b50509291905050509050615048846001600160a01b031663c67106f5898686866040518563ffffffff1660e01b8152600401808567ffffffffffffffff1667ffffffffffffffff168152602001806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b83811015614f52578181015183820152602001614f3a565b50505050905001848103835286818151815260200191508051906020019060200280838360005b83811015614f91578181015183820152602001614f79565b50505050905001848103825285818151815260200191508051906020019060200280838360005b83811015614fd0578181015183820152602001614fb8565b50505050905001975050505050505050602060405180830381600087803b158015614ffa57600080fd5b505af115801561500e573d6000803e3d6000fd5b505050506040513d602081101561502457600080fd5b81019080805190602001909291905050508f600501546153a890919063ffffffff16565b60058f01555092955050505050509695505050505050565b60008261506f575060006128ec565b8282028284828161507c57fe5b04146040518060400160405280601181526020017f4d4154485f4d554c5f4f564552464c4f5700000000000000000000000000000081525090613e2957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b6004850154600160801b900467ffffffffffffffff16156151235761537f565b80156151955760006151336143ce565b9050806001600160a01b0316636d1b229d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561517b57600080fd5b505af115801561518f573d6000803e3d6000fd5b50505050505b836152315785546001860154604080517f5f52d44e0000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152938416602482015260448101929092525191851691635f52d44e9160648082019260009290919082900301818387803b15801561521457600080fd5b505af1158015615228573d6000803e3d6000fd5b5050505061537f565b6000600286600101548161524157fe5b049050600087600101600187038154811061525857fe5b6000918252602082206006600890920201018054604080517f5f52d44e0000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152928316602482015260448101879052905192945090881692635f52d44e9260648084019382900301818387803b1580156152dc57600080fd5b505af11580156152f0573d6000803e3d6000fd5b5050506001820154604080517f5f52d44e0000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015292831660248201526044810186905290519188169250635f52d44e91606480830192600092919082900301818387803b15801561536b57600080fd5b505af11580156119a5573d6000803e3d6000fd5b505050505050565b546001600160a01b0316151590565b600101546001600160a01b0316151590565b60408051808201909152601181527f4d4154485f4144445f4f564552464c4f5700000000000000000000000000000060208201526000908383019084821015613e2957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b6000828211156040518060400160405280601281526020017f4d4154485f5355425f554e444552464c4f570000000000000000000000000000815250906154c057604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5050900390565b6000806154d26143ce565b8454604080517fe9e67d670000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015267ffffffffffffffff909316602482015290519293506000929184169163e9e67d6791604480820192602092909190829003018186803b15801561554e57600080fd5b505afa158015615562573d6000803e3d6000fd5b505050506040513d602081101561557857600080fd5b5051604087015190915060009061559090839061441d565b905067ffffffffffffffff81166155ad57600093505050506139ca565b60006155ca886020015160a0015184615aab90919063ffffffff16565b9050836001600160a01b031663605da1b287836155e56144de565b6040805163ffffffff861660e01b81526001600160a01b039094166004850152602484019290925267ffffffffffffffff1660448301525160648083019260209291908290030181600087803b15801561563e57600080fd5b505af1158015615652573d6000803e3d6000fd5b505050506040513d602081101561566857600080fd5b505161567b5760009450505050506139ca565b6001600160a01b03861660009081526003880160205260409020805467ffffffffffffffff191667ffffffffffffffff841617905560058701546156bf90826153a8565b600588015550925050509392505050565b815160208301516040840151600091829161571991906103e8906157059067ffffffffffffffff89169063ffffffff61506016565b8161570c57fe5b049063ffffffff615aab16565b91508190509250925092565b60e081015182546000918291615752916801000000000000000090910467ffffffffffffffff1690615ac4565b9050600181166139ca576001019392505050565b600061271061577b848463ffffffff61506016565b8161578257fe5b049392505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526000906136a586825b6000806040516020818551602087016000895af18015615851573d801561583e57602081146158475761584f565b6001935061584f565b600183511493505b505b5090949350505050565b60408051808201909152601581527f55494e5436345f4e554d4245525f544f4f5f4249470000000000000000000000602082015260009067ffffffffffffffff8311156158ec57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5090919050565b60008267ffffffffffffffff168267ffffffffffffffff1611156040518060400160405280601481526020017f4d41544836345f5355425f554e444552464c4f57000000000000000000000000815250906154c057604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b60005b8181101561537f5760008382815181106159ab57fe5b6020908102919091018101516001600160a01b038116600090815260038801909252604090912080549192509067ffffffffffffffff16615a2f57600286018054600181018255600091825260209091200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384161790555b8054615a4c9067ffffffffffffffff16600163ffffffff613d8f16565b815467ffffffffffffffff191667ffffffffffffffff919091161781556040516001600160a01b0383169088908a907fbfd1b785c517ac3c709db5d7c9904052346df35e7069c1cb80f3dd966579d52290600090a45050600101615995565b600061271061577b8461ffff851663ffffffff61506016565b60408051808201909152601381527f4d41544836345f4d554c5f4f564552464c4f5700000000000000000000000000602082015260009067ffffffffffffffff8481169084160290680100000000000000008210613e2957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b604051806102400160405280615b7a615d95565b8152602001615b87615c2e565b8152602001600081525090565b60408051610100810182526000808252602082018190529091820190815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b815481835581811115613761576002028160020283600052602060002091820191016137619190615dd1565b604080516060810182526000808252602082018190529181019190915290565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081019190915290565b60405180606001604052806003906020820280388339509192915050565b6040518060a001604052806005906020820280388339509192915050565b60405180604001604052806002906020820280388339509192915050565b60405180608001604052806004906020820280388339509192915050565b815481835581811115613761576008028160080283600052602060002091820191016137619190615e21565b6040518060e001604052806000815260200160008152602001600067ffffffffffffffff16815260200160008019168152602001615d72615c0e565b905290565b6040518060e001604052806007906020820280388339509192915050565b6040518060a0016040528060006001600160a01b03168152602001600061ffff1681526020016000815260200160008152602001600081525090565b61130c91905b80821115615e1d5780547fff000000000000000000000000000000000000000000000000000000000000001681556000615e146001830182615ed6565b50600201615dd7565b5090565b61130c91905b80821115615e1d5780547fffffffffffffffffffffffffffffff0000000000000000000000000000000000168155600060018201819055615e6b6002830182615ef7565b5060006004820181905560058201556006810180547fffffffffffffffffffffff0000000000000000000000000000000000000000001690556007810180547fffffffffffffffffffff00000000000000000000000000000000000000000000169055600801615e27565b50805460008255600802906000526020600020908101906108029190615e21565b5080546000825590600052602060002090810190610802919061130c91905b80821115615e1d5760008155600101615f1656fea165627a7a723058209736511eab2676614d9c8070491a2225c53a409a0088a8ce0d8d76e3016800ad0029000000000000000000000000ee4650cbe7a2b23701d416f58b41d8b76b61779700000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101815760003560e01c80637263bf2a116100d8578063bd881e531161008c578063cd604ada11610066578063cd604ada146105ef578063e3a96cbd1461067a578063eed04b80146106f757610181565b8063bd881e5314610555578063c1361a7c14610597578063c39c83d1146105c357610181565b806382a8b3b0116100bd57806382a8b3b0146104ce578063859ba187146105005780639c0065f71461052957610181565b80637263bf2a146104425780637b751b9e146104a357610181565b806324ae6a271161013a57806339ec68a31161011457806339ec68a3146103355780634b4acfd3146103cf578063710cf1ed1461042557610181565b806324ae6a27146102be5780633018205f146102ec5780633238f8f41461031057610181565b80630d03d1261161016b5780630d03d126146101db57806315fe5268146102075780631d2fa1fb1461022457610181565b80629230a51461018657806306349cfa146101af575b600080fd5b6101ad6004803603602081101561019c57600080fd5b503567ffffffffffffffff1661071a565b005b6101ad600480360360408110156101c557600080fd5b50803590602001356001600160a01b0316610805565b6101ad600480360360608110156101f157600080fd5b508035906020810135906040013560ff16610982565b6101ad6004803603602081101561021d57600080fd5b5035610c80565b6102ac6004803603606081101561023a57600080fd5b6001600160a01b038235169160ff6020820135169181019060608101604082013564010000000081111561026d57600080fd5b82018360208201111561027f57600080fd5b803590602001918460018302840111640100000000831117156102a157600080fd5b509092509050610cba565b60408051918252519081900360200190f35b6101ad600480360360408110156102d457600080fd5b506001600160a01b0381358116916020013516610ff2565b6102f46112ff565b604080516001600160a01b039092168252519081900360200190f35b61031861130f565b6040805167ffffffffffffffff9092168252519081900360200190f35b6103586004803603604081101561034b57600080fd5b5080359060200135611326565b6040805167ffffffffffffffff808c1682528a811660208301528981169282019290925287821660608201526080810187905285151560a082015260c0810185905290831660e082015261010081018260058111156103b357fe5b60ff168152602001995050505050505050505060405180910390f35b610401600480360360608110156103e557600080fd5b50803590602081013590604001356001600160a01b031661145b565b6040805167ffffffffffffffff909316835290151560208301528051918290030190f35b6101ad6004803603602081101561043b57600080fd5b50356115e4565b6104656004803603604081101561045857600080fd5b50803590602001356119b3565b604080516001600160a01b03958616815267ffffffffffffffff94851660208201529290941682850152909116606082015290519081900360800190f35b6104ab611a3c565b604080516001600160a01b03909316835260208301919091528051918290030190f35b6101ad600480360360608110156104e457600080fd5b50803590602081013590604001356001600160a01b0316611a81565b6101ad6004803603606081101561051657600080fd5b50803590602081013590604001356120c9565b6101ad6004803603606081101561053f57600080fd5b508035906020810135906040013560ff166124f9565b6105726004803603602081101561056b57600080fd5b503561278b565b604080516001600160a01b03909316835260ff90911660208301528051918290030190f35b610318600480360360408110156105ad57600080fd5b50803590602001356001600160a01b0316612884565b6101ad600480360360408110156105d957600080fd5b506001600160a01b0381351690602001356128f2565b6106126004803603604081101561060557600080fd5b5080359060200135612b84565b6040805167ffffffffffffffff808b1682528916602082015290810187600281111561063a57fe5b60ff1681526001600160a01b039096166020870152506040808601949094526060850192909252608084015260a0830152519081900360c0019350915050f35b6106976004803603602081101561069057600080fd5b5035612cdb565b604080516001600160a01b038816815260ff871660208201529081018560028111156106bf57fe5b60ff90811682529490941660208501525060408084019290925267ffffffffffffffff16606083015251908190036080019350915050f35b6101ad6004803603604081101561070d57600080fd5b5080359060200135612d7f565b61072261333e565b6001600160a01b0316336001600160a01b0316146040518060400160405280601e81526020017f4354445f53454e4445525f4e4f545f434f4e4649475f474f5645524e4f520000815250906107f857604051600160e51b62461bcd0281526004018080602001828103825283818151815260200191508051906020019080838360005b838110156107bd5781810151838201526020016107a5565b50505050905090810190601f1680156107ea5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50610802816133be565b50565b600061080f6134de565b60408051808201909152601481527f444d5f53454e4445525f4e4f545f564f54494e470000000000000000000000006020820152909150336001600160a01b038316146108a057604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000806108ad8561352d565b915091506108b9615b66565b6108c283613574565b90506108d5838360018460200151613598565b60006108e38484888561365b565b905060008167ffffffffffffffff16116040518060400160405280601481526020017f444d5f564f5445525f5745494748545f5a45524f0000000000000000000000008152509061097857604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5050505050505050565b828261098e82826136af565b60006001868154811061099d57fe5b906000526020600020906002020190506109b5615b66565b6109be82613574565b90506109d1828760038460200151613598565b60006109db6134de565b905060006109e98989613766565b90506000826001600160a01b031663084d72f4836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610a3157600080fd5b505afa158015610a45573d6000803e3d6000fd5b505050506040513d6020811015610a5b57600080fd5b5051905060ff80821690891614801590610b065750604080517fe2e7ed9f0000000000000000000000000000000000000000000000000000000081526004810184905260ff8a16602482015290516001600160a01b0385169163e2e7ed9f916044808301926020929190829003018186803b158015610ad957600080fd5b505afa158015610aed573d6000803e3d6000fd5b505050506040513d6020811015610b0357600080fd5b50515b6040518060400160405280601881526020017f444d5f494e56414c49445f41505045414c5f52554c494e47000000000000000081525090610b8b57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000856001018a81548110610b9d57fe5b600091825260209182902060089190910201600681018054337fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b60ff8e16908102919091178255604080519182525192945090928d928f927f57dc4548648c602e9f394f905942ffeba7a2041a6a704128b3a75e5b0efa11a792908290030190a3610c51615b94565b610c5c838d89613770565b9050610c713382606001518360c001516139d1565b50505050505050505050505050565b600080610c8c8361352d565b91509150610c98615b66565b610ca183613574565b9050610cb4838360018460200151613598565b50505050565b6000805460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b03163314610d4c57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000610d57613a8a565b9050600260ff861610801590610d715750600260ff861611155b6040518060400160405280601981526020017f444d5f494e56414c49445f52554c494e475f4f5054494f4e530000000000000081525090610df657604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5060018054600091610e0a90828101615be2565b9050600060018281548110610e1b57fe5b6000918252602090912060029091020180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038a16177fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000060ff8a1602177fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff16600160a01b67ffffffffffffffff8616021781559050610ee0615b66565b610ee984613ae2565b602081015160c0810151905191925090600090610f179067ffffffffffffffff88169063ffffffff613d8f16565b90508067ffffffffffffffff168b6001600160a01b0316867fd4784fc5a2aef689d6639d09cb5b543abfeabd597519d01b93f4ffef74d10396858d8d604051808467ffffffffffffffff1667ffffffffffffffff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a46000806000610fbe866000015186613e31565b925092509250610fd2886000868886613ead565b50610fde8e84836139d1565b50959750505050505050505b949350505050565b6000809054906101000a90046001600160a01b03166001600160a01b0316633c28e88b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561103f57600080fd5b505afa158015611053573d6000803e3d6000fd5b505050506040513d602081101561106957600080fd5b505160408051808201909152601d81527f4354445f53454e4445525f4e4f545f46554e44535f474f5645524e4f520000006020820152906001600160a01b031633146110f957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290516000916001600160a01b038516916370a0823191602480820192602092909190829003018186803b15801561115d57600080fd5b505afa158015611171573d6000803e3d6000fd5b505050506040513d602081101561118757600080fd5b505160408051808201909152601e81527f4354445f494e53554646494349454e545f5245434f5645525f46554e4453000060208201529091508161120f57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5061122a6001600160a01b038416838363ffffffff61405316565b6040518060400160405280601e81526020017f4354445f5245434f5645525f544f4b454e5f46554e44535f4641494c45440000815250906112af57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50604080516001600160a01b0380861682528416602082015280820183905290517f724139fea3954691c2c1ee02b3be6be1763b32ec84841f1acad6d3a18695ba0d9181900360600190a1505050565b6000546001600160a01b03165b90565b600054600160a01b900467ffffffffffffffff1681565b60008060008060008060008060008a8a61134082826136af565b600060018e8154811061134f57fe5b9060005260206000209060020201905061137e818e61136c6140de565b61137585613574565b60200151614120565b93506000816001018e8154811061139157fe5b906000526020600020906008020190508060000160009054906101000a900467ffffffffffffffff169c508060040160009054906101000a900467ffffffffffffffff169b508060000160089054906101000a900467ffffffffffffffff169a508060040160089054906101000a900467ffffffffffffffff169950806001015498508060000160109054906101000a900460ff1697508060040160109054906101000a900467ffffffffffffffff16955080600501549650505050509295985092959850929598565b600080848461146a82826136af565b60006001888154811061147957fe5b90600052602060002090600202019050600081600101888154811061149a57fe5b906000526020600020906008020190506114b2615b66565b6114bb83613574565b90506114c78982614398565b156114dd576114d682896143a5565b96506115a7565b60006114e76143ce565b8354604080517fe9e67d670000000000000000000000000000000000000000000000000000000081526001600160a01b038d8116600483015267ffffffffffffffff909316602482015290519293506000929184169163e9e67d6791604480820192602092909190829003018186803b15801561156357600080fd5b505afa158015611577573d6000803e3d6000fd5b505050506040513d602081101561158d57600080fd5b505160408401519091506115a290829061441d565b985050505b506001600160a01b039690961660009081526003909601602052505060409093205491956801000000000000000090920460ff1694509092505050565b806115ee81614452565b60006115f86112ff565b905060006116046112ff565b6001600160a01b03166350c365806040518163ffffffff1660e01b815260040160206040518083038186803b15801561163c57600080fd5b505afa158015611650573d6000803e3d6000fd5b505050506040513d602081101561166657600080fd5b505160408051808201909152601081527f444d5f5445524d5f4f5554444154454400000000000000000000000000000000602082015290915067ffffffffffffffff8216156116f957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5060006117046144de565b905060006001868154811061171557fe5b60009182526020822060029091020191508154600160f01b900460ff16600281111561173d57fe5b146040518060400160405280601881526020017f444d5f524f554e445f414c52454144595f445241465445440000000000000000815250906117c357604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50600181018054600019810191600091839081106117dd57fe5b6000918252602091829020600890910201805460408051808201909152601981527f444d5f44524146545f5445524d5f4e4f545f52454143484544000000000000009381019390935290925067ffffffffffffffff9081169190861682111561188a57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000876001600160a01b0316637d1f24c96040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156118c857600080fd5b505af11580156118dc573d6000803e3d6000fd5b505050506040513d60208110156118f257600080fd5b505190506118fe615c0e565b61190783614520565b905060006119218561191c8e898c88886145f5565b614636565b905080156119a55760048501805467ffffffffffffffff1916858a0367ffffffffffffffff1617905586547fff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160f01b1787556040516001908d907f9bfdc20780e4912d62e8c31a73ffad5cbd841d7f76d114aa9f302ceca2d8258590600090a35b505050505050505050505050565b60008060008085856119c582826136af565b6000600189815481106119d457fe5b906000526020600020906002020160010188815481106119f057fe5b600091825260209091206006600890920201908101546007909101546001600160a01b038083169c60ff600160a01b9485900481169d509183169b509290910416975095505050505050565b6000806000611a496140de565b9050611a53615b66565b611a5c82613ae2565b9050611a748160000151826020015160c00151613e31565b9196919550909350505050565b8282611a8d82826136af565b600060018681548110611a9c57fe5b906000526020600020906002020190506000816001018681548110611abd57fe5b906000526020600020906008020190508060000160109054906101000a900460ff166040518060400160405280601e81526020017f444d5f524f554e445f50454e414c544945535f4e4f545f534554544c4544000081525090611b6457604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506001600160a01b038516600090815260038201602090815260409182902080548351808501909452601984527f444d5f4a55524f525f414c52454144595f52455741524445440000000000000092840192909252919068010000000000000000900460ff1615611c1957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50805460408051808201909152601e81527f444d5f574f4e545f5245574152445f4e4f4e5f564f5445525f4a55524f52000060208201529067ffffffffffffffff16611ca957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5080547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001781556000611ce56134de565b90506000611cf38a8a613766565b8554604080517fcfa558ba00000000000000000000000000000000000000000000000000000000815260048101849052600160e81b90920460ff1660248301526001600160a01b038b81166044840152905192935084169163cfa558ba91606480820192602092909190829003018186803b158015611d7157600080fd5b505afa158015611d85573d6000803e3d6000fd5b505050506040513d6020811015611d9b57600080fd5b505160408051808201909152601f81527f444d5f574f4e545f5245574152445f494e434f484552454e545f4a55524f5200602082015290611e2057604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5060058401546000611e306143ce565b905060008215611ec057611e45878785614985565b9050816001600160a01b0316634d7edc158c836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611ea757600080fd5b505af1158015611ebb573d6000803e3d6000fd5b505050505b611ec8615b66565b611ed189613574565b90506000611ee489898b60010154614985565b9050611eee6149c5565b6001600160a01b0316635f52d44e8360000151600001518f846040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015611f6f57600080fd5b505af1158015611f83573d6000803e3d6000fd5b50505050611f918e83614398565b61205d57611f9d615c2e565b82602001519050846001600160a01b031663af8b9d0f8f836101000151846040015185602001518f60000160009054906101000a900467ffffffffffffffff160101016040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b031681526020018267ffffffffffffffff1667ffffffffffffffff16815260200192505050600060405180830381600087803b15801561204357600080fd5b505af1158015612057573d6000803e3d6000fd5b50505050505b8d8f7f3aea41188dba0e19aa929ada5527b70c76ba34b22bb672818cf2ed788c3c9e778f868560405180846001600160a01b03166001600160a01b03168152602001838152602001828152602001935050505060405180910390a3505050505050505050505050505050565b82826120d582826136af565b6000600186815481106120e457fe5b90600052602060002090600202019050846000148061212c575080600101600186038154811061211057fe5b6000918252602090912060089091020154600160801b900460ff165b6040518060400160405280601d81526020017f444d5f50524556494f55535f524f554e445f4e4f545f534554544c4544000000815250906121b157604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5060008160010186815481106121c357fe5b906000526020600020906008020190508060000160109054906101000a900460ff16156040518060400160405280601881526020017f444d5f524f554e445f414c52454144595f534554544c454400000000000000008152509061226b57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50612274615b66565b61227d83613574565b9050600061228c848a84614a14565b9050600061229a8a8a613766565b60048501549091507801000000000000000000000000000000000000000000000000900467ffffffffffffffff1661239a5760006122d66134de565b9050806001600160a01b03166385dbcf7983856040518363ffffffff1660e01b8152600401808381526020018260ff1660ff1681526020019250505060206040518083038186803b15801561232a57600080fd5b505afa15801561233e573d6000803e3d6000fd5b505050506040513d602081101561235457600080fd5b505160048601805467ffffffffffffffff909216600160801b027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909216919091179055505b60006123a46149c5565b8451519091506123b48b86614398565b156124715760006123d5878587896020015160a001518f8b60400151614b76565b9050826001600160a01b0316635f52d44e8333612403858b600001516080015161506090919063ffffffff16565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561245357600080fd5b505af1158015612467573d6000803e3d6000fd5b505050505061249e565b85547fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff16600160801b1786555b8554600160801b900460ff16156119a55760058601546040805182815290518d918f917f2f643ff79db9be434873df2e7b4cc272c517e58b5712ea5a20c5d7bfc482f5539181900360200190a3610c7188888e868686615103565b828261250582826136af565b60006001868154811061251457fe5b9060005260206000209060020201905061252c615b66565b61253582613574565b9050612548828760048460200151613598565b600082600101878154811061255957fe5b600091825260208220600890910201915060068201906125798a8a613766565b825490915060ff898116600160a01b909204161480159061261b575061259d6134de565b6001600160a01b031663e2e7ed9f828a6040518363ffffffff1660e01b8152600401808381526020018260ff1660ff1681526020019250505060206040518083038186803b1580156125ee57600080fd5b505afa158015612602573d6000803e3d6000fd5b505050506040513d602081101561261857600080fd5b50515b6040518060400160405280601881526020017f444d5f494e56414c49445f41505045414c5f52554c494e470000000000000000815250906126a057604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506126a9615b94565b6126b4848b87613770565b905060008160400151905060006126da8d83856000015186602001518760a00151613ead565b9050338560010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a8560010160146101000a81548160ff021916908360ff160217905550826000015167ffffffffffffffff16818e7f06c05c98f79e14aad019b270fad6f7d1bcb11dc267667ed908d78e4d5ec9a3eb8660200151604051808267ffffffffffffffff16815260200191505060405180910390a4610c713384606001518560e001516139d1565b6000808261279881614452565b6000600185815481106127a757fe5b6000918252602090912060029091020180546001600160a01b0316945090506127ce615b66565b6127d782613574565b90506127e4828783614a14565b935060028254600160f01b900460ff1660028111156127ff57fe5b1461287c5781547fff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0200000000000000000000000000000000000000000000000000000000000017825560405160ff85169087907f33ebf61f1f1800f29578208d33c8618cf5a27602cd0c4c1978a60651eb531d3b90600090a35b505050915091565b60008060006128928561352d565b9150915061289e615b66565b6128a783613574565b90506128ba838360028460200151613598565b60008360010183815481106128cb57fe5b906000526020600020906008020190506128e581876143a5565b9450505050505b92915050565b60005460408051808201909152601981527f4354445f53454e4445525f4e4f545f434f4e54524f4c4c4552000000000000006020820152906001600160a01b0316331461298357604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5080600061299182826136af565b6000600184815481106129a057fe5b906000526020600020906002020190506000816001016000815481106129c257fe5b6000918252602091829020845460408051808201909152601d81527f444d5f53454e4445525f4e4f545f444953505554455f5355424a4543540000009481019490945260089092020192506001600160a01b0390811690881614612a6a57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000612a75613a8a565b90506000612a9467ffffffffffffffff8316600163ffffffff613d8f16565b835460408051808201909152601c81527f444d5f45564944454e43455f504552494f445f49535f434c4f53454400000000602082015291925067ffffffffffffffff90811690831610612b2b57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50825467ffffffffffffffff191667ffffffffffffffff8281169190911784556040519083169088907f1384c9abcdf1fa5a2a50953bad79f58ea7b2999fae7783b5b1e2edff339b8d1c90600090a35050505050505050565b600080600080600080600080612b9a8a8a6136af565b600060018b81548110612ba957fe5b90600052602060002090600202019050612bc1615b66565b612bca82613574565b9050612bd68b82614398565b6040518060400160405280601181526020017f444d5f524f554e445f49535f46494e414c00000000000000000000000000000081525090612c5b57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000826001018c81548110612c6d57fe5b90600052602060002090600802019050612c85615b94565b612c90828e85613770565b9050806000015181602001518260400151836060015184608001518560a001518660c001518760e001519b509b509b509b509b509b509b509b50505050509295985092959890939650565b60008060008060008086612cee81614452565b600060018981548110612cfd57fe5b6000918252602090912060029091020180546001909101546001600160a01b0382169b7c0100000000000000000000000000000000000000000000000000000000830460ff9081169c50600160f01b840481169b50600160e81b84041699506000199091019750600160a01b90910467ffffffffffffffff1695509350505050565b8181612d8b82826136af565b600060018581548110612d9a57fe5b906000526020600020906002020190506000816001018581548110612dbb57fe5b906000526020600020906008020190508060000160109054906101000a900460ff166040518060400160405280601e81526020017f444d5f524f554e445f50454e414c544945535f4e4f545f534554544c4544000081525090612e6257604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5060068101612e7081615387565b6040518060400160405280601581526020017f444d5f524f554e445f4e4f545f41505045414c4544000000000000000000000081525090612ef557604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50600181015460408051808201909152601981527f444d5f41505045414c5f414c52454144595f534554544c4544000000000000006020820152907501000000000000000000000000000000000000000000900460ff1615612f9b57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506001810180547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055604051869088907f28d5bc8b3a7bef24e784872d5b3b9069cf63ae040039bcc6040bd0b7af32d2f290600090a3613013615b66565b61301c84613574565b9050613026615b94565b613031848984613770565b6060810151608082015160c083015160e0840151939450919290919060006130576149c5565b905061306288615396565b613102578754604080517f5f52d44e0000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152928316602482015260448101869052905191831691635f52d44e9160648082019260009290919082900301818387803b1580156130db57600080fd5b505af11580156130ef573d6000803e3d6000fd5b5050505050505050505050505050610cb4565b8954600160e81b900460ff16600061311a85856153a8565b8a5490915060ff838116600160a01b9092041614156131c75789546001600160a01b0380851691635f52d44e918a911661315a858b63ffffffff61543516565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b1580156131aa57600080fd5b505af11580156131be573d6000803e3d6000fd5b5050505061332c565b60018a015460ff838116600160a01b90920416141561320a5760018a01546001600160a01b0380851691635f52d44e918a911661315a858b63ffffffff61543516565b895460028704906001600160a01b0385811691635f52d44e918b91166132308a86615435565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561328057600080fd5b505af1158015613294573d6000803e3d6000fd5b50505060018c01546001600160a01b038087169250635f52d44e918b91166132c2898663ffffffff61543516565b6040805163ffffffff861660e01b81526001600160a01b03948516600482015292909316602483015260448201529051606480830192600092919082900301818387803b15801561331257600080fd5b505af1158015613326573d6000803e3d6000fd5b50505050505b50505050505050505050505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b03166397023f816040518163ffffffff1660e01b815260040160206040518083038186803b15801561338d57600080fd5b505afa1580156133a1573d6000803e3d6000fd5b505050506040513d60208110156133b757600080fd5b5051905090565b60408051808201909152601b81527f444d5f4241445f4d41585f44524146545f42415443485f53495a450000000000602082015267ffffffffffffffff821661344b57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b506000546040805167ffffffffffffffff600160a01b90930483168152918316602083015280517fed22db0c227e21d249167e5f9d39415fd9386958f122075463fef70fd46c95c49281900390910190a16000805467ffffffffffffffff909216600160a01b027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60008060009054906101000a90046001600160a01b03166001600160a01b0316631986d3766040518163ffffffff1660e01b815260040160206040518083038186803b15801561338d57600080fd5b60006fffffffffffffffffffffffffffffffff8216608083901c61355181836136af565b6001818154811061355e57fe5b9060005260206000209060020201925050915091565b61357c615b66565b81546128ec90600160a01b900467ffffffffffffffff16613ae2565b60006135a2613a8a565b905060006135b286868486614120565b90508360058111156135c057fe5b8160058111156135cc57fe5b146040518060400160405280601d81526020017f444d5f494e56414c49445f41444a554449434154494f4e5f53544154450000008152509061365257604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b50505050505050565b60008085600101858154811061366d57fe5b906000526020600020906008020190506136878584614398565b61369b576136968382866154c7565b6136a5565b6136a581856143a5565b9695505050505050565b6136b882614452565b600182815481106136c557fe5b90600052602060002090600202016001018054905081106040518060400160405280601781526020017f444d5f524f554e445f444f45535f4e4f545f45584953540000000000000000008152509061376157604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b505050565b60809190911b0190565b613778615b94565b613780615b94565b613788615c2e565b506020830151600486015486546000916137b59167ffffffffffffffff908116911663ffffffff613d8f16565b905060006137f883604001516137e285602001518567ffffffffffffffff16613d8f90919063ffffffff16565b67ffffffffffffffff169063ffffffff613d8f16565b905061382383608001516137e285606001518467ffffffffffffffff16613d8f90919063ffffffff16565b67ffffffffffffffff16845261012083015161384690600163ffffffff61543516565b871061393f5760016040850152600061385d6143ce565b90506000816001600160a01b0316638e12779387600001516040518263ffffffff1660e01b8152600401808267ffffffffffffffff1667ffffffffffffffff16815260200191505060206040518083038186803b1580156138bd57600080fd5b505afa1580156138d1573d6000803e3d6000fd5b505050506040513d60208110156138e757600080fd5b505160408901519091506000906138ff90839061441d565b67ffffffffffffffff81166020890152895190915061391e90826156d0565b60808a015260a08901526001600160a01b0316606088015250613985915050565b600060408501526139508884615725565b67ffffffffffffffff1660208501819052865161396c91613e31565b608087015260a08601526001600160a01b031660608501525b610140830151608085015161399f9163ffffffff61576616565b60c085015261016083015160808501516139be9163ffffffff61576616565b60e08501525091925050505b9392505050565b80156137615760006139e16149c5565b90506139fe6001600160a01b03841685838563ffffffff61578a16565b6040518060400160405280601181526020017f444d5f4445504f5349545f4641494c454400000000000000000000000000000081525090613a8357604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5050505050565b6000613a946112ff565b6001600160a01b0316633f33bf866040518163ffffffff1660e01b8152600401602060405180830381600087803b158015613ace57600080fd5b505af11580156133a1573d6000803e3d6000fd5b613aea615b66565b6000613af4615c92565b613afc615cb0565b613b04615cce565b613b0c615cec565b613b14615cce565b6000613b1e6112ff565b6001600160a01b031663e008cb628a6040518263ffffffff1660e01b8152600401808267ffffffffffffffff1667ffffffffffffffff1681526020019150506102406040518083038186803b158015613b7657600080fd5b505afa158015613b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610240811015613bb057600080fd5b50805161022082015190985060208201975060808201965061012082019550610160820194506101e090910192509050613be8615b66565b6040805160a0810182526001600160a01b038a16815260208781015161ffff1681830152895182840152898101516060830152898301516080830152908352815161018081018352885167ffffffffffffffff9081168252898301511691810191909152908101876002602002015167ffffffffffffffff16815260200187600360058110613c7357fe5b602002015167ffffffffffffffff16815260200187600460058110613c9457fe5b602002015167ffffffffffffffff16815260200186600060028110613cb557fe5b602002015161ffff16815260200185600060048110613cd057fe5b602002015167ffffffffffffffff16815260200185600160048110613cf157fe5b602002015167ffffffffffffffff16815260200185600360048110613d1257fe5b602002015167ffffffffffffffff16815260200185600260048110613d3357fe5b602002015167ffffffffffffffff16815260200184600060028110613d5457fe5b6020020151815260200184600160028110613d6b57fe5b60209081029190910151909152820152604081019190915298975050505050505050565b60408051808201909152601381527f4d41544836345f4144445f4f564552464c4f570000000000000000000000000060208201526000908383019067ffffffffffffffff8086169083161015613e2957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b509392505050565b815160408301516000908190613e589067ffffffffffffffff86169063ffffffff61506016565b91506000613e918567ffffffffffffffff16613e85886080015189606001516153a890919063ffffffff16565b9063ffffffff61506016565b9050613ea3838263ffffffff6153a816565b9150509250925092565b60008060018781548110613ebd57fe5b906000526020600020906002020190508581600001601e6101000a81548160ff02191690836002811115613eed57fe5b02179055506000816001018054809190600101613f0a9190615d0a565b90506000826001018281548110613f1d57fe5b600091825260208220600890910201805467ffffffffffffffff89811668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff918c1667ffffffffffffffff199093169290921716178155600181018790559150613f8f6134de565b90506000613f9d8b85613766565b8554604080517ffaf172f7000000000000000000000000000000000000000000000000000000008152600481018490527c010000000000000000000000000000000000000000000000000000000090920460ff166024830152519192506001600160a01b0384169163faf172f79160448082019260009290919082900301818387803b15801561402c57600080fd5b505af1158015614040573d6000803e3d6000fd5b50959d9c50505050505050505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526000906140d58582615810565b95945050505050565b60006140e86112ff565b6001600160a01b03166308135a936040518163ffffffff1660e01b815260040160206040518083038186803b15801561338d57600080fd5b60008085600101858154811061413257fe5b600091825260209091206001880154600890920201915060028754600160f01b900460ff16600281111561416257fe5b148061417d575061417a81600163ffffffff61543516565b86105b1561418d57600592505050610fea565b600482015482546000916141b49167ffffffffffffffff908116911663ffffffff613d8f16565b905060008854600160f01b900460ff1660028111156141cf57fe5b14806141ee57508067ffffffffffffffff168667ffffffffffffffff16105b156141ff5760009350505050610fea565b600061422286602001518367ffffffffffffffff16613d8f90919063ffffffff16565b90508067ffffffffffffffff168767ffffffffffffffff16101561424d576001945050505050610fea565b600061427087604001518367ffffffffffffffff16613d8f90919063ffffffff16565b90508067ffffffffffffffff168867ffffffffffffffff16101561429c57600295505050505050610fea565b610120870151841180156142b95760059650505050505050610fea565b60006142c787600601615387565b905060006142ec8a606001518567ffffffffffffffff16613d8f90919063ffffffff16565b905081614331578067ffffffffffffffff168b67ffffffffffffffff16101561432057600398505050505050505050610fea565b600598505050505050505050610fea565b60006143548b608001518367ffffffffffffffff16613d8f90919063ffffffff16565b90508067ffffffffffffffff168c67ffffffffffffffff1610156143845760049950505050505050505050610fea565b5060059d9c50505050505050505050505050565b6020015161012001511190565b6001600160a01b03166000908152600391909101602052604090205467ffffffffffffffff1690565b60008060009054906101000a90046001600160a01b03166001600160a01b031663953e46a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561338d57600080fd5b60008183101561442f575060006128ec565b6139ca826144456103e88663ffffffff61506016565b8161444c57fe5b0461585b565b60015460408051808201909152601981527f444d5f444953505554455f444f45535f4e4f545f45584953540000000000000060208201529082106144da57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5050565b60006144e86112ff565b6001600160a01b031663f7fe57896040518163ffffffff1660e01b815260040160206040518083038186803b15801561338d57600080fd5b614528615c0e565b60008060006145356112ff565b6001600160a01b03166369667005866040518263ffffffff1660e01b8152600401808267ffffffffffffffff1667ffffffffffffffff16815260200191505060606040518083038186803b15801561458c57600080fd5b505afa1580156145a0573d6000803e3d6000fd5b505050506040513d60608110156145b657600080fd5b50805160208083015160409384015184516060810186526001600160a01b03909416845261ffff16918301919091529181019190915295945050505050565b6145fd615d36565b506040805160a081018252958652602086019490945267ffffffffffffffff909216928401929092526060830191909152608082015290565b8154600483015460008054909267ffffffffffffffff680100000000000000009182900481169391909104811691600160a01b9004168361467d848463ffffffff6158f316565b905060008267ffffffffffffffff168267ffffffffffffffff16106146a257826146a4565b815b90506146ae615d77565b6040518060e00160405280896060015160001c815260200189600001518152602001896040015167ffffffffffffffff1681526020018667ffffffffffffffff1681526020018367ffffffffffffffff1681526020018767ffffffffffffffff16815260200189608001516020015161ffff16815250905060006147306143ce565b905060606000826001600160a01b031663d903bcf4856040518263ffffffff1660e01b81526004018082600760200280838360005b8381101561477d578181015183820152602001614765565b50505050905001915050600060405180830381600087803b1580156147a157600080fd5b505af11580156147b5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160409081528110156147de57600080fd5b8101908080516401000000008111156147f657600080fd5b8201602081018481111561480957600080fd5b815185602082028301116401000000008211171561482657600080fd5b5050602090910151909450925060009150614853905067ffffffffffffffff8a168363ffffffff613d8f16565b60048e0180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8416021790558c5160208e01519192506148aa918f8686615992565b60808c01516040015167ffffffffffffffff828116908c1614906000906148d7908563ffffffff61506016565b90506148e16149c5565b60808f015151604080517f5f52d44e0000000000000000000000000000000000000000000000000000000081526001600160a01b0392831660048201523360248201526044810185905290519290911691635f52d44e9160648082019260009290919082900301818387803b15801561495957600080fd5b505af115801561496d573d6000803e3d6000fd5b50939e50505050505050505050505050505092915050565b6004830154825460009167ffffffffffffffff600160801b9091048116916149b59185911663ffffffff61506016565b816149bc57fe5b04949350505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316633b19e84a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561338d57600080fd5b8254600090600160e81b900460ff1615614a3a57508254600160e81b900460ff166139ca565b600060018560010180549050039050614a5a858260058660200151613598565b6000856001018281548110614a6b57fe5b60009182526020822060089091020191506006820190614a8a82615387565b8015614a9c5750614a9a82615396565b155b9050600081614b2a57614aad6134de565b6001600160a01b031663084d72f4614ac58a88613766565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015614af957600080fd5b505afa158015614b0d573d6000803e3d6000fd5b505050506040513d6020811015614b2357600080fd5b5051614b37565b8254600160a01b900460ff165b89547fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160e81b60ff831602179099555096979650505050505050565b600080614b81613a8a565b600489015460028a01549192507801000000000000000000000000000000000000000000000000900467ffffffffffffffff1690600090614bc29083615435565b9050600086118015614bd357508581115b15614bdf575084614c0c565b89547fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff16600160801b178a555b614c1c828263ffffffff6153a816565b8a60040160186101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506000614c506143ce565b9050606082604051908082528060200260200182016040528015614c7e578160200160208202803883390190505b509050606083604051908082528060200260200182016040528015614cad578160200160208202803883390190505b50905060005b84811015614d9a5760008e60020182880181548110614cce57fe5b9060005260206000200160009054906101000a90046001600160a01b0316905080848381518110614cfb57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050614d7a8f6003016000836001600160a01b03166001600160a01b0316815260200190815260200160002060000160009054906101000a900467ffffffffffffffff1667ffffffffffffffff16613e858e8d615aab90919063ffffffff16565b838381518110614d8657fe5b602090810291909101015250600101614cb3565b506060614da56134de565b6001600160a01b03166318ce8f568e8e866040518463ffffffff1660e01b8152600401808481526020018360ff1660ff16815260200180602001828103825283818151815260200191508051906020019060200280838360005b83811015614e17578181015183820152602001614dff565b5050505090500194505050505060006040518083038186803b158015614e3c57600080fd5b505afa158015614e50573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015614e7957600080fd5b810190808051640100000000811115614e9157600080fd5b82016020810184811115614ea457600080fd5b8151856020820283011164010000000082111715614ec157600080fd5b50509291905050509050615048846001600160a01b031663c67106f5898686866040518563ffffffff1660e01b8152600401808567ffffffffffffffff1667ffffffffffffffff168152602001806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b83811015614f52578181015183820152602001614f3a565b50505050905001848103835286818151815260200191508051906020019060200280838360005b83811015614f91578181015183820152602001614f79565b50505050905001848103825285818151815260200191508051906020019060200280838360005b83811015614fd0578181015183820152602001614fb8565b50505050905001975050505050505050602060405180830381600087803b158015614ffa57600080fd5b505af115801561500e573d6000803e3d6000fd5b505050506040513d602081101561502457600080fd5b81019080805190602001909291905050508f600501546153a890919063ffffffff16565b60058f01555092955050505050509695505050505050565b60008261506f575060006128ec565b8282028284828161507c57fe5b04146040518060400160405280601181526020017f4d4154485f4d554c5f4f564552464c4f5700000000000000000000000000000081525090613e2957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b6004850154600160801b900467ffffffffffffffff16156151235761537f565b80156151955760006151336143ce565b9050806001600160a01b0316636d1b229d836040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561517b57600080fd5b505af115801561518f573d6000803e3d6000fd5b50505050505b836152315785546001860154604080517f5f52d44e0000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152938416602482015260448101929092525191851691635f52d44e9160648082019260009290919082900301818387803b15801561521457600080fd5b505af1158015615228573d6000803e3d6000fd5b5050505061537f565b6000600286600101548161524157fe5b049050600087600101600187038154811061525857fe5b6000918252602082206006600890920201018054604080517f5f52d44e0000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152928316602482015260448101879052905192945090881692635f52d44e9260648084019382900301818387803b1580156152dc57600080fd5b505af11580156152f0573d6000803e3d6000fd5b5050506001820154604080517f5f52d44e0000000000000000000000000000000000000000000000000000000081526001600160a01b03888116600483015292831660248201526044810186905290519188169250635f52d44e91606480830192600092919082900301818387803b15801561536b57600080fd5b505af11580156119a5573d6000803e3d6000fd5b505050505050565b546001600160a01b0316151590565b600101546001600160a01b0316151590565b60408051808201909152601181527f4d4154485f4144445f4f564552464c4f5700000000000000000000000000000060208201526000908383019084821015613e2957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b6000828211156040518060400160405280601281526020017f4d4154485f5355425f554e444552464c4f570000000000000000000000000000815250906154c057604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5050900390565b6000806154d26143ce565b8454604080517fe9e67d670000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015267ffffffffffffffff909316602482015290519293506000929184169163e9e67d6791604480820192602092909190829003018186803b15801561554e57600080fd5b505afa158015615562573d6000803e3d6000fd5b505050506040513d602081101561557857600080fd5b5051604087015190915060009061559090839061441d565b905067ffffffffffffffff81166155ad57600093505050506139ca565b60006155ca886020015160a0015184615aab90919063ffffffff16565b9050836001600160a01b031663605da1b287836155e56144de565b6040805163ffffffff861660e01b81526001600160a01b039094166004850152602484019290925267ffffffffffffffff1660448301525160648083019260209291908290030181600087803b15801561563e57600080fd5b505af1158015615652573d6000803e3d6000fd5b505050506040513d602081101561566857600080fd5b505161567b5760009450505050506139ca565b6001600160a01b03861660009081526003880160205260409020805467ffffffffffffffff191667ffffffffffffffff841617905560058701546156bf90826153a8565b600588015550925050509392505050565b815160208301516040840151600091829161571991906103e8906157059067ffffffffffffffff89169063ffffffff61506016565b8161570c57fe5b049063ffffffff615aab16565b91508190509250925092565b60e081015182546000918291615752916801000000000000000090910467ffffffffffffffff1690615ac4565b9050600181166139ca576001019392505050565b600061271061577b848463ffffffff61506016565b8161578257fe5b049392505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526000906136a586825b6000806040516020818551602087016000895af18015615851573d801561583e57602081146158475761584f565b6001935061584f565b600183511493505b505b5090949350505050565b60408051808201909152601581527f55494e5436345f4e554d4245525f544f4f5f4249470000000000000000000000602082015260009067ffffffffffffffff8311156158ec57604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b5090919050565b60008267ffffffffffffffff168267ffffffffffffffff1611156040518060400160405280601481526020017f4d41544836345f5355425f554e444552464c4f57000000000000000000000000815250906154c057604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b60005b8181101561537f5760008382815181106159ab57fe5b6020908102919091018101516001600160a01b038116600090815260038801909252604090912080549192509067ffffffffffffffff16615a2f57600286018054600181018255600091825260209091200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384161790555b8054615a4c9067ffffffffffffffff16600163ffffffff613d8f16565b815467ffffffffffffffff191667ffffffffffffffff919091161781556040516001600160a01b0383169088908a907fbfd1b785c517ac3c709db5d7c9904052346df35e7069c1cb80f3dd966579d52290600090a45050600101615995565b600061271061577b8461ffff851663ffffffff61506016565b60408051808201909152601381527f4d41544836345f4d554c5f4f564552464c4f5700000000000000000000000000602082015260009067ffffffffffffffff8481169084160290680100000000000000008210613e2957604051600160e51b62461bcd0281526020600482018181528351602484015283519092839260449091019190850190808383600083156107bd5781810151838201526020016107a5565b604051806102400160405280615b7a615d95565b8152602001615b87615c2e565b8152602001600081525090565b60408051610100810182526000808252602082018190529091820190815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b815481835581811115613761576002028160020283600052602060002091820191016137619190615dd1565b604080516060810182526000808252602082018190529181019190915290565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081019190915290565b60405180606001604052806003906020820280388339509192915050565b6040518060a001604052806005906020820280388339509192915050565b60405180604001604052806002906020820280388339509192915050565b60405180608001604052806004906020820280388339509192915050565b815481835581811115613761576008028160080283600052602060002091820191016137619190615e21565b6040518060e001604052806000815260200160008152602001600067ffffffffffffffff16815260200160008019168152602001615d72615c0e565b905290565b6040518060e001604052806007906020820280388339509192915050565b6040518060a0016040528060006001600160a01b03168152602001600061ffff1681526020016000815260200160008152602001600081525090565b61130c91905b80821115615e1d5780547fff000000000000000000000000000000000000000000000000000000000000001681556000615e146001830182615ed6565b50600201615dd7565b5090565b61130c91905b80821115615e1d5780547fffffffffffffffffffffffffffffff0000000000000000000000000000000000168155600060018201819055615e6b6002830182615ef7565b5060006004820181905560058201556006810180547fffffffffffffffffffffff0000000000000000000000000000000000000000001690556007810180547fffffffffffffffffffff00000000000000000000000000000000000000000000169055600801615e27565b50805460008255600802906000526020600020908101906108029190615e21565b5080546000825590600052602060002090810190610802919061130c91905b80821115615e1d5760008155600101615f1656fea165627a7a723058209736511eab2676614d9c8070491a2225c53a409a0088a8ce0d8d76e3016800ad0029
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ee4650cbe7a2b23701d416f58b41d8b76b61779700000000000000000000000000000000000000000000000000000000000000510000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _controller (address): 0xee4650cBe7a2B23701D416f58b41D8B76b617797
Arg [1] : _maxJurorsPerDraftBatch (uint64): 81
Arg [2] : _skippedDisputes (uint256): 1
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000ee4650cbe7a2b23701d416f58b41d8b76b617797
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000051
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode Sourcemap
113689:77111:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;113689:77111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;145951:165;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;145951:165:0;;;;:::i;:::-;;144162:557;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;144162:557:0;;;;;;-1:-1:-1;;;;;144162:557:0;;:::i;128640:1423::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;128640:1423:0;;;;;;;;;;;;;;:::i;143375:395::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;143375:395:0;;:::i;123964:1288::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;123964:1288:0;;;;;;;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;123964:1288:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;123964:1288: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;123964:1288:0;;-1:-1:-1;123964:1288:0;-1:-1:-1;123964:1288:0;:::i;:::-;;;;;;;;;;;;;;;;113229:346;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;113229:346:0;;;;;;;;;;:::i;108315:96::-;;;:::i;:::-;;;;-1:-1:-1;;;;;108315:96:0;;;;;;;;;;;;;;120775:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;148924:1069;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;148924:1069:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;153626:816;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;153626:816:0;;;;;;;;;;;-1:-1:-1;;;;;153626:816:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;126472:1824;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;126472:1824:0;;:::i;150564:450::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;150564:450:0;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;150564:450:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;146350:315;;;:::i;:::-;;;;-1:-1:-1;;;;;146350:315:0;;;;;;;;;;;;;;;;;;;;;137293:2979;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;137293:2979:0;;;;;;;;;;;-1:-1:-1;;;;;137293:2979:0;;:::i;133909:2960::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;133909:2960:0;;;;;;;;;;;;:::i;130446:1675::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;130446:1675:0;;;;;;;;;;;;;;:::i;132441:535::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;132441:535:0;;:::i;:::-;;;;-1:-1:-1;;;;;132441:535:0;;;;;;;;;;;;;;;;;;;;;;145174:542;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;145174:542:0;;;;;;-1:-1:-1;;;;;145174:542:0;;:::i;125540:759::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;125540:759:0;;;;;;;;:::i;152006:1152::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;152006:1152:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;152006:1152:0;;;;;;;-1:-1:-1;152006:1152:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;152006:1152:0;-1:-1:-1;;152006:1152:0;147344:614;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;147344:614:0;;:::i;:::-;;;;-1:-1:-1;;;;;147344:614:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;147344:614:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;147344:614:0;-1:-1:-1;;147344:614:0;140570:2495;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;140570:2495:0;;;;;;;:::i;145951:165::-;107414:17;:15;:17::i;:::-;-1:-1:-1;;;;;107400:31:0;:10;-1:-1:-1;;;;;107400:31:0;;107433:32;;;;;;;;;;;;;;;;;107392:74;;;;;-1:-1:-1;;;;;107392: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;107392:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;146057:51;146084:23;146057:26;:51::i;:::-;145951:165;:::o;144162:557::-;122172:16;122191:9;:7;:9::i;:::-;122250:23;;;;;;;;;;;;;;;;;122172:28;;-1:-1:-1;122219:10:0;-1:-1:-1;;;;;122219:29:0;;;122211:63;;;;-1:-1:-1;;;;;122211:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;122211:63:0;;144252:23;144277:15;144296:22;144310:7;144296:13;:22::i;:::-;144251:67;;;;144329:20;;:::i;:::-;144352:26;144370:7;144352:17;:26::i;:::-;144329:49;;144487:89;144512:7;144521;144530:28;144560:6;:15;;;144487:24;:89::i;:::-;144587:13;144603:53;144623:7;144632;144641:6;144649;144603:19;:53::i;:::-;144587:69;;144684:1;144675:6;:10;;;144687:23;;;;;;;;;;;;;;;;;144667:44;;;;;-1:-1:-1;;;;;144667:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;144667:44:0;;122285:1;;;;144162:557;;;:::o;128640:1423::-;128736:10;128748:8;122829:39;122847:10;122859:8;122829:17;:39::i;:::-;128939:23;128965:8;128974:10;128965:20;;;;;;;;;;;;;;;;;;128939:46;;128996:20;;:::i;:::-;129019:26;129037:7;129019:17;:26::i;:::-;128996:49;;129056:89;129081:7;129090:8;129100:27;129129:6;:15;;;129056:24;:89::i;:::-;129275:16;129294:9;:7;:9::i;:::-;129275:28;;129314:14;129331:32;129342:10;129354:8;129331:10;:32::i;:::-;129314:49;;129374:24;129401:6;-1:-1:-1;;;;;129401:24:0;;129426:6;129401:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;129401:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;129401:32:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;129401:32:0;;-1:-1:-1;129452:29:0;;;;;;;;;;;:71;;-1:-1:-1;129485:38:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;129485:21:0;;;;;:38;;;;;;;;;;;;;;:21;:38;;;5:2:-1;;;;30:1;27;20:12;5:2;129485:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;129485:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;129485:38:0;129452:71;129525:27;;;;;;;;;;;;;;;;;129444:109;;;;;-1:-1:-1;;;;;129444:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;129444:109:0;;129604:31;129638:7;:14;;129653:8;129638:24;;;;;;;;;;;;;;;;;;;;;;;129697:12;;;129720:25;;129735:10;129720:25;;;;;129756:31;;-1:-1:-1;;;129756:31:0;;;;;;;;;;;;129803:45;;;;;;;129638:24;;-1:-1:-1;129697:12:0;;129830:8;;129818:10;;129803:45;;;;;;;;;129892:33;;:::i;:::-;129928:45;129949:5;129956:8;129966:6;129928:20;:45::i;:::-;129892:81;;129984:71;129999:10;130011:9;:18;;;130031:9;:23;;;129984:14;:71::i;:::-;122879:1;;;;;;;;128640:1423;;;;;:::o;143375:395::-;143438:23;143463:15;143482:22;143496:7;143482:13;:22::i;:::-;143437:67;;;;143515:20;;:::i;:::-;143538:26;143556:7;143538:17;:26::i;:::-;143515:49;;143673:89;143698:7;143707;143716:28;143746:6;:15;;;143673:24;:89::i;:::-;143375:395;;;;:::o;123964:1288::-;124092:7;107630:10;;107643:27;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;107630:10:0;107608;:33;107600:71;;;;-1:-1:-1;;;;;107600:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;107600:71:0;;124112:13;124128:20;:18;:20::i;:::-;124112:36;-1:-1:-1;116316:1:0;124167:38;;;;;;;:80;;-1:-1:-1;116316:1:0;124209:38;;;;;124167:80;124249:28;;;;;;;;;;;;;;;;;124159:119;;;;;-1:-1:-1;;;;;124159:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;124159:119:0;-1:-1:-1;124342:8:0;:17;;124322;;124342;;;;;;:::i;:::-;124322:37;;124370:23;124396:8;124405:9;124396:19;;;;;;;;;;;;;;;;;;;;;124426:26;;;;-1:-1:-1;;;;;124426:26:0;;;124463:42;;;;;;;;124516:29;;-1:-1:-1;;;124516:29:0;;;;;;;124396:19;-1:-1:-1;124558:20:0;;:::i;:::-;124581;124594:6;124581:12;:20::i;:::-;124634:15;;;;:38;;;;124715:29;;124558:43;;-1:-1:-1;124634:38:0;124612:19;;124704:41;;:10;;;;:41;:10;:41;:::i;:::-;124683:62;;124793:11;124761:69;;124783:8;-1:-1:-1;;;;;124761:69:0;124772:9;124761:69;124806:12;124820:9;;124761:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;;74:27;124761:69:0;;137:4:-1;117:14;;;-1:-1;;113:30;157:16;;;124761:69:0;;;;-1:-1:-1;124761:69:0;;-1:-1:-1;;;;;124761:69:0;124903:14;124919:17;124938;124959:47;124980:6;:11;;;124993:12;124959:20;:47::i;:::-;124902:104;;;;;;125017:84;125030:9;125041:21;125064:11;125077:12;125091:9;125017:12;:84::i;:::-;;125163:54;125186:8;125197;125207:9;125163:14;:54::i;:::-;-1:-1:-1;125235:9:0;;-1:-1:-1;;;;;;;;107682:1:0;123964:1288;;;;;;:::o;113229:346::-;112676:10;;;;;;;;;-1:-1:-1;;;;;112676:10:0;-1:-1:-1;;;;;112676:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;112676:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;112676:29:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;112676:29:0;112707:31;;;;;;;;;;;;;112676:29;112707:31;;;;-1:-1:-1;;;;;112662:43:0;:10;:43;112654:85;;;;-1:-1:-1;;;;;112654:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;112654:85:0;-1:-1:-1;113334:31:0;;;;;;113359:4;113334:31;;;;;;113316:15;;-1:-1:-1;;;;;113334:16:0;;;;;:31;;;;;;;;;;;;;;;:16;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;113334:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;113334:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;113334:31:0;113397:32;;;;;;;;;;;;;113334:31;113397:32;;;113334:31;;-1:-1:-1;113384:11:0;113376:54;;;;-1:-1:-1;;;;;113376:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;113376:54:0;-1:-1:-1;113449:33:0;-1:-1:-1;;;;;113449:19:0;;113469:3;113474:7;113449:33;:19;:33;:::i;:::-;113484:32;;;;;;;;;;;;;;;;;113441:76;;;;;-1:-1:-1;;;;;113441:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;113441:76:0;-1:-1:-1;113533:34:0;;;-1:-1:-1;;;;;113533:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;112750:1;113229:346;;:::o;108315:96::-;108363:10;108393;-1:-1:-1;;;;;108393:10:0;108315:96;;:::o;120775:36::-;;;-1:-1:-1;;;120775:36:0;;;;;:::o;148924:1069::-;149060:16;149091:19;149125;149159:21;149195:17;149227:21;149263:23;149301:21;149337:23;149006:10;149018:8;122829:39;122847:10;122859:8;122829:17;:39::i;:::-;149388:23;149414:8;149423:10;149414:20;;;;;;;;;;;;;;;;;;149388:46;;149453:97;149474:7;149483:8;149493:19;:17;:19::i;:::-;149514:26;149532:7;149514:17;:26::i;:::-;:35;;;149453:20;:97::i;:::-;149445:105;;149563:31;149597:7;:14;;149612:8;149597:24;;;;;;;;;;;;;;;;;;149563:58;;149644:5;:17;;;;;;;;;;;;149632:29;;149687:5;:18;;;;;;;;;;;;149672:33;;149731:5;:18;;;;;;;;;;;;149716:33;;149777:5;:20;;;;;;;;;;;;149760:37;;149820:5;:15;;;149808:27;;149865:5;:22;;;;;;;;;;;;149846:41;;149915:5;:20;;;;;;;;;;;;149898:37;;149964:5;:21;;;149946:39;;122879:1;;148924:1069;;;;;;;;;;;;;:::o;153626:816::-;153764:13;153779;153724:10;153736:8;122829:39;122847:10;122859:8;122829:17;:39::i;:::-;153810:23;153836:8;153845:10;153836:20;;;;;;;;;;;;;;;;;;153810:46;;153867:31;153901:7;:14;;153916:8;153901:24;;;;;;;;;;;;;;;;;;153867:58;;153936:20;;:::i;:::-;153959:26;153977:7;153959:17;:26::i;:::-;153936:49;;154002:33;154018:8;154028:6;154002:15;:33::i;:::-;153998:378;;;154061:30;154077:5;154084:6;154061:15;:30::i;:::-;154052:39;;153998:378;;;154124:30;154157:17;:15;:17::i;:::-;154254;;154213:59;;;;;;-1:-1:-1;;;;;154213:59:0;;;;;;;154254:17;;;;154213:59;;;;;;154124:50;;-1:-1:-1;154189:21:0;;154213:32;;;;;;:59;;;;;;;;;;;;;;;:32;:59;;;5:2:-1;;;;30:1;27;20:12;5:2;154213:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;154213:59:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;154213:59:0;154340:23;;;;154213:59;;-1:-1:-1;154296:68:0;;154213:59;;154296:28;:68::i;:::-;154287:77;;153998:378;;;-1:-1:-1;;;;;;154399:26:0;;;;;;;;:18;;;;:26;;-1:-1:-1;;154399:26:0;;;;:35;153626:816;;154399:35;;;;;;;-1:-1:-1;153626:816:0;;-1:-1:-1;;;153626:816:0:o;126472:1824::-;126530:10;122485:31;122505:10;122485:19;:31::i;:::-;126783:12;126798:8;:6;:8::i;:::-;126783:23;;126817:26;126846:8;:6;:8::i;:::-;-1:-1:-1;;;;;126846:33:0;;:35;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;126846:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;126846:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;126846:35:0;126935:19;;;;;;;;;;;;;126846:35;126935:19;;;126846:35;;-1:-1:-1;126900:28:0;;;:33;126892:63;;;;-1:-1:-1;;;;;126892:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;126892:63:0;;126966:20;126989:23;:21;:23::i;:::-;126966:46;;127077:23;127103:8;127112:10;127103:20;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;127142:13:0;;-1:-1:-1;;;127142:13:0;;;;:38;;;;;;;;;127182:27;;;;;;;;;;;;;;;;;127134:76;;;;;-1:-1:-1;;;;;127134:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;127134:76:0;-1:-1:-1;127351:1:0;127327:14;;:21;;-1:-1:-1;;127327:25:0;;;127309:15;;127327:25;;127397:23;;;;;;;;;;;;;;;;;;;;127452:17;;127518:28;;;;;;;;;;;;;;;;;;;;127397:23;;-1:-1:-1;127452:17:0;;;;;127518:28;127488;;;;;127480:67;;;;-1:-1:-1;;;;;127480:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;127480:67:0;;127558:27;127588:5;-1:-1:-1;;;;;127588:33:0;;:35;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;127588:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;127588:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;127588:35:0;;-1:-1:-1;127702:25:0;;:::i;:::-;127730:28;127746:11;127730:15;:28::i;:::-;127702:56;;127769:15;127787:97;127794:5;127801:82;127819:10;127831:7;127840:13;127855:19;127876:6;127801:17;:82::i;:::-;127787:6;:97::i;:::-;127769:115;;127955:10;127951:338;;;128095:18;;;:48;;-1:-1:-1;;128095:48:0;128116:27;;;128095:48;;;;;128158:41;;;;-1:-1:-1;;;128158:41:0;;;128219:58;;-1:-1:-1;;128239:10:0;;128219:58;;-1:-1:-1;;128219:58:0;127951:338;122527:1;;;;;;;;;;126472:1824;;:::o;150564:450::-;150687:13;150702:21;150725:13;150740:20;150647:10;150659:8;122829:39;122847:10;122859:8;122829:17;:39::i;:::-;150778:21;150802:8;150811:10;150802:20;;;;;;;;;;;;;;;;;;:27;;150830:8;150802:37;;;;;;;;;;;;;;;;:44;:37;;;;;:44;;;150867:12;150947;;;;;-1:-1:-1;;;;;150867:12:0;;;;150907:21;-1:-1:-1;;;150907:21:0;;;;;;;-1:-1:-1;150947:12:0;;;;-1:-1:-1;150986:20:0;;;;;;-1:-1:-1;150564:450:0;-1:-1:-1;;;;;;150564:450:0:o;146350:315::-;146399:14;146415:17;146445:20;146468:19;:17;:19::i;:::-;146445:42;;146498:20;;:::i;:::-;146521:27;146534:13;146521:12;:27::i;:::-;146498:50;;146584:73;146605:6;:11;;;146618:6;:15;;;:38;;;146584:20;:73::i;:::-;146559:98;;;;-1:-1:-1;146350:315:0;;-1:-1:-1;;;;146350:315:0:o;137293:2979::-;137390:10;137402:8;122829:39;122847:10;122859:8;122829:17;:39::i;:::-;137484:23;137510:8;137519:10;137510:20;;;;;;;;;;;;;;;;;;137484:46;;137541:31;137575:7;:14;;137590:8;137575:24;;;;;;;;;;;;;;;;;;137541:58;;137618:5;:22;;;;;;;;;;;;137642:23;;;;;;;;;;;;;;;;;137610:56;;;;;-1:-1:-1;;;;;137610:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;137610:56:0;-1:-1:-1;;;;;;137799:26:0;;137767:29;137799:26;;;:18;;;:26;;;;;;;;;137845:19;;137866:28;;;;;;;;;;;;;;;;;;;137799:26;137866:28;137845:19;;;;;137844:20;137836:59;;;;-1:-1:-1;;;;;137836:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;137836:59:0;-1:-1:-1;137922:17:0;;137946:33;;;;;;;;;;;;;;;;;;137922:17;;137906:74;;;;-1:-1:-1;;;;;137906:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;137906:74:0;-1:-1:-1;137991:26:0;;;;;;;;:19;138154:9;:7;:9::i;:::-;138135:28;;138174:14;138191:32;138202:10;138214:8;138191:10;:32::i;:::-;138275:19;;138242:61;;;;;;;;;;;;-1:-1:-1;;;138275:19:0;;;;;138242:61;;;;-1:-1:-1;;;;;138242:61:0;;;;;;;;;;;-1:-1:-1;138242:24:0;;;;;:61;;;;;;;;;;;;;;;:24;:61;;;5:2:-1;;;;30:1;27;20:12;5:2;138242:61:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;138242:61:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;138242:61:0;138305:34;;;;;;;;;;;;;138242:61;138305:34;;;;138234:106;;;;-1:-1:-1;;;;;138234:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;138234:106:0;-1:-1:-1;138379:21:0;;;;138353:23;138444:17;:15;:17::i;:::-;138411:50;-1:-1:-1;138688:20:0;138723:19;;138719:447;;139031:59;139055:5;139062:10;139074:15;139031:23;:59::i;:::-;139016:74;;139105:14;-1:-1:-1;;;;;139105:27:0;;139133:6;139141:12;139105:49;;;;;;;;;;;;;-1:-1:-1;;;;;139105:49:0;-1:-1:-1;;;;;139105:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;139105:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;139105:49:0;;;;138719:447;139225:20;;:::i;:::-;139248:26;139266:7;139248:17;:26::i;:::-;139225:49;;139534:18;139555:59;139579:5;139586:10;139598:5;:15;;;139555:23;:59::i;:::-;139534:80;;139625:11;:9;:11::i;:::-;-1:-1:-1;;;;;139625:18:0;;139644:6;:11;;;:17;;;139663:6;139671:10;139625:57;;;;;;;;;;;;;-1:-1:-1;;;;;139625:57:0;-1:-1:-1;;;;;139625:57:0;;;;;;-1:-1:-1;;;;;139625:57:0;-1:-1:-1;;;;;139625:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;139625:57:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;139625:57:0;;;;139741:33;139757:8;139767:6;139741:15;:33::i;:::-;139736:442;;139896:36;;:::i;:::-;139935:6;:15;;;139896:54;;139965:14;-1:-1:-1;;;;;139965:30:0;;140014:6;140117:14;:34;;;140088:14;:26;;;140059:14;:26;;;140039:5;:17;;;;;;;;;;;;:46;:75;:112;139965:201;;;;;;;;;;;;;-1:-1:-1;;;;;139965:201:0;-1:-1:-1;;;;;139965:201:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;139965:201:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;139965:201:0;;;;139736:442;;140221:8;140209:10;140195:69;140231:6;140239:12;140253:10;140195:69;;;;-1:-1:-1;;;;;140195:69:0;-1:-1:-1;;;;;140195:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;122879:1;;;;;;;;;;137293:2979;;;;;:::o;133909:2960::-;134018:10;134030:8;122829:39;122847:10;122859:8;122829:17;:39::i;:::-;134265:23;134291:8;134300:10;134291:20;;;;;;;;;;;;;;;;;;134265:46;;134330:8;134342:1;134330:13;:62;;;;134347:7;:14;;134373:1;134362:8;:12;134347:28;;;;;;;;;;;;;;;;;;;;;:45;-1:-1:-1;;;134347:45:0;;;;134330:62;134394:28;;;;;;;;;;;;;;;;;134322:101;;;;;-1:-1:-1;;;;;134322:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;134322:101:0;;134498:31;134532:7;:14;;134547:8;134532:24;;;;;;;;;;;;;;;;;;134498:58;;134576:5;:22;;;;;;;;;;;;134575:23;134600:27;;;;;;;;;;;;;;;;;134567:61;;;;;-1:-1:-1;;;;;134567:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;134567:61:0;;134718:20;;:::i;:::-;134741:26;134759:7;134741:17;:26::i;:::-;134718:49;;134778:17;134798:47;134817:7;134826:10;134838:6;134798:18;:47::i;:::-;134778:67;;134970:14;134987:32;134998:10;135010:8;134987:10;:32::i;:::-;135034:19;;;;134970:49;;-1:-1:-1;135034:19:0;;;;;135030:463;;135364:16;135383:9;:7;:9::i;:::-;135364:28;;135437:6;-1:-1:-1;;;;;135437:22:0;;135460:6;135468:11;135437:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;135437:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;135437:43:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;135437:43:0;135407:20;;;:74;;;;;;-1:-1:-1;;;135407:74:0;;;;;;;;;;;-1:-1:-1;135030:463:0;135505:18;135526:11;:9;:11::i;:::-;135565;;:17;135505:32;;-1:-1:-1;135597:33:0;135613:8;135565:6;135597:15;:33::i;:::-;135593:971;;;135842:21;135866:126;135895:5;135902:6;135910:11;135923:6;:15;;;:26;;;135951:15;135968:6;:23;;;135866:28;:126::i;:::-;135842:150;;136007:8;-1:-1:-1;;;;;136007:15:0;;136023:8;136033:10;136045:40;136071:13;136045:6;:11;;;:21;;;:25;;:40;;;;:::i;:::-;136007:79;;;;;;;;;;-1:-1:-1;;;;;136007:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;136007:79:0;;;;;;;-1:-1:-1;136007:79:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;136007:79:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;136007:79:0;;;;135593:971;;;;136523:29;;;;-1:-1:-1;;;136523:29:0;;;135593:971;136580:22;;-1:-1:-1;;;136580:22:0;;;;136576:286;;;136645:21;;;;136686:55;;;;;;;;136715:8;;136703:10;;136686:55;;;;;;;;;136756:94;136788:7;136797:5;136804:8;136814;136824;136834:15;136756:31;:94::i;130446:1675::-;130543:10;130555:8;122829:39;122847:10;122859:8;122829:17;:39::i;:::-;130763:23;130789:8;130798:10;130789:20;;;;;;;;;;;;;;;;;;130763:46;;130820:20;;:::i;:::-;130843:26;130861:7;130843:17;:26::i;:::-;130820:49;;130880:96;130905:7;130914:8;130924:34;130960:6;:15;;;130880:24;:96::i;:::-;131100:31;131134:7;:14;;131149:8;131134:24;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;131193:12:0;;;;131233:32;131244:10;131256:8;131233:10;:32::i;:::-;131284:21;;131216:49;;-1:-1:-1;131284:32:0;;;;-1:-1:-1;;;131284:21:0;;;;:32;;;;:77;;;131320:9;:7;:9::i;:::-;-1:-1:-1;;;;;131320:24:0;;131345:6;131353:7;131320:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;131320:41:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;131320:41:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;131320:41:0;131284:77;131363:27;;;;;;;;;;;;;;;;;131276:115;;;;;-1:-1:-1;;;;;131276:115:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;131276:115:0;;131464:33;;:::i;:::-;131500:45;131521:5;131528:8;131538:6;131500:20;:45::i;:::-;131464:81;;131556:28;131587:9;:25;;;131556:56;;131623:18;131644:107;131657:10;131669:15;131686:9;:19;;;131707:9;:22;;;131731:9;:19;;;131644:12;:107::i;:::-;131623:128;;131826:10;131811:6;:12;;;:25;;;;;-1:-1:-1;;;;;131811:25:0;;;;;-1:-1:-1;;;;;131811:25:0;;;;;;131870:7;131847:6;:20;;;:30;;;;;;;;;;;;;;;;;;131939:9;:19;;;131893:90;;131927:10;131915;131893:90;131960:9;:22;;;131893:90;;;;;;;;;;;;;;;;;;;;132035:78;132050:10;132062:9;:18;;;132082:9;:30;;;132035:14;:78::i;132441:535::-;132528:19;132549:17;132507:10;122485:31;122505:10;122485:19;:31::i;:::-;132579:23;132605:8;132614:10;132605:20;;;;;;;;;;;;;;;;;;;;;132646:15;;-1:-1:-1;;;;;132646:15:0;;-1:-1:-1;132605:20:0;-1:-1:-1;132674:20:0;;:::i;:::-;132697:26;132715:7;132697:17;:26::i;:::-;132674:49;;132748:47;132767:7;132776:10;132788:6;132748:18;:47::i;:::-;132734:61;-1:-1:-1;132829:18:0;132812:13;;-1:-1:-1;;;132812:13:0;;;;:35;;;;;;;;;132808:161;;132864:34;;;;;;;;132918:39;;;;;;132933:10;;132918:39;;-1:-1:-1;;132918:39:0;132808:161;122527:1;;132441:535;;;;:::o;145174:542::-;145250:6;145270:23;145295:15;145314:22;145328:7;145314:13;:22::i;:::-;145269:67;;;;145347:20;;:::i;:::-;145370:26;145388:7;145370:17;:26::i;:::-;145347:49;;145504:88;145529:7;145538;145547:27;145576:6;:15;;;145504:24;:88::i;:::-;145603:31;145637:7;:14;;145652:7;145637:23;;;;;;;;;;;;;;;;;;145603:57;;145678:30;145694:5;145701:6;145678:15;:30::i;:::-;145671:37;;;;;;145174:542;;;;;:::o;125540:759::-;107630:10;;107643:27;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;107630:10:0;107608;:33;107600:71;;;;-1:-1:-1;;;;;107600:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;107600:71:0;;125647:10;125659:1;122829:39;122847:10;122859:8;122829:17;:39::i;:::-;125673:23;125699:8;125708:10;125699:20;;;;;;;;;;;;;;;;;;125673:46;;125730:31;125764:7;:14;;125779:1;125764:17;;;;;;;;;;;;;;;;;125800:15;;125829:32;;;;;;;;;;;;;;;;;;;;125764:17;;;;;;-1:-1:-1;;;;;;125800:15:0;;;:27;;;;125792:70;;;;-1:-1:-1;;;;;125792:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;125792:70:0;;125947:13;125963:20;:18;:20::i;:::-;125947:36;-1:-1:-1;125994:21:0;126018:13;:10;;;126029:1;126018:13;:10;:13;:::i;:::-;126067:17;;126086:31;;;;;;;;;;;;;;;;;125994:37;;-1:-1:-1;126067:17:0;;;;126050:34;;;;126042:76;;;;-1:-1:-1;;;;;126042:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;126042:76:0;-1:-1:-1;126201:34:0;;-1:-1:-1;;126201:34:0;;;;;;;;;;;126251:40;;;;;;126272:10;;126251:40;;-1:-1:-1;;126251:40:0;122879:1;;;;107682;;125540:759;;:::o;152006:1152::-;152119:25;152159:28;152202;152245:14;152274:17;152306;152338:21;152374:28;152430:39;152448:10;152460:8;152430:17;:39::i;:::-;152482:23;152508:8;152517:10;152508:20;;;;;;;;;;;;;;;;;;152482:46;;152539:20;;:::i;:::-;152562:26;152580:7;152562:17;:26::i;:::-;152539:49;;152607:33;152623:8;152633:6;152607:15;:33::i;:::-;152642:20;;;;;;;;;;;;;;;;;152599:64;;;;;-1:-1:-1;;;;;152599:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;152599:64:0;;152676:31;152710:7;:14;;152725:8;152710:24;;;;;;;;;;;;;;;;;;152676:58;;152745:33;;:::i;:::-;152781:45;152802:5;152809:8;152819:6;152781:20;:45::i;:::-;152745:81;;152859:9;:19;;;152893:9;:22;;;152930:9;:25;;;152970:9;:18;;;153003:9;:19;;;153037:9;:19;;;153071:9;:23;;;153109:9;:30;;;152837:313;;;;;;;;;;;;;;;;;;;;152006:1152;;;;;;;;;;;:::o;147344:614::-;147442:19;147463:21;147486:18;147506:17;147525:19;147546;147412:10;122485:31;122505:10;122485:19;:31::i;:::-;147583:23;147609:8;147618:10;147609:20;;;;;;;;;;;;;;;;;;;;;147652:15;;;147925:14;;;:21;-1:-1:-1;;;;;147652:15:0;;;147696:23;;;;;;;;-1:-1:-1;;;;147738:13:0;;;;;-1:-1:-1;;;;147776:19:0;;;;-1:-1:-1;;;147925:25:0;;;;-1:-1:-1;;;;147821:20:0;;;;;;-1:-1:-1;147652:15:0;-1:-1:-1;;;;147344:614:0:o;140570:2495::-;140658:10;140670:8;122829:39;122847:10;122859:8;122829:17;:39::i;:::-;140752:23;140778:8;140787:10;140778:20;;;;;;;;;;;;;;;;;;140752:46;;140809:31;140843:7;:14;;140858:8;140843:24;;;;;;;;;;;;;;;;;;140809:58;;140886:5;:22;;;;;;;;;;;;140910:23;;;;;;;;;;;;;;;;;140878:56;;;;;-1:-1:-1;;;;;140878:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;140878:56:0;-1:-1:-1;141044:12:0;;;141075:21;141044:12;141075:13;:21::i;:::-;141098:24;;;;;;;;;;;;;;;;;141067:56;;;;;-1:-1:-1;;;;;141067:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;141067:56:0;-1:-1:-1;141143:14:0;;;;141159:34;;;;;;;;;;;;;;;;;;141143:14;;;;;141142:15;141134:60;;;;-1:-1:-1;;;;;141134:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;141134:60:0;-1:-1:-1;141222:4:0;141205:14;;:21;;;;;;;;141242:42;;141275:8;;141263:10;;141242:42;;141205:21;;141242:42;141333:20;;:::i;:::-;141356:26;141374:7;141356:17;:26::i;:::-;141333:49;;141393:33;;:::i;:::-;141429:45;141450:5;141457:8;141467:6;141429:20;:45::i;:::-;141502:18;;;;141551:19;;;;141605:23;;;;141670:30;;;;141393:81;;-1:-1:-1;141502:18:0;;141551:19;;141605:23;141485:14;141820:11;:9;:11::i;:::-;141799:32;;141847:26;141866:6;141847:18;:26::i;:::-;141842:135;;141916:12;;141890:54;;;;;;-1:-1:-1;;;;;141890:54:0;;;;;;;141916:12;;;141890:54;;;;;;;;;;;;:15;;;;;;:54;;;;;141916:12;;141890:54;;;;;;;;141916:12;141890:15;:54;;;5:2:-1;;;;30:1;27;20:12;5:2;141890:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;141890:54:0;;;;141959:7;;;;;;;;;;;;141842:135;142432:19;;-1:-1:-1;;;142432:19:0;;;;142412:17;142485:39;:13;142503:20;142485:17;:39::i;:::-;142539:21;;142462:62;;-1:-1:-1;142539:36:0;;;;-1:-1:-1;;;142539:21:0;;;;:36;142535:523;;;142618:12;;-1:-1:-1;;;;;142592:15:0;;;;;;142608:8;;142618:12;142632:27;:12;142649:9;142632:27;:16;:27;:::i;:::-;142592:68;;;;;;;;;;-1:-1:-1;;;;;142592:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;142592:68:0;;;;;;;-1:-1:-1;142592:68:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;142592:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;142592:68:0;;;;142535:523;;;142682:20;;;;:35;;;;-1:-1:-1;;;142682:20:0;;;;:35;142678:380;;;142760:12;;;;-1:-1:-1;;;;;142734:15:0;;;;;;142750:8;;142760:12;142774:27;:12;142791:9;142774:27;:16;:27;:::i;142678:380::-;142910:12;;142868:1;142856:13;;;-1:-1:-1;;;;;142884:15:0;;;;;;142900:8;;142910:12;142924:29;:13;142856;142924:17;:29::i;:::-;142884:70;;;;;;;;;;-1:-1:-1;;;;;142884:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;142884:70:0;;;;;;;-1:-1:-1;142884:70:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;142884:70:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;142995:12:0;;;;-1:-1:-1;;;;;142969:15:0;;;;-1:-1:-1;142969:15:0;;142985:8;;142995:12;143009:36;:20;143034:10;143009:36;:24;:36;:::i;:::-;142969:77;;;;;;;;;;-1:-1:-1;;;;;142969:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;142969:77:0;;;;;;;-1:-1:-1;142969:77:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;142969:77:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;142969:77:0;;;;142678:380;;122879:1;;;;;;;;;;;;140570:2495;;;;:::o;109417:115::-;109467:7;109494:10;;;;;;;;;-1:-1:-1;;;;;109494:10:0;-1:-1:-1;;;;;109494:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;109494:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;109494:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;109494:30:0;;-1:-1:-1;109417:115:0;:::o;165350:317::-;165475:30;;;;;;;;;;;;;;;;;165446:27;;;165438:68;;;;-1:-1:-1;;;;;165438:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;165438:68:0;-1:-1:-1;165552:22:0;;165522:78;;;165552:22;-1:-1:-1;;;165552:22:0;;;;;165522:78;;;;;;;;;;;;;;;;;;;;;165611:22;:48;;;;;;-1:-1:-1;;;165611:48:0;;;;;;;;;;;165350:317::o;110351:112::-;110393:9;110432:10;;;;;;;;;-1:-1:-1;;;;;110432:10:0;-1:-1:-1;;;;;110432:20:0;;:22;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;177715:289:0;177778:23;116710:66;177886:22;;177862:3;177851:14;;;177919:37;177851:14;177886:22;177919:17;:37::i;:::-;177977:8;177986:9;177977:19;;;;;;;;;;;;;;;;;;177967:29;;177715:289;;;;:::o;175586:235::-;175662:13;;:::i;:::-;175791:21;;175778:35;;-1:-1:-1;;;175791:21:0;;;;175778:12;:35::i;156353:386::-;156522:13;156538:20;:18;:20::i;:::-;156522:36;;156569:28;156600:57;156621:8;156631;156641:6;156649:7;156600:20;:57::i;:::-;156569:88;;156690:6;156676:20;;;;;;;;:10;:20;;;;;;;;;156698:32;;;;;;;;;;;;;;;;;156668:63;;;;;-1:-1:-1;;;;;156668:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;156668:63:0;;156353:386;;;;;;:::o;162618:388::-;162748:6;162767:31;162801:8;:15;;162817:8;162801:25;;;;;;;;;;;;;;;;;;162767:59;;162846:34;162862:8;162872:7;162846:15;:34::i;:::-;:152;;162942:56;162975:7;162984:5;162991:6;162942:32;:56::i;:::-;162846:152;;;162896:30;162912:5;162919:6;162896:15;:30::i;:::-;162839:159;162618:388;-1:-1:-1;;;;;;162618:388:0:o;177152:222::-;177242:31;177262:10;177242:19;:31::i;:::-;177303:8;177312:10;177303:20;;;;;;;;;;;;;;;;;;:27;;:34;;;;177292:8;:45;177339:26;;;;;;;;;;;;;;;;;177284:82;;;;;-1:-1:-1;;;;;177284:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;177284:82:0;;177152:222;;:::o;178387:146::-;178510:3;178496:17;;;;178495:30;;178387:146::o;167589:2859::-;167726:23;;:::i;:::-;167767:33;;:::i;:::-;167811:36;;:::i;:::-;-1:-1:-1;167850:16:0;;;;167988:19;;;;167965:18;;167939:23;;167965:43;;167988:19;167965:18;;;;167988:19;167965:43;:22;:43;:::i;:::-;167939:69;;168019:34;168056:80;168109:14;:26;;;168056:48;168077:14;:26;;;168056:16;:20;;;;:48;;;;:::i;:::-;:52;;;:80;:52;:80;:::i;:::-;168019:117;;168169:98;168233:14;:33;;;168169:59;168201:14;:26;;;168169:27;:31;;;;:59;;;;:::i;:98::-;168147:120;;;;168386:37;;;;:44;;168428:1;168386:44;:41;:44;:::i;:::-;168374:8;:56;168370:1784;;168549:25;168521;;;:53;168997:30;169030:17;:15;:17::i;:::-;168997:50;;169062:26;169091:14;-1:-1:-1;;;;;169091:35:0;;169127:9;:19;;;169091:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;169091:56:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;169091:56:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;169091:56:0;169233:24;;;;169091:56;;-1:-1:-1;169162:19:0;;169184:74;;169091:56;;169184:28;:74::i;:::-;169273:37;;;:22;;;:37;169509:12;;169162:96;;-1:-1:-1;169490:46:0;;169162:96;169490:18;:46::i;:::-;169467:19;;;169425:111;169446:19;;;169425:111;-1:-1:-1;;;;;169425:111:0;169426:18;;;169425:111;-1:-1:-1;168370:1784:0;;-1:-1:-1;;168370:1784:0;;169662:21;169634:25;;;:49;169841:56;169874:6;169882:14;169841:32;:56::i;:::-;169816:81;;:22;;;:81;;;170105:12;;170084:58;;:20;:58::i;:::-;170061:19;;;170019:123;170040:19;;;170019:123;-1:-1:-1;;;;;170019:123:0;170020:18;;;170019:123;168370:1784;170259:37;;;;170232:19;;;;:65;;;:26;:65;:::i;:::-;170206:23;;;:91;170368:44;;;;170341:19;;;;:72;;;:26;:72;:::i;:::-;170308:30;;;:105;-1:-1:-1;170308:9:0;;-1:-1:-1;;;167589:2859:0;;;;;;:::o;166041:277::-;166135:11;;166131:180;;166163:18;166184:11;:9;:11::i;:::-;166163:32;-1:-1:-1;166218:58:0;-1:-1:-1;;;;;166218:23:0;;166242:5;166163:32;166268:7;166218:58;:23;:58;:::i;:::-;166278:20;;;;;;;;;;;;;;;;;166210:89;;;;;-1:-1:-1;;;;;166210:89:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;166210:89:0;;166131:180;166041:277;;;:::o;108601:110::-;108649:6;108675:8;:6;:8::i;:::-;-1:-1:-1;;;;;108675:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;108675:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;104274:1432:0;104335:13;;:::i;:::-;104362:15;104388:23;;:::i;:::-;104422:37;;:::i;:::-;104470:22;;:::i;:::-;104503:29;;:::i;:::-;104543:41;;:::i;:::-;104595:25;104624:14;:12;:14::i;:::-;-1:-1:-1;;;;;104624:24:0;;104649:7;104624:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;104624:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;104624: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;104624:33:0;;;;;;;;-1:-1:-1;104624:33:0;;;;-1:-1:-1;104624:33:0;;;;-1:-1:-1;104624:33:0;;;;-1:-1:-1;104624:33:0;;;;-1:-1:-1;104624:33:0;;;;;-1:-1:-1;104624:33:0;-1:-1:-1;104670:20:0;;:::i;:::-;104717:198;;;;;;;;-1:-1:-1;;;;;104717:198:0;;;;;104895:8;;;;104717:198;;;;;;104784:8;;104717:198;;;;104817:8;;;;104717:198;;;;104851:8;;;;104717:198;;;;104703:212;;;104946:670;;;;;;;104991:23;;104946:670;;;;;;105042:23;;;;104946:670;;;;;;;;;;;104991:23;105114:1;105093:23;;;;104946:670;;;;;;105144:20;105165:1;105144:23;;;;;;;;;;;104946:670;;;;;;105202:20;105223:1;105202:23;;;;;;;;;;;104946:670;;;;;;105252:5;105258:1;105252:8;;;;;;;;;;;104946:670;;;;;;105299:12;105312:1;105299:15;;;;;;;;;;;104946:670;;;;;;105347:12;105360:1;105347:15;;;;;;;;;;;104946:670;;;;;;105452:12;105465:1;105452:15;;;;;;;;;;;104946:670;;;;;;105401:12;105414:1;105401:15;;;;;;;;;;;104946:670;;;;;;105506:23;105530:1;105506:26;;;;;;;;;;;104946:670;;;;105578:23;105602:1;105578:26;;;;;;;;;;;;;;;;104946:670;;;104928:15;;:688;105629:23;;;:43;;;;104928:15;104274:1432;-1:-1:-1;;;;;;;;104274:1432:0:o;8923:171::-;9046:18;;;;;;;;;;;;;;;;;8981:6;;9011:7;;;;9037;;;;;;;;;9029:36;;;;-1:-1:-1;;;;;9029:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;9029:36:0;-1:-1:-1;9085:1:0;8923:171;-1:-1:-1;;;8923:171:0:o;179769:643::-;179961:13;;180128:16;;;;179880:14;;;;180101:44;;:22;;;;:44;:26;:44;:::i;:::-;180089:56;;180250:26;180279:69;180333:13;180325:22;;180280:39;180301:7;:17;;;180280:7;:16;;;:20;;:39;;;;:::i;:::-;180279:45;:69;:45;:69;:::i;:::-;180250:98;-1:-1:-1;180371:33:0;:9;180250:98;180371:33;:13;:33;:::i;:::-;180359:45;;179769:643;;;;;;:::o;155022:828::-;155182:7;155240:23;155266:8;155275:10;155266:20;;;;;;;;;;;;;;;;;;155240:46;;155313:13;155297:7;:13;;;:29;;;;;;;;;;;;;;;;;;;;;;;;155378:15;155396:7;:14;;:23;;;;;;;;;;;:::i;:::-;155378:41;;155430:31;155464:7;:14;;155479:7;155464:23;;;;;;;;;;;;;;;;;;;;155498:32;;;155541:34;;;;;;155498:32;;;-1:-1:-1;;155498:32:0;;;;;;;155541:34;;;;155498:32;155586:15;;:28;;;155464:23;-1:-1:-1;155692:9:0;:7;:9::i;:::-;155673:28;;155712:14;155729:31;155740:10;155752:7;155729:10;:31::i;:::-;155793:23;;155771:46;;;;;;;;;;;;155793:23;;;;;;155771:46;;;;;;;-1:-1:-1;;;;;;155771:13:0;;;;;:46;;;;;-1:-1:-1;;155771:46:0;;;;;;;;-1:-1:-1;155771:13:0;:46;;;5:2:-1;;;;30:1;27;20:12;5:2;155771:46:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;155835:7:0;;155022:828;-1:-1:-1;;;;;;;;;;;;;155022:828:0:o;1908:320::-;2041:105;;;-1:-1:-1;;;;;2041:105:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;2041:105:0;;;;;;;;25:18:-1;;61:17;;2041:105:0;182:15:-1;2078:17:0;179:29:-1;160:49;;1992:4:0;;2164:56;2194:6;2041:105;2164:21;:56::i;:::-;2157:63;1908:320;-1:-1:-1;;;;;1908:320:0:o;109155:113::-;109207:6;109233:8;:6;:8::i;:::-;-1:-1:-1;;;;;109233:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;172132:3241:0;172285:17;172320:31;172354:8;:15;;172370:8;172354:25;;;;;;;;;;;;;;;;172514:15;;;:22;172354:25;;;;;;-1:-1:-1;172569:18:0;172551:14;;-1:-1:-1;;;172551:14:0;;;;:36;;;;;;;;;:72;;;-1:-1:-1;172602:21:0;:14;172621:1;172602:21;:18;:21;:::i;:::-;172591:8;:32;172551:72;172547:135;;;172647:23;172640:30;;;;;;172547:135;172888:18;;;;172866:17;;172837:26;;172866:41;;172888:18;172866:17;;;;172888:18;172866:41;:21;:41;:::i;:::-;172837:70;-1:-1:-1;172940:21:0;172922:14;;-1:-1:-1;;;172922:14:0;;;;:39;;;;;;;;;:72;;;;172975:19;172965:29;;:7;:29;;;172922:72;172918:137;;;173018:25;173011:32;;;;;;;172918:137;173209:22;173234:44;173258:7;:19;;;173234;:23;;;;:44;;;;:::i;:::-;173209:69;;173303:15;173293:25;;:7;:25;;;173289:93;;;173342:28;173335:35;;;;;;;;173289:93;173536:22;173561:40;173581:7;:19;;;173561:15;:19;;;;:40;;;;:::i;:::-;173536:65;;173626:15;173616:25;;:7;:25;;;173612:92;;;173665:27;173658:34;;;;;;;;;173612:92;173883:30;;;;173866:47;;173924:79;;;;173968:23;173961:30;;;;;;;;;;173924:79;174119:24;174146:27;174160:5;:12;;174146:13;:27::i;:::-;174119:54;;174184:34;174221:40;174241:7;:19;;;174221:15;:19;;;;:40;;;;:::i;:::-;174184:77;;174277:19;174272:378;;174470:27;174460:37;;:7;:37;;;174456:183;;;174525:27;174518:34;;;;;;;;;;;;174456:183;174600:23;174593:30;;;;;;;;;;;;174456:183;175016:32;175051:59;175083:7;:26;;;175051:27;:31;;;;:59;;;;:::i;:::-;175016:94;;175135:25;175125:35;;:7;:35;;;175121:109;;;175184:34;175177:41;;;;;;;;;;;;;175121:109;-1:-1:-1;175342:23:0;;172132:3241;-1:-1:-1;;;;;;;;;;;;;172132:3241:0:o;182104:171::-;182228:16;;;:39;;;-1:-1:-1;182217:50:0;182104:171::o;166896:166::-;-1:-1:-1;;;;;167020:27:0;166994:6;167020:27;;;:19;;;;;:27;;;;;:34;;;;166896:166::o;110972:140::-;111022:15;111073:10;;;;;;;;;-1:-1:-1;;;;;111073:10:0;-1:-1:-1;;;;;111073:28:0;;:30;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;182951:681:0;183063:6;183282:17;183265:14;:34;183261:75;;;-1:-1:-1;183323:1:0;183316:8;;183261:75;183543:81;183595:17;183544:48;116619:4;183577:14;183544:48;:32;:48;:::i;:::-;:68;;;;;;183543:79;:81::i;176723:149::-;176818:8;:15;176835:28;;;;;;;;;;;;;;;;;;176805;;176797:67;;;;-1:-1:-1;;;;;176797:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;176797:67:0;;176723:149;:::o;108875:121::-;108931:6;108957:8;:6;:8::i;:::-;-1:-1:-1;;;;;108957:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;105934:294:0;105998:18;;:::i;:::-;106030:14;106046:16;106064:17;106085:14;:12;:14::i;:::-;-1:-1:-1;;;;;106085:29:0;;106115:7;106085:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;106085:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;106085:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;106085:38:0;;;;;;;;;;;;106141:79;;106085:38;106141:79;;;;-1:-1:-1;;;;;106141:79:0;;;;;;;;;;;;;;;;;;;;;;105934:294;-1:-1:-1;;;;;105934:294:0:o;184194:447::-;184382:18;;:::i;:::-;-1:-1:-1;184425:208:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;184194:447::o;184999:1804::-;185138:19;;185192:21;;;;185099:4;185251:22;;185099:4;;185138:19;;;;;;;;;185192:21;;;;;;;-1:-1:-1;;;185251:22:0;;;185099:4;185311:32;185138:19;185192:21;185311:32;:16;:32;:::i;:::-;185284:59;;185473:22;185518:17;185498:37;;:17;:37;;;:77;;185558:17;185498:77;;;185538:17;185498:77;185473:102;;185618:24;;:::i;:::-;:341;;;;;;;;185668:12;:32;;;185660:41;;185618:341;;;;185716:12;:22;;;185618:341;;;;185761:12;:19;;;185753:28;;185618:341;;;;185804:14;185796:23;;185618:341;;;;185842:15;185834:24;;185618:341;;;;185881:12;185873:21;;185618:341;;;;185917:12;:19;;;:30;;;185909:39;;185618:341;;;;;186021:30;186054:17;:15;:17::i;:::-;186021:50;;186083:23;186108:21;186133:14;-1:-1:-1;;;;;186133:20:0;;186154:6;186133: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;186133:28:0;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;186133:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;186133:28:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;186133: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;186133: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;;186133:28:0;;;;;;;-1:-1:-1;186133:28:0;-1:-1:-1;186231:24:0;;-1:-1:-1;186258:41:0;;-1:-1:-1;186258:18:0;;;186133:28;186258:41;:18;:41;:::i;:::-;186310:21;;;:41;;;;;;;;;;;;186388:22;;186412:20;;;;186310:41;;-1:-1:-1;186362:102:0;;186310:21;186442:6;186450:13;186362:25;:102::i;:::-;186638:19;;;;:28;;;186493:33;;;;;;;;;186475:15;;186638:47;;186671:13;186638:47;:32;:47;:::i;:::-;186618:67;;186696:11;:9;:11::i;:::-;186715:19;;;;:28;186696:71;;;;;;-1:-1:-1;;;;;186696:71:0;;;;;;;186745:10;186696:71;;;;;;;;;;;;:18;;;;;;;:71;;;;;186715:28;;186696:71;;;;;;;;186715:28;186696:18;:71;;;5:2:-1;;;;30:1;27;20:12;5:2;186696:71:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;186785:10:0;;-1:-1:-1;;;;;;;;;;;;;;;184999:1804:0;;;;:::o;178919:295::-;179185:21;;;;179163:18;;179119:7;;179185:21;-1:-1:-1;;;179185:21:0;;;;;;179151:31;;:7;;179163:18;179151:31;:11;:31;:::i;:::-;:55;;;;;;;178919:295;-1:-1:-1;;;;178919:295:0:o;110044:116::-;110088:9;110127:10;;;;;;;;;-1:-1:-1;;;;;110127:10:0;-1:-1:-1;;;;;110127:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;157161:1414:0;157367:20;;157276:5;;-1:-1:-1;;;157367:20:0;;;;157359:33;157355:93;;-1:-1:-1;157416:20:0;;-1:-1:-1;;;157416:20:0;;;;157409:27;;157355:93;157609:19;157656:1;157631:8;:15;;:22;;;;:26;157609:48;;157668:90;157693:8;157703:11;157716:23;157741:7;:16;;;157668:24;:90::i;:::-;157998:35;158036:8;:15;;158052:11;158036:28;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;158103:16:0;;;;158168:25;158103:16;158168:13;:25::i;:::-;:60;;;;;158198:30;158217:10;158198:18;:30::i;:::-;158197:31;158168:60;158130:98;;158239:17;158259:30;:151;;158346:9;:7;:9::i;:::-;-1:-1:-1;;;;;158346:27:0;;158374:35;158385:10;158397:11;158374:10;:35::i;:::-;158346:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;158346:64:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;158346:64:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;158346:64:0;158259:151;;;158305:25;;-1:-1:-1;;;158305:25:0;;;;158259:151;158504:34;;;;-1:-1:-1;;;158504:34:0;;;;;;;;-1:-1:-1;158504:34:0;;157161:1414;-1:-1:-1;;;;;;;157161:1414:0:o;159483:2645::-;159761:7;159786:13;159802:20;:18;:20::i;:::-;159952;;;;160218:13;;;:20;159786:36;;-1:-1:-1;159952:20:0;;;;;;159923:26;;160218:44;;159952:20;160218:24;:44::i;:::-;160189:73;;160661:1;160643:15;:19;:59;;;;;160687:15;160666:18;:36;160643:59;160639:191;;;-1:-1:-1;160740:15:0;160639:191;;;160788:30;;;;-1:-1:-1;;;160788:30:0;;;160639:191;160927:42;:18;160950;160927:42;:22;:42;:::i;:::-;160897:6;:20;;;:73;;;;;;;;;;;;;;;;;;161110:30;161143:17;:15;:17::i;:::-;161110:50;;161171:23;161211:18;161197:33;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;161197:33:0;;161171:59;;161241:26;161284:18;161270:33;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;161270:33:0;-1:-1:-1;161241:62:0;-1:-1:-1;161319:9:0;161314:264;161338:18;161334:1;:22;161314:264;;;161378:13;161394:6;:13;;161429:1;161408:18;:22;161394:37;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;161394:37:0;161378:53;;161458:5;161446:6;161453:1;161446:9;;;;;;;;;;;;;:17;-1:-1:-1;;;;;161446:17:0;;;-1:-1:-1;;;;;161446:17:0;;;;;161493:73;161532:6;:19;;:26;161552:5;-1:-1:-1;;;;;161532:26:0;-1:-1:-1;;;;;161532:26:0;;;;;;;;;;;;:33;;;;;;;;;;;;161493:73;;:34;161515:11;161493:17;:21;;:34;;;;:::i;:73::-;161478:9;161488:1;161478:12;;;;;;;;;;;;;;;;;:88;-1:-1:-1;161358:3:0;;161314:264;;;;161861:27;161891:9;:7;:9::i;:::-;-1:-1:-1;;;;;161891:28:0;;161920:7;161929:12;161943:6;161891: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;161891:59:0;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;161891:59:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;161891:59:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;161891: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;161891: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;;161891:59:0;;;;;;161861:89;;161986:98;162013:14;-1:-1:-1;;;;;162013:28:0;;162042:6;162050;162058:9;162069:13;162013:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;162013: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;162013: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;162013:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;162013:70:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;162013:70:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;162013:70:0;;;;;;;;;;;;;;;;161986:6;:22;;;:26;;:98;;;;:::i;:::-;161961:22;;;:123;-1:-1:-1;162102:18:0;;-1:-1:-1;;;;;;159483:2645:0;;;;;;;;:::o;5384:460::-;5444:7;5688;5684:48;;-1:-1:-1;5719:1:0;5712:8;;5684:48;5756:7;;;5761:2;5756;:7;:2;5782:6;;;;;:12;5796:18;;;;;;;;;;;;;;;;;5774:41;;;;;-1:-1:-1;;;;;5774:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;188836:1630:0;189212:21;;;;-1:-1:-1;;;189212:21:0;;;;:25;189208:64;;189254:7;;189208:64;189597:20;;189593:161;;189634:30;189667:17;:15;:17::i;:::-;189634:50;;189699:14;-1:-1:-1;;;;;189699:25:0;;189725:16;189699:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;189699:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;189699:43:0;;;;189593:161;;190015:13;190011:448;;190086:16;;;190105;;;190045:77;;;;;;-1:-1:-1;;;;;190045:77:0;;;;;;;190086:16;;;190045:77;;;;;;;;;;;;:21;;;;;;:77;;;;;190086:16;;190045:77;;;;;;;;190086:16;190045:21;:77;;;5:2:-1;;;;30:1;27;20:12;5:2;190045:77:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;190045:77:0;;;;190011:448;;;190155:18;190195:1;190176:6;:16;;;:20;;;;;;190155:41;;190211:31;190245:8;:15;;190272:1;190261:8;:12;190245:29;;;;;;;;;;;;;;;:36;:29;;;;;:36;190329:22;;190296:68;;;;;;-1:-1:-1;;;;;190296:68:0;;;;;;;190329:22;;;190296:68;;;;;;;;;;;;190245:36;;-1:-1:-1;190296:21:0;;;;;;:68;;;;;;;;;;190245:29;190296:21;:68;;;5:2:-1;;;;30:1;27;20:12;5:2;190296:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;190412:22:0;;;;190379:68;;;;;;-1:-1:-1;;;;;190379:68:0;;;;;;;190412:22;;;190379:68;;;;;;;;;;;;:21;;;;-1:-1:-1;190379:21:0;;:68;;;;;190412:22;;190379:68;;;;;;;190412:22;190379:21;:68;;;5:2:-1;;;;30:1;27;20:12;5:2;190379:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;190011:448:0;188836:1630;;;;;;:::o;176049:129::-;176143:13;-1:-1:-1;;;;;176143:13:0;:27;;;176049:129::o;176395:134::-;176494:13;;;-1:-1:-1;;;;;176494:13:0;:27;;;176395:134::o;6665:175::-;6792:18;;;;;;;;;;;;;;;;;6725:7;;6757;;;;6783;;;;6775:36;;;;-1:-1:-1;;;;;6775:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;6412:177:0;6472:7;6506:2;6500;:8;;6510:19;;;;;;;;;;;;;;;;;6492:38;;;;;-1:-1:-1;;;;;6492:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;6492:38:0;-1:-1:-1;;6553:7:0;;;6412:177::o;163672:1475::-;163814:6;163929:30;163962:17;:15;:17::i;:::-;164055:18;;164014:60;;;;;;-1:-1:-1;;;;;164014:60:0;;;;;;;164055:18;;;;164014:60;;;;;;163929:50;;-1:-1:-1;163990:21:0;;164014:32;;;;;;:60;;;;;;;;;;;;;;;:32;:60;;;5:2:-1;;;;30:1;27;20:12;5:2;164014:60:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;164014:60:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;164014:60:0;164145:24;;;;164014:60;;-1:-1:-1;164085:13:0;;164101:69;;164014:60;;164101:28;:69::i;:::-;164085:85;-1:-1:-1;164259:11:0;;;164255:60;;164301:1;164287:16;;;;;;;164255:60;164544:23;164570:46;164588:7;:16;;;:27;;;164570:13;:17;;:46;;;;:::i;:::-;164544:72;;164743:14;-1:-1:-1;;;;;164743:28:0;;164772:6;164780:15;164797:23;:21;:23::i;:::-;164743:78;;;;;;;;;;-1:-1:-1;;;;;164743:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;164743:78:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;164743:78:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;164743:78:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;164743:78:0;164738:128;;164852:1;164838:16;;;;;;;;164738:128;-1:-1:-1;;;;;164991:27:0;;;;;;:19;;;:27;;;;;:43;;-1:-1:-1;;164991:43:0;;;;;;;165070:22;;;;:43;;165097:15;165070:26;:43::i;:::-;165045:22;;;:68;-1:-1:-1;165133:6:0;-1:-1:-1;;;163672:1475:0;;;;;:::o;180953:751::-;181143:13;;181553:27;;;;181499:16;;;;181062:14;;;;181471:110;;181553:27;116619:4;;181472:44;;:22;;;;:44;:26;:44;:::i;:::-;:75;;;;;;;181471:110;:81;:110;:::i;:::-;181459:122;;181687:9;181675:21;;180953:751;;;;;:::o;170996:539::-;171263:24;;;;171239:19;;171126:6;;;;171239:49;;:19;;;;;;;:23;:49::i;:::-;171217:71;-1:-1:-1;171425:25:0;;;171421:77;;171472:14;;171515:12;170996:539;-1:-1:-1;;;170996:539:0:o;24929:127::-;24996:7;24646:5;25023:14;:4;25032;25023:14;:8;:14;:::i;:::-;:25;;;;;;;24929:127;-1:-1:-1;;;24929:127:0:o;2416:378::-;2572:136;;;-1:-1:-1;;;;;2572:136:0;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;2572:136:0;;;;;;;;25:18:-1;;61:17;;2572:136:0;182:15:-1;2609:28:0;179:29:-1;160:49;;2519:4:0;;2726:60;2609:6;2572:136;3318:1346;3405:4;3422:8;3482:4;3476:11;3913:4;3841:3;3789:9;3783:16;3741:4;3730:9;3726:20;3675:1;3625:5;3567:3;3544:423;3986:14;;3983:2;;4098:14;4186:57;;;;4325:4;4320:189;;;;4091:519;;4186:57;4223:1;4216:8;;4186:57;;4320:189;4488:1;4482:3;4476:10;4473:17;4466:24;;4091:519;;3983:2;-1:-1:-1;4653:3:0;;3318:1346;-1:-1:-1;;;;3318:1346:0:o;10097:159::-;10193:27;;;;;;;;;;;;;;;;;10149:6;;10181:10;10176:15;;;10168:53;;;;-1:-1:-1;;;;;10168:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;10168:53:0;-1:-1:-1;10246:1:0;;10097:159;-1:-1:-1;10097:159:0:o;8674:173::-;8732:6;8765:2;8759:8;;:2;:8;;;;8769:19;;;;;;;;;;;;;;;;;8751:38;;;;;-1:-1:-1;;;;;8751:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;187462:744:0;187709:9;187704:495;187728:14;187724:1;:18;187704:495;;;187764:13;187780:7;187788:1;187780:10;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;187837:26:0;;187805:29;187837:26;;;:19;;;:26;;;;;;;187981:17;;187780:10;;-1:-1:-1;187837:26:0;187981:17;;187969:97;;188025:13;;;27:10:-1;;39:1;23:18;;45:23;;-1:-1;188025:25:0;;;;;;;;;;;;-1:-1:-1;;;;;188025:25:0;;;;;187969:97;188102:17;;:24;;:17;;188124:1;188102:24;:21;:24;:::i;:::-;188082:44;;-1:-1:-1;;188082:44:0;;;;;;;;;188146:41;;-1:-1:-1;;;;;188146:41:0;;;188171:8;;188159:10;;188146:41;;-1:-1:-1;;188146:41:0;-1:-1:-1;;187744:3:0;;187704:495;;24789:132;24852:7;24646:5;24879:23;:4;24888:13;;;24879:23;:8;:23;:::i;7866:244::-;8025:18;;;;;;;;;;;;;;;;;7924:6;;7969:11;7955;;;7969;;;7955:25;;8003:20;7999:24;;7991:53;;;;-1:-1:-1;;;;;7991:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;113689:77111:0;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;-1:-1:-1;113689:77111:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;113689:77111:0;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;113689:77111:0;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;-1:-1:-1;113689:77111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;113689:77111:0;;;-1:-1:-1;;113689:77111:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;113689:77111:0;;;-1:-1:-1;;113689:77111:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;113689:77111:0;;;-1:-1:-1;;113689:77111:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;113689:77111:0;;;-1:-1:-1;;113689:77111:0:o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;113689:77111:0;;;-1:-1:-1;;113689:77111:0:o;:::-;;;;;;;;;;-1:-1:-1;;;;;113689:77111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;113689:77111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Swarm Source
bzzr://9736511eab2676614d9c8070491a2225c53a409a0088a8ce0d8d76e3016800ad
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.