false
false
0

Contract Address Details

0x301779E4c95f951D2E17B4c3EdDC717551df2EBb

Contract Name
RewardManager
Creator
0xd73462–49788f at 0x45b331–cd6b05
Balance
0
Tokens
Fetching tokens...
Transactions
12 Transactions
Transfers
0 Transfers
Gas Used
522,140
Last Balance Update
3503942
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
RewardManager




Optimization enabled
true
Compiler version
v0.8.4+commit.c7e474f2




Optimization runs
3000
Verified at
2022-08-26T14:23:21.770002Z

contracts/Core/RewardManager.sol

Sol2uml
new
// 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/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/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/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/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/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/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/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/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++;
    }
}
          

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

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

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

@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/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/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":"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":"uint256","name":"","internalType":"uint256"}],"name":"blockReward","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract ICollectionManager"}],"name":"collectionManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getRoleAdmin","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"giveBlockReward","inputs":[{"type":"uint32","name":"stakerId","internalType":"uint32"},{"type":"uint32","name":"epoch","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"giveInactivityPenalties","inputs":[{"type":"uint32","name":"epoch","internalType":"uint32"},{"type":"uint32","name":"stakerId","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"givePenalties","inputs":[{"type":"uint32","name":"epoch","internalType":"uint32"},{"type":"uint32","name":"stakerId","internalType":"uint32"}]},{"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":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"stakeManagerAddress","internalType":"address"},{"type":"address","name":"voteManagersAddress","internalType":"address"},{"type":"address","name":"blockManagerAddress","internalType":"address"},{"type":"address","name":"collectionManagerAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"maxAge","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"maxCommission","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"maxTolerance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"penaltyAgeNotRevealNum","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"penaltyNotRevealNum","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":"setBlockReward","inputs":[{"type":"uint256","name":"_blockReward","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxAge","inputs":[{"type":"uint32","name":"_maxAge","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxCommission","inputs":[{"type":"uint8","name":"_maxCommission","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxTolerance","inputs":[{"type":"uint32","name":"_maxTolerance","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPenaltyAgeNotRevealNum","inputs":[{"type":"uint32","name":"_penaltyAgeNotRevealNumerator","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPenaltyNotRevealNum","inputs":[{"type":"uint32","name":"_penaltyNotRevealNumerator","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IStakeManager"}],"name":"stakeManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IVoteManager"}],"name":"voteManager","inputs":[]}]
              

Contract Creation Code

0x6080604052600280546001600160601b0319166a0f4240000186a0000003e817905568056bc75e2d631000006003556004805464ffffffffff19166414000f42401790553480156200005057600080fd5b506200005e60003362000064565b620000fc565b62000070828262000074565b5050565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff16620000705760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b61296e806200010c6000396000f3fe608060405234801561001057600080fd5b50600436106102ff5760003560e01c8063817a973a1161019c578063c0becaa9116100ee578063da98429511610097578063f36c8f5c11610071578063f36c8f5c146107b4578063f8c8765e146107db578063fccc2813146107ee57600080fd5b8063da9842951461073f578063ed6c935d14610766578063ef8bf6841461078d57600080fd5b8063ce55bf1c116100c8578063ce55bf1c14610706578063d547741f14610719578063d9169b321461072c57600080fd5b8063c0becaa9146106d0578063c30e36b3146106e3578063ca29dc5f146106f657600080fd5b8063a86f5a3f11610150578063b0daafef1161012a578063b0daafef1461068c578063b76daeb5146106b3578063bd859584146106c657600080fd5b8063a86f5a3f1461064b578063ac4746ab1461065b578063ac9d82cf1461067757600080fd5b806391d148541161018157806391d14854146105f75780639fdf846914610630578063a217fddf1461064357600080fd5b8063817a973a146105bd578063885fc094146105d057600080fd5b8063389ed267116102555780635b070278116102095780637542ff95116101e35780637542ff9514610562578063776076e71461057e5780638018499f146105a557600080fd5b80635b070278146104e3578063622f93301461050a578063687043c51461053157600080fd5b806341d296f71161023a57806341d296f71461046a57806342c1e587146104915780634912b72a146104bc57600080fd5b8063389ed267146104305780633c5580821461045757600080fd5b8063248a9ca3116102b75780632f50bcc4116102915780632f50bcc4146103e357806334b23d6f1461040a57806336568abe1461041d57600080fd5b8063248a9ca3146103855780632d93b9a0146103a95780632f2ff15d146103d057600080fd5b806305db56df116102e857806305db56df146103415780630ac168a11461035b5780631a18e7071461037257600080fd5b806301f47e381461030457806301ffc9a714610319575b600080fd5b610317610312366004612538565b6107f7565b005b61032c6103273660046122ff565b610bf1565b60405190151581526020015b60405180910390f35b610349600581565b60405160ff9091168152602001610338565b61036460035481565b604051908152602001610338565b6103176103803660046122b8565b610c8a565b6103646103933660046122b8565b6000908152600160208190526040909120015490565b6103647f912208965b92edeb3eb82a612c87b38b5e844f7539cb396f0d08ec012e511b0781565b6103176103de3660046122d0565b610cba565b6103647f46aaf8a125792dfff6db03d74f94fe1acaf55c8cab22f65297c15809c364465c81565b610317610418366004612500565b610ce5565b61031761042b3660046122d0565b610d4f565b6103647f139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d81565b610317610465366004612500565b610ddb565b6103647f91f5d9ea80c4d04985e669bc72870410b28b57afdf61c0d50d377766d86a374881565b6005546104a4906001600160a01b031681565b6040516001600160a01b039091168152602001610338565b6103647f6b7da7a33355c6e035439beb2ac6a052f1558db73f08690b1c9ef5a4e838959781565b6103647fce3e6c780f179d7a08d28e380f7be9c36d990f56515174f8adb6287c543e30dc81565b6103647f518d8c39717318f051dfb836a4ebe5b3c34aa2cb7fce26c21a89745422ba804381565b60025461054d9068010000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610338565b6004546104a4906501000000000090046001600160a01b031681565b6103647fdbaaaff2c3744aa215ebd99971829e1c1b728703a0bf252f96685d29011fc80481565b60025461054d90640100000000900463ffffffff1681565b6103176105cb366004612500565b610e49565b6103647fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd29481565b61032c6106053660046122d0565b60009182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6007546104a4906001600160a01b031681565b610364600081565b60025461054d9063ffffffff1681565b6106646104b081565b60405161ffff9091168152602001610338565b60045461034990640100000000900460ff1681565b6103647ff31dda80d37c96a1a0852ace387dda52a75487d7d4eb74895e749ede3e0987b481565b6103176106c1366004612565565b610e90565b61054d6298968081565b6103176106de366004612500565b610ef7565b6103176106f1366004612538565b610f3e565b60045461054d9063ffffffff1681565b610317610714366004612538565b610fc4565b6103176107273660046122d0565b61104a565b6006546104a4906001600160a01b031681565b6103647f18797bc7973e1dadee1895be2f1003818e30eae3b0e7a01eb9b2e66f3ea2771f81565b6103647fca51085219bef34771da292cb24ee4fcf0ae6bdba1a62c17d1fb7d58be80288381565b6103647fcabcaf259dd9a27f23bd8a92bacd65983c2ebf027c853f89f941715905271a8d81565b6103647f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb181565b6103176107e936600461225d565b611070565b6104a461dead81565b60005460ff1661084e5760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a6564000060448201526064015b60405180910390fd5b7fcabcaf259dd9a27f23bd8a92bacd65983c2ebf027c853f89f941715905271a8d610878816111e4565b600480546040517feb04d42a00000000000000000000000000000000000000000000000000000000815263ffffffff861692810192909252600091650100000000009091046001600160a01b03169063eb04d42a906024016101606040518083038186803b1580156108e957600080fd5b505afa1580156108fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109219190612401565b905060008160c0015190506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561096757600080fd5b505afa15801561097b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099f91906124e8565b60a08401516040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152919250600091908416906370a082319060240160206040518083038186803b158015610a0557600080fd5b505afa158015610a19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3d91906124e8565b905060008282600354610a5091906127cb565b610a5a91906127ab565b600354610a6791906127ea565b600454604087015191925060009160ff6401000000009092048216911610610a9c57600454640100000000900460ff16610aa2565b85604001515b905060006064610ab560ff8416856127cb565b610abf91906127ab565b9050600460059054906101000a90046001600160a01b03166001600160a01b031663f056357a8a8c60008b610120015186600354610afd91906127ea565b8d6101200151610b0d919061276b565b6040518663ffffffff1660e01b8152600401610b2d959493929190612635565b600060405180830381600087803b158015610b4757600080fd5b505af1158015610b5b573d6000803e3d6000fd5b50506004546101408a0151650100000000009091046001600160a01b0316925063ea8e156a91508b908d90600090610b93878261276b565b6040518663ffffffff1660e01b8152600401610bb3959493929190612676565b600060405180830381600087803b158015610bcd57600080fd5b505af1158015610be1573d6000803e3d6000fd5b5050505050505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610c8457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1610cb4816111e4565b50600355565b60008281526001602081905260409091200154610cd6816111e4565b610ce083836111f1565b505050565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1610d0f816111e4565b506002805463ffffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff909216919091179055565b6001600160a01b0381163314610dcd5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610845565b610dd78282611278565b5050565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1610e05816111e4565b506002805463ffffffff90921668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff909216919091179055565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1610e73816111e4565b506004805463ffffffff191663ffffffff92909216919091179055565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1610eba816111e4565b506004805460ff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff909216919091179055565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1610f21816111e4565b506002805463ffffffff191663ffffffff92909216919091179055565b60005460ff16610f905760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610845565b7fcabcaf259dd9a27f23bd8a92bacd65983c2ebf027c853f89f941715905271a8d610fba816111e4565b610ce083836112fb565b60005460ff166110165760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610845565b7fcabcaf259dd9a27f23bd8a92bacd65983c2ebf027c853f89f941715905271a8d611040816111e4565b610ce08383611a0e565b60008281526001602081905260409091200154611066816111e4565b610ce08383611278565b600054610100900460ff1680611089575060005460ff16155b6110d55760405162461bcd60e51b815260206004820152601c60248201527f636f6e747261637420616c726561647920696e697469616c697a6564000000006044820152606401610845565b600054610100900460ff1615801561111457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b600061111f816111e4565b50600480547fffffffffffffff0000000000000000000000000000000000000000ffffffffff16650100000000006001600160a01b038881169190910291909117909155600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116878416179091556006805482168684161790556007805490911691841691909117905580156111dd57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b5050505050565b6111ee8133611d7b565b50565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff16610dd75760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff1615610dd75760008281526001602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6113058282611a0e565b600480546040517feb04d42a00000000000000000000000000000000000000000000000000000000815263ffffffff841692810192909252600091650100000000009091046001600160a01b03169063eb04d42a906024016101606040518083038186803b15801561137657600080fd5b505afa15801561138a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ae9190612401565b6005546040517f0bb34f5600000000000000000000000000000000000000000000000000000000815263ffffffff851660048201529192506000916001600160a01b0390911690630bb34f569060240160206040518083038186803b15801561141657600080fd5b505afa15801561142a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144e919061251c565b905063ffffffff81161580159061147a575061146b600185612801565b63ffffffff168163ffffffff16105b156114855750505050565b600082608001516127106114999190612783565b60025463ffffffff91821692506801000000000000000090041681116114bf57806114d5565b60025468010000000000000000900463ffffffff165b6006546040517f1bea14e900000000000000000000000000000000000000000000000000000000815263ffffffff851660048201529192506000916001600160a01b0390911690631bea14e99060240160006040518083038186803b15801561153d57600080fd5b505afa158015611551573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611579919081019061233f565b604081015160a082015181519293509091611598575050505050505050565b6000805b83518161ffff1610156119485760075484516000916001600160a01b03169063b55fbd3590879061ffff86169081106115e557634e487b7160e01b600052603260045260246000fd5b60200260200101516040518263ffffffff1660e01b8152600401611613919061ffff91909116815260200190565b60206040518083038186803b15801561162b57600080fd5b505afa15801561163f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166391906124ce565b6005549091506000906001600160a01b0316633e85b95f61168560018f612801565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815263ffffffff9182166004820152908e16602482015261ffff8516604482015260640160206040518083038186803b1580156116eb57600080fd5b505afa1580156116ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172391906124e8565b90508015611933576000858461ffff168151811061175157634e487b7160e01b600052603260045260246000fd5b60200260200101519050806000141561176c57505050611936565b60006117828367ffffffffffffffff8c166127cb565b60075489519192506000916001600160a01b039091169063ff524958908b9061ffff8a169081106117c357634e487b7160e01b600052603260045260246000fd5b60200260200101516040518263ffffffff1660e01b81526004016117f1919061ffff91909116815260200190565b60206040518083038186803b15801561180957600080fd5b505afa15801561181d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611841919061251c565b60045490915063ffffffff90811690821611156118665760045463ffffffff16611868565b805b905060006298968061188063ffffffff8416866127cb565b61188a91906127ab565b611894908561276b565b90506000629896806118ac63ffffffff8516876127cb565b6118b691906127ab565b6118c090866127ea565b9050818611156118fa5767ffffffffffffffff8d166118df83866127ab565b6118e991906127ea565b6118f3908a61276b565b985061192d565b8086101561192d5761190c81856127ab565b6119209067ffffffffffffffff8f166127ea565b61192a908a61276b565b98505b50505050505b50505b806119408161288e565b91505061159c565b508467ffffffffffffffff16811161196f5761196a63ffffffff821686612826565b611972565b60005b6004805460608a01516040517fd1b705bd000000000000000000000000000000000000000000000000000000008152939850650100000000009091046001600160a01b03169263d1b705bd926119d1928e9290918b9160019101612694565b600060405180830381600087803b1580156119eb57600080fd5b505af11580156119ff573d6000803e3d6000fd5b50505050505050505050505050565b6005546040517f0bb34f5600000000000000000000000000000000000000000000000000000000815263ffffffff831660048201526000916001600160a01b031690630bb34f569060240160206040518083038186803b158015611a7157600080fd5b505afa158015611a85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa9919061251c565b600480546040517feb04d42a00000000000000000000000000000000000000000000000000000000815263ffffffff8616928101929092529192506000916501000000000090046001600160a01b03169063eb04d42a906024016101606040518083038186803b158015611b1c57600080fd5b505afa158015611b30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b549190612401565b905060008263ffffffff168260e0015163ffffffff1610611b79578160e00151611b7b565b825b90506000611b898287612801565b63ffffffff1615611baf576001611ba08388612801565b611baa9190612801565b611bb2565b60005b61012084015160808501519192509081908063ffffffff851615611be157611bdb858484611dfb565b90935090505b83831015611d0457600480546040517fd8a41b0400000000000000000000000000000000000000000000000000000000815263ffffffff808e1693820193909352918b1660248301526501000000000090046001600160a01b03169063d8a41b0490604401600060405180830381600087803b158015611c6057600080fd5b505af1158015611c74573d6000803e3d6000fd5b5050600480546040517ff056357a000000000000000000000000000000000000000000000000000000008152650100000000009091046001600160a01b0316935063f056357a9250611cd1918e918e916001918b918b9101612635565b600060405180830381600087803b158015611ceb57600080fd5b505af1158015611cff573d6000803e3d6000fd5b505050505b8163ffffffff168163ffffffff161015611d6f57600480546040517fd1b705bd000000000000000000000000000000000000000000000000000000008152650100000000009091046001600160a01b03169163d1b705bd91610bb3918e918e91879160009101612694565b50505050505050505050565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff16610dd757611db9816001600160a01b03166014611ecc565b611dc4836020611ecc565b604051602001611dd5929190612581565b60408051601f198184030181529082905262461bcd60e51b825261084591600401612602565b600254600090819081906298968090611e1a9063ffffffff16876127cb565b611e2a9063ffffffff89166127cb565b611e3491906127ab565b90506000858210611e46576000611e50565b611e5082876127ea565b6002549091506000906298968090611e7a90640100000000900463ffffffff9081169089166127cb565b611e8a9063ffffffff8b166127cb565b611e9491906127ab565b905060008663ffffffff168263ffffffff1610611eb2576000611ebc565b611ebc8288612801565b9299929850919650505050505050565b60606000611edb8360026127cb565b611ee690600261276b565b67ffffffffffffffff811115611f0c57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611f36576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110611f7b57634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611fec57634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006120288460026127cb565b61203390600161276b565b90505b60018111156120ec577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061208257634e487b7160e01b600052603260045260246000fd5b1a60f81b8282815181106120a657634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936120e581612877565b9050612036565b50831561213b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610845565b9392505050565b805161214d81612902565b919050565b600082601f830112612162578081fd5b8151602061217761217283612747565b612716565b80838252828201915082860187848660051b8901011115612196578586fd5b855b858110156121bb576121a982612235565b84529284019290840190600101612198565b5090979650505050505050565b600082601f8301126121d8578081fd5b815160206121e861217283612747565b80838252828201915082860187848660051b8901011115612207578586fd5b855b858110156121bb57815184529284019290840190600101612209565b8051801515811461214d57600080fd5b805161ffff8116811461214d57600080fd5b805161214d81612917565b805161214d81612929565b60008060008060808587031215612272578384fd5b843561227d81612902565b9350602085013561228d81612902565b9250604085013561229d81612902565b915060608501356122ad81612902565b939692955090935050565b6000602082840312156122c9578081fd5b5035919050565b600080604083850312156122e2578182fd5b8235915060208301356122f481612902565b809150509250929050565b600060208284031215612310578081fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461213b578182fd5b600060208284031215612350578081fd5b815167ffffffffffffffff80821115612367578283fd5b9083019060c0828603121561237a578283fd5b6123826126c9565b61238b83612225565b815261239960208401612247565b60208201526040830151828111156123af578485fd5b6123bb87828601612152565b604083015250606083015160608201526080830151608082015260a0830151828111156123e6578485fd5b6123f2878286016121c8565b60a08301525095945050505050565b60006101608284031215612413578081fd5b61241b6126f2565b61242483612225565b815261243260208401612225565b602082015261244360408401612252565b604082015261245460608401612247565b606082015261246560808401612247565b608082015261247660a08401612142565b60a082015261248760c08401612142565b60c082015261249860e08401612247565b60e08201526101006124ab818501612247565b908201526101208381015190820152610140928301519281019290925250919050565b6000602082840312156124df578081fd5b61213b82612235565b6000602082840312156124f9578081fd5b5051919050565b600060208284031215612511578081fd5b813561213b81612917565b60006020828403121561252d578081fd5b815161213b81612917565b6000806040838503121561254a578182fd5b823561255581612917565b915060208301356122f481612917565b600060208284031215612576578081fd5b813561213b81612929565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516125b9816017850160208801612847565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516125f6816028840160208801612847565b01602801949350505050565b6020815260008251806020840152612621816040850160208701612847565b601f01601f19169190910160400192915050565b63ffffffff86811682528516602082015260a081016003851061265a5761265a6128c6565b8460408301528360608301528260808301529695505050505050565b63ffffffff86811682528516602082015260a0810161265a856128f2565b63ffffffff8581168252848116602083015283166040820152608081016126ba836128f2565b82606083015295945050505050565b60405160c0810167ffffffffffffffff811182821017156126ec576126ec6128dc565b60405290565b604051610160810167ffffffffffffffff811182821017156126ec576126ec6128dc565b604051601f8201601f1916810167ffffffffffffffff8111828210171561273f5761273f6128dc565b604052919050565b600067ffffffffffffffff821115612761576127616128dc565b5060051b60200190565b6000821982111561277e5761277e6128b0565b500190565b600063ffffffff8083168185168083038211156127a2576127a26128b0565b01949350505050565b6000826127c657634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156127e5576127e56128b0565b500290565b6000828210156127fc576127fc6128b0565b500390565b600063ffffffff8381169083168181101561281e5761281e6128b0565b039392505050565b600067ffffffffffffffff8381169083168181101561281e5761281e6128b0565b60005b8381101561286257818101518382015260200161284a565b83811115612871576000848401525b50505050565b600081612886576128866128b0565b506000190190565b600061ffff808316818114156128a6576128a66128b0565b6001019392505050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600281106111ee576111ee6128c6565b6001600160a01b03811681146111ee57600080fd5b63ffffffff811681146111ee57600080fd5b60ff811681146111ee57600080fdfea2646970667358221220b442a55b9710934d4bbb4e1b0f86e9647737d3dc2a2b44c0e5489689d17015d664736f6c63430008040033

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106102ff5760003560e01c8063817a973a1161019c578063c0becaa9116100ee578063da98429511610097578063f36c8f5c11610071578063f36c8f5c146107b4578063f8c8765e146107db578063fccc2813146107ee57600080fd5b8063da9842951461073f578063ed6c935d14610766578063ef8bf6841461078d57600080fd5b8063ce55bf1c116100c8578063ce55bf1c14610706578063d547741f14610719578063d9169b321461072c57600080fd5b8063c0becaa9146106d0578063c30e36b3146106e3578063ca29dc5f146106f657600080fd5b8063a86f5a3f11610150578063b0daafef1161012a578063b0daafef1461068c578063b76daeb5146106b3578063bd859584146106c657600080fd5b8063a86f5a3f1461064b578063ac4746ab1461065b578063ac9d82cf1461067757600080fd5b806391d148541161018157806391d14854146105f75780639fdf846914610630578063a217fddf1461064357600080fd5b8063817a973a146105bd578063885fc094146105d057600080fd5b8063389ed267116102555780635b070278116102095780637542ff95116101e35780637542ff9514610562578063776076e71461057e5780638018499f146105a557600080fd5b80635b070278146104e3578063622f93301461050a578063687043c51461053157600080fd5b806341d296f71161023a57806341d296f71461046a57806342c1e587146104915780634912b72a146104bc57600080fd5b8063389ed267146104305780633c5580821461045757600080fd5b8063248a9ca3116102b75780632f50bcc4116102915780632f50bcc4146103e357806334b23d6f1461040a57806336568abe1461041d57600080fd5b8063248a9ca3146103855780632d93b9a0146103a95780632f2ff15d146103d057600080fd5b806305db56df116102e857806305db56df146103415780630ac168a11461035b5780631a18e7071461037257600080fd5b806301f47e381461030457806301ffc9a714610319575b600080fd5b610317610312366004612538565b6107f7565b005b61032c6103273660046122ff565b610bf1565b60405190151581526020015b60405180910390f35b610349600581565b60405160ff9091168152602001610338565b61036460035481565b604051908152602001610338565b6103176103803660046122b8565b610c8a565b6103646103933660046122b8565b6000908152600160208190526040909120015490565b6103647f912208965b92edeb3eb82a612c87b38b5e844f7539cb396f0d08ec012e511b0781565b6103176103de3660046122d0565b610cba565b6103647f46aaf8a125792dfff6db03d74f94fe1acaf55c8cab22f65297c15809c364465c81565b610317610418366004612500565b610ce5565b61031761042b3660046122d0565b610d4f565b6103647f139c2898040ef16910dc9f44dc697df79363da767d8bc92f2e310312b816e46d81565b610317610465366004612500565b610ddb565b6103647f91f5d9ea80c4d04985e669bc72870410b28b57afdf61c0d50d377766d86a374881565b6005546104a4906001600160a01b031681565b6040516001600160a01b039091168152602001610338565b6103647f6b7da7a33355c6e035439beb2ac6a052f1558db73f08690b1c9ef5a4e838959781565b6103647fce3e6c780f179d7a08d28e380f7be9c36d990f56515174f8adb6287c543e30dc81565b6103647f518d8c39717318f051dfb836a4ebe5b3c34aa2cb7fce26c21a89745422ba804381565b60025461054d9068010000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610338565b6004546104a4906501000000000090046001600160a01b031681565b6103647fdbaaaff2c3744aa215ebd99971829e1c1b728703a0bf252f96685d29011fc80481565b60025461054d90640100000000900463ffffffff1681565b6103176105cb366004612500565b610e49565b6103647fa3a75e7cd2b78fcc3ae2046ab93bfa4ac0b87ed7ea56646a312cbcb73eabd29481565b61032c6106053660046122d0565b60009182526001602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6007546104a4906001600160a01b031681565b610364600081565b60025461054d9063ffffffff1681565b6106646104b081565b60405161ffff9091168152602001610338565b60045461034990640100000000900460ff1681565b6103647ff31dda80d37c96a1a0852ace387dda52a75487d7d4eb74895e749ede3e0987b481565b6103176106c1366004612565565b610e90565b61054d6298968081565b6103176106de366004612500565b610ef7565b6103176106f1366004612538565b610f3e565b60045461054d9063ffffffff1681565b610317610714366004612538565b610fc4565b6103176107273660046122d0565b61104a565b6006546104a4906001600160a01b031681565b6103647f18797bc7973e1dadee1895be2f1003818e30eae3b0e7a01eb9b2e66f3ea2771f81565b6103647fca51085219bef34771da292cb24ee4fcf0ae6bdba1a62c17d1fb7d58be80288381565b6103647fcabcaf259dd9a27f23bd8a92bacd65983c2ebf027c853f89f941715905271a8d81565b6103647f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb181565b6103176107e936600461225d565b611070565b6104a461dead81565b60005460ff1661084e5760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a6564000060448201526064015b60405180910390fd5b7fcabcaf259dd9a27f23bd8a92bacd65983c2ebf027c853f89f941715905271a8d610878816111e4565b600480546040517feb04d42a00000000000000000000000000000000000000000000000000000000815263ffffffff861692810192909252600091650100000000009091046001600160a01b03169063eb04d42a906024016101606040518083038186803b1580156108e957600080fd5b505afa1580156108fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109219190612401565b905060008160c0015190506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561096757600080fd5b505afa15801561097b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099f91906124e8565b60a08401516040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152919250600091908416906370a082319060240160206040518083038186803b158015610a0557600080fd5b505afa158015610a19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3d91906124e8565b905060008282600354610a5091906127cb565b610a5a91906127ab565b600354610a6791906127ea565b600454604087015191925060009160ff6401000000009092048216911610610a9c57600454640100000000900460ff16610aa2565b85604001515b905060006064610ab560ff8416856127cb565b610abf91906127ab565b9050600460059054906101000a90046001600160a01b03166001600160a01b031663f056357a8a8c60008b610120015186600354610afd91906127ea565b8d6101200151610b0d919061276b565b6040518663ffffffff1660e01b8152600401610b2d959493929190612635565b600060405180830381600087803b158015610b4757600080fd5b505af1158015610b5b573d6000803e3d6000fd5b50506004546101408a0151650100000000009091046001600160a01b0316925063ea8e156a91508b908d90600090610b93878261276b565b6040518663ffffffff1660e01b8152600401610bb3959493929190612676565b600060405180830381600087803b158015610bcd57600080fd5b505af1158015610be1573d6000803e3d6000fd5b5050505050505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b000000000000000000000000000000000000000000000000000000001480610c8457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1610cb4816111e4565b50600355565b60008281526001602081905260409091200154610cd6816111e4565b610ce083836111f1565b505050565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1610d0f816111e4565b506002805463ffffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff909216919091179055565b6001600160a01b0381163314610dcd5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610845565b610dd78282611278565b5050565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1610e05816111e4565b506002805463ffffffff90921668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff909216919091179055565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1610e73816111e4565b506004805463ffffffff191663ffffffff92909216919091179055565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1610eba816111e4565b506004805460ff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff909216919091179055565b7f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1610f21816111e4565b506002805463ffffffff191663ffffffff92909216919091179055565b60005460ff16610f905760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610845565b7fcabcaf259dd9a27f23bd8a92bacd65983c2ebf027c853f89f941715905271a8d610fba816111e4565b610ce083836112fb565b60005460ff166110165760405162461bcd60e51b815260206004820152601e60248201527f436f6e74726163742073686f756c6420626520696e697469616c697a656400006044820152606401610845565b7fcabcaf259dd9a27f23bd8a92bacd65983c2ebf027c853f89f941715905271a8d611040816111e4565b610ce08383611a0e565b60008281526001602081905260409091200154611066816111e4565b610ce08383611278565b600054610100900460ff1680611089575060005460ff16155b6110d55760405162461bcd60e51b815260206004820152601c60248201527f636f6e747261637420616c726561647920696e697469616c697a6564000000006044820152606401610845565b600054610100900460ff1615801561111457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000166101011790555b600061111f816111e4565b50600480547fffffffffffffff0000000000000000000000000000000000000000ffffffffff16650100000000006001600160a01b038881169190910291909117909155600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116878416179091556006805482168684161790556007805490911691841691909117905580156111dd57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b5050505050565b6111ee8133611d7b565b50565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff16610dd75760008281526001602081815260408084206001600160a01b0386168086529252808420805460ff19169093179092559051339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff1615610dd75760008281526001602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6113058282611a0e565b600480546040517feb04d42a00000000000000000000000000000000000000000000000000000000815263ffffffff841692810192909252600091650100000000009091046001600160a01b03169063eb04d42a906024016101606040518083038186803b15801561137657600080fd5b505afa15801561138a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ae9190612401565b6005546040517f0bb34f5600000000000000000000000000000000000000000000000000000000815263ffffffff851660048201529192506000916001600160a01b0390911690630bb34f569060240160206040518083038186803b15801561141657600080fd5b505afa15801561142a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144e919061251c565b905063ffffffff81161580159061147a575061146b600185612801565b63ffffffff168163ffffffff16105b156114855750505050565b600082608001516127106114999190612783565b60025463ffffffff91821692506801000000000000000090041681116114bf57806114d5565b60025468010000000000000000900463ffffffff165b6006546040517f1bea14e900000000000000000000000000000000000000000000000000000000815263ffffffff851660048201529192506000916001600160a01b0390911690631bea14e99060240160006040518083038186803b15801561153d57600080fd5b505afa158015611551573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611579919081019061233f565b604081015160a082015181519293509091611598575050505050505050565b6000805b83518161ffff1610156119485760075484516000916001600160a01b03169063b55fbd3590879061ffff86169081106115e557634e487b7160e01b600052603260045260246000fd5b60200260200101516040518263ffffffff1660e01b8152600401611613919061ffff91909116815260200190565b60206040518083038186803b15801561162b57600080fd5b505afa15801561163f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166391906124ce565b6005549091506000906001600160a01b0316633e85b95f61168560018f612801565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815263ffffffff9182166004820152908e16602482015261ffff8516604482015260640160206040518083038186803b1580156116eb57600080fd5b505afa1580156116ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172391906124e8565b90508015611933576000858461ffff168151811061175157634e487b7160e01b600052603260045260246000fd5b60200260200101519050806000141561176c57505050611936565b60006117828367ffffffffffffffff8c166127cb565b60075489519192506000916001600160a01b039091169063ff524958908b9061ffff8a169081106117c357634e487b7160e01b600052603260045260246000fd5b60200260200101516040518263ffffffff1660e01b81526004016117f1919061ffff91909116815260200190565b60206040518083038186803b15801561180957600080fd5b505afa15801561181d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611841919061251c565b60045490915063ffffffff90811690821611156118665760045463ffffffff16611868565b805b905060006298968061188063ffffffff8416866127cb565b61188a91906127ab565b611894908561276b565b90506000629896806118ac63ffffffff8516876127cb565b6118b691906127ab565b6118c090866127ea565b9050818611156118fa5767ffffffffffffffff8d166118df83866127ab565b6118e991906127ea565b6118f3908a61276b565b985061192d565b8086101561192d5761190c81856127ab565b6119209067ffffffffffffffff8f166127ea565b61192a908a61276b565b98505b50505050505b50505b806119408161288e565b91505061159c565b508467ffffffffffffffff16811161196f5761196a63ffffffff821686612826565b611972565b60005b6004805460608a01516040517fd1b705bd000000000000000000000000000000000000000000000000000000008152939850650100000000009091046001600160a01b03169263d1b705bd926119d1928e9290918b9160019101612694565b600060405180830381600087803b1580156119eb57600080fd5b505af11580156119ff573d6000803e3d6000fd5b50505050505050505050505050565b6005546040517f0bb34f5600000000000000000000000000000000000000000000000000000000815263ffffffff831660048201526000916001600160a01b031690630bb34f569060240160206040518083038186803b158015611a7157600080fd5b505afa158015611a85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa9919061251c565b600480546040517feb04d42a00000000000000000000000000000000000000000000000000000000815263ffffffff8616928101929092529192506000916501000000000090046001600160a01b03169063eb04d42a906024016101606040518083038186803b158015611b1c57600080fd5b505afa158015611b30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b549190612401565b905060008263ffffffff168260e0015163ffffffff1610611b79578160e00151611b7b565b825b90506000611b898287612801565b63ffffffff1615611baf576001611ba08388612801565b611baa9190612801565b611bb2565b60005b61012084015160808501519192509081908063ffffffff851615611be157611bdb858484611dfb565b90935090505b83831015611d0457600480546040517fd8a41b0400000000000000000000000000000000000000000000000000000000815263ffffffff808e1693820193909352918b1660248301526501000000000090046001600160a01b03169063d8a41b0490604401600060405180830381600087803b158015611c6057600080fd5b505af1158015611c74573d6000803e3d6000fd5b5050600480546040517ff056357a000000000000000000000000000000000000000000000000000000008152650100000000009091046001600160a01b0316935063f056357a9250611cd1918e918e916001918b918b9101612635565b600060405180830381600087803b158015611ceb57600080fd5b505af1158015611cff573d6000803e3d6000fd5b505050505b8163ffffffff168163ffffffff161015611d6f57600480546040517fd1b705bd000000000000000000000000000000000000000000000000000000008152650100000000009091046001600160a01b03169163d1b705bd91610bb3918e918e91879160009101612694565b50505050505050505050565b60008281526001602090815260408083206001600160a01b038516845290915290205460ff16610dd757611db9816001600160a01b03166014611ecc565b611dc4836020611ecc565b604051602001611dd5929190612581565b60408051601f198184030181529082905262461bcd60e51b825261084591600401612602565b600254600090819081906298968090611e1a9063ffffffff16876127cb565b611e2a9063ffffffff89166127cb565b611e3491906127ab565b90506000858210611e46576000611e50565b611e5082876127ea565b6002549091506000906298968090611e7a90640100000000900463ffffffff9081169089166127cb565b611e8a9063ffffffff8b166127cb565b611e9491906127ab565b905060008663ffffffff168263ffffffff1610611eb2576000611ebc565b611ebc8288612801565b9299929850919650505050505050565b60606000611edb8360026127cb565b611ee690600261276b565b67ffffffffffffffff811115611f0c57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611f36576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110611f7b57634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611fec57634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006120288460026127cb565b61203390600161276b565b90505b60018111156120ec577f303132333435363738396162636465660000000000000000000000000000000085600f166010811061208257634e487b7160e01b600052603260045260246000fd5b1a60f81b8282815181106120a657634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936120e581612877565b9050612036565b50831561213b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610845565b9392505050565b805161214d81612902565b919050565b600082601f830112612162578081fd5b8151602061217761217283612747565b612716565b80838252828201915082860187848660051b8901011115612196578586fd5b855b858110156121bb576121a982612235565b84529284019290840190600101612198565b5090979650505050505050565b600082601f8301126121d8578081fd5b815160206121e861217283612747565b80838252828201915082860187848660051b8901011115612207578586fd5b855b858110156121bb57815184529284019290840190600101612209565b8051801515811461214d57600080fd5b805161ffff8116811461214d57600080fd5b805161214d81612917565b805161214d81612929565b60008060008060808587031215612272578384fd5b843561227d81612902565b9350602085013561228d81612902565b9250604085013561229d81612902565b915060608501356122ad81612902565b939692955090935050565b6000602082840312156122c9578081fd5b5035919050565b600080604083850312156122e2578182fd5b8235915060208301356122f481612902565b809150509250929050565b600060208284031215612310578081fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461213b578182fd5b600060208284031215612350578081fd5b815167ffffffffffffffff80821115612367578283fd5b9083019060c0828603121561237a578283fd5b6123826126c9565b61238b83612225565b815261239960208401612247565b60208201526040830151828111156123af578485fd5b6123bb87828601612152565b604083015250606083015160608201526080830151608082015260a0830151828111156123e6578485fd5b6123f2878286016121c8565b60a08301525095945050505050565b60006101608284031215612413578081fd5b61241b6126f2565b61242483612225565b815261243260208401612225565b602082015261244360408401612252565b604082015261245460608401612247565b606082015261246560808401612247565b608082015261247660a08401612142565b60a082015261248760c08401612142565b60c082015261249860e08401612247565b60e08201526101006124ab818501612247565b908201526101208381015190820152610140928301519281019290925250919050565b6000602082840312156124df578081fd5b61213b82612235565b6000602082840312156124f9578081fd5b5051919050565b600060208284031215612511578081fd5b813561213b81612917565b60006020828403121561252d578081fd5b815161213b81612917565b6000806040838503121561254a578182fd5b823561255581612917565b915060208301356122f481612917565b600060208284031215612576578081fd5b813561213b81612929565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516125b9816017850160208801612847565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516125f6816028840160208801612847565b01602801949350505050565b6020815260008251806020840152612621816040850160208701612847565b601f01601f19169190910160400192915050565b63ffffffff86811682528516602082015260a081016003851061265a5761265a6128c6565b8460408301528360608301528260808301529695505050505050565b63ffffffff86811682528516602082015260a0810161265a856128f2565b63ffffffff8581168252848116602083015283166040820152608081016126ba836128f2565b82606083015295945050505050565b60405160c0810167ffffffffffffffff811182821017156126ec576126ec6128dc565b60405290565b604051610160810167ffffffffffffffff811182821017156126ec576126ec6128dc565b604051601f8201601f1916810167ffffffffffffffff8111828210171561273f5761273f6128dc565b604052919050565b600067ffffffffffffffff821115612761576127616128dc565b5060051b60200190565b6000821982111561277e5761277e6128b0565b500190565b600063ffffffff8083168185168083038211156127a2576127a26128b0565b01949350505050565b6000826127c657634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156127e5576127e56128b0565b500290565b6000828210156127fc576127fc6128b0565b500390565b600063ffffffff8381169083168181101561281e5761281e6128b0565b039392505050565b600067ffffffffffffffff8381169083168181101561281e5761281e6128b0565b60005b8381101561286257818101518382015260200161284a565b83811115612871576000848401525b50505050565b600081612886576128866128b0565b506000190190565b600061ffff808316818114156128a6576128a66128b0565b6001019392505050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600281106111ee576111ee6128c6565b6001600160a01b03811681146111ee57600080fd5b63ffffffff811681146111ee57600080fd5b60ff811681146111ee57600080fdfea2646970667358221220b442a55b9710934d4bbb4e1b0f86e9647737d3dc2a2b44c0e5489689d17015d664736f6c63430008040033