Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- CollectionManager
- Optimization enabled
- true
- Compiler version
- v0.8.4+commit.c7e474f2
- Optimization runs
- 3000
- Verified at
- 2022-08-26T14:15:43.554993Z
contracts/Core/CollectionManager.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "./interface/ICollectionManager.sol"; import "./interface/IBlockManager.sol"; import "./interface/IVoteManager.sol"; import "./storage/CollectionStorage.sol"; import "../Initializable.sol"; import "./parameters/child/CollectionManagerParams.sol"; import "./StateManager.sol"; contract CollectionManager is Initializable, CollectionStorage, StateManager, CollectionManagerParams, ICollectionManager { IBlockManager public blockManager; IVoteManager public voteManager; /** * @dev Emitted when a job has been created * @param id the id of the job that was created * @param timestamp time at which the job was created */ event JobCreated(uint16 indexed id, uint256 timestamp); /** * @dev Emitted when a collection has been created * @param id the id of the collection that was created * @param timestamp time at which the collection was created */ event CollectionCreated(uint16 indexed id, uint256 timestamp); /** * @dev Emitted when a job has been updated * @param id the id of the job that was updated * @param selectorType updated selector type of the job * @param epoch in which the job was updated * @param weight updated weight * @param power updated power * @param timestamp time at which the job was updated * @param selector updated selector * @param url updated url */ event JobUpdated( uint16 indexed id, JobSelectorType selectorType, uint32 epoch, uint8 weight, int8 power, uint256 timestamp, string selector, string url ); /** * @dev Emiited when there is a change in status of an existing collection * @param active updated status of the collection * @param id of the collection for which the status has been changed * @param epoch in which the status change took place * @param timestamp time at which the status change took place */ event CollectionActivityStatus(bool active, uint16 indexed id, uint32 epoch, uint256 timestamp); /** * @dev Emitted when a collection has been updated * @param id the id of the collection that was updated * @param power updated power * @param epoch in which the collection was updated * @param aggregationMethod updated aggregationMethod * @param tolerance updated tolerance * @param updatedJobIDs updated job ids for the collections * @param timestamp time at which the collection was updated */ event CollectionUpdated( uint16 indexed id, int8 power, uint32 epoch, uint32 aggregationMethod, uint32 tolerance, uint16[] updatedJobIDs, uint256 timestamp ); /** * @param voteManagerAddress The address of the Vote Manager contract * @param blockManagerAddress The address of the Block Manager contract */ function initialize(address voteManagerAddress, address blockManagerAddress) external initializer onlyRole(DEFAULT_ADMIN_ROLE) { voteManager = IVoteManager(voteManagerAddress); blockManager = IBlockManager(blockManagerAddress); } /** @notice Creates a Job in the network. * @dev Jobs are not directly reported by staker but just stores the URL and its corresponding details * @param weight specifies the weight the result of each job carries * @param power is used to specify the decimal shifts required on the result of a Job query * @param selectorType defines the selectorType of the URL. Can be JSON/XHTML * @param name of the URL * @param selector of the URL * @param url to be used for retrieving the data */ function createJob( uint8 weight, int8 power, JobSelectorType selectorType, string calldata name, string calldata selector, string calldata url ) external initialized onlyRole(COLLECTION_MODIFIER_ROLE) { require(weight <= 100, "Weight beyond max"); numJobs = numJobs + 1; jobs[numJobs] = Structs.Job(numJobs, uint8(selectorType), weight, power, name, selector, url); emit JobCreated(numJobs, block.timestamp); } /** * @notice Updates a Job in the network. * @param jobID the job id for which the details need to change * @param weight specifies the weight the result of each job carries * @param power is used to specify the decimal shifts required on the result of a Job query * @param selectorType defines the selectorType of the URL. Can be JSON/XHTML * @param selector of the URL * @param url to be used for retrieving the data */ function updateJob( uint16 jobID, uint8 weight, int8 power, JobSelectorType selectorType, string calldata selector, string calldata url ) external initialized onlyRole(COLLECTION_MODIFIER_ROLE) notState(State.Commit, buffer) { require(jobID != 0, "ID cannot be 0"); require(jobs[jobID].id == jobID, "Job ID not present"); require(weight <= 100, "Weight beyond max"); uint32 epoch = _getEpoch(); jobs[jobID].url = url; jobs[jobID].selector = selector; jobs[jobID].selectorType = uint8(selectorType); jobs[jobID].weight = weight; jobs[jobID].power = power; emit JobUpdated(jobID, selectorType, epoch, weight, power, block.timestamp, selector, url); } /** @notice Sets the status of the collection in the network. * @param assetStatus the status that needs to be set for the collection * @param id the collection id for which the status needs to change */ function setCollectionStatus(bool assetStatus, uint16 id) external initialized onlyRole(COLLECTION_MODIFIER_ROLE) checkState(State.Confirm, buffer) { require(id != 0, "ID cannot be 0"); require(id <= numCollections, "ID does not exist"); uint32 epoch = _getEpoch(); // slither-disable-next-line incorrect-equality,timestamp if (updateRegistryEpoch <= epoch) { _updateDelayedRegistry(); } if (assetStatus) { require(!collections[id].active, "ID already active"); numActiveCollections = numActiveCollections + 1; collections[id].active = assetStatus; } else { require(collections[id].active, "ID already inactive"); numActiveCollections = numActiveCollections - 1; collections[id].active = assetStatus; } updateRegistryEpoch = epoch + 1; _updateRegistry(); emit CollectionActivityStatus(collections[id].active, id, epoch, block.timestamp); voteManager.storeDepth(_getDepth()); // update depth now only, as from next epoch's commit it starts } /** @notice Creates a collection in the network. * @dev Collections are to be reported by staker by querying the URLs in each job assigned in the collection * and aggregating them based on the aggregation method specified in the collection * @param tolerance specifies the percentage by which the staker's value can deviate from the value decided by the network * @param power is used to specify the decimal shifts required on the result of a Collection * @param aggregationMethod specifies the aggregation method to be used by the stakers * @param jobIDs an array that holds which jobs should the stakers query for the stakers to report for the collection * @param name of the collection */ function createCollection( uint32 tolerance, int8 power, uint32 aggregationMethod, uint16[] memory jobIDs, string calldata name ) external initialized onlyRole(COLLECTION_MODIFIER_ROLE) checkState(State.Confirm, buffer) { require(jobIDs.length > 0, "no jobs added"); require(tolerance <= maxTolerance, "Invalid tolerance value"); uint32 epoch = _getEpoch(); // slither-disable-next-line incorrect-equality,timestamp if (updateRegistryEpoch <= epoch) { _updateDelayedRegistry(); } uint256 jobsLength = jobIDs.length; for (uint8 i = 0; i < jobsLength; i++) { require(jobs[jobIDs[i]].id == jobIDs[i], "job not present"); } numCollections = numCollections + 1; collections[numCollections] = Structs.Collection(true, numCollections, power, tolerance, aggregationMethod, jobIDs, name); numActiveCollections = numActiveCollections + 1; updateRegistryEpoch = epoch + 1; _updateRegistry(); emit CollectionCreated(numCollections, block.timestamp); _setIDName(name, numCollections); voteManager.storeDepth(_getDepth()); } /** @notice Updates a Collection in the network. * @param collectionID the collection id for which the details need to change * @param tolerance specifies the percentage by which the staker's value can deviate from the value decided by the network * @param aggregationMethod specifies the aggregation method to be used by the stakers * @param power is used to specify the decimal shifts required on the result of a Collection * @param jobIDs an array that holds which jobs should the stakers query for the stakers to report for the collection */ function updateCollection( uint16 collectionID, uint32 tolerance, uint32 aggregationMethod, int8 power, uint16[] memory jobIDs ) external initialized onlyRole(COLLECTION_MODIFIER_ROLE) notState(State.Commit, buffer) { require(jobIDs.length > 0, "no jobs added"); require(collectionID <= numCollections, "Collection ID not present"); require(tolerance <= maxTolerance, "Invalid tolerance value"); uint32 epoch = _getEpoch(); uint256 jobsLength = jobIDs.length; for (uint8 i = 0; i < jobsLength; i++) { require(jobs[jobIDs[i]].id == jobIDs[i], "job not present"); } collections[collectionID].power = power; collections[collectionID].tolerance = tolerance; collections[collectionID].aggregationMethod = aggregationMethod; collections[collectionID].jobIDs = jobIDs; emit CollectionUpdated(collectionID, power, epoch, aggregationMethod, tolerance, jobIDs, block.timestamp); } /// @inheritdoc ICollectionManager function updateDelayedRegistry() external override initialized onlyRole(REGISTRY_MODIFIER_ROLE) { _updateDelayedRegistry(); } /** * @param id the id of the job * @return job the Struct of the job information */ function getJob(uint16 id) external view returns (Structs.Job memory job) { require(id != 0, "ID cannot be 0"); require(id <= numJobs, "ID does not exist"); return jobs[id]; } /** * @param id the id of the collection * @return collection the Struct of the collection information */ function getCollection(uint16 id) external view returns (Structs.Collection memory collection) { require(id != 0, "ID cannot be 0"); require(id <= numCollections, "ID does not exist"); return collections[id]; } /// @inheritdoc ICollectionManager function getResult(bytes32 _name) external view override returns (uint256, int8) { uint16 id = ids[_name]; return getResultFromID(id); } /// @inheritdoc ICollectionManager function getCollectionStatus(uint16 id) external view override returns (bool) { return collections[id].active; } /// @inheritdoc ICollectionManager function getCollectionTolerance(uint16 id) external view override returns (uint32) { return collections[id].tolerance; } /// @inheritdoc ICollectionManager function getCollectionPower(uint16 id) external view override returns (int8) { require(id <= numCollections, "ID does not exist"); return collections[id].power; } /// @inheritdoc ICollectionManager function getCollectionID(bytes32 _hname) external view override returns (uint16) { return ids[_hname]; } /** * @return total number of jobs */ function getNumJobs() external view returns (uint16) { return numJobs; } /// @inheritdoc ICollectionManager function getNumCollections() external view override returns (uint16) { return numCollections; } /// @inheritdoc ICollectionManager function getNumActiveCollections() external view override returns (uint16) { return numActiveCollections; } /// @inheritdoc ICollectionManager function getUpdateRegistryEpoch() external view override returns (uint32) { return updateRegistryEpoch; } /// @inheritdoc ICollectionManager function getLeafIdOfCollection(uint16 id) external view override returns (uint16) { return collectionIdToLeafIdRegistry[id]; } /// @inheritdoc ICollectionManager function getLeafIdOfCollectionForLastEpoch(uint16 id) external view override returns (uint16) { return collectionIdToLeafIdRegistryOfLastEpoch[id]; } /// @inheritdoc ICollectionManager function getCollectionIdFromLeafId(uint16 leafId) external view override returns (uint16) { return leafIdToCollectionIdRegistry[leafId]; } /** * @return array of active collections */ function getActiveCollections() external view override returns (uint16[] memory) { uint16[] memory result = new uint16[](numActiveCollections); uint16 j = 0; for (uint16 i = 1; i <= numCollections; i++) { if (collections[i].active) { result[j] = i; j = j + 1; } } return result; } function getDepth() external view returns (uint256) { return _getDepth(); } /// @inheritdoc ICollectionManager function getResultFromID(uint16 _id) public view override returns (uint256, int8) { return (blockManager.getLatestResults(_id), collections[_id].power); } /** * @dev updates the collectionIdToLeafIdRegistry and leafIdToCollectionIdRegistry everytime a collection has been activated/deactivated/created * being called by setCollectionStatus and createCollection in CollectionManager */ function _updateRegistry() internal { uint16 j = 0; for (uint16 i = 1; i <= numCollections; i++) { if (collections[i].active) { collectionIdToLeafIdRegistry[i] = j; leafIdToCollectionIdRegistry[j] = i; j = j + 1; } else { collectionIdToLeafIdRegistry[i] = 0; } } } /** being called by claimBlockReward and confirmPreviousBlockEpoch in block manager by setCollectionStatus and createCollection in CollectionManager */ function _updateDelayedRegistry() internal { uint16 j = 0; for (uint16 i = 1; i <= numCollections; i++) { if (collections[i].active) { collectionIdToLeafIdRegistryOfLastEpoch[i] = j; j = j + 1; } else { collectionIdToLeafIdRegistryOfLastEpoch[i] = 0; } } } /** * @dev hashes the name of the collection and the hashed value is mapped to its corresponding collection ID */ function _setIDName(string calldata name, uint16 _id) internal { bytes32 _name = keccak256(abi.encodePacked(name)); require(ids[_name] == 0, "Collection exists with same name"); ids[_name] = _id; } /** * @dev calculates the current depth of the merkle tree that stakers have to submit at the time of commit/reveal */ function _getDepth() internal view returns (uint256 n) { // numActiveCollection is uint16, so further range not needed // Inspired and modified from : https://medium.com/coinmonks/math-in-solidity-part-5-exponent-and-logarithm-9aef8515136e // 100000; // >= 2**4 , n = 4 // 000010; // >= 2**1 // n = n+ 1 == 5 uint256 x = numActiveCollections; // X = 2 ** n ; // Optimised way // for (; x > 0; x >>= 1) { // if (x >= 2**8) { x >>= 8; n += 8; } // if (x >= 2**4) { x >>= 4; n += 4; } // if (x >= 2**2) { x >>= 2; n += 2; } // if (x >= 2**1) { x >>= 1; n += 1; } // if (x == 1) { x >>= 1; n += 1; } // } // for 6 // 110 // optimised version of above would return 2 // 000 // but we want 3 // so we have to give importance to 1(1)0 as well // as in our case result for 100 and 110 is diff // so thats why we have to go unoptimised way // I dont know if we can use above optimised way and somehow detect that in middle(1) as well // So thats why lets have above as commented // and check in new issue, if we could do so //6 //110, 6 //011, 3 //001, 1 //000, 0 // 8 // 1000 // 0100 // 0010 // 0001 // 0000 // Have tested function upto 2**16; bool flag = false; for (n = 0; x > 1; x >>= 1) { // O(n) 1<n<=16 if (x % 2 != 0) flag = true; // for that (1) n += 1; } if (flag) n++; } }
@openzeppelin/contracts/utils/Strings.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
@openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
contracts/Core/parameters/interfaces/ICollectionManagerParams.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface ICollectionManagerParams { /** * @notice changing the maximum percentage deviation allowed from medians for all collections * @dev can be called only by the the address that has the governance role * @param _maxTolerance updated value for maxTolerance */ function setMaxTolerance(uint32 _maxTolerance) external; /** * @notice changing buffer length between the states * @dev can be called only by the the address that has the governance role * @param _bufferLength updated value to be set for buffer */ function setBufferLength(uint8 _bufferLength) external; }
@openzeppelin/contracts/access/AccessControl.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
contracts/tokenization/IStakedTokenFactory.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface IStakedTokenFactory { /** * @dev a factory contract where the sRZR for a new staker is being deployed * @param stakeManagerAddress address of the stake Manager contract * @param stakedID id of the staker whom the sRZR is being deployed */ function createStakedToken(address stakeManagerAddress, uint32 stakedID) external returns (address); }
contracts/tokenization/StakedTokenFactory.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "./StakedToken.sol"; import "./IStakedTokenFactory.sol"; contract StakedTokenFactory is IStakedTokenFactory { /// @inheritdoc IStakedTokenFactory function createStakedToken(address stakeManagerAddress, uint32 stakerID) external override returns (address) { require(stakeManagerAddress != address(0x0), "zero address check"); StakedToken sToken = new StakedToken(stakeManagerAddress, stakerID); return address(sToken); } }
contracts/Core/parameters/child/CollectionManagerParams.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../interfaces/ICollectionManagerParams.sol"; import "../ACL.sol"; import "../../storage/Constants.sol"; abstract contract CollectionManagerParams is ACL, ICollectionManagerParams, Constants { uint8 public buffer = 5; /// @notice maximum percentage deviation allowed from medians for all collections uint32 public maxTolerance = 1_000_000; /// @inheritdoc ICollectionManagerParams function setMaxTolerance(uint32 _maxTolerance) external override onlyRole(GOVERNANCE_ROLE) { // slither-reason: Disabled across all params childs // as they are being called by governance contract only // and their before setting, we are emitting event // slither-disable-next-line events-maths maxTolerance = _maxTolerance; } function setBufferLength(uint8 _bufferLength) external override onlyRole(GOVERNANCE_ROLE) { // slither-reason: Disabled across all params childs // as they are being called by governance contract only // and their before setting, we are emitting event // slither-disable-next-line events-maths buffer = _bufferLength; } }
contracts/Core/parameters/interfaces/IRewardManagerParams.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface IRewardManagerParams { /** * @notice changing the percentage stake penalty to be given out for inactivity * @dev can be called only by the the address that has the governance role * @param _penaltyNotRevealNumerator updated value to be set for penaltyNotRevealNumerator */ function setPenaltyNotRevealNum(uint32 _penaltyNotRevealNumerator) external; /** * @notice changing the percentage age penalty to be given out for inactivity * @dev can be called only by the the address that has the governance role * @param _penaltyAgeNotRevealNumerator updated value to be set for penaltyAgeNotRevealNumerator */ function setPenaltyAgeNotRevealNum(uint32 _penaltyAgeNotRevealNumerator) external; /** * @notice changing the block reward given out to stakers * @dev can be called only by the the address that has the governance role * @param _blockReward updated value to be set for blockReward */ function setBlockReward(uint256 _blockReward) external; /** * @notice changing the maximum age a staker can have * @dev can be called only by the the address that has the governance role * @param _maxAge updated value to be set for maxAge */ function setMaxAge(uint32 _maxAge) external; /** * @notice changing the maximum percentage deviation allowed from medians for all collections * @dev can be called only by the the address that has the governance role * @param _maxTolerance updated value for maxTolerance */ function setMaxTolerance(uint32 _maxTolerance) external; /** * @notice changing maximum commission stakers can charge from delegators on their profits * @dev can be called only by the the address that has the governance role * @param _maxCommission updated value to be set for maxCommission */ function setMaxCommission(uint8 _maxCommission) external; }
@openzeppelin/contracts/utils/cryptography/ECDSA.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
contracts/Core/storage/CollectionStorage.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../../lib/Structs.sol"; contract CollectionStorage { enum JobSelectorType { JSON, XHTML } /// @notice mapping for JobID -> Job Info mapping(uint16 => Structs.Job) public jobs; /// @notice mapping for CollectionID -> Collection Info mapping(uint16 => Structs.Collection) public collections; // For next epoch : Penalties /// @notice delayed mappping collectionid -> leafId mapping(uint16 => uint16) public collectionIdToLeafIdRegistryOfLastEpoch; /// For this epoch : Disputes /// @notice mapping for collectionid -> leafId mapping(uint16 => uint16) public collectionIdToLeafIdRegistry; /// @notice mapping for leafId -> collectionid mapping(uint16 => uint16) public leafIdToCollectionIdRegistry; /// @notice mapping for name of collection in bytes32 -> collectionid mapping(bytes32 => uint16) public ids; /// @notice number of active collections in the network uint16 public numActiveCollections; /// @notice epoch in which the registry needs to be updated uint32 public updateRegistryEpoch; /// @notice number of collections in the network uint16 public numCollections; /// @notice number of jobs in the network uint16 public numJobs; }
contracts/Core/interface/ICollectionManager.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface ICollectionManager { /** * @notice updates the collectionIdToLeafIdRegistryOfLastEpoch resgistries. * @dev It is called by the blockManager when a block is confirmed. It is only called if there was a change in the * status of collections in the network */ function updateDelayedRegistry() external; /** * @param id the id of the collection * @return status of the collection */ function getCollectionStatus(uint16 id) external view returns (bool); /** * @return total number of active collections */ function getNumActiveCollections() external view returns (uint16); /** * @return ids of active collections */ function getActiveCollections() external view returns (uint16[] memory); /** * @param id the id of the collection * @return power of the collection */ function getCollectionPower(uint16 id) external view returns (int8); /** * @return total number of collections */ function getNumCollections() external view returns (uint16); /** * @param i the leafId of the collection * @return tolerance of the collection */ function getCollectionTolerance(uint16 i) external view returns (uint32); /** * @param id the id of the collection * @return the leafId of the collection from collectionIdToLeafIdRegistry */ function getLeafIdOfCollection(uint16 id) external view returns (uint16); /** * @param leafId, the leafId of the collection * @return the id of the collection */ function getCollectionIdFromLeafId(uint16 leafId) external view returns (uint16); /** * @param id the id of the collection * @return the leafId of the collection from collectionIdToLeafIdRegistryOfLastEpoch */ function getLeafIdOfCollectionForLastEpoch(uint16 id) external view returns (uint16); /** * @param _name the name of the collection in bytes32 * @return collection ID */ function getCollectionID(bytes32 _name) external view returns (uint16); /** * @notice returns the result of the collection based on the name sent by the client * @param _name the name of the collection in bytes32 * @return result of the collection * @return power of the resultant collection */ function getResult(bytes32 _name) external view returns (uint256, int8); /** * @notice returns the result of the collection based on the id sent by the client * @param _id the id of the collection * @return result of the collection * @return power of the resultant collection */ function getResultFromID(uint16 _id) external view returns (uint256, int8); /** * @return epoch in which the registry needs to be updated */ function getUpdateRegistryEpoch() external view returns (uint32); }
contracts/mocks/MerklePosAwareTest.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../lib/MerklePosAware.sol"; contract MerklePosAwareTest { function verifyMultiple( bytes32[][] memory proofs, bytes32 root, bytes32[] memory leaves, uint16[] memory leafId, uint256 depth, uint16 maxAssets ) external pure returns (bool) { return MerklePosAware.verifyMultiple(proofs, root, leaves, leafId, depth, maxAssets); } function getSequence(uint256 leafId, uint256 depth) external pure returns (bytes memory) { return MerklePosAware.getSequence(leafId, depth); } //function getSequence(uint256 leafId, uint256 depth) external // function verify( // bytes32[] memory proof, // bytes32 root, // bytes32 leaf, // uint16 leafId, // uint256 depth, // uint16 maxAssets // ) external pure returns (bool) { // return MerklePosAware.verify(proof, root, leaf, leafId, depth, maxAssets); // } // function getSequence(uint256 leafId, uint256 depth) external pure returns (string memory) { // return string(MerklePosAware.getSequence(leafId, depth)); // } }
contracts/Core/RewardManager.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "./interface/IBlockManager.sol"; import "./interface/IStakeManager.sol"; import "./interface/IVoteManager.sol"; import "./interface/IRewardManager.sol"; import "./interface/ICollectionManager.sol"; import "../tokenization/IStakedToken.sol"; import "../Initializable.sol"; import "./storage/Constants.sol"; import "./parameters/child/RewardManagerParams.sol"; /** @title RewardManager * @notice RewardManager gives penalties and rewards to stakers based on * their behaviour */ contract RewardManager is Initializable, Constants, RewardManagerParams, IRewardManager { IStakeManager public stakeManager; IVoteManager public voteManager; IBlockManager public blockManager; ICollectionManager public collectionManager; /** * @param stakeManagerAddress The address of the StakeManager contract * @param voteManagersAddress The address of the VoteManager contract * @param blockManagerAddress The address of the BlockManager contract * @param collectionManagerAddress The address of the CollectionManager contract */ function initialize( address stakeManagerAddress, address voteManagersAddress, address blockManagerAddress, address collectionManagerAddress ) external initializer onlyRole(DEFAULT_ADMIN_ROLE) { stakeManager = IStakeManager(stakeManagerAddress); voteManager = IVoteManager(voteManagersAddress); blockManager = IBlockManager(blockManagerAddress); collectionManager = ICollectionManager(collectionManagerAddress); } /// @inheritdoc IRewardManager function givePenalties(uint32 epoch, uint32 stakerId) external override initialized onlyRole(REWARD_MODIFIER_ROLE) { _givePenalties(epoch, stakerId); } /// @inheritdoc IRewardManager function giveBlockReward(uint32 stakerId, uint32 epoch) external override initialized onlyRole(REWARD_MODIFIER_ROLE) { Structs.Staker memory staker = stakeManager.getStaker(stakerId); IStakedToken sToken = IStakedToken(staker.tokenAddress); uint256 totalSupply = sToken.totalSupply(); uint256 stakerSRZR = sToken.balanceOf(staker._address); uint256 delegatorShare = blockReward - ((blockReward * stakerSRZR) / totalSupply); uint8 commissionApplicable = staker.commission < maxCommission ? staker.commission : maxCommission; uint256 stakerReward = (delegatorShare * commissionApplicable) / 100; stakeManager.setStakerStake(epoch, stakerId, StakeChanged.BlockReward, staker.stake, staker.stake + (blockReward - stakerReward)); stakeManager.setStakerReward( epoch, stakerId, StakerRewardChanged.StakerRewardAdded, staker.stakerReward, staker.stakerReward + stakerReward ); } /// @inheritdoc IRewardManager function giveInactivityPenalties(uint32 epoch, uint32 stakerId) external override initialized onlyRole(REWARD_MODIFIER_ROLE) { _giveInactivityPenalties(epoch, stakerId); } /** * @dev inactivity penalties are given to stakers if they have been inactive for more than the grace period. * For each inactive epoch, stakers lose their age by 1*10000 and their stake by penaltyNotRevealNum. * Activity is calculated based on the epoch the staker last revealed in. */ function _giveInactivityPenalties(uint32 epoch, uint32 stakerId) internal { uint32 epochLastRevealed = voteManager.getEpochLastRevealed(stakerId); Structs.Staker memory thisStaker = stakeManager.getStaker(stakerId); uint32 epochLastActive = thisStaker.epochFirstStakedOrLastPenalized < epochLastRevealed ? epochLastRevealed : thisStaker.epochFirstStakedOrLastPenalized; // penalize or reward if last active more than epoch - 1 uint32 inactiveEpochs = (epoch - epochLastActive == 0) ? 0 : epoch - epochLastActive - 1; uint256 previousStake = thisStaker.stake; uint256 newStake = thisStaker.stake; uint32 previousAge = thisStaker.age; uint32 newAge = thisStaker.age; if (inactiveEpochs > 0) { (newStake, newAge) = _calculateInactivityPenalties(inactiveEpochs, newStake, previousAge); } // uint256 currentStake = previousStake; if (newStake < previousStake) { stakeManager.setStakerEpochFirstStakedOrLastPenalized(epoch, stakerId); stakeManager.setStakerStake(epoch, stakerId, StakeChanged.InactivityPenalty, previousStake, newStake); } if (newAge < previousAge) { stakeManager.setStakerAge(epoch, stakerId, newAge, AgeChanged.InactivityPenalty); } } /** * @dev Penalties are given to stakers based their activity if they have been inactive for more than the grace period * and their votes in the previous epoch compared to the medians confirmed. Penalties on votes depend upon how far were * the staker's votes from the median value. There is tolerance being added for each collection thereby not penalizing * stakers of their vote was within the tolerance limits of the collection */ function _givePenalties(uint32 epoch, uint32 stakerId) internal { _giveInactivityPenalties(epoch, stakerId); Structs.Staker memory thisStaker = stakeManager.getStaker(stakerId); uint32 epochLastRevealed = voteManager.getEpochLastRevealed(stakerId); if (epochLastRevealed != 0 && epochLastRevealed < epoch - 1) { return; } uint64 age = thisStaker.age + 10000; // cap age to maxAge age = age > maxAge ? maxAge : age; Structs.Block memory _block = blockManager.getBlock(epochLastRevealed); uint16[] memory idsRevealedLastEpoch = _block.ids; uint256[] memory mediansLastEpoch = _block.medians; if (idsRevealedLastEpoch.length == 0) return; uint256 penalty = 0; for (uint16 i = 0; i < idsRevealedLastEpoch.length; i++) { // get leaf id from collection id, as voting happens w.r.t leaf ids // slither-disable-next-line calls-loop uint16 leafId = collectionManager.getLeafIdOfCollectionForLastEpoch(idsRevealedLastEpoch[i]); // slither-disable-next-line calls-loop uint256 voteValueLastEpoch = voteManager.getVoteValue(epoch - 1, stakerId, leafId); if ( voteValueLastEpoch != 0 ) // Only penalise if given asset revealed, please note here again revealed value of asset cant be zero { uint256 medianLastEpoch = mediansLastEpoch[i]; if (medianLastEpoch == 0) continue; //WARNING: unreachable. Can be removed uint256 prod = age * voteValueLastEpoch; // slither-disable-next-line calls-loop uint32 tolerance = collectionManager.getCollectionTolerance(idsRevealedLastEpoch[i]); tolerance = tolerance <= maxTolerance ? tolerance : maxTolerance; uint256 maxVoteTolerance = medianLastEpoch + ((medianLastEpoch * tolerance) / BASE_DENOMINATOR); uint256 minVoteTolerance = medianLastEpoch - ((medianLastEpoch * tolerance) / BASE_DENOMINATOR); // if (voteWeightLastEpoch > 0) { if (voteValueLastEpoch > maxVoteTolerance) { //penalty = age(vote/maxvote-1) penalty = penalty + (prod / maxVoteTolerance - age); } else if (voteValueLastEpoch < minVoteTolerance) { //penalty = age(1-vote/minvote) penalty = penalty + (age - prod / minVoteTolerance); } } } age = penalty > age ? 0 : age - uint32(penalty); stakeManager.setStakerAge(epoch, thisStaker.id, uint32(age), AgeChanged.VotingRewardOrPenalty); } /** @notice Calculates the stake and age inactivity penalties of the staker * @param epochs The difference of epochs where the staker was inactive * @param stakeValue The Stake that staker had in last epoch * @param ageValue The age that staker had in last epoch */ function _calculateInactivityPenalties( uint32 epochs, uint256 stakeValue, uint32 ageValue ) internal view returns (uint256, uint32) { uint256 penalty = ((epochs) * (stakeValue * penaltyNotRevealNum)) / BASE_DENOMINATOR; uint256 newStake = penalty < stakeValue ? stakeValue - penalty : 0; uint256 penaltyAge = (uint256(epochs) * (uint256(ageValue) * uint256(penaltyAgeNotRevealNum))) / BASE_DENOMINATOR; uint32 newAge = uint32(penaltyAge) < ageValue ? ageValue - uint32(penaltyAge) : 0; return (newStake, newAge); } }
contracts/tokenization/RAZOR.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; /** * @title RAZOR * @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator. * Note they can later distribute these tokens as they wish using `transfer` and other * `ERC20` functions. */ contract RAZOR is ERC20 { /** * @dev Constructor that gives msg.sender all of existing tokens. */ constructor(uint256 initialSupply) ERC20("RAZOR", "RAZOR") { _mint(msg.sender, initialSupply); } }
@openzeppelin/contracts/utils/introspection/IERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
contracts/IDelegator.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface IDelegator { /** * @dev updates the address of the Collection Manager contract from where the delegator will fetch * results of the oracle * @param newDelegateAddress address of the Collection Manager * @param newRandomNoManagerAddress address of the Random Number Manager */ function updateAddress(address newDelegateAddress, address newRandomNoManagerAddress) external; /** * @notice Allows Client to register for random number * Per request a rquest id is generated, which is binded to one epoch * this epoch is current epoch if Protocol is in commit state, or epoch + 1 if in any other state * @return requestId : unique request id */ function register() external returns (bytes32); /** * @dev using the hash of collection name, clients can query collection id with respect to its hash * @param _name bytes32 hash of the collection name * @return collection ID */ function getCollectionID(bytes32 _name) external view returns (uint16); /** * @dev using the hash of collection name, clients can query the result of that collection * @param _name bytes32 hash of the collection name * @return result of the collection and its power */ function getResult(bytes32 _name) external view returns (uint256, int8); /** * @dev using the collection id, clients can query the result of the collection * @param _id collection ID * @return result of the collection and its power */ function getResultFromID(uint16 _id) external view returns (uint256, int8); /** * @return ids of active collections in the oracle */ function getActiveCollections() external view returns (uint16[] memory); /** * @dev using the collection id, clients can query the status of collection * @param _id collection ID * @return status of the collection */ function getCollectionStatus(uint16 _id) external view returns (bool); /** * @notice Allows client to pull random number once available * Random no is generated from secret of that epoch and request id, its unique per requestid * @param requestId : A unique id per request */ function getRandomNumber(bytes32 requestId) external view returns (uint256); /** * @notice Fetch generic random number of last epoch * @return random number */ function getGenericRandomNumberOfLastEpoch() external view returns (uint256); /** * @dev using epoch, clients can query random number generated of the epoch * @param _epoch epoch * @return random number */ function getGenericRandomNumber(uint32 _epoch) external view returns (uint256); }
contracts/randomNumber/RandomNoManager.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../Core/parameters/child/RandomNoManagerParams.sol"; import "../Core/parameters/ACL.sol"; import "./IRandomNoClient.sol"; import "./IRandomNoProvider.sol"; import "../Initializable.sol"; import "../lib/Random.sol"; import "../Core/StateManager.sol"; import "./RandomNoStorage.sol"; /** * @title : RandomNoManager * @notice : Allows clients to register for random no, and pull it once available */ contract RandomNoManager is Initializable, StateManager, RandomNoStorage, RandomNoManagerParams, IRandomNoClient, IRandomNoProvider { event RandomNumberAvailable(uint32 epoch); /** * @param blockManagerAddress The address of the BlockManager Contract */ function initialize(address blockManagerAddress) external initializer onlyRole(DEFAULT_ADMIN_ROLE) { grantRole(SECRETS_MODIFIER_ROLE, blockManagerAddress); } /// @inheritdoc IRandomNoClient function register() external override initialized returns (bytes32 requestId) { uint32 epoch = _getEpoch(); nonce[msg.sender] = nonce[msg.sender] + 1; requestId = keccak256(abi.encodePacked(nonce[msg.sender], msg.sender)); requests[requestId] = epoch + 1; } /// @inheritdoc IRandomNoProvider function provideSecret(uint32 epoch, bytes32 _secret) external override initialized onlyRole(SECRETS_MODIFIER_ROLE) { /// @dev this require is added for extra assurance to clients, /// to give them assurance that once secret is set for epoch, it cant be changed /// as admin could always override this SECRETS_MODIFIER_ROLE role require(secrets[epoch] == 0x0, "Secret already set"); secrets[epoch] = _secret; emit RandomNumberAvailable(epoch); } /// @inheritdoc IRandomNoClient function getRandomNumber(bytes32 requestId) external view override returns (uint256) { uint32 epochOfRequest = requests[requestId]; return _generateRandomNumber(epochOfRequest, requestId); } /// @inheritdoc IRandomNoClient function getGenericRandomNumberOfLastEpoch() external view override returns (uint256) { uint32 epoch = _getEpoch(); return _generateRandomNumber(epoch - 1, 0); } /// @inheritdoc IRandomNoClient function getGenericRandomNumber(uint32 epoch) external view override returns (uint256) { return _generateRandomNumber(epoch, 0); } function _generateRandomNumber(uint32 epoch, bytes32 requestId) internal view returns (uint256) { bytes32 secret = secrets[epoch]; if (secret == 0x0) { revert("Random Number not genarated yet"); } else { return uint256(Random.prngHash(secret, requestId)); } } }
contracts/Core/parameters/child/BlockManagerParams.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../interfaces/IBlockManagerParams.sol"; import "../ACL.sol"; import "../../storage/Constants.sol"; abstract contract BlockManagerParams is ACL, IBlockManagerParams, Constants { /// @notice maximum number of best proposed blocks to be considered for dispute uint8 public maxAltBlocks = 5; uint8 public buffer = 5; /// @notice reward given to staker whose block is confirmed uint256 public blockReward = 100 * (10**18); /// @notice minimum amount of stake required to participate uint256 public minStake = 20000 * (10**18); /// @inheritdoc IBlockManagerParams function setMaxAltBlocks(uint8 _maxAltBlocks) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths maxAltBlocks = _maxAltBlocks; } function setBufferLength(uint8 _bufferLength) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths buffer = _bufferLength; } /// @inheritdoc IBlockManagerParams function setBlockReward(uint256 _blockReward) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths blockReward = _blockReward; } /// @inheritdoc IBlockManagerParams function setMinStake(uint256 _minStake) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths minStake = _minStake; } }
contracts/tokenization/IStakedToken.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IStakedToken is IERC20 { /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function mint( address account, uint256 amount, uint256 razorDeposited ) external returns (bool); /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function burn(address account, uint256 amount) external returns (bool); /// @notice Used in withdraw // At any time via calling this one can find out how much RZR was deposited for this much sRZR function getRZRDeposited(address delegator, uint256 sAmount) external view returns (uint256); }
contracts/Core/parameters/interfaces/IVoteManagerParams.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface IVoteManagerParams { /** * @notice changing minimum amount that to be staked for participation * @dev can be called only by the the address that has the governance role * @param _minStake updated value to be set for minStake */ function setMinStake(uint256 _minStake) external; /** * @notice changing maximum number of collections that can be assigned to the staker * @dev can be called only by the the address that has the governance role * @param _toAssign updated value to be set for toAssign */ function setToAssign(uint16 _toAssign) external; /** * @notice changing buffer length between the states * @dev can be called only by the the address that has the governance role * @param _bufferLength updated value to be set for buffer */ function setBufferLength(uint8 _bufferLength) external; }
contracts/Core/parameters/ACL.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "@openzeppelin/contracts/access/AccessControl.sol"; contract ACL is AccessControl { /** * @dev the deployer of the network is given to the default admin role which gives other roles to contracts */ constructor() { _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); } }
contracts/randomNumber/IRandomNoClient.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface IRandomNoClient { /** * @notice Allows Client to register for random number * Per request a rquest id is generated, which is binded to one epoch * this epoch is current epoch if Protocol is in commit state, or epoch + 1 if in any other state * @return requestId : unique request id */ function register() external returns (bytes32); /** * @notice Allows client to pull random number once available * Random no is generated from secret of that epoch and request id, its unique per requestid * @param requestId : A unique id per request */ function getRandomNumber(bytes32 requestId) external view returns (uint256); /** * @notice Allows client to get generic random number of last epoch * @return random number */ function getGenericRandomNumberOfLastEpoch() external view returns (uint256); /** * @notice Allows client to get generic random number of any epoch * @param epoch random no of which epoch * @return random number */ function getGenericRandomNumber(uint32 epoch) external view returns (uint256); }
contracts/Core/interface/IBlockManager.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../../lib/Structs.sol"; interface IBlockManager { /** * @notice if the proposed staker, whose block is valid and has the lowest iteration, does not call claimBlockReward() * then in commit state, the staker who commits first will confirm this block and will receive the block reward inturn * @param stakerId id of the staker that is confirming the block */ function confirmPreviousEpochBlock(uint32 stakerId) external; /** * @notice return the struct of the confirmed block * @param epoch in which this block was confirmed * @return _block : struct of the confirmed block */ function getBlock(uint32 epoch) external view returns (Structs.Block memory _block); /** * @notice this is to check whether a block was confirmed in a particular epoch or not * @param epoch for which this check is being done * @return true or false. true if a block has been confirmed, else false */ function isBlockConfirmed(uint32 epoch) external view returns (bool); /** * @notice Allows to get latest result of collection from id, used by delegator * @param id Collection ID */ function getLatestResults(uint16 id) external view returns (uint256); }
contracts/Core/parameters/interfaces/IBlockManagerParams.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface IBlockManagerParams { /** * @notice changing the maximum number of best proposed blocks to be considered for dispute * @dev can be called only by the the address that has the governance role * @param _maxAltBlocks updated value to be set for maxAltBlocks */ function setMaxAltBlocks(uint8 _maxAltBlocks) external; /** * @notice changing the block reward given out to stakers * @dev can be called only by the the address that has the governance role * @param _blockReward updated value to be set for blockReward */ function setBlockReward(uint256 _blockReward) external; /** * @notice changing minimum amount that to be staked for participation * @dev can be called only by the the address that has the governance role * @param _minStake updated value to be set for minStake */ function setMinStake(uint256 _minStake) external; /** * @notice changing buffer length between the states * @dev can be called only by the the address that has the governance role * @param _bufferLength updated value to be set for buffer */ function setBufferLength(uint8 _bufferLength) external; }
contracts/Delegator.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "./Core/StateManager.sol"; import "./Core/interface/ICollectionManager.sol"; import "./IDelegator.sol"; import "./randomNumber/IRandomNoClient.sol"; import "./Core/parameters/ACL.sol"; import "./Core/storage/Constants.sol"; import "./Pause.sol"; /** @title Delegator * @notice Delegator acts as a bridge between the client and the protocol */ contract Delegator is ACL, StateManager, Pause, IDelegator { ICollectionManager public collectionManager; IRandomNoClient public randomNoManager; /// @inheritdoc IDelegator function updateAddress(address newDelegateAddress, address newRandomNoManagerAddress) external override onlyRole(DEFAULT_ADMIN_ROLE) { require(newDelegateAddress != address(0x0) && newRandomNoManagerAddress != address(0x0), "Zero Address check"); collectionManager = ICollectionManager(newDelegateAddress); randomNoManager = IRandomNoClient(newRandomNoManagerAddress); } /// @inheritdoc IDelegator function register() external override whenNotPaused returns (bytes32) { return randomNoManager.register(); } /// @inheritdoc IDelegator function getActiveCollections() external view override whenNotPaused returns (uint16[] memory) { return collectionManager.getActiveCollections(); } /// @inheritdoc IDelegator function getCollectionStatus(uint16 _id) external view override whenNotPaused returns (bool) { return collectionManager.getCollectionStatus(_id); } /// @inheritdoc IDelegator function getCollectionID(bytes32 _hname) external view override whenNotPaused returns (uint16) { return collectionManager.getCollectionID(_hname); } /// @inheritdoc IDelegator function getResult(bytes32 _name) external view override whenNotPaused returns (uint256, int8) { return collectionManager.getResult(_name); } /// @inheritdoc IDelegator function getResultFromID(uint16 _id) external view override whenNotPaused returns (uint256, int8) { return collectionManager.getResultFromID(_id); } /// @inheritdoc IDelegator function getRandomNumber(bytes32 requestId) external view override whenNotPaused returns (uint256) { return randomNoManager.getRandomNumber(requestId); } /// @inheritdoc IDelegator function getGenericRandomNumberOfLastEpoch() external view override whenNotPaused returns (uint256) { return randomNoManager.getGenericRandomNumberOfLastEpoch(); } /// @inheritdoc IDelegator function getGenericRandomNumber(uint32 _epoch) external view override whenNotPaused returns (uint256) { return randomNoManager.getGenericRandomNumber(_epoch); } }
contracts/Core/storage/BlockStorage.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../../lib/Structs.sol"; contract BlockStorage { /// @notice mapping of epoch -> address -> dispute mapping(uint32 => mapping(address => Structs.Dispute)) public disputes; /// @notice mapping of epoch -> blockId -> block mapping(uint32 => mapping(uint32 => Structs.Block)) public proposedBlocks; /// @notice mapping of epoch->blockId mapping(uint32 => uint32[]) public sortedProposedBlockIds; /// @notice mapping of stakerId->epoch mapping(uint32 => uint32) public epochLastProposed; // @notice mapping for latest results of collection id->result mapping(uint16 => uint256) public latestResults; /// @notice total number of proposed blocks in an epoch // slither-disable-next-line constable-states uint32 public numProposedBlocks; /// @notice block index that is to be confirmed if not disputed // slither-disable-next-line constable-states int8 public blockIndexToBeConfirmed; // Index in sortedProposedBlockIds /// @notice mapping of epoch -> blocks mapping(uint32 => Structs.Block) public blocks; }
contracts/lib/MerklePosAware.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle trees (hash trees), */ library MerklePosAware { function verifyMultiple( bytes32[][] memory proofs, bytes32 root, bytes32[] memory leaves, uint16[] memory leafId, uint256 depth, uint16 maxAssets ) internal pure returns (bool) { for (uint256 i = 0; i < proofs.length; i++) { if (!verify(proofs[i], root, leaves[i], leafId[i], depth, maxAssets)) return false; } return true; } /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf, uint16 leafId, uint256 depth, uint16 maxAssets ) internal pure returns (bool) { bytes32 computedHash = leaf; bytes memory seq = bytes(getSequence(leafId, depth)); uint256 lastNode = maxAssets; uint256 myNode = leafId + 1; uint256 j = depth; uint256 i = 0; while (j > 0) { bytes32 proofElement = proof[i]; j--; //skip proof check if my node is last node and number of nodes on level is odd if (lastNode % 2 == 1 && lastNode == myNode) { myNode = myNode / 2 + (myNode % 2); // (myNode % 2) always equal to 1 lastNode = lastNode / 2 + (lastNode % 2); // (lastNode % 2) always equal to 1 continue; } // 0x30 is 0, 0x31 is 1 if (seq[j] == 0x30) { computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); } else { computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); } i++; myNode = myNode / 2 + (myNode % 2); lastNode = lastNode / 2 + (lastNode % 2); } return computedHash == root; } function getSequence(uint256 leafId, uint256 depth) internal pure returns (bytes memory) { bytes memory output = new bytes(depth); for (uint8 i = 0; i < depth; i++) { output[depth - 1 - i] = (leafId % 2 == 1) ? bytes1("1") : bytes1("0"); leafId /= 2; } return output; } }
contracts/Core/parameters/child/RandomNoManagerParams.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../interfaces/IRandomNoManagerParams.sol"; import "../ACL.sol"; import "../../storage/Constants.sol"; abstract contract RandomNoManagerParams is ACL, IRandomNoManagerParams, Constants { uint8 public buffer = 5; function setBufferLength(uint8 _bufferLength) external override onlyRole(GOVERNANCE_ROLE) { // slither-reason: Disabled across all params childs // as they are being called by governance contract only // and their before setting, we are emitting event // slither-disable-next-line events-maths buffer = _bufferLength; } }
contracts/Core/parameters/interfaces/IRandomNoManagerParams.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface IRandomNoManagerParams { /** * @notice changing buffer length between the states * @dev can be called only by the the address that has the governance role * @param _bufferLength updated value to be set for buffer */ function setBufferLength(uint8 _bufferLength) external; }
@openzeppelin/contracts/security/Pausable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
contracts/Core/parameters/child/VoteManagerParams.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../interfaces/IVoteManagerParams.sol"; import "../ACL.sol"; import "../../storage/Constants.sol"; abstract contract VoteManagerParams is ACL, IVoteManagerParams, Constants { uint8 public buffer = 5; /// @notice maximum number of collections that can be assigned to the staker uint16 public toAssign = 3; /// @notice minimum amount of stake required to participate uint256 public minStake = 20000 * (10**18); /// @inheritdoc IVoteManagerParams function setMinStake(uint256 _minStake) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths minStake = _minStake; } /// @inheritdoc IVoteManagerParams function setToAssign(uint16 _toAssign) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths toAssign = _toAssign; } function setBufferLength(uint8 _bufferLength) external override onlyRole(GOVERNANCE_ROLE) { // slither-reason: Disabled across all params childs // as they are being called by governance contract only // and their before setting, we are emitting event // slither-disable-next-line events-maths buffer = _bufferLength; } }
contracts/Core/StateManager.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "./storage/Constants.sol"; /** @title StateManager * @notice StateManager manages the state of the network */ contract StateManager is Constants { /** * @notice a check to ensure the epoch value sent in the function is of the currect epoch */ modifier checkEpoch(uint32 epoch) { // slither-disable-next-line incorrect-equality require(epoch == _getEpoch(), "incorrect epoch"); _; } /** * @notice a check to ensure the function was called in the state specified */ modifier checkState(State state, uint8 buffer) { // slither-disable-next-line incorrect-equality require(state == _getState(buffer), "incorrect state"); _; } /** * @notice a check to ensure the function was not called in the state specified */ modifier notState(State state, uint8 buffer) { // slither-disable-next-line incorrect-equality require(state != _getState(buffer), "incorrect state"); _; } /** @notice a check to ensure the epoch value sent in the function is of the currect epoch * and was called in the state specified */ modifier checkEpochAndState( State state, uint32 epoch, uint8 buffer ) { // slither-disable-next-line incorrect-equality require(epoch == _getEpoch(), "incorrect epoch"); // slither-disable-next-line incorrect-equality require(state == _getState(buffer), "incorrect state"); _; } function _getEpoch() internal view returns (uint32) { return (uint32(block.timestamp) / (EPOCH_LENGTH)); } function _getState(uint8 buffer) internal view returns (State) { uint8 lowerLimit = buffer; uint16 upperLimit = EPOCH_LENGTH / NUM_STATES - buffer; // slither-disable-next-line timestamp,weak-prng if (block.timestamp % (EPOCH_LENGTH / NUM_STATES) > upperLimit || block.timestamp % (EPOCH_LENGTH / NUM_STATES) < lowerLimit) { return State.Buffer; } // slither-disable-next-line timestamp,weak-prng uint8 state = uint8(((block.timestamp) / (EPOCH_LENGTH / NUM_STATES)) % (NUM_STATES)); return State(state); } }
@openzeppelin/contracts/token/ERC20/ERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer( address from, address to, uint256 amount ) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; } _balances[to] += amount; emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance( address owner, address spender, uint256 amount ) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
contracts/Core/storage/VoteStorage.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../../lib/Structs.sol"; contract VoteStorage { /// @notice mapping of stakerid -> commitment mapping(uint32 => Structs.Commitment) public commitments; // Epoch needs to be brought back due to AAR, each epoch would have different set of assets revealed /// @notice mapping of epoch -> stakerid -> assetid -> vote mapping(uint32 => mapping(uint32 => mapping(uint16 => uint256))) public votes; /// @notice mapping of epoch -> assetid -> weight mapping(uint32 => mapping(uint16 => uint256)) public totalInfluenceRevealed; /// @notice mapping of epoch -> assetid -> voteValue -> weight mapping(uint32 => mapping(uint16 => mapping(uint256 => uint256))) public voteWeights; /// @notice mapping of epoch-> stakerid->influence mapping(uint32 => mapping(uint32 => uint256)) public influenceSnapshot; /// @notice mapping of epoch-> stakerid->stake mapping(uint32 => mapping(uint32 => uint256)) public stakeSnapshot; /// @notice mapping of stakerid=> epochLastRevealed mapping(uint32 => uint32) public epochLastRevealed; /// @notice hash of last epoch and its block medians bytes32 public salt; /// @notice depth of a valid merkle tree uint256 public depth; // uint32 possible, pack if opp arise }
contracts/lib/Structs.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; library Structs { struct Commitment { uint32 epoch; bytes32 commitmentHash; } struct Staker { // Slot 1 bool acceptDelegation; bool isSlashed; uint8 commission; uint32 id; uint32 age; address _address; // Slot 2 address tokenAddress; uint32 epochFirstStakedOrLastPenalized; uint32 epochCommissionLastUpdated; // Slot 3 uint256 stake; uint256 stakerReward; } struct Lock { uint256 amount; //amount in sRZR/RZR uint256 unlockAfter; // Can be made uint32 later if packing is possible } struct BountyLock { uint32 redeemAfter; address bountyHunter; uint256 amount; //amount in RZR } struct Block { bool valid; uint32 proposerId; uint16[] ids; uint256 iteration; uint256 biggestStake; uint256[] medians; } struct Dispute { uint16 leafId; uint256 lastVisitedValue; uint256 accWeight; uint256 median; } struct Job { uint16 id; uint8 selectorType; // 0-1 uint8 weight; // 1-100 int8 power; string name; string selector; string url; } struct Collection { bool active; uint16 id; int8 power; uint32 tolerance; uint32 aggregationMethod; uint16[] jobIDs; string name; } struct AssignedAsset { uint16 leafId; uint256 value; } struct MerkleTree { Structs.AssignedAsset[] values; bytes32[][] proofs; bytes32 root; } }
contracts/Core/parameters/child/StakeManagerParams.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../interfaces/IStakeManagerParams.sol"; import "../ACL.sol"; import "../../storage/Constants.sol"; abstract contract StakeManagerParams is ACL, IStakeManagerParams, Constants { struct SlashNums { // percent bounty from staker's stake to be received by the bounty hunter uint32 bounty; // percent RAZOR burn from staker's stake uint32 burn; // percent from staker's stake to be kept by staker uint32 keep; } /// @notice a boolean, if true, the default admin role can remove all the funds incase of emergency bool public escapeHatchEnabled = true; uint8 public buffer = 5; /// @notice the number of epochs for which the sRZRs are locked for calling unstake() uint16 public unstakeLockPeriod = 1; /// @notice the number of epochs for which the RAZORs are locked after initiating withdraw uint16 public withdrawLockPeriod = 1; /// @notice the number of epochs where staker/delegator needs to initiate withdraw uint16 public withdrawInitiationPeriod = 5; /** * @notice percentage stake penalty from the locked amount for extending unstake lock * incase withdrawInitiationPeriod was missed */ uint32 public resetUnstakeLockPenalty = 100_000; /// @notice maximum commission stakers can charge from delegators on their profits uint8 public maxCommission = 20; /// @notice maximum commission change a staker can do uint8 public deltaCommission = 3; /// @notice the number of epochs for which a staker cant change commission once set/change uint16 public epochLimitForUpdateCommission = 100; /// @notice slashing params being used if staker is slashed. Slash Penalty = bounty + burned + kept == 100% SlashNums public slashNums = SlashNums(500_000, 9_500_000, 0); /// @notice minimum amount of stake required to participate uint256 public minStake = 20000 * (10**18); /// @notice minimum amount of stake required to become a staker uint256 public minSafeRazor = 10000 * (10**18); /// @inheritdoc IStakeManagerParams function setSlashParams( uint32 _bounty, uint32 _burn, uint32 _keep ) external override onlyRole(GOVERNANCE_ROLE) { require(_bounty + _burn + _keep <= BASE_DENOMINATOR, "params sum exceeds denominator"); // slither-disable-next-line events-maths slashNums = SlashNums(_bounty, _burn, _keep); } /// @inheritdoc IStakeManagerParams function setDeltaCommission(uint8 _deltaCommission) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths deltaCommission = _deltaCommission; } /// @inheritdoc IStakeManagerParams function setEpochLimitForUpdateCommission(uint16 _epochLimitForUpdateCommission) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths epochLimitForUpdateCommission = _epochLimitForUpdateCommission; } /// @inheritdoc IStakeManagerParams function setUnstakeLockPeriod(uint16 _unstakeLockPeriod) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths unstakeLockPeriod = _unstakeLockPeriod; } /// @inheritdoc IStakeManagerParams function setWithdrawLockPeriod(uint16 _withdrawLockPeriod) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths withdrawLockPeriod = _withdrawLockPeriod; } /// @inheritdoc IStakeManagerParams function setWithdrawInitiationPeriod(uint16 _withdrawInitiationPeriod) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths withdrawInitiationPeriod = _withdrawInitiationPeriod; } /// @inheritdoc IStakeManagerParams function setResetUnstakeLockPenalty(uint32 _resetUnstakeLockPenalty) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths resetUnstakeLockPenalty = _resetUnstakeLockPenalty; } /// @inheritdoc IStakeManagerParams function setMinStake(uint256 _minStake) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths minStake = _minStake; } /// @inheritdoc IStakeManagerParams function setMinSafeRazor(uint256 _minSafeRazor) external override onlyRole(GOVERNANCE_ROLE) { require(_minSafeRazor <= minStake, "minSafeRazor beyond minStake"); // slither-disable-next-line events-maths minSafeRazor = _minSafeRazor; } /// @inheritdoc IStakeManagerParams function setMaxCommission(uint8 _maxCommission) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths maxCommission = _maxCommission; } /// @inheritdoc IStakeManagerParams function disableEscapeHatch() external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths escapeHatchEnabled = false; } function setBufferLength(uint8 _bufferLength) external override onlyRole(GOVERNANCE_ROLE) { // slither-reason: Disabled across all params childs // as they are being called by governance contract only // and their before setting, we are emitting event // slither-disable-next-line events-maths buffer = _bufferLength; } }
contracts/mocks/InitializableMock.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../Initializable.sol"; /** * @title InitializableMock * @dev This contract is a mock to test initializable functionality */ contract InitializableMock is Initializable { bool public initializerRan; function initializeNested() external initializer { initialize(); } function initialize() public initializer { initializerRan = true; } }
contracts/Core/storage/StakeStorage.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../../lib/Structs.sol"; contract StakeStorage { enum LockType { Unstake, Withdraw } /// @notice total number of stakers // slither-disable-next-line constable-states uint32 public numStakers; /// @notice total number of bounties given out // slither-disable-next-line constable-states uint32 public bountyCounter; /// @notice mapping of staker address -> staker id info mapping(address => uint32) public stakerIds; /// @notice mapping of staker id -> staker info mapping(uint32 => Structs.Staker) public stakers; /// @notice mapping of staker/delegator address -> staker sRZR address -> LockType -> Lock info mapping(address => mapping(address => mapping(LockType => Structs.Lock))) public locks; /// @notice mapping of bounty id -> bounty lock info mapping(uint32 => Structs.BountyLock) public bountyLocks; /// @notice maturity calculation for each index = [math.floor(math.sqrt(i*10000)/2) for i in range(1,100)] uint16[101] public maturities = [ 50, 70, 86, 100, 111, 122, 132, 141, 150, 158, 165, 173, 180, 187, 193, 200, 206, 212, 217, 223, 229, 234, 239, 244, 250, 254, 259, 264, 269, 273, 278, 282, 287, 291, 295, 300, 304, 308, 312, 316, 320, 324, 327, 331, 335, 339, 342, 346, 350, 353, 357, 360, 364, 367, 370, 374, 377, 380, 384, 387, 390, 393, 396, 400, 403, 406, 409, 412, 415, 418, 421, 424, 427, 430, 433, 435, 438, 441, 444, 447, 450, 452, 455, 458, 460, 463, 466, 469, 471, 474, 476, 479, 482, 484, 487, 489, 492, 494, 497, 500, 502 ]; }
contracts/Pause.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "@openzeppelin/contracts/security/Pausable.sol"; import "./Core/parameters/ACL.sol"; import "./Core/storage/Constants.sol"; contract Pause is Pausable, ACL, Constants { function pause() external onlyRole(PAUSE_ROLE) { Pausable._pause(); } function unpause() external onlyRole(PAUSE_ROLE) { Pausable._unpause(); } }
contracts/Core/parameters/interfaces/IStakeManagerParams.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface IStakeManagerParams { /** * @notice changing slashing parameters * @dev can be called only by the the address that has the governance role * @param _bounty updated percent value to be set for bounty * @param _burn updated percent value to be set for burn * @param _keep updated percent value to be set for keep */ function setSlashParams( uint32 _bounty, uint32 _burn, uint32 _keep ) external; /** * @notice changing the number of epochs for which the RAZORs are locked after initiating withdraw * @dev can be called only by the the address that has the governance role * @param _withdrawLockPeriod updated value to be set for withdrawLockPeriod */ function setWithdrawLockPeriod(uint16 _withdrawLockPeriod) external; /** * @notice changing the number of epochs for which the sRZRs are locked for calling unstake() * @dev can be called only by the the address that has the governance role * @param _unstakeLockPeriod updated value to be set for unstakeLockPeriod */ function setUnstakeLockPeriod(uint16 _unstakeLockPeriod) external; /** * @notice changing the number of epochs where staker/delegator needs to initiate withdraw * @dev can be called only by the the address that has the governance role * @param _withdrawInitiationPeriod updated value to be set for withdrawInitiationPeriod */ function setWithdrawInitiationPeriod(uint16 _withdrawInitiationPeriod) external; /** * @notice changing percentage stake penalty from the locked amount for extending unstake lock * incase withdrawInitiationPeriod was missed * @dev can be called only by the the address that has the governance role * @param _resetUnstakePenalty updated value to be set for resetUnstakePenalty */ function setResetUnstakeLockPenalty(uint32 _resetUnstakePenalty) external; /** * @notice changing minimum amount that to be staked for participation * @dev can be called only by the the address that has the governance role * @param _minStake updated value to be set for minStake */ function setMinStake(uint256 _minStake) external; /** * @notice changing minimum amount that to be staked to become a staker * @dev can be called only by the the address that has the governance role * @param _minSafeRazor updated value to be set for minSafeRazor */ function setMinSafeRazor(uint256 _minSafeRazor) external; /** * @notice changing maximum commission stakers can charge from delegators on their profits * @dev can be called only by the the address that has the governance role * @param _maxCommission updated value to be set for maxCommission */ function setMaxCommission(uint8 _maxCommission) external; /** * @notice changing maximum commission change a staker can do * @dev can be called only by the the address that has the governance role * @param _deltaCommission updated value to be set for deltaCommission */ function setDeltaCommission(uint8 _deltaCommission) external; /** * @notice changing the number of epochs for which a staker cant change commission once set/change * @dev can be called only by the the address that has the governance role * @param _epochLimitForUpdateCommission updated value to be set for epochLimitForUpdateCommission */ function setEpochLimitForUpdateCommission(uint16 _epochLimitForUpdateCommission) external; /** * @notice sets escape hatch to false permanently * @dev can be called only by the the address that has the governance role */ function disableEscapeHatch() external; /** * @notice changing buffer length between the states * @dev can be called only by the the address that has the governance role * @param _bufferLength updated value to be set for buffer */ function setBufferLength(uint8 _bufferLength) external; }
contracts/randomNumber/RandomNoStorage.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; contract RandomNoStorage { /// @notice mapping of client address => nonce mapping(address => uint32) public nonce; /// @notice mapping of requestId => epoch mapping(bytes32 => uint32) public requests; /// @notice mapping of epoch => secrets mapping(uint32 => bytes32) public secrets; }
contracts/Core/VoteManager.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "./interface/IVoteManager.sol"; import "./interface/IStakeManager.sol"; import "./interface/IRewardManager.sol"; import "./interface/IBlockManager.sol"; import "./interface/ICollectionManager.sol"; import "./storage/VoteStorage.sol"; import "./parameters/child/VoteManagerParams.sol"; import "./StateManager.sol"; import "../Initializable.sol"; import "../lib/MerklePosAware.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; /** @title VoteManager * @notice VoteManager manages the commitments of votes of the stakers */ contract VoteManager is Initializable, VoteStorage, StateManager, VoteManagerParams, IVoteManager { IStakeManager public stakeManager; IRewardManager public rewardManager; IBlockManager public blockManager; ICollectionManager public collectionManager; /** * @dev Emitted when a staker commits * @param epoch epoch when the commitment was sent * @param stakerId id of the staker that committed * @param commitment the staker's commitment * @param timestamp time when the commitment was set for the staker */ event Committed(uint32 epoch, uint32 indexed stakerId, bytes32 commitment, uint256 timestamp); /** * @dev Emitted when a staker reveals * @param epoch epoch when the staker revealed * @param stakerId id of the staker that reveals * @param influence influence of the staker * @param values of the collections assigned to the staker * @param timestamp time when the staker revealed */ event Revealed(uint32 epoch, uint32 indexed stakerId, uint256 influence, Structs.AssignedAsset[] values, uint256 timestamp); /** * @dev Emitted when bountyHunter snitch the staker * @param epoch epoch when the bountyHunter snitch the staker * @param stakerId id of the staker that is snitched * @param bountyHunter address who will snitch the staker */ event Snitch(uint32 epoch, uint32 indexed stakerId, address indexed bountyHunter); /** * @param stakeManagerAddress The address of the StakeManager contract * @param rewardManagerAddress The address of the RewardManager contract * @param blockManagerAddress The address of the BlockManager contract * @param collectionManagerAddress The address of the CollectionManager contract */ function initialize( address stakeManagerAddress, address rewardManagerAddress, address blockManagerAddress, address collectionManagerAddress ) external initializer onlyRole(DEFAULT_ADMIN_ROLE) { stakeManager = IStakeManager(stakeManagerAddress); rewardManager = IRewardManager(rewardManagerAddress); blockManager = IBlockManager(blockManagerAddress); collectionManager = ICollectionManager(collectionManagerAddress); } /** * @notice stakers query the jobs in collection, aggregate and instead of revealing them instantly, * they need to submit a hash of their results which becomes their commitment and send it to the protocol * @dev After query and aggregation is done, the staker would have to construct a merkle tree of their votes. * * The commitment sent by the staker is hash of root of the merkle tree and seed, which * is the hash of the salt and the staker's secret. * * Collection allocation of each staker is done using seed and the staker would know in commit itself their allocations * but wouldn't know other staker's allocation unless they have their seed. Hence, it is advisable to fetch results for * only those collections that they have been assigned and set rest to 0 and construct a merkle tree accordingly * * Before the staker's commitment is registered, the staker confirms the block of the previous epoch incase the initial * proposer had not confirmed the block. The staker then gets the block reward if confirmed by the staker and is then * given out penalties based on their votes in the previous epoch or incase of inactivity. * * @param epoch epoch when the commitment was sent * @param commitment the commitment */ function commit(uint32 epoch, bytes32 commitment) external initialized checkEpochAndState(State.Commit, epoch, buffer) { require(commitment != 0x0, "Invalid commitment"); uint32 stakerId = stakeManager.getStakerId(msg.sender); require(!stakeManager.getStaker(stakerId).isSlashed, "VM : staker is slashed"); require(stakerId > 0, "Staker does not exist"); require(commitments[stakerId].epoch != epoch, "already commited"); // Switch to call confirm block only when block in previous epoch has not been confirmed // and if previous epoch do have proposed blocks // slither-disable-next-line reentrancy-events,reentrancy-no-eth if (!blockManager.isBlockConfirmed(epoch - 1)) { blockManager.confirmPreviousEpochBlock(stakerId); } // slither-disable-next-line reentrancy-events,reentrancy-no-eth rewardManager.givePenalties(epoch, stakerId); uint256 thisStakerStake = stakeManager.getStake(stakerId); if (thisStakerStake >= minStake) { commitments[stakerId].epoch = epoch; commitments[stakerId].commitmentHash = commitment; emit Committed(epoch, stakerId, commitment, block.timestamp); } } /** * @notice staker reveal the votes that they had committed to the protocol in the commit state. * Stakers would only reveal the collections they have been allocated, the rest of their votes wont matter * @dev stakers would need to submit their votes in accordance of how they were assigned to the staker. * for example, if they are assigned the following ids: [2,5,4], they would to send their votes in the following order only * The votes of other ids dont matter but they should not be passed in the values. * So staker would have to pass the proof path of the assigned values of the merkle tree, root of the merkle tree and * the values being revealed into a struct in the Structs.MerkleTree format. * @param epoch epoch when the revealed their votes * @param tree the merkle tree struct of the staker * @param signature staker's signature on the messageHash which calculates * the secret using which seed would be calculated and thereby checking for collection allocation */ function reveal( uint32 epoch, Structs.MerkleTree memory tree, bytes memory signature ) external initialized checkEpochAndState(State.Reveal, epoch, buffer) { uint32 stakerId = stakeManager.getStakerId(msg.sender); require(stakerId > 0, "Staker does not exist"); require(commitments[stakerId].epoch == epoch, "not committed in this epoch"); require(tree.values.length == toAssign, "values length mismatch"); bytes32 messageHash = keccak256(abi.encodePacked(msg.sender, epoch, block.chainid, "razororacle")); require(ECDSA.recover(ECDSA.toEthSignedMessageHash(messageHash), signature) == msg.sender, "invalid signature"); bytes32 secret = keccak256(signature); bytes32 seed = keccak256(abi.encode(salt, secret)); require(keccak256(abi.encode(tree.root, seed)) == commitments[stakerId].commitmentHash, "incorrect secret/value"); { uint256 stakerStake = stakeManager.getStake(stakerId); require(stakerStake >= minStake, "stake below minimum"); stakeSnapshot[epoch][stakerId] = stakerStake; } //below line also avoid double reveal attack since once revealed, commitment has will be set to 0x0 commitments[stakerId].commitmentHash = 0x0; uint256 influence = stakeManager.getInfluence(stakerId); influenceSnapshot[epoch][stakerId] = influence; uint16 max = collectionManager.getNumActiveCollections(); for (uint16 i = 0; i < tree.values.length; i++) { require(_isAssetAllotedToStaker(seed, i, max, tree.values[i].leafId), "Revealed asset not alloted"); // If Job Not Revealed before, like its not in same reveal batch of this // As it would be redundant to check // please note due to this job result cant be zero if (votes[epoch][stakerId][tree.values[i].leafId] == 0) { // Check if asset value is zero // Reason for doing this is, staker can vote 0 for assigned coll, and get away with penalties" require(tree.values[i].value != 0, "0 vote for assigned coll"); // reason to ignore : its internal lib not a external call // slither-disable-next-line calls-loop require( MerklePosAware.verify( tree.proofs[i], tree.root, keccak256(abi.encode(tree.values[i].value)), tree.values[i].leafId, depth, collectionManager.getNumActiveCollections() ), "invalid merkle proof" ); votes[epoch][stakerId][tree.values[i].leafId] = tree.values[i].value; voteWeights[epoch][tree.values[i].leafId][tree.values[i].value] = voteWeights[epoch][tree.values[i].leafId][tree.values[i].value] + influence; totalInfluenceRevealed[epoch][tree.values[i].leafId] = totalInfluenceRevealed[epoch][tree.values[i].leafId] + influence; } } epochLastRevealed[stakerId] = epoch; emit Revealed(epoch, stakerId, influence, tree.values, block.timestamp); } //bounty hunter revealing secret in commit state /** * @notice incase the staker's secret and root of the merkle tree is leaked before the staker reveals, * a bounty hunter can snitch on the staker and reveal the root and secret to the protocol * @dev when the staker is correctly snitched, their stake is slashed and the bounty hunter receives * a part of their stake based on the Slash Nums parameters. A staker can be snitched only in the commit state * @param epoch epoch when the bounty hunter snitched. * @param root of the staker's merkle tree * @param secret secret of the staker being snitched * @param stakerAddress the address of the staker */ function snitch( uint32 epoch, bytes32 root, bytes32 secret, address stakerAddress ) external initialized checkEpochAndState(State.Commit, epoch, buffer) { require(msg.sender != stakerAddress, "cant snitch on yourself"); uint32 thisStakerId = stakeManager.getStakerId(stakerAddress); require(thisStakerId > 0, "Staker does not exist"); require(commitments[thisStakerId].epoch == epoch, "not committed in this epoch"); // avoid innocent staker getting slashed due to empty secret require(secret != 0x0, "secret cannot be empty"); bytes32 seed = keccak256(abi.encode(salt, secret)); require(keccak256(abi.encode(root, seed)) == commitments[thisStakerId].commitmentHash, "incorrect secret/value"); //below line also avoid double reveal attack since once revealed, commitment has will be set to 0x0 commitments[thisStakerId].commitmentHash = 0x0; emit Snitch(epoch, thisStakerId, msg.sender); stakeManager.slash(epoch, thisStakerId, msg.sender); } /// @inheritdoc IVoteManager function storeSalt(bytes32 _salt) external override initialized onlyRole(SALT_MODIFIER_ROLE) { salt = _salt; } /// @inheritdoc IVoteManager function storeDepth(uint256 _depth) external override initialized onlyRole(DEPTH_MODIFIER_ROLE) { depth = _depth; } function getCommitment(uint32 stakerId) external view returns (Structs.Commitment memory commitment) { //epoch -> stakerid -> commitment return (commitments[stakerId]); } /// @inheritdoc IVoteManager function getVoteValue( uint32 epoch, uint32 stakerId, uint16 leafId ) external view override returns (uint256) { //epoch -> stakerid -> asserId return votes[epoch][stakerId][leafId]; } /// @inheritdoc IVoteManager function getVoteWeight( uint32 epoch, uint16 leafId, uint256 voteValue ) external view override returns (uint256) { //epoch -> leafId -> voteValue -> weight return (voteWeights[epoch][leafId][voteValue]); } /// @inheritdoc IVoteManager function getInfluenceSnapshot(uint32 epoch, uint32 stakerId) external view override returns (uint256) { //epoch -> stakerId return (influenceSnapshot[epoch][stakerId]); } /// @inheritdoc IVoteManager function getStakeSnapshot(uint32 epoch, uint32 stakerId) external view override returns (uint256) { //epoch -> stakerId return (stakeSnapshot[epoch][stakerId]); } /// @inheritdoc IVoteManager function getTotalInfluenceRevealed(uint32 epoch, uint16 leafId) external view override returns (uint256) { return (totalInfluenceRevealed[epoch][leafId]); } /// @inheritdoc IVoteManager function getEpochLastCommitted(uint32 stakerId) external view override returns (uint32) { return commitments[stakerId].epoch; } /// @inheritdoc IVoteManager function getEpochLastRevealed(uint32 stakerId) external view override returns (uint32) { return epochLastRevealed[stakerId]; } /// @inheritdoc IVoteManager function getSalt() external view override returns (bytes32) { return salt; } /** * @dev an internal function used to check whether the particular collection was allocated to the staker * @param seed hash of salt and staker's secret * @param iterationOfLoop positioning of the collection allocation sequence * @param leafId leafId of the collection that is being checked for allotment */ function _isAssetAllotedToStaker( bytes32 seed, uint16 iterationOfLoop, uint16 max, uint16 leafId ) internal view initialized returns (bool) { // max= numAssets, prng_seed = seed+ iteration of for loop if (_prng(keccak256(abi.encode(seed, iterationOfLoop)), max) == leafId) return true; return false; } /** * @dev an internal function used by _isAssetAllotedToStaker to check for allocation * @param prngSeed hash of seed and exact position in sequence * @param max total number of active collections */ function _prng(bytes32 prngSeed, uint256 max) internal pure returns (uint256) { uint256 sum = uint256(prngSeed); return (sum % max); } }
@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
contracts/Core/parameters/child/RewardManagerParams.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../interfaces/IRewardManagerParams.sol"; import "../ACL.sol"; import "../../storage/Constants.sol"; abstract contract RewardManagerParams is ACL, IRewardManagerParams, Constants { /// @notice percentage stake penalty to be given out for inactivity uint32 public penaltyNotRevealNum = 1000; /// @notice percentage age penalty to be given out for inactivity uint32 public penaltyAgeNotRevealNum = 100_000; /// @notice maximum age a staker can have uint32 public maxAge = 100 * 10000; /// @notice reward given to staker whose block is confirmed uint256 public blockReward = 100 * (10**18); /// @notice maximum percentage deviation allowed from medians for all collections uint32 public maxTolerance = 1_000_000; /// @notice maximum commission stakers can charge from delegators on their profits uint8 public maxCommission = 20; /// @inheritdoc IRewardManagerParams function setPenaltyNotRevealNum(uint32 _penaltyNotRevealNumerator) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths penaltyNotRevealNum = _penaltyNotRevealNumerator; } /// @inheritdoc IRewardManagerParams function setPenaltyAgeNotRevealNum(uint32 _penaltyAgeNotRevealNumerator) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths penaltyAgeNotRevealNum = _penaltyAgeNotRevealNumerator; } /// @inheritdoc IRewardManagerParams function setBlockReward(uint256 _blockReward) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths blockReward = _blockReward; } /// @inheritdoc IRewardManagerParams function setMaxAge(uint32 _maxAge) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths maxAge = _maxAge; } /// @inheritdoc IRewardManagerParams function setMaxTolerance(uint32 _maxTolerance) external override onlyRole(GOVERNANCE_ROLE) { // slither-reason: Disabled across all params childs // as they are being called by governance contract only // and their before setting, we are emitting event // slither-disable-next-line events-maths maxTolerance = _maxTolerance; } /// @inheritdoc IRewardManagerParams function setMaxCommission(uint8 _maxCommission) external override onlyRole(GOVERNANCE_ROLE) { // slither-disable-next-line events-maths maxCommission = _maxCommission; } }
contracts/tokenization/StakedToken.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "./IStakedToken.sol"; import "../Core/interface/IStakeManager.sol"; contract StakedToken is ERC20, IStakedToken { address private _owner; uint32 public stakerID; IStakeManager public stakeManager; /** * @notice Mapping to store the amount of RZR delegated or staked by user * hence at any time we can calculate gain = (current Rel * sRZRamount) - ((razorDeposited/balOfsRZR()) * sRZRamount) * razorDeposited/balOfsRZR() indicates, for 1 sRZR, how much you had put in */ mapping(address => uint256) public razorDeposited; modifier onlyOwner() { require(_owner == msg.sender, "Ownable: caller is not the owner"); _; } /** * @dev unique ERC20 sToken contract is deployed for every new staker that stakes into the protocol * @param stakeManagerAddress address of the stake manager contract * @param _stakerID the id of staker for whom the sToken is being deployed */ constructor(address stakeManagerAddress, uint32 _stakerID) ERC20("sRZR", "sRZR") { require(stakeManagerAddress != address(0), "zero Address Check"); _owner = stakeManagerAddress; stakeManager = IStakeManager(stakeManagerAddress); stakerID = _stakerID; } /// @inheritdoc IStakedToken function mint( address account, uint256 amount, uint256 _razorDeposited ) external override onlyOwner returns (bool) { razorDeposited[account] = razorDeposited[account] + _razorDeposited; _mint(account, amount); return true; } /// @inheritdoc IStakedToken function burn(address account, uint256 amount) external override onlyOwner returns (bool) { _burn(account, amount); return true; } /// @inheritdoc IStakedToken function getRZRDeposited(address user, uint256 sAmount) public view override returns (uint256) { require(balanceOf(user) >= sAmount, "Amount Exceeds Balance"); return ((sAmount * razorDeposited[user]) / balanceOf(user)); } /** * @dev an internal function that handles the amount os razor deposited based on sRZR token transfer. * If sRZR is transferred from to another account, razor deposited should also be transferred * @param from address from where sRZR is being transferred from * @param to address where sRZR is being transferred to * @param amount amount sRZR being transferred */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual override { //mint : addition, would happen in case of delegate or stake //burn : subtraction, would happeen when staker calls withdraw //transfer : add and sub // Mint case is handled up only if (to == address(0)) { //Burn uint256 propotionalRazorContribution = getRZRDeposited(from, amount); razorDeposited[from] = razorDeposited[from] - propotionalRazorContribution; } else if (from != address(0)) { uint256 propotionalRazorContribution = getRZRDeposited(from, amount); razorDeposited[from] = razorDeposited[from] - propotionalRazorContribution; razorDeposited[to] = razorDeposited[to] + propotionalRazorContribution; } stakeManager.srzrTransfer(from, to, amount, stakerID); } }
contracts/Core/parameters/Governance.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../../Initializable.sol"; import "./interfaces/IBlockManagerParams.sol"; import "./interfaces/IRewardManagerParams.sol"; import "./interfaces/IRandomNoManagerParams.sol"; import "./interfaces/IStakeManagerParams.sol"; import "./interfaces/IVoteManagerParams.sol"; import "./interfaces/ICollectionManagerParams.sol"; import "./../interface/IStakeManager.sol"; import "../storage/Constants.sol"; import "./ACL.sol"; // slither-reason : Disabled as slither is suggesting to have params interfaces to be inherited here // Though function signatures are same, meaning is diff // also two interfaces are going to have some common functions in this case // slither-disable-next-line missing-inheritance contract Governance is Initializable, ACL, Constants { IBlockManagerParams public blockManagerParams; IRewardManagerParams public rewardManagerParams; IStakeManagerParams public stakeManagerParams; IVoteManagerParams public voteManagerParams; ICollectionManagerParams public collectionManagerParams; IStakeManager public stakeManager; IRandomNoManagerParams public randomNoManagerParams; bytes32 public constant GOVERNER_ROLE = 0x704c992d358ec8f6051d88e5bd9f92457afedcbc3e2d110fcd019b5eda48e52e; /** * @notice emitted when any governance parameter value changes. * @param admin address of the admin * @param parameterName the parameter that is changing * @param valueChangedTo new value of the parameter * @param timestamp the exact time the parameter change took place */ event ParameterChanged(address indexed admin, string parameterName, uint256 valueChangedTo, uint256 timestamp); /** * @param blockManagerAddress The address of the BlockManager contract * @param rewardManagerAddress The address of the RewardManager contract * @param stakeManagerAddress The address of the StakeManager contract * @param voteManagerAddress The address of the VoteManager contract * @param collectionManagerAddress The address of the CollectionManager contract */ function initialize( address blockManagerAddress, address rewardManagerAddress, address stakeManagerAddress, address voteManagerAddress, address collectionManagerAddress, address randomNoManagerAddress ) external initializer onlyRole(DEFAULT_ADMIN_ROLE) { blockManagerParams = IBlockManagerParams(blockManagerAddress); rewardManagerParams = IRewardManagerParams(rewardManagerAddress); stakeManagerParams = IStakeManagerParams(stakeManagerAddress); voteManagerParams = IVoteManagerParams(voteManagerAddress); collectionManagerParams = ICollectionManagerParams(collectionManagerAddress); stakeManager = IStakeManager(stakeManagerAddress); randomNoManagerParams = IRandomNoManagerParams(randomNoManagerAddress); } /** * @notice changing the percentage stake penalty to be given out for inactivity * @dev can be called only by the the address that has the governer role * @param _penaltyNotRevealNumerator updated value to be set for penaltyNotRevealNumerator */ function setPenaltyNotRevealNum(uint32 _penaltyNotRevealNumerator) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "penaltyNotRevealNum", _penaltyNotRevealNumerator, block.timestamp); rewardManagerParams.setPenaltyNotRevealNum(_penaltyNotRevealNumerator); } /** * @notice changing the percentage age penalty to be given out for inactivity * @dev can be called only by the the address that has the governer role * @param _penaltyAgeNotRevealNumerator updated value to be set for penaltyAgeNotRevealNumerator */ function setPenaltyAgeNotRevealNum(uint32 _penaltyAgeNotRevealNumerator) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "penaltyAgeNotRevealNum", _penaltyAgeNotRevealNumerator, block.timestamp); rewardManagerParams.setPenaltyAgeNotRevealNum(_penaltyAgeNotRevealNumerator); } /** * @notice changing slashing parameters * @dev can be called only by the the address that has the governer role * @param _bounty updated percent value to be set for bounty * @param _burn updated percent value to be set for burn * @param _keep updated percent value to be set for keep */ function setSlashParams( uint32 _bounty, uint32 _burn, uint32 _keep ) external initialized onlyRole(GOVERNER_ROLE) { require(_bounty + _burn + _keep <= BASE_DENOMINATOR, "Slash nums addtion exceeds 10mil"); emit ParameterChanged(msg.sender, "bountySlashNum", _bounty, block.timestamp); emit ParameterChanged(msg.sender, "burnSlashNum", _burn, block.timestamp); emit ParameterChanged(msg.sender, "keepSlashNum", _keep, block.timestamp); stakeManagerParams.setSlashParams(_bounty, _burn, _keep); } /** * @notice changing the number of epochs for which the sRZRs are locked for calling unstake() * @dev can be called only by the the address that has the governer role * @param _unstakeLockPeriod updated value to be set for unstakeLockPeriod */ function setUnstakeLockPeriod(uint16 _unstakeLockPeriod) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "unstakeLockPeriod", _unstakeLockPeriod, block.timestamp); stakeManagerParams.setUnstakeLockPeriod(_unstakeLockPeriod); } /** * @notice changing the number of epochs for which the RAZORs are locked after initiating withdraw * @dev can be called only by the the address that has the governer role * @param _withdrawLockPeriod updated value to be set for withdrawLockPeriod */ function setWithdrawLockPeriod(uint16 _withdrawLockPeriod) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "withdrawLockPeriod", _withdrawLockPeriod, block.timestamp); stakeManagerParams.setWithdrawLockPeriod(_withdrawLockPeriod); } /** * @notice changing the number of epochs where staker/delegator needs to initiate withdraw * @dev can be called only by the the address that has the governer role * @param _withdrawInitiationPeriod updated value to be set for withdrawInitiationPeriod */ function setWithdrawInitiationPeriod(uint16 _withdrawInitiationPeriod) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "withdrawInitiationPeriod", _withdrawInitiationPeriod, block.timestamp); stakeManagerParams.setWithdrawInitiationPeriod(_withdrawInitiationPeriod); } /** * @notice changing percentage stake penalty from the locked amount for extending unstake lock * incase withdrawInitiationPeriod was missed * @dev can be called only by the the address that has the governer role * @param _extendLockPenalty updated value to be set for extendLockPenalty */ function setResetUnstakeLockPenalty(uint32 _extendLockPenalty) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "extendLockPenalty", _extendLockPenalty, block.timestamp); stakeManagerParams.setResetUnstakeLockPenalty(_extendLockPenalty); } /** * @notice changing the maximum number of best proposed blocks to be considered for dispute * @dev can be called only by the the address that has the governer role * @param _maxAltBlocks updated value to be set for maxAltBlocks */ function setMaxAltBlocks(uint8 _maxAltBlocks) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "maxAltBlocks", _maxAltBlocks, block.timestamp); blockManagerParams.setMaxAltBlocks(_maxAltBlocks); } /** * @notice changing minimum amount that to be staked for participation * @dev can be called only by the the address that has the governer role * @param _minStake updated value to be set for minStake */ function setMinStake(uint256 _minStake) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "minStake", _minStake, block.timestamp); stakeManagerParams.setMinStake(_minStake); voteManagerParams.setMinStake(_minStake); blockManagerParams.setMinStake(_minStake); } /** * @notice changing minimum amount that to be staked to become a staker * @dev can be called only by the the address that has the governer role * @param _minSafeRazor updated value to be set for minSafeRazor */ function setMinSafeRazor(uint256 _minSafeRazor) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "minSafeRazor", _minSafeRazor, block.timestamp); stakeManagerParams.setMinSafeRazor(_minSafeRazor); } /** * @notice changing the block reward given out to stakers * @dev can be called only by the the address that has the governer role * @param _blockReward updated value to be set for blockReward */ function setBlockReward(uint256 _blockReward) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "blockReward", _blockReward, block.timestamp); blockManagerParams.setBlockReward(_blockReward); rewardManagerParams.setBlockReward(_blockReward); } /** * @notice changing the maximum age a staker can have * @dev can be called only by the the address that has the governer role * @param _maxAge updated value to be set for maxAge */ function setMaxAge(uint32 _maxAge) external initialized onlyRole(GOVERNER_ROLE) { require(_maxAge <= stakeManager.maturitiesLength() * 10000, "Invalid Max Age Update"); emit ParameterChanged(msg.sender, "maxAge", _maxAge, block.timestamp); rewardManagerParams.setMaxAge(_maxAge); } /** * @notice changing maximum commission stakers can charge from delegators on their profits * @dev can be called only by the the address that has the governance role * @param _maxCommission updated value to be set for maxCommission */ function setMaxCommission(uint8 _maxCommission) external initialized onlyRole(GOVERNER_ROLE) { require(_maxCommission <= 100, "Invalid Max Commission Update"); emit ParameterChanged(msg.sender, "maxCommission", _maxCommission, block.timestamp); stakeManagerParams.setMaxCommission(_maxCommission); rewardManagerParams.setMaxCommission(_maxCommission); } /** * @notice sets escape hatch to false permanently * @dev can be called only by the the address that has the governer role */ function disableEscapeHatch() external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "escapeHatchEnabled", 0, block.timestamp); stakeManagerParams.disableEscapeHatch(); } /** * @notice changing maximum commission change a staker can do * @dev can be called only by the the address that has the governance role * @param _deltaCommission updated value to be set for deltaCommission */ function setDeltaCommission(uint8 _deltaCommission) external initialized onlyRole(GOVERNER_ROLE) { require(_deltaCommission <= 100, "deltaCommission exceeds 100"); emit ParameterChanged(msg.sender, "deltaCommission", _deltaCommission, block.timestamp); stakeManagerParams.setDeltaCommission(_deltaCommission); } /** * @notice changing the number of epochs for which a staker cant change commission once set/change * @dev can be called only by the the address that has the governance role * @param _epochLimitForUpdateCommission updated value to be set for epochLimitForUpdateCommission */ function setEpochLimitForUpdateCommission(uint16 _epochLimitForUpdateCommission) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "epochLimitForUpdateCommission", _epochLimitForUpdateCommission, block.timestamp); stakeManagerParams.setEpochLimitForUpdateCommission(_epochLimitForUpdateCommission); } /** * @notice changing the maximum percentage deviation allowed from medians for all collections * @dev can be called only by the the address that has the governance role * @param _maxTolerance updated value for maxTolerance */ function setMaxTolerance(uint32 _maxTolerance) external initialized onlyRole(GOVERNER_ROLE) { require(_maxTolerance <= BASE_DENOMINATOR, "maxTolerance exceeds baseDenom"); emit ParameterChanged(msg.sender, "maxTolerance", _maxTolerance, block.timestamp); collectionManagerParams.setMaxTolerance(_maxTolerance); rewardManagerParams.setMaxTolerance(_maxTolerance); } /** * @notice changing maximum number of collections that can be assigned to the staker * @dev can be called only by the the address that has the governance role * @param _toAssign updated value to be set for toAssign */ function setToAssign(uint16 _toAssign) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "toAssign", _toAssign, block.timestamp); voteManagerParams.setToAssign(_toAssign); } /** * @notice chnaging the buffer length of all the contracts * @dev can be called only by the the address that has the governance role * @param _bufferLength updated value to be set for buffer */ function setBufferLength(uint8 _bufferLength) external initialized onlyRole(GOVERNER_ROLE) { emit ParameterChanged(msg.sender, "_bufferLength", _bufferLength, block.timestamp); blockManagerParams.setBufferLength(_bufferLength); voteManagerParams.setBufferLength(_bufferLength); collectionManagerParams.setBufferLength(_bufferLength); randomNoManagerParams.setBufferLength(_bufferLength); } }
contracts/Core/interface/IRewardManager.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../../lib/Structs.sol"; interface IRewardManager { /** * @notice gives penalty to stakers for failing to reveal or * reveal value deviations * @param stakerId The id of staker currently in consideration * @param epoch the epoch value */ function givePenalties(uint32 epoch, uint32 stakerId) external; /** * @notice The function gives block reward for one valid proposer in the * previous epoch by increasing stake of staker * called from confirmBlock function of BlockManager contract. Commission * from the delegator's pool is given out to the staker from the block reward * @param stakerId The ID of the staker */ function giveBlockReward(uint32 epoch, uint32 stakerId) external; /** * @notice The function gives out penalties to stakers during commit. * The penalties are given for inactivity, failing to reveal * , deviation from the median value of particular asset * @param stakerId The staker id * @param epoch The Epoch value in consideration */ function giveInactivityPenalties(uint32 epoch, uint32 stakerId) external; }
contracts/randomNumber/IRandomNoProvider.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface IRandomNoProvider { /** * @notice Called by BlockManager in ClaimBlockReward or ConfirmBlockLastEpoch * @param epoch current epoch * @param _secret hash of encoded rando secret from stakers */ function provideSecret(uint32 epoch, bytes32 _secret) external; }
contracts/Initializable.sol
// SPDX-License-Identifier: MIT // solhint-disable-next-line compiler-version pragma solidity ^0.8.0; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * Forked from OZ's (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/b9125001f0a1c44d596ca3a47536f1a467e3a29d/contracts/proxy/utils/Initializable.sol) */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { require(_initializing || !_initialized, "contract already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } modifier initialized() { require(_initialized, "Contract should be initialized"); _; } }
@openzeppelin/contracts/utils/introspection/ERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
contracts/lib/Random.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; library Random { // pseudo random number generator based on hash. returns 0 -> max-1 // slither ignore reason : Internal library // slither-disable-next-line dead-code function prng(uint256 max, bytes32 randHash) internal pure returns (uint256) { uint256 sum = uint256(randHash); return (sum % max); } // pseudo random hash generator based on hashes. // slither ignore reason : Internal library // slither-disable-next-line dead-code function prngHash(bytes32 seed, bytes32 salt) internal pure returns (bytes32) { bytes32 prngHashVal = keccak256(abi.encodePacked(seed, salt)); return (prngHashVal); } }
contracts/Core/interface/IVoteManager.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../../lib/Structs.sol"; interface IVoteManager { /** * @notice stores the salt calculated in block manager * @param _salt the hash of the last epoch and medians of the block */ function storeSalt(bytes32 _salt) external; /** * @notice stores the depth of a valid merkle tree. Depth of the merkle tree sent by the stakers should match with this * for a valid commit/reveal * @param _depth depth of the merkle tree */ function storeDepth(uint256 _depth) external; /** * @notice returns vote value of a collection reported by a particular staker * @param epoch in which the staker reveal this value * @param stakerId id of the staker * @param leafId seq position of collection in merkle tree * @return vote value */ function getVoteValue( uint32 epoch, uint32 stakerId, uint16 leafId ) external view returns (uint256); /** * @notice returns vote weight of the value of the collection reported * @param epoch in which the staker reveal this value * @param leafId seq position of collection in merkle tree * @param voteValue one of the values of the collection being reported * @return vote weight of the vote */ function getVoteWeight( uint32 epoch, uint16 leafId, uint256 voteValue ) external view returns (uint256); /** * @notice returns snapshot of influence of the staker when they revealed * @param epoch when the snapshot was taken * @param stakerId id of the staker * @return influence of the staker */ function getInfluenceSnapshot(uint32 epoch, uint32 stakerId) external view returns (uint256); /** * @notice returns snapshot of stake of the staker when they revealed * @param epoch when the snapshot was taken * @param stakerId id of the staker * @return stake of the staker */ function getStakeSnapshot(uint32 epoch, uint32 stakerId) external view returns (uint256); /** * @notice returns the total influence revealed of the collection * @param epoch when asset was being revealed * @param leafId seq position of collection in merkle tree * @return total influence revealed of the collection */ function getTotalInfluenceRevealed(uint32 epoch, uint16 leafId) external view returns (uint256); /** * @notice returns the epoch a staker last revealed their votes * @param stakerId id of the staker * @return epoch last revealed */ function getEpochLastRevealed(uint32 stakerId) external view returns (uint32); /** * @notice returns the epoch a staker last committed their votes * @param stakerId id of the staker * @return epoch last committed */ function getEpochLastCommitted(uint32 stakerId) external view returns (uint32); /** * @return the salt */ function getSalt() external view returns (bytes32); }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
@openzeppelin/contracts/access/IAccessControl.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
contracts/Core/storage/Constants.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; contract Constants { enum State { Commit, Reveal, Propose, Dispute, Confirm, Buffer } enum StakeChanged { BlockReward, InactivityPenalty, Slashed } enum StakerRewardChanged { StakerRewardAdded, StakerRewardClaimed } enum AgeChanged { InactivityPenalty, VotingRewardOrPenalty } uint8 public constant NUM_STATES = 5; uint16 public constant EPOCH_LENGTH = 1200; // slither-disable-next-line too-many-digits address public constant BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD; uint32 public constant BASE_DENOMINATOR = 10_000_000; // keccak256("BLOCK_CONFIRMER_ROLE") bytes32 public constant BLOCK_CONFIRMER_ROLE = 0x18797bc7973e1dadee1895be2f1003818e30eae3b0e7a01eb9b2e66f3ea2771f; // keccak256("STAKE_MODIFIER_ROLE") bytes32 public constant STAKE_MODIFIER_ROLE = 0xdbaaaff2c3744aa215ebd99971829e1c1b728703a0bf252f96685d29011fc804; // keccak256("REWARD_MODIFIER_ROLE") bytes32 public constant REWARD_MODIFIER_ROLE = 0xcabcaf259dd9a27f23bd8a92bacd65983c2ebf027c853f89f941715905271a8d; // keccak256("COLLECTION_MODIFIER_ROLE") bytes32 public constant COLLECTION_MODIFIER_ROLE = 0xa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd294; // keccak256("VOTE_MODIFIER_ROLE") bytes32 public constant VOTE_MODIFIER_ROLE = 0x912208965b92edeb3eb82a612c87b38b5e844f7539cb396f0d08ec012e511b07; // keccak256("DELEGATOR_MODIFIER_ROLE") bytes32 public constant DELEGATOR_MODIFIER_ROLE = 0x6b7da7a33355c6e035439beb2ac6a052f1558db73f08690b1c9ef5a4e8389597; // keccak256("REGISTRY_MODIFIER_ROLE") bytes32 public constant REGISTRY_MODIFIER_ROLE = 0xca51085219bef34771da292cb24ee4fcf0ae6bdba1a62c17d1fb7d58be802883; // keccak256("SECRETS_MODIFIER_ROLE") bytes32 public constant SECRETS_MODIFIER_ROLE = 0x46aaf8a125792dfff6db03d74f94fe1acaf55c8cab22f65297c15809c364465c; // keccak256("PAUSE_ROLE") bytes32 public constant PAUSE_ROLE = 0x139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d; // keccak256("GOVERNANCE_ROLE") bytes32 public constant GOVERNANCE_ROLE = 0x71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1; // keccak256("STOKEN_ROLE") bytes32 public constant STOKEN_ROLE = 0xce3e6c780f179d7a08d28e380f7be9c36d990f56515174f8adb6287c543e30dc; // keccak256("SALT_MODIFIER_ROLE") bytes32 public constant SALT_MODIFIER_ROLE = 0xf31dda80d37c96a1a0852ace387dda52a75487d7d4eb74895e749ede3e0987b4; // keccak256("DEPTH_MODIFIER_ROLE)") bytes32 public constant DEPTH_MODIFIER_ROLE = 0x91f5d9ea80c4d04985e669bc72870410b28b57afdf61c0d50d377766d86a3748; // keccak256("ESCAPE_HATCH_ROLE") bytes32 public constant ESCAPE_HATCH_ROLE = 0x518d8c39717318f051dfb836a4ebe5b3c34aa2cb7fce26c21a89745422ba8043; }
contracts/Core/interface/IStakeManager.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; import "../../lib/Structs.sol"; import "../storage/Constants.sol"; interface IStakeManager { /** * @notice External function for setting stake of the staker * Used by RewardManager * @param _epoch The epoch in which stake changes * @param _id of the staker * @param reason the reason for stake to change * @param prevStake previous stake of the staker * @param _stake updated stake of the staker */ function setStakerStake( uint32 _epoch, uint32 _id, Constants.StakeChanged reason, uint256 prevStake, uint256 _stake ) external; /** * @notice The function is used by the Votemanager reveal function and BlockManager FinalizeDispute * to penalise the staker who lost his secret and make his stake less by "slashPenaltyAmount" and * transfer to bounty hunter half the "slashPenaltyAmount" of the staker * @param stakerId The ID of the staker who is penalised * @param bountyHunter The address of the bounty hunter */ function slash( uint32 epoch, uint32 stakerId, address bountyHunter ) external; /** * @notice External function for setting staker age of the staker * Used by RewardManager * @param _epoch The epoch in which age changes * @param _id of the staker * @param _age the updated new age * @param reason the reason for age change */ function setStakerAge( uint32 _epoch, uint32 _id, uint32 _age, Constants.AgeChanged reason ) external; /** * @notice External function for setting stakerReward of the staker * Used by RewardManager * @param _epoch The epoch in which stakerReward changes * @param _id of the staker * @param reason the reason for stakerReward to change * @param prevStakerReward previous stakerReward of the staker * @param _stakerReward updated stakerReward of the staker */ function setStakerReward( uint32 _epoch, uint32 _id, Constants.StakerRewardChanged reason, uint256 prevStakerReward, uint256 _stakerReward ) external; /** * @notice External function for setting epochLastPenalized of the staker * Used by RewardManager * @param _id of the staker */ function setStakerEpochFirstStakedOrLastPenalized(uint32 _epoch, uint32 _id) external; /** * @notice remove all funds in case of emergency */ function escape(address _address) external; /** * @notice event being thrown after every successful sRZR transfer taking place * @param from sender * @param to recepient * @param amount srzr amount being transferred * @param stakerId of the staker */ function srzrTransfer( address from, address to, uint256 amount, uint32 stakerId ) external; /** * @param _address Address of the staker * @return The staker ID */ function getStakerId(address _address) external view returns (uint32); /** * @param _id The staker ID * @return staker The Struct of staker information */ function getStaker(uint32 _id) external view returns (Structs.Staker memory staker); /** * @return The number of stakers in the razor network */ function getNumStakers() external view returns (uint32); /** * @return influence of staker */ function getInfluence(uint32 stakerId) external view returns (uint256); /** * @return stake of staker */ function getStake(uint32 stakerId) external view returns (uint256); /** * @return epochFirstStakedOrLastPenalized of staker */ function getEpochFirstStakedOrLastPenalized(uint32 stakerId) external view returns (uint32); /** * @return length of maturities array */ function maturitiesLength() external view returns (uint32); }
Contract ABI
[{"type":"event","name":"CollectionActivityStatus","inputs":[{"type":"bool","name":"active","internalType":"bool","indexed":false},{"type":"uint16","name":"id","internalType":"uint16","indexed":true},{"type":"uint32","name":"epoch","internalType":"uint32","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CollectionCreated","inputs":[{"type":"uint16","name":"id","internalType":"uint16","indexed":true},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CollectionUpdated","inputs":[{"type":"uint16","name":"id","internalType":"uint16","indexed":true},{"type":"int8","name":"power","internalType":"int8","indexed":false},{"type":"uint32","name":"epoch","internalType":"uint32","indexed":false},{"type":"uint32","name":"aggregationMethod","internalType":"uint32","indexed":false},{"type":"uint32","name":"tolerance","internalType":"uint32","indexed":false},{"type":"uint16[]","name":"updatedJobIDs","internalType":"uint16[]","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"JobCreated","inputs":[{"type":"uint16","name":"id","internalType":"uint16","indexed":true},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"JobUpdated","inputs":[{"type":"uint16","name":"id","internalType":"uint16","indexed":true},{"type":"uint8","name":"selectorType","internalType":"enum CollectionStorage.JobSelectorType","indexed":false},{"type":"uint32","name":"epoch","internalType":"uint32","indexed":false},{"type":"uint8","name":"weight","internalType":"uint8","indexed":false},{"type":"int8","name":"power","internalType":"int8","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false},{"type":"string","name":"selector","internalType":"string","indexed":false},{"type":"string","name":"url","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"previousAdminRole","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"newAdminRole","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"BASE_DENOMINATOR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"BLOCK_CONFIRMER_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"BURN_ADDRESS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"COLLECTION_MODIFIER_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DEFAULT_ADMIN_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DELEGATOR_MODIFIER_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DEPTH_MODIFIER_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"EPOCH_LENGTH","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"ESCAPE_HATCH_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"GOVERNANCE_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"NUM_STATES","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"PAUSE_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"REGISTRY_MODIFIER_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"REWARD_MODIFIER_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"SALT_MODIFIER_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"SECRETS_MODIFIER_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"STAKE_MODIFIER_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"STOKEN_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"VOTE_MODIFIER_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IBlockManager"}],"name":"blockManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"buffer","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"collectionIdToLeafIdRegistry","inputs":[{"type":"uint16","name":"","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"collectionIdToLeafIdRegistryOfLastEpoch","inputs":[{"type":"uint16","name":"","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"active","internalType":"bool"},{"type":"uint16","name":"id","internalType":"uint16"},{"type":"int8","name":"power","internalType":"int8"},{"type":"uint32","name":"tolerance","internalType":"uint32"},{"type":"uint32","name":"aggregationMethod","internalType":"uint32"},{"type":"string","name":"name","internalType":"string"}],"name":"collections","inputs":[{"type":"uint16","name":"","internalType":"uint16"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createCollection","inputs":[{"type":"uint32","name":"tolerance","internalType":"uint32"},{"type":"int8","name":"power","internalType":"int8"},{"type":"uint32","name":"aggregationMethod","internalType":"uint32"},{"type":"uint16[]","name":"jobIDs","internalType":"uint16[]"},{"type":"string","name":"name","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createJob","inputs":[{"type":"uint8","name":"weight","internalType":"uint8"},{"type":"int8","name":"power","internalType":"int8"},{"type":"uint8","name":"selectorType","internalType":"enum CollectionStorage.JobSelectorType"},{"type":"string","name":"name","internalType":"string"},{"type":"string","name":"selector","internalType":"string"},{"type":"string","name":"url","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16[]","name":"","internalType":"uint16[]"}],"name":"getActiveCollections","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"collection","internalType":"struct Structs.Collection","components":[{"type":"bool","name":"active","internalType":"bool"},{"type":"uint16","name":"id","internalType":"uint16"},{"type":"int8","name":"power","internalType":"int8"},{"type":"uint32","name":"tolerance","internalType":"uint32"},{"type":"uint32","name":"aggregationMethod","internalType":"uint32"},{"type":"uint16[]","name":"jobIDs","internalType":"uint16[]"},{"type":"string","name":"name","internalType":"string"}]}],"name":"getCollection","inputs":[{"type":"uint16","name":"id","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"getCollectionID","inputs":[{"type":"bytes32","name":"_hname","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"getCollectionIdFromLeafId","inputs":[{"type":"uint16","name":"leafId","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"int8","name":"","internalType":"int8"}],"name":"getCollectionPower","inputs":[{"type":"uint16","name":"id","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"getCollectionStatus","inputs":[{"type":"uint16","name":"id","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"getCollectionTolerance","inputs":[{"type":"uint16","name":"id","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getDepth","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"job","internalType":"struct Structs.Job","components":[{"type":"uint16","name":"id","internalType":"uint16"},{"type":"uint8","name":"selectorType","internalType":"uint8"},{"type":"uint8","name":"weight","internalType":"uint8"},{"type":"int8","name":"power","internalType":"int8"},{"type":"string","name":"name","internalType":"string"},{"type":"string","name":"selector","internalType":"string"},{"type":"string","name":"url","internalType":"string"}]}],"name":"getJob","inputs":[{"type":"uint16","name":"id","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"getLeafIdOfCollection","inputs":[{"type":"uint16","name":"id","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"getLeafIdOfCollectionForLastEpoch","inputs":[{"type":"uint16","name":"id","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"getNumActiveCollections","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"getNumCollections","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"getNumJobs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"int8","name":"","internalType":"int8"}],"name":"getResult","inputs":[{"type":"bytes32","name":"_name","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"int8","name":"","internalType":"int8"}],"name":"getResultFromID","inputs":[{"type":"uint16","name":"_id","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getRoleAdmin","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"getUpdateRegistryEpoch","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"grantRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"ids","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"voteManagerAddress","internalType":"address"},{"type":"address","name":"blockManagerAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"id","internalType":"uint16"},{"type":"uint8","name":"selectorType","internalType":"uint8"},{"type":"uint8","name":"weight","internalType":"uint8"},{"type":"int8","name":"power","internalType":"int8"},{"type":"string","name":"name","internalType":"string"},{"type":"string","name":"selector","internalType":"string"},{"type":"string","name":"url","internalType":"string"}],"name":"jobs","inputs":[{"type":"uint16","name":"","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"leafIdToCollectionIdRegistry","inputs":[{"type":"uint16","name":"","internalType":"uint16"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"maxTolerance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"numActiveCollections","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"numCollections","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"numJobs","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBufferLength","inputs":[{"type":"uint8","name":"_bufferLength","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setCollectionStatus","inputs":[{"type":"bool","name":"assetStatus","internalType":"bool"},{"type":"uint16","name":"id","internalType":"uint16"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxTolerance","inputs":[{"type":"uint32","name":"_maxTolerance","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateCollection","inputs":[{"type":"uint16","name":"collectionID","internalType":"uint16"},{"type":"uint32","name":"tolerance","internalType":"uint32"},{"type":"uint32","name":"aggregationMethod","internalType":"uint32"},{"type":"int8","name":"power","internalType":"int8"},{"type":"uint16[]","name":"jobIDs","internalType":"uint16[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateDelayedRegistry","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateJob","inputs":[{"type":"uint16","name":"jobID","internalType":"uint16"},{"type":"uint8","name":"weight","internalType":"uint8"},{"type":"int8","name":"power","internalType":"int8"},{"type":"uint8","name":"selectorType","internalType":"enum CollectionStorage.JobSelectorType"},{"type":"string","name":"selector","internalType":"string"},{"type":"string","name":"url","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"updateRegistryEpoch","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IVoteManager"}],"name":"voteManager","inputs":[]}]
Contract Creation Code
0x60806040526009805464ffffffffff1916630f4240051790553480156200002557600080fd5b506200003360003362000039565b620000ed565b62000045828262000049565b5050565b60008281526008602090815260408083206001600160a01b038516845290915290205460ff16620000455760008281526008602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620000a93390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6143c780620000fd6000396000f3fe608060405234801561001057600080fd5b50600436106103eb5760003560e01c80637e0c00ed1161021a578063be379bd211610135578063db7b4996116100c8578063edaafe2011610097578063f36c8f5c1161007c578063f36c8f5c14610b1a578063fccc281314610b41578063ff52495814610b4a57600080fd5b8063edaafe2014610ae6578063ef8bf68414610af357600080fd5b8063db7b499614610a81578063e1fd528514610a94578063e7e6d4a114610aa7578063ed6c935d14610abf57600080fd5b8063d547741f11610104578063d547741f14610a18578063d55f7e5f14610a2b578063d9169b3214610a3e578063da98429514610a5a57600080fd5b8063be379bd2146109a8578063ca29dc5f146109bb578063cdad524d146109d0578063cf7b4a09146109f457600080fd5b80639212051c116101ad578063ade232c71161017c578063ade232c71461093d578063b0daafef14610950578063b55fbd3514610977578063bd8595841461099e57600080fd5b80639212051c146108ff578063a217fddf14610919578063ac4746ab14610921578063add4c7841461092a57600080fd5b80638c5e6582116101e95780638c5e65821461086a5780638f2702ef146108915780638fa1838a1461089f57806391d14854146108c657600080fd5b80637e0c00ed146107f8578063817a973a14610810578063828bdd6314610823578063885fc0941461084357600080fd5b806337f27c021161030a578063485cc9551161029d578063618b0bb71161026c578063618b0bb714610779578063622f93301461078557806370fc4c6b146107ac578063776076e7146107d157600080fd5b8063485cc955146106f45780634912b72a14610707578063585c49051461072e5780635b0702781461075257600080fd5b8063421a7f56116102d9578063421a7f561461068757806342c1e587146106ad57806342e8e34e146106d857806344f7cf5c146106e057600080fd5b806337f27c02146105e8578063389ed2671461060e5780633bce5d4c1461063557806341d296f71461066057600080fd5b80632d93b9a01161038257806336568abe1161035157806336568abe14610582578063367506ef14610595578063377411711461059d5780633790004e146105c157600080fd5b80632d93b9a0146104f65780632e9ddcde1461051d5780632f2ff15d146105485780632f50bcc41461055b57600080fd5b80630d40ec33116103be5780630d40ec33146104675780631a8c36211461047c578063248a9ca3146104a15780632864da1c146104d257600080fd5b806301ffc9a7146103f057806305db56df1461041857806309ee4376146104325780630baffe0014610452575b600080fd5b6104036103fe366004613a46565b610b7c565b60405190151581526020015b60405180910390f35b610420600581565b60405160ff909116815260200161040f565b610445610440366004613a86565b610c15565b60405161040f9190613fde565b610465610460366004613bff565b610e90565b005b61046f611493565b60405161040f9190613ea1565b6007546601000000000000900461ffff165b60405161ffff909116815260200161040f565b6104c46104af366004613a0c565b60009081526008602052604090206001015490565b60405190815260200161040f565b61048e6104e0366004613a0c565b60009081526006602052604090205461ffff1690565b6104c47f912208965b92edeb3eb82a612c87b38b5e844f7539cb396f0d08ec012e511b0781565b6007546105339062010000900463ffffffff1681565b60405163ffffffff909116815260200161040f565b610465610556366004613a24565b61158e565b6104c47f46aaf8a125792dfff6db03d74f94fe1acaf55c8cab22f65297c15809c364465c81565b610465610590366004613a24565b6115b8565b6104c4611644565b61048e6105ab366004613a86565b60046020526000908152604090205461ffff1681565b61048e6105cf366004613a86565b61ffff9081166000908152600460205260409020541690565b6105fb6105f6366004613a86565b611653565b60405160009190910b815260200161040f565b6104c47f139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d81565b610648610643366004613a86565b6116da565b6040805192835260009190910b60208301520161040f565b6104c47f91f5d9ea80c4d04985e669bc72870410b28b57afdf61c0d50d377766d86a374881565b61069a610695366004613a86565b6117a6565b60405161040f9796959493929190614106565b600a546106c0906001600160a01b031681565b6040516001600160a01b03909116815260200161040f565b610465611990565b60075462010000900463ffffffff16610533565b6104656107023660046139ab565b611a17565b6104c47f6b7da7a33355c6e035439beb2ac6a052f1558db73f08690b1c9ef5a4e838959781565b61048e61073c366004613a86565b60056020526000908152604090205461ffff1681565b6104c47fce3e6c780f179d7a08d28e380f7be9c36d990f56515174f8adb6287c543e30dc81565b60075461ffff1661048e565b6104c47f518d8c39717318f051dfb836a4ebe5b3c34aa2cb7fce26c21a89745422ba804381565b6107bf6107ba366004613a86565b611b4f565b60405161040f96959493929190613eb4565b6104c47fdbaaaff2c3744aa215ebd99971829e1c1b728703a0bf252f96685d29011fc80481565b60075468010000000000000000900461ffff1661048e565b61046561081e366004613be5565b611c2e565b610836610831366004613a86565b611c95565b60405161040f9190614068565b6104c47fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd29481565b61048e610878366004613a86565b61ffff9081166000908152600560205260409020541690565b60075461048e9061ffff1681565b6104036108ad366004613a86565b61ffff1660009081526002602052604090205460ff1690565b6104036108d4366004613a24565b60009182526008602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60075461048e9068010000000000000000900461ffff1681565b6104c4600081565b61048e6104b081565b610648610938366004613a0c565b611f2f565b61046561094b366004613b1e565b611f57565b6104c47ff31dda80d37c96a1a0852ace387dda52a75487d7d4eb74895e749ede3e0987b481565b61048e610985366004613a86565b61ffff9081166000908152600360205260409020541690565b6105336298968081565b6104656109b63660046139dd565b6122ee565b60095461053390610100900463ffffffff1681565b61048e6109de366004613a86565b60036020526000908152604090205461ffff1681565b61048e610a02366004613a0c565b60066020526000908152604090205461ffff1681565b610465610a26366004613a24565b612744565b610465610a39366004613cb2565b612769565b6009546106c0906501000000000090046001600160a01b031681565b6104c47f18797bc7973e1dadee1895be2f1003818e30eae3b0e7a01eb9b2e66f3ea2771f81565b610465610a8f366004613c98565b612af6565b610465610aa2366004613aa0565b612b37565b60075461048e906601000000000000900461ffff1681565b6104c47fca51085219bef34771da292cb24ee4fcf0ae6bdba1a62c17d1fb7d58be80288381565b6009546104209060ff1681565b6104c47fcabcaf259dd9a27f23bd8a92bacd65983c2ebf027c853f89f941715905271a8d81565b6104c47f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb181565b6106c061dead81565b610533610b58366004613a86565b61ffff16600090815260026020526040902054640100000000900463ffffffff1690565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610c0f57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261ffff8216610ca65760405162461bcd60e51b815260206004820152600e60248201527f49442063616e6e6f74206265203000000000000000000000000000000000000060448201526064015b60405180910390fd5b60075461ffff660100000000000090910481169083161115610d0a5760405162461bcd60e51b815260206004820152601160248201527f494420646f6573206e6f742065786973740000000000000000000000000000006044820152606401610c9d565b61ffff8083166000908152600260209081526040808320815160e081018352815460ff81161515825261010081049096168185015263010000008604850b850b90940b8483015263ffffffff64010000000086048116606086015268010000000000000000909504909416608084015260018401805482518185028101850190935280835293949360a0860193830182828015610dee57602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610db55790505b50505050508152602001600282018054610e07906142a3565b80601f0160208091040260200160405190810160405280929190818152602001828054610e33906142a3565b8015610e805780601f10610e5557610100808354040283529160200191610e80565b820191906000526020600020905b815481529060010190602001808311610e6357829003601f168201915b5050505050815250509050919050565b60005460ff16610ee25760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610c9d565b7fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd294610f0c81612f3e565b60095460049060ff16610f1e81612f48565b6005811115610f3d57634e487b7160e01b600052602160045260246000fd5b826005811115610f5d57634e487b7160e01b600052602160045260246000fd5b14610faa5760405162461bcd60e51b815260206004820152600f60248201527f696e636f727265637420737461746500000000000000000000000000000000006044820152606401610c9d565b6000865111610ffb5760405162461bcd60e51b815260206004820152600d60248201527f6e6f206a6f6273206164646564000000000000000000000000000000000000006044820152606401610c9d565b60095463ffffffff6101009091048116908a16111561105c5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420746f6c6572616e63652076616c75650000000000000000006044820152606401610c9d565b6000611066613016565b60075490915063ffffffff80831662010000909204161161108957611089613024565b865160005b818160ff16101561117157888160ff16815181106110bc57634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff16600160008b8460ff16815181106110ef57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015161ffff90811683529082019290925260400160002054161461115f5760405162461bcd60e51b815260206004820152600f60248201527f6a6f62206e6f742070726573656e7400000000000000000000000000000000006044820152606401610c9d565b806111698161431b565b91505061108e565b5060075461118e906601000000000000900461ffff166001614171565b600760066101000a81548161ffff021916908361ffff1602179055506040518060e00160405280600115158152602001600760069054906101000a900461ffff1661ffff1681526020018b60000b81526020018c63ffffffff1681526020018a63ffffffff16815260200189815260200188888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509390945250506007546601000000000000900461ffff908116825260026020908152604080842086518154888501519389015160608a015160808b015162ffffff199093169315157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff169390931761010095909716949094029590951767ffffffffff0000001916630100000060ff9490970b939093169590950267ffffffff0000000019169190911764010000000063ffffffff95861602177fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1668010000000000000000949093169390930291909117825560a0840151805192935061134292600185019291909101906136a5565b5060c0820151805161135e91600284019160209091019061374e565b5050600754611373915061ffff166001614171565b6007805461ffff191661ffff929092169190911790556113948260016141af565b600760026101000a81548163ffffffff021916908363ffffffff1602179055506113bc6130c5565b600754604051428152660100000000000090910461ffff16907f625e8df1aa9054aa4509937a80f8f8eabc0ac709458dbb50be225927c07a2d6a9060200160405180910390a261141d8787600760069054906101000a900461ffff1661317b565b600a546001600160a01b031663d257450c61143661322f565b6040518263ffffffff1660e01b815260040161145491815260200190565b600060405180830381600087803b15801561146e57600080fd5b505af1158015611482573d6000803e3d6000fd5b505050505050505050505050505050565b60075460609060009061ffff1667ffffffffffffffff8111156114c657634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156114ef578160200160208202803683370190505b509050600060015b60075461ffff66010000000000009091048116908216116115865761ffff811660009081526002602052604090205460ff16156115745780838361ffff168151811061155357634e487b7160e01b600052603260045260246000fd5b61ffff90921660209283029190910190910152611571826001614171565b91505b8061157e816142de565b9150506114f7565b509092915050565b6000828152600860205260409020600101546115a981612f3e565b6115b3838361328a565b505050565b6001600160a01b03811633146116365760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610c9d565b611640828261332c565b5050565b600061164e61322f565b905090565b60075460009061ffff6601000000000000909104811690831611156116ba5760405162461bcd60e51b815260206004820152601160248201527f494420646f6573206e6f742065786973740000000000000000000000000000006044820152606401610c9d565b5061ffff1660009081526002602052604081205463010000009004900b90565b6009546040517f67ba825c00000000000000000000000000000000000000000000000000000000815261ffff831660048201526000918291650100000000009091046001600160a01b0316906367ba825c9060240160206040518083038186803b15801561174757600080fd5b505afa15801561175b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177f9190613bcd565b61ffff90931660009081526002602052604081205493946301000000909404900b92915050565b600160208190526000918252604082208054918101805461ffff84169460ff620100008604811695630100000081049091169464010000000090910490910b9290916117f1906142a3565b80601f016020809104026020016040519081016040528092919081815260200182805461181d906142a3565b801561186a5780601f1061183f5761010080835404028352916020019161186a565b820191906000526020600020905b81548152906001019060200180831161184d57829003601f168201915b50505050509080600201805461187f906142a3565b80601f01602080910402602001604051908101604052809291908181526020018280546118ab906142a3565b80156118f85780601f106118cd576101008083540402835291602001916118f8565b820191906000526020600020905b8154815290600101906020018083116118db57829003601f168201915b50505050509080600301805461190d906142a3565b80601f0160208091040260200160405190810160405280929190818152602001828054611939906142a3565b80156119865780601f1061195b57610100808354040283529160200191611986565b820191906000526020600020905b81548152906001019060200180831161196957829003601f168201915b5050505050905087565b60005460ff166119e25760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610c9d565b7fca51085219bef34771da292cb24ee4fcf0ae6bdba1a62c17d1fb7d58be802883611a0c81612f3e565b611a14613024565b50565b600054610100900460ff1680611a30575060005460ff16155b611a7c5760405162461bcd60e51b815260206004820152601c60248201527f636f6e747261637420616c726561647920696e697469616c697a6564000000006044820152606401610c9d565b600054610100900460ff16158015611a9e576000805461ffff19166101011790555b6000611aa981612f3e565b50600a80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0385811691909117909155600980547fffffffffffffff0000000000000000000000000000000000000000ffffffffff16650100000000009285169290920291909117905580156115b357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055505050565b600260208190526000918252604082208054918101805460ff84169461ffff610100860416946301000000810490910b9363ffffffff6401000000008304811694680100000000000000009093041692909190611bab906142a3565b80601f0160208091040260200160405190810160405280929190818152602001828054611bd7906142a3565b8015611c245780601f10611bf957610100808354040283529160200191611c24565b820191906000526020600020905b815481529060010190602001808311611c0757829003601f168201915b5050505050905086565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1611c5881612f3e565b506009805463ffffffff909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff909216919091179055565b611ce16040518060e00160405280600061ffff168152602001600060ff168152602001600060ff1681526020016000800b81526020016060815260200160608152602001606081525090565b61ffff8216611d325760405162461bcd60e51b815260206004820152600e60248201527f49442063616e6e6f7420626520300000000000000000000000000000000000006044820152606401610c9d565b60075461ffff6801000000000000000090910481169083161115611d985760405162461bcd60e51b815260206004820152601160248201527f494420646f6573206e6f742065786973740000000000000000000000000000006044820152606401610c9d565b61ffff8083166000908152600160208181526040808420815160e0810183528154968716815260ff6201000088048116948201949094526301000000870490931691830191909152640100000000909404830b830b90920b606083015282018054919291608084019190611e0b906142a3565b80601f0160208091040260200160405190810160405280929190818152602001828054611e37906142a3565b8015611e845780601f10611e5957610100808354040283529160200191611e84565b820191906000526020600020905b815481529060010190602001808311611e6757829003601f168201915b50505050508152602001600282018054611e9d906142a3565b80601f0160208091040260200160405190810160405280929190818152602001828054611ec9906142a3565b8015611f165780601f10611eeb57610100808354040283529160200191611f16565b820191906000526020600020905b815481529060010190602001808311611ef957829003601f168201915b50505050508152602001600382018054610e07906142a3565b600081815260066020526040812054819061ffff16611f4d816116da565b9250925050915091565b60005460ff16611fa95760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610c9d565b7fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd294611fd381612f3e565b60095460009060ff16611fe581612f48565b600581111561200457634e487b7160e01b600052602160045260246000fd5b82600581111561202457634e487b7160e01b600052602160045260246000fd5b14156120725760405162461bcd60e51b815260206004820152600f60248201527f696e636f727265637420737461746500000000000000000000000000000000006044820152606401610c9d565b61ffff8b166120c35760405162461bcd60e51b815260206004820152600e60248201527f49442063616e6e6f7420626520300000000000000000000000000000000000006044820152606401610c9d565b61ffff808c16600081815260016020526040902054909116146121285760405162461bcd60e51b815260206004820152601260248201527f4a6f62204944206e6f742070726573656e7400000000000000000000000000006044820152606401610c9d565b60648a60ff16111561217c5760405162461bcd60e51b815260206004820152601160248201527f576569676874206265796f6e64206d61780000000000000000000000000000006044820152606401610c9d565b6000612186613016565b61ffff8d1660009081526001602052604090209091506121aa9060030187876137c2565b5061ffff8c1660009081526001602052604090206121cc9060020189896137c2565b508860018111156121ed57634e487b7160e01b600052602160045260246000fd5b600160008e61ffff1661ffff16815260200190815260200160002060000160026101000a81548160ff021916908360ff1602179055508a600160008e61ffff1661ffff16815260200190815260200160002060000160036101000a81548160ff021916908360ff16021790555089600160008e61ffff1661ffff16815260200190815260200160002060000160046101000a81548160ff021916908360000b60ff1602179055508b61ffff167fefd160aad4b75c8736880e140d62ed38df6dc44639b0b63c2fd4971b0e15e0248a838e8e428e8e8e8e6040516122d899989796959493929190613f03565b60405180910390a2505050505050505050505050565b60005460ff166123405760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610c9d565b7fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd29461236a81612f3e565b60095460049060ff1661237c81612f48565b600581111561239b57634e487b7160e01b600052602160045260246000fd5b8260058111156123bb57634e487b7160e01b600052602160045260246000fd5b146124085760405162461bcd60e51b815260206004820152600f60248201527f696e636f727265637420737461746500000000000000000000000000000000006044820152606401610c9d565b61ffff84166124595760405162461bcd60e51b815260206004820152600e60248201527f49442063616e6e6f7420626520300000000000000000000000000000000000006044820152606401610c9d565b60075461ffff6601000000000000909104811690851611156124bd5760405162461bcd60e51b815260206004820152601160248201527f494420646f6573206e6f742065786973740000000000000000000000000000006044820152606401610c9d565b60006124c7613016565b60075490915063ffffffff8083166201000090920416116124ea576124ea613024565b85156125995761ffff851660009081526002602052604090205460ff16156125545760405162461bcd60e51b815260206004820152601160248201527f494420616c7265616479206163746976650000000000000000000000000000006044820152606401610c9d565b6007546125669061ffff166001614171565b6007805461ffff191661ffff92831617905585166000908152600260205260409020805460ff191687151517905561263e565b61ffff851660009081526002602052604090205460ff166125fc5760405162461bcd60e51b815260206004820152601360248201527f494420616c726561647920696e616374697665000000000000000000000000006044820152606401610c9d565b60075461260f9060019061ffff16614239565b6007805461ffff191661ffff92831617905585166000908152600260205260409020805460ff19168715151790555b6126498160016141af565b600760026101000a81548163ffffffff021916908363ffffffff1602179055506126716130c5565b61ffff851660008181526002602090815260409182902054825160ff9091161515815263ffffffff851691810191909152428183015290517ff0b5874d363139e5f9c359f28c68eaa5833e8018c74483703075e3de02ba89b99181900360600190a2600a546001600160a01b031663d257450c6126ec61322f565b6040518263ffffffff1660e01b815260040161270a91815260200190565b600060405180830381600087803b15801561272457600080fd5b505af1158015612738573d6000803e3d6000fd5b50505050505050505050565b60008281526008602052604090206001015461275f81612f3e565b6115b3838361332c565b60005460ff166127bb5760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610c9d565b7fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd2946127e581612f3e565b60648a60ff1611156128395760405162461bcd60e51b815260206004820152601160248201527f576569676874206265796f6e64206d61780000000000000000000000000000006044820152606401610c9d565b6007546128579068010000000000000000900461ffff166001614171565b600780547fffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffff166801000000000000000061ffff938416810291909117918290556040805160e0810190915291049091168152602081018960018111156128cd57634e487b7160e01b600052602160045260246000fd5b60ff1681526020018b60ff1681526020018a60000b815260200188888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250604080516020601f890181900481028201810190925287815291810191908890889081908401838280828437600092019190915250505090825250604080516020601f870181900481028201810190925285815291810191908690869081908401838280828437600092018290525093909452505060075461ffff68010000000000000000909104811682526001602081815260408085208751815489850151938a015160608b015190980b60ff908116640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff998216630100000002999099167fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffff91909516620100000262ffffff19909216929097169190911717949094161793909317825560808501518051929450612a66939185019291019061374e565b5060a08201518051612a8291600284019160209091019061374e565b5060c08201518051612a9e91600384019160209091019061374e565b50506007546040514281526801000000000000000090910461ffff1691507f2af60a3bf9cf4dd5faca2cf55ed47a2af51f35c08083d7585d462bdd1e17d47e906020015b60405180910390a250505050505050505050565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1612b2081612f3e565b506009805460ff191660ff92909216919091179055565b60005460ff16612b895760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610c9d565b7fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd294612bb381612f3e565b60095460009060ff16612bc581612f48565b6005811115612be457634e487b7160e01b600052602160045260246000fd5b826005811115612c0457634e487b7160e01b600052602160045260246000fd5b1415612c525760405162461bcd60e51b815260206004820152600f60248201527f696e636f727265637420737461746500000000000000000000000000000000006044820152606401610c9d565b6000845111612ca35760405162461bcd60e51b815260206004820152600d60248201527f6e6f206a6f6273206164646564000000000000000000000000000000000000006044820152606401610c9d565b60075461ffff660100000000000090910481169089161115612d075760405162461bcd60e51b815260206004820152601960248201527f436f6c6c656374696f6e204944206e6f742070726573656e74000000000000006044820152606401610c9d565b60095463ffffffff61010090910481169088161115612d685760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420746f6c6572616e63652076616c75650000000000000000006044820152606401610c9d565b6000612d72613016565b855190915060005b818160ff161015612e5d57868160ff1681518110612da857634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff1660016000898460ff1681518110612ddb57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015161ffff908116835290820192909252604001600020541614612e4b5760405162461bcd60e51b815260206004820152600f60248201527f6a6f62206e6f742070726573656e7400000000000000000000000000000000006044820152606401610c9d565b80612e558161431b565b915050612d7a565b5061ffff8a1660009081526002602090815260408220805463ffffffff8c811668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff918f166401000000000267ffffffff0000000019968e900b60ff166301000000029690961667ffffffffff000000199093169290921794909417939093169290921782558751612eff92600101918901906136a5565b508961ffff167f88a18739a2f3afe1c3ba001fd79a42a83d4e8fb98ecea04a4b4f0abd3c1f668688848b8d8b42604051612ae296959493929190613f7f565b611a1481336133af565b6000818160ff8216612f5d60056104b06141ce565b612f679190614239565b905061ffff8116612f7b60056104b06141ce565b612f899061ffff164261433b565b1180612fb1575060ff8216612fa160056104b06141ce565b612faf9061ffff164261433b565b105b15612fc0575060059392505050565b60006005612fd0816104b06141ce565b612fde9061ffff16426141ef565b612fe8919061433b565b90508060ff16600581111561300d57634e487b7160e01b600052602160045260246000fd5b95945050505050565b600061164e6104b042614203565b600060015b60075461ffff66010000000000009091048116908216116116405761ffff811660009081526002602052604090205460ff16156130965761ffff8181166000908152600360205260409020805461ffff191691841691909117905561308f826001614171565b91506130b3565b61ffff81166000908152600360205260409020805461ffff191690555b806130bd816142de565b915050613029565b600060015b60075461ffff66010000000000009091048116908216116116405761ffff811660009081526002602052604090205460ff161561314c5761ffff8082166000818152600460209081526040808320805495881661ffff1996871681179091558352600590915290208054909216179055613145826001614171565b9150613169565b61ffff81166000908152600460205260409020805461ffff191690555b80613173816142de565b9150506130ca565b60008383604051602001613190929190613e10565b60408051601f1981840301815291815281516020928301206000818152600690935291205490915061ffff16156132095760405162461bcd60e51b815260206004820181905260248201527f436f6c6c656374696f6e2065786973747320776974682073616d65206e616d656044820152606401610c9d565b6000908152600660205260409020805461ffff191661ffff929092169190911790555050565b60075460009061ffff16815b60018211156132715761324f60028361433b565b15613258575060015b613263600184614197565b9250600182901c915061323b565b8015613285578261328181614300565b9350505b505090565b60008281526008602090815260408083206001600160a01b038516845290915290205460ff166116405760008281526008602090815260408083206001600160a01b03851684529091529020805460ff191660011790556132e83390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526008602090815260408083206001600160a01b038516845290915290205460ff16156116405760008281526008602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60008281526008602090815260408083206001600160a01b038516845290915290205460ff16611640576133ed816001600160a01b0316601461342f565b6133f883602061342f565b604051602001613409929190613e20565b60408051601f198184030181529082905262461bcd60e51b8252610c9d91600401613fcb565b6060600061343e83600261421a565b613449906002614197565b67ffffffffffffffff81111561346f57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613499576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106134de57634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061354f57634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061358b84600261421a565b613596906001614197565b90505b600181111561364f577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106135e557634e487b7160e01b600052603260045260246000fd5b1a60f81b82828151811061360957634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936136488161428c565b9050613599565b50831561369e5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610c9d565b9392505050565b82805482825590600052602060002090600f0160109004810192821561373e5791602002820160005b8382111561370e57835183826101000a81548161ffff021916908361ffff16021790555092602001926002016020816001010492830192600103026136ce565b801561373c5782816101000a81549061ffff021916905560020160208160010104928301926001030261370e565b505b5061374a929150613836565b5090565b82805461375a906142a3565b90600052602060002090601f01602090048101928261377c576000855561373e565b82601f1061379557805160ff191683800117855561373e565b8280016001018555821561373e579182015b8281111561373e5782518255916020019190600101906137a7565b8280546137ce906142a3565b90600052602060002090601f0160209004810192826137f0576000855561373e565b82601f106138095782800160ff1982351617855561373e565b8280016001018555821561373e579182015b8281111561373e57823582559160200191906001019061381b565b5b8082111561374a5760008155600101613837565b80356001600160a01b038116811461386257600080fd5b919050565b600082601f830112613877578081fd5b8135602067ffffffffffffffff808311156138945761389461437b565b8260051b604051601f19603f830116810181811084821117156138b9576138b961437b565b604052848152838101925086840182880185018910156138d7578687fd5b8692505b85831015613900576138ec81613974565b8452928401926001929092019184016138db565b50979650505050505050565b80356002811061386257600080fd5b8035600081900b811461386257600080fd5b60008083601f84011261393e578182fd5b50813567ffffffffffffffff811115613955578182fd5b60208301915083602082850101111561396d57600080fd5b9250929050565b803561ffff8116811461386257600080fd5b803563ffffffff8116811461386257600080fd5b803560ff8116811461386257600080fd5b600080604083850312156139bd578182fd5b6139c68361384b565b91506139d46020840161384b565b90509250929050565b600080604083850312156139ef578182fd5b823580151581146139fe578283fd5b91506139d460208401613974565b600060208284031215613a1d578081fd5b5035919050565b60008060408385031215613a36578182fd5b823591506139d46020840161384b565b600060208284031215613a57578081fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461369e578182fd5b600060208284031215613a97578081fd5b61369e82613974565b600080600080600060a08688031215613ab7578081fd5b613ac086613974565b9450613ace60208701613986565b9350613adc60408701613986565b9250613aea6060870161391b565b9150608086013567ffffffffffffffff811115613b05578182fd5b613b1188828901613867565b9150509295509295909350565b60008060008060008060008060c0898b031215613b39578283fd5b613b4289613974565b9750613b5060208a0161399a565b9650613b5e60408a0161391b565b9550613b6c60608a0161390c565b9450608089013567ffffffffffffffff80821115613b88578485fd5b613b948c838d0161392d565b909650945060a08b0135915080821115613bac578384fd5b50613bb98b828c0161392d565b999c989b5096995094979396929594505050565b600060208284031215613bde578081fd5b5051919050565b600060208284031215613bf6578081fd5b61369e82613986565b60008060008060008060a08789031215613c17578182fd5b613c2087613986565b9550613c2e6020880161391b565b9450613c3c60408801613986565b9350606087013567ffffffffffffffff80821115613c58578384fd5b613c648a838b01613867565b94506080890135915080821115613c79578384fd5b50613c8689828a0161392d565b979a9699509497509295939492505050565b600060208284031215613ca9578081fd5b61369e8261399a565b600080600080600080600080600060c08a8c031215613ccf578283fd5b613cd88a61399a565b9850613ce660208b0161391b565b9750613cf460408b0161390c565b965060608a013567ffffffffffffffff80821115613d10578485fd5b613d1c8d838e0161392d565b909850965060808c0135915080821115613d34578485fd5b613d408d838e0161392d565b909650945060a08c0135915080821115613d58578283fd5b50613d658c828d0161392d565b915080935050809150509295985092959850929598565b6000815180845260208085019450808401835b83811015613daf57815161ffff1687529582019590820190600101613d8f565b509495945050505050565b8183528181602085013750600080602083850101526020601f19601f840116840101905092915050565b60008151808452613dfc81602086016020860161425c565b601f01601f19169290920160200192915050565b8183823760009101908152919050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613e5881601785016020880161425c565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351613e9581602884016020880161425c565b01602801949350505050565b60208152600061369e6020830184613d7c565b861515815261ffff86166020820152600085810b604083015263ffffffff808616606084015280851660808401525060c060a0830152613ef760c0830184613de4565b98975050505050505050565b600060028b10613f2157634e487b7160e01b81526021600452602481fd5b8a825263ffffffff8a16602083015260ff8916604083015287810b606083015286608083015260e060a0830152613f5c60e083018688613dba565b82810360c0840152613f6f818587613dba565b9c9b505050505050505050505050565b600087810b825263ffffffff8088166020840152808716604084015280861660608401525060c06080830152613fb860c0830185613d7c565b90508260a0830152979650505050505050565b60208152600061369e6020830184613de4565b6020815281511515602082015261ffff602083015116604082015260006040830151810b6060830152606083015161401e608084018263ffffffff169052565b50608083015163ffffffff811660a08401525060a083015160e060c084015261404b610100840182613d7c565b905060c0840151601f198483030160e085015261300d8282613de4565b6020815261ffff825116602082015260ff60208301511660408201526000604083015161409a606084018260ff169052565b5060608301516140af608084018260000b9052565b50608083015160e060a08401526140ca610100840182613de4565b905060a0840151601f19808584030160c08601526140e88383613de4565b925060c08601519150808584030160e08601525061300d8282613de4565b61ffff8816815260ff8716602082015260ff86166040820152600085810b606083015260e0608083015261413d60e0830186613de4565b82810360a084015261414f8186613de4565b905082810360c08401526141638185613de4565b9a9950505050505050505050565b600061ffff80831681851680830382111561418e5761418e61434f565b01949350505050565b600082198211156141aa576141aa61434f565b500190565b600063ffffffff80831681851680830382111561418e5761418e61434f565b600061ffff808416806141e3576141e3614365565b92169190910492915050565b6000826141fe576141fe614365565b500490565b600063ffffffff808416806141e3576141e3614365565b60008160001904831182151516156142345761423461434f565b500290565b600061ffff838116908316818110156142545761425461434f565b039392505050565b60005b8381101561427757818101518382015260200161425f565b83811115614286576000848401525b50505050565b60008161429b5761429b61434f565b506000190190565b600181811c908216806142b757607f821691505b602082108114156142d857634e487b7160e01b600052602260045260246000fd5b50919050565b600061ffff808316818114156142f6576142f661434f565b6001019392505050565b60006000198214156143145761431461434f565b5060010190565b600060ff821660ff8114156143325761433261434f565b60010192915050565b60008261434a5761434a614365565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea264697066735822122009d2ff203a7e90c1f2ada4894785e7ad2b51ef9d8d4b30cc6466c1d568c749a364736f6c63430008040033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106103eb5760003560e01c80637e0c00ed1161021a578063be379bd211610135578063db7b4996116100c8578063edaafe2011610097578063f36c8f5c1161007c578063f36c8f5c14610b1a578063fccc281314610b41578063ff52495814610b4a57600080fd5b8063edaafe2014610ae6578063ef8bf68414610af357600080fd5b8063db7b499614610a81578063e1fd528514610a94578063e7e6d4a114610aa7578063ed6c935d14610abf57600080fd5b8063d547741f11610104578063d547741f14610a18578063d55f7e5f14610a2b578063d9169b3214610a3e578063da98429514610a5a57600080fd5b8063be379bd2146109a8578063ca29dc5f146109bb578063cdad524d146109d0578063cf7b4a09146109f457600080fd5b80639212051c116101ad578063ade232c71161017c578063ade232c71461093d578063b0daafef14610950578063b55fbd3514610977578063bd8595841461099e57600080fd5b80639212051c146108ff578063a217fddf14610919578063ac4746ab14610921578063add4c7841461092a57600080fd5b80638c5e6582116101e95780638c5e65821461086a5780638f2702ef146108915780638fa1838a1461089f57806391d14854146108c657600080fd5b80637e0c00ed146107f8578063817a973a14610810578063828bdd6314610823578063885fc0941461084357600080fd5b806337f27c021161030a578063485cc9551161029d578063618b0bb71161026c578063618b0bb714610779578063622f93301461078557806370fc4c6b146107ac578063776076e7146107d157600080fd5b8063485cc955146106f45780634912b72a14610707578063585c49051461072e5780635b0702781461075257600080fd5b8063421a7f56116102d9578063421a7f561461068757806342c1e587146106ad57806342e8e34e146106d857806344f7cf5c146106e057600080fd5b806337f27c02146105e8578063389ed2671461060e5780633bce5d4c1461063557806341d296f71461066057600080fd5b80632d93b9a01161038257806336568abe1161035157806336568abe14610582578063367506ef14610595578063377411711461059d5780633790004e146105c157600080fd5b80632d93b9a0146104f65780632e9ddcde1461051d5780632f2ff15d146105485780632f50bcc41461055b57600080fd5b80630d40ec33116103be5780630d40ec33146104675780631a8c36211461047c578063248a9ca3146104a15780632864da1c146104d257600080fd5b806301ffc9a7146103f057806305db56df1461041857806309ee4376146104325780630baffe0014610452575b600080fd5b6104036103fe366004613a46565b610b7c565b60405190151581526020015b60405180910390f35b610420600581565b60405160ff909116815260200161040f565b610445610440366004613a86565b610c15565b60405161040f9190613fde565b610465610460366004613bff565b610e90565b005b61046f611493565b60405161040f9190613ea1565b6007546601000000000000900461ffff165b60405161ffff909116815260200161040f565b6104c46104af366004613a0c565b60009081526008602052604090206001015490565b60405190815260200161040f565b61048e6104e0366004613a0c565b60009081526006602052604090205461ffff1690565b6104c47f912208965b92edeb3eb82a612c87b38b5e844f7539cb396f0d08ec012e511b0781565b6007546105339062010000900463ffffffff1681565b60405163ffffffff909116815260200161040f565b610465610556366004613a24565b61158e565b6104c47f46aaf8a125792dfff6db03d74f94fe1acaf55c8cab22f65297c15809c364465c81565b610465610590366004613a24565b6115b8565b6104c4611644565b61048e6105ab366004613a86565b60046020526000908152604090205461ffff1681565b61048e6105cf366004613a86565b61ffff9081166000908152600460205260409020541690565b6105fb6105f6366004613a86565b611653565b60405160009190910b815260200161040f565b6104c47f139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d81565b610648610643366004613a86565b6116da565b6040805192835260009190910b60208301520161040f565b6104c47f91f5d9ea80c4d04985e669bc72870410b28b57afdf61c0d50d377766d86a374881565b61069a610695366004613a86565b6117a6565b60405161040f9796959493929190614106565b600a546106c0906001600160a01b031681565b6040516001600160a01b03909116815260200161040f565b610465611990565b60075462010000900463ffffffff16610533565b6104656107023660046139ab565b611a17565b6104c47f6b7da7a33355c6e035439beb2ac6a052f1558db73f08690b1c9ef5a4e838959781565b61048e61073c366004613a86565b60056020526000908152604090205461ffff1681565b6104c47fce3e6c780f179d7a08d28e380f7be9c36d990f56515174f8adb6287c543e30dc81565b60075461ffff1661048e565b6104c47f518d8c39717318f051dfb836a4ebe5b3c34aa2cb7fce26c21a89745422ba804381565b6107bf6107ba366004613a86565b611b4f565b60405161040f96959493929190613eb4565b6104c47fdbaaaff2c3744aa215ebd99971829e1c1b728703a0bf252f96685d29011fc80481565b60075468010000000000000000900461ffff1661048e565b61046561081e366004613be5565b611c2e565b610836610831366004613a86565b611c95565b60405161040f9190614068565b6104c47fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd29481565b61048e610878366004613a86565b61ffff9081166000908152600560205260409020541690565b60075461048e9061ffff1681565b6104036108ad366004613a86565b61ffff1660009081526002602052604090205460ff1690565b6104036108d4366004613a24565b60009182526008602090815260408084206001600160a01b0393909316845291905290205460ff1690565b60075461048e9068010000000000000000900461ffff1681565b6104c4600081565b61048e6104b081565b610648610938366004613a0c565b611f2f565b61046561094b366004613b1e565b611f57565b6104c47ff31dda80d37c96a1a0852ace387dda52a75487d7d4eb74895e749ede3e0987b481565b61048e610985366004613a86565b61ffff9081166000908152600360205260409020541690565b6105336298968081565b6104656109b63660046139dd565b6122ee565b60095461053390610100900463ffffffff1681565b61048e6109de366004613a86565b60036020526000908152604090205461ffff1681565b61048e610a02366004613a0c565b60066020526000908152604090205461ffff1681565b610465610a26366004613a24565b612744565b610465610a39366004613cb2565b612769565b6009546106c0906501000000000090046001600160a01b031681565b6104c47f18797bc7973e1dadee1895be2f1003818e30eae3b0e7a01eb9b2e66f3ea2771f81565b610465610a8f366004613c98565b612af6565b610465610aa2366004613aa0565b612b37565b60075461048e906601000000000000900461ffff1681565b6104c47fca51085219bef34771da292cb24ee4fcf0ae6bdba1a62c17d1fb7d58be80288381565b6009546104209060ff1681565b6104c47fcabcaf259dd9a27f23bd8a92bacd65983c2ebf027c853f89f941715905271a8d81565b6104c47f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb181565b6106c061dead81565b610533610b58366004613a86565b61ffff16600090815260026020526040902054640100000000900463ffffffff1690565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610c0f57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261ffff8216610ca65760405162461bcd60e51b815260206004820152600e60248201527f49442063616e6e6f74206265203000000000000000000000000000000000000060448201526064015b60405180910390fd5b60075461ffff660100000000000090910481169083161115610d0a5760405162461bcd60e51b815260206004820152601160248201527f494420646f6573206e6f742065786973740000000000000000000000000000006044820152606401610c9d565b61ffff8083166000908152600260209081526040808320815160e081018352815460ff81161515825261010081049096168185015263010000008604850b850b90940b8483015263ffffffff64010000000086048116606086015268010000000000000000909504909416608084015260018401805482518185028101850190935280835293949360a0860193830182828015610dee57602002820191906000526020600020906000905b82829054906101000a900461ffff1661ffff1681526020019060020190602082600101049283019260010382029150808411610db55790505b50505050508152602001600282018054610e07906142a3565b80601f0160208091040260200160405190810160405280929190818152602001828054610e33906142a3565b8015610e805780601f10610e5557610100808354040283529160200191610e80565b820191906000526020600020905b815481529060010190602001808311610e6357829003601f168201915b5050505050815250509050919050565b60005460ff16610ee25760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610c9d565b7fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd294610f0c81612f3e565b60095460049060ff16610f1e81612f48565b6005811115610f3d57634e487b7160e01b600052602160045260246000fd5b826005811115610f5d57634e487b7160e01b600052602160045260246000fd5b14610faa5760405162461bcd60e51b815260206004820152600f60248201527f696e636f727265637420737461746500000000000000000000000000000000006044820152606401610c9d565b6000865111610ffb5760405162461bcd60e51b815260206004820152600d60248201527f6e6f206a6f6273206164646564000000000000000000000000000000000000006044820152606401610c9d565b60095463ffffffff6101009091048116908a16111561105c5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420746f6c6572616e63652076616c75650000000000000000006044820152606401610c9d565b6000611066613016565b60075490915063ffffffff80831662010000909204161161108957611089613024565b865160005b818160ff16101561117157888160ff16815181106110bc57634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff16600160008b8460ff16815181106110ef57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015161ffff90811683529082019290925260400160002054161461115f5760405162461bcd60e51b815260206004820152600f60248201527f6a6f62206e6f742070726573656e7400000000000000000000000000000000006044820152606401610c9d565b806111698161431b565b91505061108e565b5060075461118e906601000000000000900461ffff166001614171565b600760066101000a81548161ffff021916908361ffff1602179055506040518060e00160405280600115158152602001600760069054906101000a900461ffff1661ffff1681526020018b60000b81526020018c63ffffffff1681526020018a63ffffffff16815260200189815260200188888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509390945250506007546601000000000000900461ffff908116825260026020908152604080842086518154888501519389015160608a015160808b015162ffffff199093169315157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff169390931761010095909716949094029590951767ffffffffff0000001916630100000060ff9490970b939093169590950267ffffffff0000000019169190911764010000000063ffffffff95861602177fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1668010000000000000000949093169390930291909117825560a0840151805192935061134292600185019291909101906136a5565b5060c0820151805161135e91600284019160209091019061374e565b5050600754611373915061ffff166001614171565b6007805461ffff191661ffff929092169190911790556113948260016141af565b600760026101000a81548163ffffffff021916908363ffffffff1602179055506113bc6130c5565b600754604051428152660100000000000090910461ffff16907f625e8df1aa9054aa4509937a80f8f8eabc0ac709458dbb50be225927c07a2d6a9060200160405180910390a261141d8787600760069054906101000a900461ffff1661317b565b600a546001600160a01b031663d257450c61143661322f565b6040518263ffffffff1660e01b815260040161145491815260200190565b600060405180830381600087803b15801561146e57600080fd5b505af1158015611482573d6000803e3d6000fd5b505050505050505050505050505050565b60075460609060009061ffff1667ffffffffffffffff8111156114c657634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156114ef578160200160208202803683370190505b509050600060015b60075461ffff66010000000000009091048116908216116115865761ffff811660009081526002602052604090205460ff16156115745780838361ffff168151811061155357634e487b7160e01b600052603260045260246000fd5b61ffff90921660209283029190910190910152611571826001614171565b91505b8061157e816142de565b9150506114f7565b509092915050565b6000828152600860205260409020600101546115a981612f3e565b6115b3838361328a565b505050565b6001600160a01b03811633146116365760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610c9d565b611640828261332c565b5050565b600061164e61322f565b905090565b60075460009061ffff6601000000000000909104811690831611156116ba5760405162461bcd60e51b815260206004820152601160248201527f494420646f6573206e6f742065786973740000000000000000000000000000006044820152606401610c9d565b5061ffff1660009081526002602052604081205463010000009004900b90565b6009546040517f67ba825c00000000000000000000000000000000000000000000000000000000815261ffff831660048201526000918291650100000000009091046001600160a01b0316906367ba825c9060240160206040518083038186803b15801561174757600080fd5b505afa15801561175b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061177f9190613bcd565b61ffff90931660009081526002602052604081205493946301000000909404900b92915050565b600160208190526000918252604082208054918101805461ffff84169460ff620100008604811695630100000081049091169464010000000090910490910b9290916117f1906142a3565b80601f016020809104026020016040519081016040528092919081815260200182805461181d906142a3565b801561186a5780601f1061183f5761010080835404028352916020019161186a565b820191906000526020600020905b81548152906001019060200180831161184d57829003601f168201915b50505050509080600201805461187f906142a3565b80601f01602080910402602001604051908101604052809291908181526020018280546118ab906142a3565b80156118f85780601f106118cd576101008083540402835291602001916118f8565b820191906000526020600020905b8154815290600101906020018083116118db57829003601f168201915b50505050509080600301805461190d906142a3565b80601f0160208091040260200160405190810160405280929190818152602001828054611939906142a3565b80156119865780601f1061195b57610100808354040283529160200191611986565b820191906000526020600020905b81548152906001019060200180831161196957829003601f168201915b5050505050905087565b60005460ff166119e25760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610c9d565b7fca51085219bef34771da292cb24ee4fcf0ae6bdba1a62c17d1fb7d58be802883611a0c81612f3e565b611a14613024565b50565b600054610100900460ff1680611a30575060005460ff16155b611a7c5760405162461bcd60e51b815260206004820152601c60248201527f636f6e747261637420616c726561647920696e697469616c697a6564000000006044820152606401610c9d565b600054610100900460ff16158015611a9e576000805461ffff19166101011790555b6000611aa981612f3e565b50600a80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0385811691909117909155600980547fffffffffffffff0000000000000000000000000000000000000000ffffffffff16650100000000009285169290920291909117905580156115b357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055505050565b600260208190526000918252604082208054918101805460ff84169461ffff610100860416946301000000810490910b9363ffffffff6401000000008304811694680100000000000000009093041692909190611bab906142a3565b80601f0160208091040260200160405190810160405280929190818152602001828054611bd7906142a3565b8015611c245780601f10611bf957610100808354040283529160200191611c24565b820191906000526020600020905b815481529060010190602001808311611c0757829003601f168201915b5050505050905086565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1611c5881612f3e565b506009805463ffffffff909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff909216919091179055565b611ce16040518060e00160405280600061ffff168152602001600060ff168152602001600060ff1681526020016000800b81526020016060815260200160608152602001606081525090565b61ffff8216611d325760405162461bcd60e51b815260206004820152600e60248201527f49442063616e6e6f7420626520300000000000000000000000000000000000006044820152606401610c9d565b60075461ffff6801000000000000000090910481169083161115611d985760405162461bcd60e51b815260206004820152601160248201527f494420646f6573206e6f742065786973740000000000000000000000000000006044820152606401610c9d565b61ffff8083166000908152600160208181526040808420815160e0810183528154968716815260ff6201000088048116948201949094526301000000870490931691830191909152640100000000909404830b830b90920b606083015282018054919291608084019190611e0b906142a3565b80601f0160208091040260200160405190810160405280929190818152602001828054611e37906142a3565b8015611e845780601f10611e5957610100808354040283529160200191611e84565b820191906000526020600020905b815481529060010190602001808311611e6757829003601f168201915b50505050508152602001600282018054611e9d906142a3565b80601f0160208091040260200160405190810160405280929190818152602001828054611ec9906142a3565b8015611f165780601f10611eeb57610100808354040283529160200191611f16565b820191906000526020600020905b815481529060010190602001808311611ef957829003601f168201915b50505050508152602001600382018054610e07906142a3565b600081815260066020526040812054819061ffff16611f4d816116da565b9250925050915091565b60005460ff16611fa95760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610c9d565b7fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd294611fd381612f3e565b60095460009060ff16611fe581612f48565b600581111561200457634e487b7160e01b600052602160045260246000fd5b82600581111561202457634e487b7160e01b600052602160045260246000fd5b14156120725760405162461bcd60e51b815260206004820152600f60248201527f696e636f727265637420737461746500000000000000000000000000000000006044820152606401610c9d565b61ffff8b166120c35760405162461bcd60e51b815260206004820152600e60248201527f49442063616e6e6f7420626520300000000000000000000000000000000000006044820152606401610c9d565b61ffff808c16600081815260016020526040902054909116146121285760405162461bcd60e51b815260206004820152601260248201527f4a6f62204944206e6f742070726573656e7400000000000000000000000000006044820152606401610c9d565b60648a60ff16111561217c5760405162461bcd60e51b815260206004820152601160248201527f576569676874206265796f6e64206d61780000000000000000000000000000006044820152606401610c9d565b6000612186613016565b61ffff8d1660009081526001602052604090209091506121aa9060030187876137c2565b5061ffff8c1660009081526001602052604090206121cc9060020189896137c2565b508860018111156121ed57634e487b7160e01b600052602160045260246000fd5b600160008e61ffff1661ffff16815260200190815260200160002060000160026101000a81548160ff021916908360ff1602179055508a600160008e61ffff1661ffff16815260200190815260200160002060000160036101000a81548160ff021916908360ff16021790555089600160008e61ffff1661ffff16815260200190815260200160002060000160046101000a81548160ff021916908360000b60ff1602179055508b61ffff167fefd160aad4b75c8736880e140d62ed38df6dc44639b0b63c2fd4971b0e15e0248a838e8e428e8e8e8e6040516122d899989796959493929190613f03565b60405180910390a2505050505050505050505050565b60005460ff166123405760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610c9d565b7fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd29461236a81612f3e565b60095460049060ff1661237c81612f48565b600581111561239b57634e487b7160e01b600052602160045260246000fd5b8260058111156123bb57634e487b7160e01b600052602160045260246000fd5b146124085760405162461bcd60e51b815260206004820152600f60248201527f696e636f727265637420737461746500000000000000000000000000000000006044820152606401610c9d565b61ffff84166124595760405162461bcd60e51b815260206004820152600e60248201527f49442063616e6e6f7420626520300000000000000000000000000000000000006044820152606401610c9d565b60075461ffff6601000000000000909104811690851611156124bd5760405162461bcd60e51b815260206004820152601160248201527f494420646f6573206e6f742065786973740000000000000000000000000000006044820152606401610c9d565b60006124c7613016565b60075490915063ffffffff8083166201000090920416116124ea576124ea613024565b85156125995761ffff851660009081526002602052604090205460ff16156125545760405162461bcd60e51b815260206004820152601160248201527f494420616c7265616479206163746976650000000000000000000000000000006044820152606401610c9d565b6007546125669061ffff166001614171565b6007805461ffff191661ffff92831617905585166000908152600260205260409020805460ff191687151517905561263e565b61ffff851660009081526002602052604090205460ff166125fc5760405162461bcd60e51b815260206004820152601360248201527f494420616c726561647920696e616374697665000000000000000000000000006044820152606401610c9d565b60075461260f9060019061ffff16614239565b6007805461ffff191661ffff92831617905585166000908152600260205260409020805460ff19168715151790555b6126498160016141af565b600760026101000a81548163ffffffff021916908363ffffffff1602179055506126716130c5565b61ffff851660008181526002602090815260409182902054825160ff9091161515815263ffffffff851691810191909152428183015290517ff0b5874d363139e5f9c359f28c68eaa5833e8018c74483703075e3de02ba89b99181900360600190a2600a546001600160a01b031663d257450c6126ec61322f565b6040518263ffffffff1660e01b815260040161270a91815260200190565b600060405180830381600087803b15801561272457600080fd5b505af1158015612738573d6000803e3d6000fd5b50505050505050505050565b60008281526008602052604090206001015461275f81612f3e565b6115b3838361332c565b60005460ff166127bb5760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610c9d565b7fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd2946127e581612f3e565b60648a60ff1611156128395760405162461bcd60e51b815260206004820152601160248201527f576569676874206265796f6e64206d61780000000000000000000000000000006044820152606401610c9d565b6007546128579068010000000000000000900461ffff166001614171565b600780547fffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffff166801000000000000000061ffff938416810291909117918290556040805160e0810190915291049091168152602081018960018111156128cd57634e487b7160e01b600052602160045260246000fd5b60ff1681526020018b60ff1681526020018a60000b815260200188888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250604080516020601f890181900481028201810190925287815291810191908890889081908401838280828437600092019190915250505090825250604080516020601f870181900481028201810190925285815291810191908690869081908401838280828437600092018290525093909452505060075461ffff68010000000000000000909104811682526001602081815260408085208751815489850151938a015160608b015190980b60ff908116640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff998216630100000002999099167fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffff91909516620100000262ffffff19909216929097169190911717949094161793909317825560808501518051929450612a66939185019291019061374e565b5060a08201518051612a8291600284019160209091019061374e565b5060c08201518051612a9e91600384019160209091019061374e565b50506007546040514281526801000000000000000090910461ffff1691507f2af60a3bf9cf4dd5faca2cf55ed47a2af51f35c08083d7585d462bdd1e17d47e906020015b60405180910390a250505050505050505050565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1612b2081612f3e565b506009805460ff191660ff92909216919091179055565b60005460ff16612b895760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610c9d565b7fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd294612bb381612f3e565b60095460009060ff16612bc581612f48565b6005811115612be457634e487b7160e01b600052602160045260246000fd5b826005811115612c0457634e487b7160e01b600052602160045260246000fd5b1415612c525760405162461bcd60e51b815260206004820152600f60248201527f696e636f727265637420737461746500000000000000000000000000000000006044820152606401610c9d565b6000845111612ca35760405162461bcd60e51b815260206004820152600d60248201527f6e6f206a6f6273206164646564000000000000000000000000000000000000006044820152606401610c9d565b60075461ffff660100000000000090910481169089161115612d075760405162461bcd60e51b815260206004820152601960248201527f436f6c6c656374696f6e204944206e6f742070726573656e74000000000000006044820152606401610c9d565b60095463ffffffff61010090910481169088161115612d685760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420746f6c6572616e63652076616c75650000000000000000006044820152606401610c9d565b6000612d72613016565b855190915060005b818160ff161015612e5d57868160ff1681518110612da857634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff1660016000898460ff1681518110612ddb57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015161ffff908116835290820192909252604001600020541614612e4b5760405162461bcd60e51b815260206004820152600f60248201527f6a6f62206e6f742070726573656e7400000000000000000000000000000000006044820152606401610c9d565b80612e558161431b565b915050612d7a565b5061ffff8a1660009081526002602090815260408220805463ffffffff8c811668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff918f166401000000000267ffffffff0000000019968e900b60ff166301000000029690961667ffffffffff000000199093169290921794909417939093169290921782558751612eff92600101918901906136a5565b508961ffff167f88a18739a2f3afe1c3ba001fd79a42a83d4e8fb98ecea04a4b4f0abd3c1f668688848b8d8b42604051612ae296959493929190613f7f565b611a1481336133af565b6000818160ff8216612f5d60056104b06141ce565b612f679190614239565b905061ffff8116612f7b60056104b06141ce565b612f899061ffff164261433b565b1180612fb1575060ff8216612fa160056104b06141ce565b612faf9061ffff164261433b565b105b15612fc0575060059392505050565b60006005612fd0816104b06141ce565b612fde9061ffff16426141ef565b612fe8919061433b565b90508060ff16600581111561300d57634e487b7160e01b600052602160045260246000fd5b95945050505050565b600061164e6104b042614203565b600060015b60075461ffff66010000000000009091048116908216116116405761ffff811660009081526002602052604090205460ff16156130965761ffff8181166000908152600360205260409020805461ffff191691841691909117905561308f826001614171565b91506130b3565b61ffff81166000908152600360205260409020805461ffff191690555b806130bd816142de565b915050613029565b600060015b60075461ffff66010000000000009091048116908216116116405761ffff811660009081526002602052604090205460ff161561314c5761ffff8082166000818152600460209081526040808320805495881661ffff1996871681179091558352600590915290208054909216179055613145826001614171565b9150613169565b61ffff81166000908152600460205260409020805461ffff191690555b80613173816142de565b9150506130ca565b60008383604051602001613190929190613e10565b60408051601f1981840301815291815281516020928301206000818152600690935291205490915061ffff16156132095760405162461bcd60e51b815260206004820181905260248201527f436f6c6c656374696f6e2065786973747320776974682073616d65206e616d656044820152606401610c9d565b6000908152600660205260409020805461ffff191661ffff929092169190911790555050565b60075460009061ffff16815b60018211156132715761324f60028361433b565b15613258575060015b613263600184614197565b9250600182901c915061323b565b8015613285578261328181614300565b9350505b505090565b60008281526008602090815260408083206001600160a01b038516845290915290205460ff166116405760008281526008602090815260408083206001600160a01b03851684529091529020805460ff191660011790556132e83390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526008602090815260408083206001600160a01b038516845290915290205460ff16156116405760008281526008602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60008281526008602090815260408083206001600160a01b038516845290915290205460ff16611640576133ed816001600160a01b0316601461342f565b6133f883602061342f565b604051602001613409929190613e20565b60408051601f198184030181529082905262461bcd60e51b8252610c9d91600401613fcb565b6060600061343e83600261421a565b613449906002614197565b67ffffffffffffffff81111561346f57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613499576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106134de57634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061354f57634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061358b84600261421a565b613596906001614197565b90505b600181111561364f577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106135e557634e487b7160e01b600052603260045260246000fd5b1a60f81b82828151811061360957634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936136488161428c565b9050613599565b50831561369e5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610c9d565b9392505050565b82805482825590600052602060002090600f0160109004810192821561373e5791602002820160005b8382111561370e57835183826101000a81548161ffff021916908361ffff16021790555092602001926002016020816001010492830192600103026136ce565b801561373c5782816101000a81549061ffff021916905560020160208160010104928301926001030261370e565b505b5061374a929150613836565b5090565b82805461375a906142a3565b90600052602060002090601f01602090048101928261377c576000855561373e565b82601f1061379557805160ff191683800117855561373e565b8280016001018555821561373e579182015b8281111561373e5782518255916020019190600101906137a7565b8280546137ce906142a3565b90600052602060002090601f0160209004810192826137f0576000855561373e565b82601f106138095782800160ff1982351617855561373e565b8280016001018555821561373e579182015b8281111561373e57823582559160200191906001019061381b565b5b8082111561374a5760008155600101613837565b80356001600160a01b038116811461386257600080fd5b919050565b600082601f830112613877578081fd5b8135602067ffffffffffffffff808311156138945761389461437b565b8260051b604051601f19603f830116810181811084821117156138b9576138b961437b565b604052848152838101925086840182880185018910156138d7578687fd5b8692505b85831015613900576138ec81613974565b8452928401926001929092019184016138db565b50979650505050505050565b80356002811061386257600080fd5b8035600081900b811461386257600080fd5b60008083601f84011261393e578182fd5b50813567ffffffffffffffff811115613955578182fd5b60208301915083602082850101111561396d57600080fd5b9250929050565b803561ffff8116811461386257600080fd5b803563ffffffff8116811461386257600080fd5b803560ff8116811461386257600080fd5b600080604083850312156139bd578182fd5b6139c68361384b565b91506139d46020840161384b565b90509250929050565b600080604083850312156139ef578182fd5b823580151581146139fe578283fd5b91506139d460208401613974565b600060208284031215613a1d578081fd5b5035919050565b60008060408385031215613a36578182fd5b823591506139d46020840161384b565b600060208284031215613a57578081fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461369e578182fd5b600060208284031215613a97578081fd5b61369e82613974565b600080600080600060a08688031215613ab7578081fd5b613ac086613974565b9450613ace60208701613986565b9350613adc60408701613986565b9250613aea6060870161391b565b9150608086013567ffffffffffffffff811115613b05578182fd5b613b1188828901613867565b9150509295509295909350565b60008060008060008060008060c0898b031215613b39578283fd5b613b4289613974565b9750613b5060208a0161399a565b9650613b5e60408a0161391b565b9550613b6c60608a0161390c565b9450608089013567ffffffffffffffff80821115613b88578485fd5b613b948c838d0161392d565b909650945060a08b0135915080821115613bac578384fd5b50613bb98b828c0161392d565b999c989b5096995094979396929594505050565b600060208284031215613bde578081fd5b5051919050565b600060208284031215613bf6578081fd5b61369e82613986565b60008060008060008060a08789031215613c17578182fd5b613c2087613986565b9550613c2e6020880161391b565b9450613c3c60408801613986565b9350606087013567ffffffffffffffff80821115613c58578384fd5b613c648a838b01613867565b94506080890135915080821115613c79578384fd5b50613c8689828a0161392d565b979a9699509497509295939492505050565b600060208284031215613ca9578081fd5b61369e8261399a565b600080600080600080600080600060c08a8c031215613ccf578283fd5b613cd88a61399a565b9850613ce660208b0161391b565b9750613cf460408b0161390c565b965060608a013567ffffffffffffffff80821115613d10578485fd5b613d1c8d838e0161392d565b909850965060808c0135915080821115613d34578485fd5b613d408d838e0161392d565b909650945060a08c0135915080821115613d58578283fd5b50613d658c828d0161392d565b915080935050809150509295985092959850929598565b6000815180845260208085019450808401835b83811015613daf57815161ffff1687529582019590820190600101613d8f565b509495945050505050565b8183528181602085013750600080602083850101526020601f19601f840116840101905092915050565b60008151808452613dfc81602086016020860161425c565b601f01601f19169290920160200192915050565b8183823760009101908152919050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351613e5881601785016020880161425c565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351613e9581602884016020880161425c565b01602801949350505050565b60208152600061369e6020830184613d7c565b861515815261ffff86166020820152600085810b604083015263ffffffff808616606084015280851660808401525060c060a0830152613ef760c0830184613de4565b98975050505050505050565b600060028b10613f2157634e487b7160e01b81526021600452602481fd5b8a825263ffffffff8a16602083015260ff8916604083015287810b606083015286608083015260e060a0830152613f5c60e083018688613dba565b82810360c0840152613f6f818587613dba565b9c9b505050505050505050505050565b600087810b825263ffffffff8088166020840152808716604084015280861660608401525060c06080830152613fb860c0830185613d7c565b90508260a0830152979650505050505050565b60208152600061369e6020830184613de4565b6020815281511515602082015261ffff602083015116604082015260006040830151810b6060830152606083015161401e608084018263ffffffff169052565b50608083015163ffffffff811660a08401525060a083015160e060c084015261404b610100840182613d7c565b905060c0840151601f198483030160e085015261300d8282613de4565b6020815261ffff825116602082015260ff60208301511660408201526000604083015161409a606084018260ff169052565b5060608301516140af608084018260000b9052565b50608083015160e060a08401526140ca610100840182613de4565b905060a0840151601f19808584030160c08601526140e88383613de4565b925060c08601519150808584030160e08601525061300d8282613de4565b61ffff8816815260ff8716602082015260ff86166040820152600085810b606083015260e0608083015261413d60e0830186613de4565b82810360a084015261414f8186613de4565b905082810360c08401526141638185613de4565b9a9950505050505050505050565b600061ffff80831681851680830382111561418e5761418e61434f565b01949350505050565b600082198211156141aa576141aa61434f565b500190565b600063ffffffff80831681851680830382111561418e5761418e61434f565b600061ffff808416806141e3576141e3614365565b92169190910492915050565b6000826141fe576141fe614365565b500490565b600063ffffffff808416806141e3576141e3614365565b60008160001904831182151516156142345761423461434f565b500290565b600061ffff838116908316818110156142545761425461434f565b039392505050565b60005b8381101561427757818101518382015260200161425f565b83811115614286576000848401525b50505050565b60008161429b5761429b61434f565b506000190190565b600181811c908216806142b757607f821691505b602082108114156142d857634e487b7160e01b600052602260045260246000fd5b50919050565b600061ffff808316818114156142f6576142f661434f565b6001019392505050565b60006000198214156143145761431461434f565b5060010190565b600060ff821660ff8114156143325761433261434f565b60010192915050565b60008261434a5761434a614365565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea264697066735822122009d2ff203a7e90c1f2ada4894785e7ad2b51ef9d8d4b30cc6466c1d568c749a364736f6c63430008040033