- We're indexing this chain right now. Some of the counts may be inaccurate.

Contract Address Details

0xDc342De801De342EdE013C7E6e7a78Fa4f548041

Token
RAZOR (RAZOR)
Creator
0x441e0b–a83d92 at 0xbb76ff–e3eae8
Balance
0 sFUEL
Tokens
Fetching tokens...
Transactions
1,555 Transactions
Transfers
0 Transfers
Gas Used
66,533,818
Last Balance Update
2110421
Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB 0xad1259343cf69a916a1a9aaf6250d2db67606a5d.
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
Verify & Publish
Contract name:
RAZOR




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




Optimization runs
3000
Verified at
2022-10-03 06:39:15.283756Z

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

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

@openzeppelin/contracts/utils/Strings.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @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);
}
}

@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.5.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, _msgSender());
_;
}
/**
* @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 `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.
*/
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.
*/
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`.
*/
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.
*
* [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.
*/
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.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}

contracts/tokenization/IStakedTokenFactory.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
interface IStakedTokenFactory {
/**
* @dev a factory contract where the sRZR for a new staker is being deployed
* @param stakeManagerAddress address of the stake Manager contract
* @param stakedID id of the staker whom the sRZR is being deployed
*/
function createStakedToken(address stakeManagerAddress, uint32 stakedID) external returns (address);
}

contracts/tokenization/StakedTokenFactory.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "./StakedToken.sol";
import "./IStakedTokenFactory.sol";
contract StakedTokenFactory is IStakedTokenFactory {
/// @inheritdoc IStakedTokenFactory
function createStakedToken(address stakeManagerAddress, uint32 stakerID) external override returns (address) {
require(stakeManagerAddress != address(0x0), "zero address check");
StakedToken sToken = new StakedToken(stakeManagerAddress, stakerID);
return address(sToken);
}
}

contracts/Core/parameters/child/CollectionManagerParams.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "../interfaces/ICollectionManagerParams.sol";
import "../ACL.sol";
import "../../storage/Constants.sol";
abstract contract CollectionManagerParams is ACL, ICollectionManagerParams, Constants {
uint8 public buffer = 5;
/// @notice maximum percentage deviation allowed from medians for all collections
uint32 public maxTolerance = 1_000_000;
/// @inheritdoc ICollectionManagerParams
function setMaxTolerance(uint32 _maxTolerance) external override onlyRole(GOVERNANCE_ROLE) {
// slither-reason: Disabled across all params childs
// as they are being called by governance contract only
// and their before setting, we are emitting event
// slither-disable-next-line events-maths
maxTolerance = _maxTolerance;
}
function setBufferLength(uint8 _bufferLength) external override onlyRole(GOVERNANCE_ROLE) {
// slither-reason: Disabled across all params childs
// as they are being called by governance contract only
// and their before setting, we are emitting event
// slither-disable-next-line events-maths
buffer = _bufferLength;
}
}

contracts/Core/parameters/interfaces/IRewardManagerParams.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
interface IRewardManagerParams {
/**
* @notice changing the percentage stake penalty to be given out for inactivity
* @dev can be called only by the the address that has the governance role
* @param _penaltyNotRevealNumerator updated value to be set for penaltyNotRevealNumerator
*/
function setPenaltyNotRevealNum(uint32 _penaltyNotRevealNumerator) external;
/**
* @notice changing the percentage age penalty to be given out for inactivity
* @dev can be called only by the the address that has the governance role
* @param _penaltyAgeNotRevealNumerator updated value to be set for penaltyAgeNotRevealNumerator
*/
function setPenaltyAgeNotRevealNum(uint32 _penaltyAgeNotRevealNumerator) external;
/**
* @notice changing the block reward given out to stakers
* @dev can be called only by the the address that has the governance role
* @param _blockReward updated value to be set for blockReward
*/
function setBlockReward(uint256 _blockReward) external;
/**
* @notice changing the maximum age a staker can have
* @dev can be called only by the the address that has the governance role
* @param _maxAge updated value to be set for maxAge
*/
function setMaxAge(uint32 _maxAge) external;
/**
* @notice changing the maximum percentage deviation allowed from medians for all collections
* @dev can be called only by the the address that has the governance role
* @param _maxTolerance updated value for maxTolerance
*/
function setMaxTolerance(uint32 _maxTolerance) external;
/**
* @notice changing maximum commission stakers can charge from delegators on their profits
* @dev can be called only by the the address that has the governance role
* @param _maxCommission updated value to be set for maxCommission
*/
function setMaxCommission(uint8 _maxCommission) external;
}

@openzeppelin/contracts/utils/cryptography/ECDSA.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (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) {
// Check the signature length
// - case 65: r,s,v signature (standard)
// - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
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.
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 if (signature.length == 64) {
bytes32 r;
bytes32 vs;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return tryRecover(hash, r, vs);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}

contracts/Core/storage/CollectionStorage.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "../../lib/Structs.sol";
contract CollectionStorage {
enum JobSelectorType {
JSON,
XHTML
}
/// @notice mapping for JobID -> Job Info
mapping(uint16 => Structs.Job) public jobs;
/// @notice mapping for CollectionID -> Collection Info
mapping(uint16 => Structs.Collection) public collections;
// For next epoch : Penalties
/// @notice delayed mappping collectionid -> leafId
mapping(uint16 => uint16) public collectionIdToLeafIdRegistryOfLastEpoch;
/// For this epoch : Disputes
/// @notice mapping for collectionid -> leafId
mapping(uint16 => uint16) public collectionIdToLeafIdRegistry;
/// @notice mapping for leafId -> collectionid
mapping(uint16 => uint16) public leafIdToCollectionIdRegistry;
/// @notice mapping for name of collection in bytes32 -> collectionid
mapping(bytes32 => uint16) public ids;
/// @notice number of active collections in the network
uint16 public numActiveCollections;
/// @notice epoch in which the registry needs to be updated
uint32 public updateRegistryEpoch;
/// @notice number of collections in the network
uint16 public numCollections;
/// @notice number of jobs in the network
uint16 public numJobs;
}

contracts/Core/interface/ICollectionManager.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
interface ICollectionManager {
/**
* @notice updates the collectionIdToLeafIdRegistryOfLastEpoch resgistries.
* @dev It is called by the blockManager when a block is confirmed. It is only called if there was a change in the
* status of collections in the network
*/
function updateDelayedRegistry() external;
/**
* @param id the id of the collection
* @return status of the collection
*/
function getCollectionStatus(uint16 id) external view returns (bool);
/**
* @return total number of active collections
*/
function getNumActiveCollections() external view returns (uint16);
/**
* @return ids of active collections
*/
function getActiveCollections() external view returns (uint16[] memory);
/**
* @param id the id of the collection
* @return power of the collection
*/
function getCollectionPower(uint16 id) external view returns (int8);
/**
* @return total number of collections
*/
function getNumCollections() external view returns (uint16);
/**
* @param i the leafId of the collection
* @return tolerance of the collection
*/
function getCollectionTolerance(uint16 i) external view returns (uint32);
/**
* @param id the id of the collection
* @return the leafId of the collection from collectionIdToLeafIdRegistry
*/
function getLeafIdOfCollection(uint16 id) external view returns (uint16);
/**
* @param leafId, the leafId of the collection
* @return the id of the collection
*/
function getCollectionIdFromLeafId(uint16 leafId) external view returns (uint16);
/**
* @param id the id of the collection
* @return the leafId of the collection from collectionIdToLeafIdRegistryOfLastEpoch
*/
function getLeafIdOfCollectionForLastEpoch(uint16 id) external view returns (uint16);
/**
* @param _name the name of the collection in bytes32
* @return collection ID
*/
function getCollectionID(bytes32 _name) external view returns (uint16);
/**
* @notice returns the result of the collection based on the name sent by the client
* @param _name the name of the collection in bytes32
* @return result of the collection
* @return power of the resultant collection
*/
function getResult(bytes32 _name) external view returns (uint256, int8);
/**
* @notice returns the result of the collection based on the id sent by the client
* @param _id the id of the collection
* @return result of the collection
* @return power of the resultant collection
*/
function getResultFromID(uint16 _id) external view returns (uint256, int8);
/**
* @return epoch in which the registry needs to be updated
*/
function getUpdateRegistryEpoch() external view returns (uint32);
}

contracts/mocks/MerklePosAwareTest.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "../lib/MerklePosAware.sol";
contract MerklePosAwareTest {
function verifyMultiple(
bytes32[][] memory proofs,
bytes32 root,
bytes32[] memory leaves,
uint16[] memory leafId,
uint256 depth,
uint16 maxAssets
) external pure returns (bool) {
return MerklePosAware.verifyMultiple(proofs, root, leaves, leafId, depth, maxAssets);
}
function getSequence(uint256 leafId, uint256 depth) external pure returns (bytes memory) {
return MerklePosAware.getSequence(leafId, depth);
}
//function getSequence(uint256 leafId, uint256 depth) external
// function verify(
// bytes32[] memory proof,
// bytes32 root,
// bytes32 leaf,
// uint16 leafId,
// uint256 depth,
// uint16 maxAssets
// ) external pure returns (bool) {
// return MerklePosAware.verify(proof, root, leaf, leafId, depth, maxAssets);
// }
// function getSequence(uint256 leafId, uint256 depth) external pure returns (string memory) {
// return string(MerklePosAware.getSequence(leafId, depth));
// }
}

contracts/Core/RewardManager.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "./interface/IBlockManager.sol";
import "./interface/IStakeManager.sol";
import "./interface/IVoteManager.sol";
import "./interface/IRewardManager.sol";
import "./interface/ICollectionManager.sol";
import "../tokenization/IStakedToken.sol";
import "../Initializable.sol";
import "./storage/Constants.sol";
import "./parameters/child/RewardManagerParams.sol";
/** @title RewardManager
* @notice RewardManager gives penalties and rewards to stakers based on
* their behaviour
*/
contract RewardManager is Initializable, Constants, RewardManagerParams, IRewardManager {
IStakeManager public stakeManager;
IVoteManager public voteManager;
IBlockManager public blockManager;
ICollectionManager public collectionManager;
/**
* @param stakeManagerAddress The address of the StakeManager contract
* @param voteManagersAddress The address of the VoteManager contract
* @param blockManagerAddress The address of the BlockManager contract
* @param collectionManagerAddress The address of the CollectionManager contract
*/
function initialize(
address stakeManagerAddress,
address voteManagersAddress,
address blockManagerAddress,
address collectionManagerAddress
) external initializer onlyRole(DEFAULT_ADMIN_ROLE) {
stakeManager = IStakeManager(stakeManagerAddress);
voteManager = IVoteManager(voteManagersAddress);
blockManager = IBlockManager(blockManagerAddress);
collectionManager = ICollectionManager(collectionManagerAddress);
}
/// @inheritdoc IRewardManager
function givePenalties(uint32 epoch, uint32 stakerId) external override initialized onlyRole(REWARD_MODIFIER_ROLE) {
_givePenalties(epoch, stakerId);
}
/// @inheritdoc IRewardManager
function giveBlockReward(uint32 stakerId, uint32 epoch) external override initialized onlyRole(REWARD_MODIFIER_ROLE) {
Structs.Staker memory staker = stakeManager.getStaker(stakerId);
IStakedToken sToken = IStakedToken(staker.tokenAddress);
uint256 totalSupply = sToken.totalSupply();
uint256 stakerSRZR = sToken.balanceOf(staker._address);
uint256 delegatorShare = blockReward - ((blockReward * stakerSRZR) / totalSupply);
uint8 commissionApplicable = staker.commission < maxCommission ? staker.commission : maxCommission;
uint256 stakerReward = (delegatorShare * commissionApplicable) / 100;
stakeManager.setStakerStake(epoch, stakerId, StakeChanged.BlockReward, staker.stake, staker.stake + (blockReward - stakerReward));
stakeManager.setStakerReward(
epoch,
stakerId,
StakerRewardChanged.StakerRewardAdded,
staker.stakerReward,
staker.stakerReward + stakerReward
);
}
/// @inheritdoc IRewardManager
function giveInactivityPenalties(uint32 epoch, uint32 stakerId) external override initialized onlyRole(REWARD_MODIFIER_ROLE) {
_giveInactivityPenalties(epoch, stakerId);
}
/**
* @dev inactivity penalties are given to stakers if they have been inactive for more than the grace period.
* For each inactive epoch, stakers lose their age by 1*10000 and their stake by penaltyNotRevealNum.
* Activity is calculated based on the epoch the staker last revealed in.
*/
function _giveInactivityPenalties(uint32 epoch, uint32 stakerId) internal {
uint32 epochLastRevealed = voteManager.getEpochLastRevealed(stakerId);
Structs.Staker memory thisStaker = stakeManager.getStaker(stakerId);
uint32 epochLastActive = thisStaker.epochFirstStakedOrLastPenalized < epochLastRevealed
? epochLastRevealed
: thisStaker.epochFirstStakedOrLastPenalized;
// penalize or reward if last active more than epoch - 1
uint32 inactiveEpochs = (epoch - epochLastActive == 0) ? 0 : epoch - epochLastActive - 1;
uint256 previousStake = thisStaker.stake;
uint256 newStake = thisStaker.stake;
uint32 previousAge = thisStaker.age;
uint32 newAge = thisStaker.age;
if (inactiveEpochs > 0) {
(newStake, newAge) = _calculateInactivityPenalties(inactiveEpochs, newStake, previousAge);
}
// uint256 currentStake = previousStake;
if (newStake < previousStake) {
stakeManager.setStakerEpochFirstStakedOrLastPenalized(epoch, stakerId);
stakeManager.setStakerStake(epoch, stakerId, StakeChanged.InactivityPenalty, previousStake, newStake);
}
if (newAge < previousAge) {
stakeManager.setStakerAge(epoch, stakerId, newAge, AgeChanged.InactivityPenalty);
}
}
/**
* @dev Penalties are given to stakers based their activity if they have been inactive for more than the grace period
* and their votes in the previous epoch compared to the medians confirmed. Penalties on votes depend upon how far were
* the staker's votes from the median value. There is tolerance being added for each collection thereby not penalizing
* stakers of their vote was within the tolerance limits of the collection
*/
function _givePenalties(uint32 epoch, uint32 stakerId) internal {
_giveInactivityPenalties(epoch, stakerId);
Structs.Staker memory thisStaker = stakeManager.getStaker(stakerId);
uint32 epochLastRevealed = voteManager.getEpochLastRevealed(stakerId);
if (epochLastRevealed != 0 && epochLastRevealed < epoch - 1) {
return;
}
uint64 age = thisStaker.age + 10000;
// cap age to maxAge
age = age > maxAge ? maxAge : age;
Structs.Block memory _block = blockManager.getBlock(epochLastRevealed);
uint16[] memory idsRevealedLastEpoch = _block.ids;
uint256[] memory mediansLastEpoch = _block.medians;
if (idsRevealedLastEpoch.length == 0) return;
uint256 penalty = 0;
for (uint16 i = 0; i < idsRevealedLastEpoch.length; i++) {
// get leaf id from collection id, as voting happens w.r.t leaf ids
// slither-disable-next-line calls-loop
uint16 leafId = collectionManager.getLeafIdOfCollectionForLastEpoch(idsRevealedLastEpoch[i]);
// slither-disable-next-line calls-loop
uint256 voteValueLastEpoch = voteManager.getVoteValue(epoch - 1, stakerId, leafId);
if (
voteValueLastEpoch != 0
) // Only penalise if given asset revealed, please note here again revealed value of asset cant be zero
{
uint256 medianLastEpoch = mediansLastEpoch[i];
if (medianLastEpoch == 0) continue; //WARNING: unreachable. Can be removed
uint256 prod = age * voteValueLastEpoch;
// slither-disable-next-line calls-loop
uint32 tolerance = collectionManager.getCollectionTolerance(idsRevealedLastEpoch[i]);
tolerance = tolerance <= maxTolerance ? tolerance : maxTolerance;
uint256 maxVoteTolerance = medianLastEpoch + ((medianLastEpoch * tolerance) / BASE_DENOMINATOR);
uint256 minVoteTolerance = medianLastEpoch - ((medianLastEpoch * tolerance) / BASE_DENOMINATOR);
// if (voteWeightLastEpoch > 0) {
if (voteValueLastEpoch > maxVoteTolerance) {
//penalty = age(vote/maxvote-1)
penalty = penalty + (prod / maxVoteTolerance - age);
} else if (voteValueLastEpoch < minVoteTolerance) {
//penalty = age(1-vote/minvote)
penalty = penalty + (age - prod / minVoteTolerance);
}
}
}
age = penalty > age ? 0 : age - uint32(penalty);
stakeManager.setStakerAge(epoch, thisStaker.id, uint32(age), AgeChanged.VotingRewardOrPenalty);
}
/** @notice Calculates the stake and age inactivity penalties of the staker
* @param epochs The difference of epochs where the staker was inactive
* @param stakeValue The Stake that staker had in last epoch
* @param ageValue The age that staker had in last epoch
*/
function _calculateInactivityPenalties(
uint32 epochs,
uint256 stakeValue,
uint32 ageValue
) internal view returns (uint256, uint32) {
uint256 penalty = ((epochs) * (stakeValue * penaltyNotRevealNum)) / BASE_DENOMINATOR;
uint256 newStake = penalty < stakeValue ? stakeValue - penalty : 0;
uint256 penaltyAge = (uint256(epochs) * (uint256(ageValue) * uint256(penaltyAgeNotRevealNum))) / BASE_DENOMINATOR;
uint32 newAge = uint32(penaltyAge) < ageValue ? ageValue - uint32(penaltyAge) : 0;
return (newStake, newAge);
}
}

@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 v4.4.1 (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 Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
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.5.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, _allowances[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 = _allowances[owner][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `sender` to `recipient`.
*
* 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 Spend `amount` form the allowance of `owner` toward `spender`.
*
* 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);
}
}

contracts/Greeter.sol

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
contract Greeter {
string public greeting;
constructor(string memory _greeting) {
greeting = _greeting;
}
function setGreeting(string memory _greeting) public {
greeting = _greeting;
}
function greet() public view returns (string memory) {
return greeting;
}
}

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.5.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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);
/**
* @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);
}

@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":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"initialSupply","internalType":"uint256"}]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"decreaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"subtractedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"increaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"addedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]}]
            

Contract Creation Code

Verify & Publish
0x60806040523480156200001157600080fd5b5060405162000ca838038062000ca8833981016040819052620000349162000234565b6040805180820182526005808252642920ad27a960d91b60208084018281528551808701909652928552840152815191929162000074916003916200018e565b5080516200008a9060049060208401906200018e565b5050506200009f3382620000a660201b60201c565b50620002af565b6001600160a01b038216620001015760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b80600260008282546200011591906200024d565b90915550506001600160a01b03821660009081526020819052604081208054839290620001449084906200024d565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b8280546200019c9062000272565b90600052602060002090601f016020900481019282620001c057600085556200020b565b82601f10620001db57805160ff19168380011785556200020b565b828001600101855582156200020b579182015b828111156200020b578251825591602001919060010190620001ee565b50620002199291506200021d565b5090565b5b808211156200021957600081556001016200021e565b60006020828403121562000246578081fd5b5051919050565b600082198211156200026d57634e487b7160e01b81526011600452602481fd5b500190565b600181811c908216806200028757607f821691505b60208210811415620002a957634e487b7160e01b600052602260045260246000fd5b50919050565b6109e980620002bf6000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80633950935111610081578063a457c2d71161005b578063a457c2d714610187578063a9059cbb1461019a578063dd62ed3e146101ad57600080fd5b8063395093511461014357806370a082311461015657806395d89b411461017f57600080fd5b806318160ddd116100b257806318160ddd1461010f57806323b872dd14610121578063313ce5671461013457600080fd5b806306fdde03146100ce578063095ea7b3146100ec575b600080fd5b6100d66101e6565b6040516100e391906108b1565b60405180910390f35b6100ff6100fa366004610888565b610278565b60405190151581526020016100e3565b6002545b6040519081526020016100e3565b6100ff61012f36600461084d565b610290565b604051601281526020016100e3565b6100ff610151366004610888565b6102b4565b6101136101643660046107fa565b6001600160a01b031660009081526020819052604090205490565b6100d66102f3565b6100ff610195366004610888565b610302565b6100ff6101a8366004610888565b6103b1565b6101136101bb36600461081b565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6060600380546101f59061095f565b80601f01602080910402602001604051908101604052809291908181526020018280546102219061095f565b801561026e5780601f106102435761010080835404028352916020019161026e565b820191906000526020600020905b81548152906001019060200180831161025157829003601f168201915b5050505050905090565b6000336102868185856103bf565b5060019392505050565b60003361029e858285610517565b6102a98585856105c7565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919061028690829086906102ee908790610922565b6103bf565b6060600480546101f59061095f565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190838110156103a45760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102a982868684036103bf565b6000336102868185856105c7565b6001600160a01b03831661043a5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161039b565b6001600160a01b0382166104b65760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161039b565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146105c157818110156105b45760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161039b565b6105c184848484036103bf565b50505050565b6001600160a01b0383166106435760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161039b565b6001600160a01b0382166106bf5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161039b565b6001600160a01b0383166000908152602081905260409020548181101561074e5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161039b565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290610785908490610922565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516107d191815260200190565b60405180910390a36105c1565b80356001600160a01b03811681146107f557600080fd5b919050565b60006020828403121561080b578081fd5b610814826107de565b9392505050565b6000806040838503121561082d578081fd5b610836836107de565b9150610844602084016107de565b90509250929050565b600080600060608486031215610861578081fd5b61086a846107de565b9250610878602085016107de565b9150604084013590509250925092565b6000806040838503121561089a578182fd5b6108a3836107de565b946020939093013593505050565b6000602080835283518082850152825b818110156108dd578581018301518582016040015282016108c1565b818111156108ee5783604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000821982111561095a577f4e487b710000000000000000000000000000000000000000000000000000000081526011600452602481fd5b500190565b600181811c9082168061097357607f821691505b602082108114156109ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b5091905056fea26469706673582212204d1aa2b28bd9bbad6af804837c084f53b4309b8df5accd816ee51388520f9d6e64736f6c634300080400330000000000000000000000000000000000000000033b2e3c9fd0803ce8000000

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100c95760003560e01c80633950935111610081578063a457c2d71161005b578063a457c2d714610187578063a9059cbb1461019a578063dd62ed3e146101ad57600080fd5b8063395093511461014357806370a082311461015657806395d89b411461017f57600080fd5b806318160ddd116100b257806318160ddd1461010f57806323b872dd14610121578063313ce5671461013457600080fd5b806306fdde03146100ce578063095ea7b3146100ec575b600080fd5b6100d66101e6565b6040516100e391906108b1565b60405180910390f35b6100ff6100fa366004610888565b610278565b60405190151581526020016100e3565b6002545b6040519081526020016100e3565b6100ff61012f36600461084d565b610290565b604051601281526020016100e3565b6100ff610151366004610888565b6102b4565b6101136101643660046107fa565b6001600160a01b031660009081526020819052604090205490565b6100d66102f3565b6100ff610195366004610888565b610302565b6100ff6101a8366004610888565b6103b1565b6101136101bb36600461081b565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6060600380546101f59061095f565b80601f01602080910402602001604051908101604052809291908181526020018280546102219061095f565b801561026e5780601f106102435761010080835404028352916020019161026e565b820191906000526020600020905b81548152906001019060200180831161025157829003601f168201915b5050505050905090565b6000336102868185856103bf565b5060019392505050565b60003361029e858285610517565b6102a98585856105c7565b506001949350505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919061028690829086906102ee908790610922565b6103bf565b6060600480546101f59061095f565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190838110156103a45760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102a982868684036103bf565b6000336102868185856105c7565b6001600160a01b03831661043a5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161039b565b6001600160a01b0382166104b65760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161039b565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146105c157818110156105b45760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161039b565b6105c184848484036103bf565b50505050565b6001600160a01b0383166106435760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161039b565b6001600160a01b0382166106bf5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161039b565b6001600160a01b0383166000908152602081905260409020548181101561074e5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161039b565b6001600160a01b03808516600090815260208190526040808220858503905591851681529081208054849290610785908490610922565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516107d191815260200190565b60405180910390a36105c1565b80356001600160a01b03811681146107f557600080fd5b919050565b60006020828403121561080b578081fd5b610814826107de565b9392505050565b6000806040838503121561082d578081fd5b610836836107de565b9150610844602084016107de565b90509250929050565b600080600060608486031215610861578081fd5b61086a846107de565b9250610878602085016107de565b9150604084013590509250925092565b6000806040838503121561089a578182fd5b6108a3836107de565b946020939093013593505050565b6000602080835283518082850152825b818110156108dd578581018301518582016040015282016108c1565b818111156108ee5783604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000821982111561095a577f4e487b710000000000000000000000000000000000000000000000000000000081526011600452602481fd5b500190565b600181811c9082168061097357607f821691505b602082108114156109ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b5091905056fea26469706673582212204d1aa2b28bd9bbad6af804837c084f53b4309b8df5accd816ee51388520f9d6e64736f6c63430008040033