creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV5.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.5.16;\n\nimport \"./IAccessControlManagerV5.sol\";\n\n/**\n * @title AccessControlledV5\n * @author Venus\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.5.16)\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\n */\ncontract AccessControlledV5 {\n    /// @notice Access control manager contract\n    IAccessControlManagerV5 private _accessControlManager;\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n\n    /// @notice Emitted when access control manager contract address is changed\n    event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\n\n    /**\n     * @notice Returns the address of the access control manager contract\n     */\n    function accessControlManager() external view returns (IAccessControlManagerV5) {\n        return _accessControlManager;\n    }\n\n    /**\n     * @dev Internal function to set address of AccessControlManager\n     * @param accessControlManager_ The new address of the AccessControlManager\n     */\n    function _setAccessControlManager(address accessControlManager_) internal {\n        require(address(accessControlManager_) != address(0), \"invalid acess control manager address\");\n        address oldAccessControlManager = address(_accessControlManager);\n        _accessControlManager = IAccessControlManagerV5(accessControlManager_);\n        emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\n    }\n\n    /**\n     * @notice Reverts if the call is not allowed by AccessControlManager\n     * @param signature Method signature\n     */\n    function _checkAccessAllowed(string memory signature) internal view {\n        bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\n\n        if (!isAllowedToCall) {\n            revert(\"Unauthorized\");\n        }\n    }\n}\n"
      },
      "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV5.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.5.16;\n\n/**\n * @title IAccessControlManagerV5\n * @author Venus\n * @notice Interface implemented by the `AccessControlManagerV5` contract.\n */\ninterface IAccessControlManagerV5 {\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     *\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) external;\n\n    /**\n     * @notice Gives a function call permission to one single account\n     * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\n     * \t\tMay emit a {RoleGranted} event.\n     * @param contractAddress address of contract for which call permissions will be granted\n     * @param functionSig signature e.g. \"functionName(uint,bool)\"\n     */\n    function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\n\n    /**\n     * @notice Revokes an account's permission to a particular function call\n     * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\n     * \t\tMay emit a {RoleRevoked} event.\n     * @param contractAddress address of contract for which call permissions will be revoked\n     * @param functionSig signature e.g. \"functionName(uint,bool)\"\n     */\n    function revokeCallPermission(\n        address contractAddress,\n        string calldata functionSig,\n        address accountToRevoke\n    ) external;\n\n    /**\n     * @notice Verifies if the given account can call a praticular contract's function\n     * @dev Since the contract is calling itself this function, we can get contracts address with msg.sender\n     * @param account address (eoa or contract) for which call permissions will be checked\n     * @param functionSig signature e.g. \"functionName(uint,bool)\"\n     * @return false if the user account cannot call the particular contract function\n     *\n     */\n    function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\n\n    function hasPermission(\n        address account,\n        address contractAddress,\n        string calldata functionSig\n    ) external view returns (bool);\n}\n"
      },
      "@venusprotocol/solidity-utilities/contracts/TimeManagerV5.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.5.16;\n\ncontract TimeManagerV5 {\n    /// @dev The approximate number of seconds per year\n    uint256 public constant SECONDS_PER_YEAR = 31_536_000;\n\n    /// @notice Number of blocks per year or seconds per year\n    uint256 public blocksOrSecondsPerYear;\n\n    /// @dev Sets true when block timestamp is used\n    bool public isTimeBased;\n\n    /// @dev Sets true when contract is initialized\n    bool private isInitialized;\n\n    /// @notice Deprecated slot for _getCurrentSlot function pointer\n    bytes8 private __deprecatedSlot1;\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[48] private __gap;\n\n    /**\n     * @dev Function to simply retrieve block number or block timestamp\n     * @return Current block number or block timestamp\n     */\n    function getBlockNumberOrTimestamp() public view returns (uint256) {\n        return isTimeBased ? _getBlockTimestamp() : _getBlockNumber();\n    }\n\n    /**\n     * @dev Initializes the contract to use either blocks or seconds\n     * @param timeBased_ A boolean indicating whether the contract is based on time or block\n     * If timeBased is true than blocksPerYear_ param is ignored as blocksOrSecondsPerYear is set to SECONDS_PER_YEAR\n     * @param blocksPerYear_ The number of blocks per year\n     */\n    function _initializeTimeManager(bool timeBased_, uint256 blocksPerYear_) internal {\n        if (isInitialized) revert(\"Already initialized TimeManager\");\n\n        if (!timeBased_ && blocksPerYear_ == 0) {\n            revert(\"Invalid blocks per year\");\n        }\n        if (timeBased_ && blocksPerYear_ != 0) {\n            revert(\"Invalid time based configuration\");\n        }\n\n        isTimeBased = timeBased_;\n        blocksOrSecondsPerYear = timeBased_ ? SECONDS_PER_YEAR : blocksPerYear_;\n        isInitialized = true;\n    }\n\n    /**\n     * @dev Returns the current timestamp in seconds\n     * @return The current timestamp\n     */\n    function _getBlockTimestamp() private view returns (uint256) {\n        return block.timestamp;\n    }\n\n    /**\n     * @dev Returns the current block number\n     * @return The current block number\n     */\n    function _getBlockNumber() private view returns (uint256) {\n        return block.number;\n    }\n}\n"
      },
      "contracts/Tokens/Prime/IPrime.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.5.16;\npragma experimental ABIEncoderV2;\n\n/**\n * @title IPrime\n * @author Venus\n * @notice Interface for Prime Token\n */\ninterface IPrime {\n    /**\n     * @notice Executed by XVSVault whenever user's XVSVault balance changes\n     * @param user the account address whose balance was updated\n     */\n    function xvsUpdated(address user) external;\n\n    /**\n     * @notice accrues interest and updates score for an user for a specific market\n     * @param user the account address for which to accrue interest and update score\n     * @param market the market for which to accrue interest and update score\n     */\n    function accrueInterestAndUpdateScore(address user, address market) external;\n\n    /**\n     * @notice Distributes income from market since last distribution\n     * @param vToken the market for which to distribute the income\n     */\n    function accrueInterest(address vToken) external;\n\n    /**\n     * @notice Returns if user is a prime holder\n     * @param isPrimeHolder returns if the user is a prime holder\n     */\n    function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\n}\n"
      },
      "contracts/Utils/Address.sol": {
        "content": "pragma solidity ^0.5.5;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\n        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\n        // for accounts without code, i.e. `keccak256('')`\n        bytes32 codehash;\n        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            codehash := extcodehash(account)\n        }\n        return (codehash != accountHash && codehash != 0x0);\n    }\n\n    /**\n     * @dev Converts an `address` into `address payable`. Note that this is\n     * simply a type cast: the actual underlying value is not changed.\n     *\n     * _Available since v2.4.0._\n     */\n    function toPayable(address account) internal pure returns (address payable) {\n        return address(uint160(account));\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     *\n     * _Available since v2.4.0._\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        // solhint-disable-next-line avoid-call-value\n        // solium-disable-next-line security/no-call-value\n        (bool success, ) = recipient.call.value(amount)(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n}\n"
      },
      "contracts/Utils/ECDSA.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Adapted from OpenZeppelin Contracts v4.3.2 (utils/cryptography/ECDSA.sol)\n\n// SPDX-Copyright-Text: OpenZeppelin, 2021\n// SPDX-Copyright-Text: Venus, 2021\n\npragma solidity ^0.5.16;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\ncontract ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS,\n        InvalidSignatureV\n    }\n\n    function _throwError(RecoverError error) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert(\"ECDSA: invalid signature\");\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert(\"ECDSA: invalid signature length\");\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert(\"ECDSA: invalid signature 's' value\");\n        } else if (error == RecoverError.InvalidSignatureV) {\n            revert(\"ECDSA: invalid signature 'v' value\");\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n        _throwError(error);\n        return recovered;\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature` or error string. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     *\n     * _Available since v4.3._\n     */\n    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS);\n        }\n        if (v != 27 && v != 28) {\n            return (address(0), RecoverError.InvalidSignatureV);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature);\n        }\n\n        return (signer, RecoverError.NoError);\n    }\n}\n"
      },
      "contracts/Utils/IBEP20.sol": {
        "content": "pragma solidity ^0.5.0;\n\n/**\n * @dev Interface of the BEP20 standard as defined in the EIP. Does not include\n * the optional functions; to access them see {BEP20Detailed}.\n */\ninterface IBEP20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
      },
      "contracts/Utils/SafeBEP20.sol": {
        "content": "pragma solidity ^0.5.0;\n\nimport \"./SafeMath.sol\";\nimport \"./IBEP20.sol\";\nimport \"./Address.sol\";\n\n/**\n * @title SafeBEP20\n * @dev Wrappers around BEP20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeBEP20 for BEP20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeBEP20 {\n    using SafeMath for uint256;\n    using Address for address;\n\n    function safeTransfer(IBEP20 token, address to, uint256 value) internal {\n        callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(IBEP20 token, address from, address to, uint256 value) internal {\n        callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    function safeApprove(IBEP20 token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        // solhint-disable-next-line max-line-length\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeBEP20: approve from non-zero to non-zero allowance\"\n        );\n        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(IBEP20 token, address spender, uint256 value) internal {\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\n        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(IBEP20 token, address spender, uint256 value) internal {\n        uint256 newAllowance = token.allowance(address(this), spender).sub(\n            value,\n            \"SafeBEP20: decreased allowance below zero\"\n        );\n        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function callOptionalReturn(IBEP20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves.\n\n        // A Solidity high level call has three parts:\n        //  1. The target address is checked to verify it contains contract code\n        //  2. The call itself is made, and success asserted\n        //  3. The return value is decoded, which in turn checks the size of the returned data.\n        // solhint-disable-next-line max-line-length\n        require(address(token).isContract(), \"SafeBEP20: call to non-contract\");\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, bytes memory returndata) = address(token).call(data);\n        require(success, \"SafeBEP20: low-level call failed\");\n\n        if (returndata.length > 0) {\n            // Return data is optional\n            // solhint-disable-next-line max-line-length\n            require(abi.decode(returndata, (bool)), \"SafeBEP20: BEP20 operation did not succeed\");\n        }\n    }\n}\n"
      },
      "contracts/Utils/SafeCast.sol": {
        "content": "pragma solidity ^0.5.16;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value < 2 ** 128, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value < 2 ** 64, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value < 2 ** 32, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value < 2 ** 16, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits.\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value < 2 ** 8, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value >= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128) {\n        require(value >= -2 ** 127 && value < 2 ** 127, \"SafeCast: value doesn't fit in 128 bits\");\n        return int128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64) {\n        require(value >= -2 ** 63 && value < 2 ** 63, \"SafeCast: value doesn't fit in 64 bits\");\n        return int64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32) {\n        require(value >= -2 ** 31 && value < 2 ** 31, \"SafeCast: value doesn't fit in 32 bits\");\n        return int32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16) {\n        require(value >= -2 ** 15 && value < 2 ** 15, \"SafeCast: value doesn't fit in 16 bits\");\n        return int16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits.\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8) {\n        require(value >= -2 ** 7 && value < 2 ** 7, \"SafeCast: value doesn't fit in 8 bits\");\n        return int8(value);\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        require(value < 2 ** 255, \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n"
      },
      "contracts/Utils/SafeMath.sol": {
        "content": "pragma solidity ^0.5.16;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        return add(a, b, \"SafeMath: addition overflow\");\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     * - Subtraction cannot overflow.\n     */\n    function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        uint256 c = a + b;\n        require(c >= a, errorMessage);\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        return sub(a, b, \"SafeMath: subtraction overflow\");\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b <= a, errorMessage);\n        uint256 c = a - b;\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n        // benefit is lost if 'b' is also tested.\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n        if (a == 0) {\n            return 0;\n        }\n\n        uint256 c = a * b;\n        require(c / a == b, \"SafeMath: multiplication overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers. Reverts on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        return div(a, b, \"SafeMath: division by zero\");\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        // Solidity only automatically asserts when dividing by 0\n        require(b > 0, errorMessage);\n        uint256 c = a / b;\n        // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * Reverts when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        return mod(a, b, \"SafeMath: modulo by zero\");\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * Reverts with custom message when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b != 0, errorMessage);\n        return a % b;\n    }\n}\n"
      },
      "contracts/XVSVault/XVSStore.sol": {
        "content": "pragma solidity 0.5.16;\nimport \"../Utils/SafeBEP20.sol\";\nimport \"../Utils/IBEP20.sol\";\n\n/**\n * @title XVS Store\n * @author Venus\n * @notice XVS Store responsible for distributing XVS rewards\n */\ncontract XVSStore {\n    using SafeMath for uint256;\n    using SafeBEP20 for IBEP20;\n\n    /// @notice The Admin Address\n    address public admin;\n\n    /// @notice The pending admin address\n    address public pendingAdmin;\n\n    /// @notice The Owner Address\n    address public owner;\n\n    /// @notice The reward tokens\n    mapping(address => bool) public rewardTokens;\n\n    /// @notice Emitted when pendingAdmin is changed\n    event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n    /// @notice Event emitted when admin changed\n    event AdminTransferred(address indexed oldAdmin, address indexed newAdmin);\n\n    /// @notice Event emitted when owner changed\n    event OwnerTransferred(address indexed oldOwner, address indexed newOwner);\n\n    constructor() public {\n        admin = msg.sender;\n    }\n\n    modifier onlyAdmin() {\n        require(msg.sender == admin, \"only admin can\");\n        _;\n    }\n\n    modifier onlyOwner() {\n        require(msg.sender == owner, \"only owner can\");\n        _;\n    }\n\n    /**\n     * @notice Safely transfer rewards. Only active reward tokens can be sent using this function.\n     * Only callable by owner\n     * @dev Safe reward token transfer function, just in case if rounding error causes pool to not have enough tokens.\n     * @param token Reward token to transfer\n     * @param _to Destination address of the reward\n     * @param _amount Amount to transfer\n     */\n    function safeRewardTransfer(address token, address _to, uint256 _amount) external onlyOwner {\n        require(rewardTokens[token] == true, \"only reward token can\");\n\n        if (address(token) != address(0)) {\n            uint256 tokenBalance = IBEP20(token).balanceOf(address(this));\n            if (_amount > tokenBalance) {\n                IBEP20(token).safeTransfer(_to, tokenBalance);\n            } else {\n                IBEP20(token).safeTransfer(_to, _amount);\n            }\n        }\n    }\n\n    /**\n     * @notice Allows the admin to propose a new admin\n     * Only callable admin\n     * @param _admin Propose an account as admin of the XVS store\n     */\n    function setPendingAdmin(address _admin) external onlyAdmin {\n        address oldPendingAdmin = pendingAdmin;\n        pendingAdmin = _admin;\n        emit NewPendingAdmin(oldPendingAdmin, _admin);\n    }\n\n    /**\n     * @notice Allows an account that is pending as admin to accept the role\n     * nly calllable by the pending admin\n     */\n    function acceptAdmin() external {\n        require(msg.sender == pendingAdmin, \"only pending admin\");\n        address oldAdmin = admin;\n        address oldPendingAdmin = pendingAdmin;\n\n        admin = pendingAdmin;\n        pendingAdmin = address(0);\n\n        emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n        emit AdminTransferred(oldAdmin, admin);\n    }\n\n    /**\n     * @notice Set the contract owner\n     * @param _owner The address of the owner to set\n     * Only callable admin\n     */\n    function setNewOwner(address _owner) external onlyAdmin {\n        require(_owner != address(0), \"new owner is the zero address\");\n        address oldOwner = owner;\n        owner = _owner;\n        emit OwnerTransferred(oldOwner, _owner);\n    }\n\n    /**\n     * @notice Set or disable a reward token\n     * @param _tokenAddress The address of a token to set as active or inactive\n     * @param status Set whether a reward token is active or not\n     */\n    function setRewardToken(address _tokenAddress, bool status) external {\n        require(msg.sender == admin || msg.sender == owner, \"only admin or owner can\");\n        rewardTokens[_tokenAddress] = status;\n    }\n\n    /**\n     * @notice Security function to allow the owner of the contract to withdraw from the contract\n     * @param _tokenAddress Reward token address to withdraw\n     * @param _amount Amount of token to withdraw\n     */\n    function emergencyRewardWithdraw(address _tokenAddress, uint256 _amount) external onlyOwner {\n        IBEP20(_tokenAddress).safeTransfer(address(msg.sender), _amount);\n    }\n}\n"
      },
      "contracts/XVSVault/XVSVault.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"../Utils/ECDSA.sol\";\nimport \"../Utils/SafeBEP20.sol\";\nimport \"../Utils/IBEP20.sol\";\nimport \"./XVSVaultStorage.sol\";\nimport \"../Tokens/Prime/IPrime.sol\";\nimport \"../Utils/SafeCast.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV5.sol\";\nimport \"@venusprotocol/solidity-utilities/contracts/TimeManagerV5.sol\";\n\nimport { XVSStore } from \"./XVSStore.sol\";\nimport { XVSVaultProxy } from \"./XVSVaultProxy.sol\";\n\n/**\n * @title XVS Vault\n * @author Venus\n * @notice The XVS Vault allows XVS holders to lock their XVS to recieve voting rights in Venus governance and are rewarded with XVS.\n */\ncontract XVSVault is XVSVaultStorage, ECDSA, AccessControlledV5, TimeManagerV5 {\n    using SafeMath for uint256;\n    using SafeCast for uint256;\n    using SafeBEP20 for IBEP20;\n\n    /// @notice The upper bound for the lock period in a pool, 10 years\n    uint256 public constant MAX_LOCK_PERIOD = 60 * 60 * 24 * 365 * 10;\n\n    /// @notice Event emitted when deposit\n    event Deposit(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);\n\n    /// @notice Event emitted when execute withrawal\n    event ExecutedWithdrawal(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);\n\n    /// @notice Event emitted when request withrawal\n    event RequestedWithdrawal(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);\n\n    /// @notice An event thats emitted when an account changes its delegate\n    event DelegateChangedV2(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n    /// @notice An event thats emitted when a delegate account's vote balance changes\n    event DelegateVotesChangedV2(address indexed delegate, uint previousBalance, uint newBalance);\n\n    /// @notice An event emitted when the reward store address is updated\n    event StoreUpdated(address oldXvs, address oldStore, address newXvs, address newStore);\n\n    /// @notice An event emitted when the withdrawal locking period is updated for a pool\n    event WithdrawalLockingPeriodUpdated(address indexed rewardToken, uint indexed pid, uint oldPeriod, uint newPeriod);\n\n    /// @notice An event emitted when the reward amount per block or second is modified for a pool\n    event RewardAmountUpdated(address indexed rewardToken, uint oldReward, uint newReward);\n\n    /// @notice An event emitted when a new pool is added\n    event PoolAdded(\n        address indexed rewardToken,\n        uint indexed pid,\n        address indexed token,\n        uint allocPoints,\n        uint rewardPerBlockOrSecond,\n        uint lockPeriod\n    );\n\n    /// @notice An event emitted when a pool allocation points are updated\n    event PoolUpdated(address indexed rewardToken, uint indexed pid, uint oldAllocPoints, uint newAllocPoints);\n\n    /// @notice Event emitted when reward claimed\n    event Claim(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);\n\n    /// @notice Event emitted when vault is paused\n    event VaultPaused(address indexed admin);\n\n    /// @notice Event emitted when vault is resumed after pause\n    event VaultResumed(address indexed admin);\n\n    /// @notice Event emitted when protocol logs a debt to a user due to insufficient funds for pending reward distribution\n    event VaultDebtUpdated(\n        address indexed rewardToken,\n        address indexed userAddress,\n        uint256 oldOwedAmount,\n        uint256 newOwedAmount\n    );\n\n    /// @notice Emitted when prime token contract address is changed\n    event NewPrimeToken(\n        IPrime indexed oldPrimeToken,\n        IPrime indexed newPrimeToken,\n        address oldPrimeRewardToken,\n        address newPrimeRewardToken,\n        uint256 oldPrimePoolId,\n        uint256 newPrimePoolId\n    );\n\n    /**\n     * @notice XVSVault constructor\n     */\n    constructor() public {\n        admin = msg.sender;\n    }\n\n    modifier onlyAdmin() {\n        require(msg.sender == admin, \"only admin can\");\n        _;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     */\n    modifier nonReentrant() {\n        require(_notEntered, \"re-entered\");\n        _notEntered = false;\n        _;\n        _notEntered = true; // get a gas-refund post-Istanbul\n    }\n\n    /**\n     * @dev Prevents functions to execute when vault is paused.\n     */\n    modifier isActive() {\n        require(!vaultPaused, \"Vault is paused\");\n        _;\n    }\n\n    /**\n     * @notice Pauses vault\n     */\n    function pause() external {\n        _checkAccessAllowed(\"pause()\");\n        require(!vaultPaused, \"Vault is already paused\");\n        vaultPaused = true;\n        emit VaultPaused(msg.sender);\n    }\n\n    /**\n     * @notice Resume vault\n     */\n    function resume() external {\n        _checkAccessAllowed(\"resume()\");\n        require(vaultPaused, \"Vault is not paused\");\n        vaultPaused = false;\n        emit VaultResumed(msg.sender);\n    }\n\n    /**\n     * @notice Returns the number of pools with the specified reward token\n     * @param rewardToken Reward token address\n     * @return Number of pools that distribute the specified token as a reward\n     */\n    function poolLength(address rewardToken) external view returns (uint256) {\n        return poolInfos[rewardToken].length;\n    }\n\n    /**\n     * @notice Returns the number of reward tokens created per block or second\n     * @param _rewardToken Reward token address\n     * @return Number of reward tokens created per block or second\n     */\n    function rewardTokenAmountsPerBlock(address _rewardToken) external view returns (uint256) {\n        return rewardTokenAmountsPerBlockOrSecond[_rewardToken];\n    }\n\n    /**\n     * @notice Add a new token pool\n     * @dev This vault DOES NOT support deflationary tokens — it expects that\n     *   the amount of transferred tokens would equal the actually deposited\n     *   amount. In practice this means that this vault DOES NOT support USDT\n     *   and similar tokens (that do not provide these guarantees).\n     * @param _rewardToken Reward token address\n     * @param _allocPoint Number of allocation points assigned to this pool\n     * @param _token Staked token\n     * @param _rewardPerBlockOrSecond Initial reward per block or second, in terms of _rewardToken\n     * @param _lockPeriod A period between withdrawal request and a moment when it's executable\n     */\n    function add(\n        address _rewardToken,\n        uint256 _allocPoint,\n        IBEP20 _token,\n        uint256 _rewardPerBlockOrSecond,\n        uint256 _lockPeriod\n    ) external {\n        _checkAccessAllowed(\"add(address,uint256,address,uint256,uint256)\");\n        _ensureNonzeroAddress(_rewardToken);\n        _ensureNonzeroAddress(address(_token));\n        require(address(xvsStore) != address(0), \"Store contract address is empty\");\n        require(_allocPoint > 0, \"Alloc points must not be zero\");\n\n        massUpdatePools(_rewardToken);\n\n        PoolInfo[] storage poolInfo = poolInfos[_rewardToken];\n\n        uint256 length = poolInfo.length;\n        for (uint256 pid = 0; pid < length; ++pid) {\n            require(poolInfo[pid].token != _token, \"Pool already added\");\n        }\n\n        // We use balanceOf to get the supply amount, so shouldn't be possible to\n        // configure pools with different reward token but the same staked token\n        require(!isStakedToken[address(_token)], \"Token exists in other pool\");\n\n        totalAllocPoints[_rewardToken] = totalAllocPoints[_rewardToken].add(_allocPoint);\n\n        rewardTokenAmountsPerBlockOrSecond[_rewardToken] = _rewardPerBlockOrSecond;\n\n        poolInfo.push(\n            PoolInfo({\n                token: _token,\n                allocPoint: _allocPoint,\n                lastRewardBlockOrSecond: getBlockNumberOrTimestamp(),\n                accRewardPerShare: 0,\n                lockPeriod: _lockPeriod\n            })\n        );\n        isStakedToken[address(_token)] = true;\n\n        XVSStore(xvsStore).setRewardToken(_rewardToken, true);\n\n        emit PoolAdded(\n            _rewardToken,\n            poolInfo.length - 1,\n            address(_token),\n            _allocPoint,\n            _rewardPerBlockOrSecond,\n            _lockPeriod\n        );\n    }\n\n    /**\n     * @notice Update the given pool's reward allocation point\n     * @param _rewardToken Reward token address\n     * @param _pid Pool index\n     * @param _allocPoint Number of allocation points assigned to this pool\n     */\n    function set(address _rewardToken, uint256 _pid, uint256 _allocPoint) external {\n        _checkAccessAllowed(\"set(address,uint256,uint256)\");\n        _ensureValidPool(_rewardToken, _pid);\n\n        massUpdatePools(_rewardToken);\n\n        PoolInfo[] storage poolInfo = poolInfos[_rewardToken];\n        uint256 newTotalAllocPoints = totalAllocPoints[_rewardToken].sub(poolInfo[_pid].allocPoint).add(_allocPoint);\n        require(newTotalAllocPoints > 0, \"Alloc points per reward token must not be zero\");\n\n        uint256 oldAllocPoints = poolInfo[_pid].allocPoint;\n        poolInfo[_pid].allocPoint = _allocPoint;\n        totalAllocPoints[_rewardToken] = newTotalAllocPoints;\n\n        emit PoolUpdated(_rewardToken, _pid, oldAllocPoints, _allocPoint);\n    }\n\n    /**\n     * @notice Update the given reward token's amount per block or second\n     * @param _rewardToken Reward token address\n     * @param _rewardAmount Number of allocation points assigned to this pool\n     */\n    function setRewardAmountPerBlockOrSecond(address _rewardToken, uint256 _rewardAmount) external {\n        _checkAccessAllowed(\"setRewardAmountPerBlockOrSecond(address,uint256)\");\n        require(XVSStore(xvsStore).rewardTokens(_rewardToken), \"Invalid reward token\");\n        massUpdatePools(_rewardToken);\n        uint256 oldReward = rewardTokenAmountsPerBlockOrSecond[_rewardToken];\n        rewardTokenAmountsPerBlockOrSecond[_rewardToken] = _rewardAmount;\n\n        emit RewardAmountUpdated(_rewardToken, oldReward, _rewardAmount);\n    }\n\n    /**\n     * @notice Update the lock period after which a requested withdrawal can be executed\n     * @param _rewardToken Reward token address\n     * @param _pid Pool index\n     * @param _newPeriod New lock period\n     */\n    function setWithdrawalLockingPeriod(address _rewardToken, uint256 _pid, uint256 _newPeriod) external {\n        _checkAccessAllowed(\"setWithdrawalLockingPeriod(address,uint256,uint256)\");\n        _ensureValidPool(_rewardToken, _pid);\n        require(_newPeriod > 0 && _newPeriod < MAX_LOCK_PERIOD, \"Invalid new locking period\");\n        PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n        uint256 oldPeriod = pool.lockPeriod;\n        pool.lockPeriod = _newPeriod;\n\n        emit WithdrawalLockingPeriodUpdated(_rewardToken, _pid, oldPeriod, _newPeriod);\n    }\n\n    /**\n     * @notice Deposit XVSVault for XVS allocation\n     * @param _rewardToken The Reward Token Address\n     * @param _pid The Pool Index\n     * @param _amount The amount to deposit to vault\n     */\n    function deposit(address _rewardToken, uint256 _pid, uint256 _amount) external nonReentrant isActive {\n        _ensureValidPool(_rewardToken, _pid);\n        PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n        UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];\n        _updatePool(_rewardToken, _pid);\n        require(pendingWithdrawalsBeforeUpgrade(_rewardToken, _pid, msg.sender) == 0, \"execute pending withdrawal\");\n\n        if (user.amount > 0) {\n            uint256 pending = _computeReward(user, pool);\n            if (pending > 0) {\n                _transferReward(_rewardToken, msg.sender, pending);\n                emit Claim(msg.sender, _rewardToken, _pid, pending);\n            }\n        }\n        pool.token.safeTransferFrom(msg.sender, address(this), _amount);\n        user.amount = user.amount.add(_amount);\n        user.rewardDebt = _cumulativeReward(user, pool);\n\n        // Update Delegate Amount\n        if (address(pool.token) == xvsAddress) {\n            _moveDelegates(address(0), delegates[msg.sender], safe96(_amount, \"XVSVault::deposit: votes overflow\"));\n        }\n\n        if (primeRewardToken == _rewardToken && _pid == primePoolId) {\n            primeToken.xvsUpdated(msg.sender);\n        }\n\n        emit Deposit(msg.sender, _rewardToken, _pid, _amount);\n    }\n\n    /**\n     * @notice Claim rewards for pool\n     * @param _account The account for which to claim rewards\n     * @param _rewardToken The Reward Token Address\n     * @param _pid The Pool Index\n     */\n    function claim(address _account, address _rewardToken, uint256 _pid) external nonReentrant isActive {\n        _ensureValidPool(_rewardToken, _pid);\n        PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n        UserInfo storage user = userInfos[_rewardToken][_pid][_account];\n        _updatePool(_rewardToken, _pid);\n        require(pendingWithdrawalsBeforeUpgrade(_rewardToken, _pid, _account) == 0, \"execute pending withdrawal\");\n\n        if (user.amount > 0) {\n            uint256 pending = _computeReward(user, pool);\n\n            if (pending > 0) {\n                user.rewardDebt = _cumulativeReward(user, pool);\n\n                _transferReward(_rewardToken, _account, pending);\n                emit Claim(_account, _rewardToken, _pid, pending);\n            }\n        }\n    }\n\n    /**\n     * @notice Pushes withdrawal request to the requests array and updates\n     *   the pending withdrawals amount. The requests are always sorted\n     *   by unlock time (descending) so that the earliest to execute requests\n     *   are always at the end of the array.\n     * @param _user The user struct storage pointer\n     * @param _requests The user's requests array storage pointer\n     * @param _amount The amount being requested\n     */\n    function pushWithdrawalRequest(\n        UserInfo storage _user,\n        WithdrawalRequest[] storage _requests,\n        uint _amount,\n        uint _lockedUntil\n    ) internal {\n        uint i = _requests.length;\n        _requests.push(WithdrawalRequest(0, 0, 1));\n        // Keep it sorted so that the first to get unlocked request is always at the end\n        for (; i > 0 && _requests[i - 1].lockedUntil <= _lockedUntil; --i) {\n            _requests[i] = _requests[i - 1];\n        }\n        _requests[i] = WithdrawalRequest(_amount, _lockedUntil.toUint128(), 1);\n        _user.pendingWithdrawals = _user.pendingWithdrawals.add(_amount);\n    }\n\n    /**\n     * @notice Pops the requests with unlock time < now from the requests\n     *   array and deducts the computed amount from the user's pending\n     *   withdrawals counter. Assumes that the requests array is sorted\n     *   by unclock time (descending).\n     * @dev This function **removes** the eligible requests from the requests\n     *   array. If this function is called, the withdrawal should actually\n     *   happen (or the transaction should be reverted).\n     * @param _user The user struct storage pointer\n     * @param _requests The user's requests array storage pointer\n     * @return beforeUpgradeWithdrawalAmount The amount eligible for withdrawal before upgrade (this amount should be\n     *   sent to the user, otherwise the state would be inconsistent).\n     * @return afterUpgradeWithdrawalAmount The amount eligible for withdrawal after upgrade (this amount should be\n     *   sent to the user, otherwise the state would be inconsistent).\n     */\n    function popEligibleWithdrawalRequests(\n        UserInfo storage _user,\n        WithdrawalRequest[] storage _requests\n    ) internal returns (uint beforeUpgradeWithdrawalAmount, uint afterUpgradeWithdrawalAmount) {\n        // Since the requests are sorted by their unlock time, we can just\n        // pop them from the array and stop at the first not-yet-eligible one\n        for (uint i = _requests.length; i > 0 && isUnlocked(_requests[i - 1]); --i) {\n            if (_requests[i - 1].afterUpgrade == 1) {\n                afterUpgradeWithdrawalAmount = afterUpgradeWithdrawalAmount.add(_requests[i - 1].amount);\n            } else {\n                beforeUpgradeWithdrawalAmount = beforeUpgradeWithdrawalAmount.add(_requests[i - 1].amount);\n            }\n\n            _requests.pop();\n        }\n        _user.pendingWithdrawals = _user.pendingWithdrawals.sub(\n            afterUpgradeWithdrawalAmount.add(beforeUpgradeWithdrawalAmount)\n        );\n        return (beforeUpgradeWithdrawalAmount, afterUpgradeWithdrawalAmount);\n    }\n\n    /**\n     * @notice Checks if the request is eligible for withdrawal.\n     * @param _request The request struct storage pointer\n     * @return True if the request is eligible for withdrawal, false otherwise\n     */\n    function isUnlocked(WithdrawalRequest storage _request) private view returns (bool) {\n        return _request.lockedUntil <= block.timestamp;\n    }\n\n    /**\n     * @notice Execute withdrawal to XVSVault for XVS allocation\n     * @param _rewardToken The Reward Token Address\n     * @param _pid The Pool Index\n     */\n    function executeWithdrawal(address _rewardToken, uint256 _pid) external nonReentrant isActive {\n        _ensureValidPool(_rewardToken, _pid);\n        PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n        UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];\n        WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][msg.sender];\n\n        uint256 beforeUpgradeWithdrawalAmount;\n        uint256 afterUpgradeWithdrawalAmount;\n\n        (beforeUpgradeWithdrawalAmount, afterUpgradeWithdrawalAmount) = popEligibleWithdrawalRequests(user, requests);\n        require(beforeUpgradeWithdrawalAmount > 0 || afterUpgradeWithdrawalAmount > 0, \"nothing to withdraw\");\n\n        // Having both old-style and new-style requests is not allowed and shouldn't be possible\n        require(beforeUpgradeWithdrawalAmount == 0 || afterUpgradeWithdrawalAmount == 0, \"inconsistent state\");\n\n        if (beforeUpgradeWithdrawalAmount > 0) {\n            _updatePool(_rewardToken, _pid);\n            uint256 pending = user.amount.mul(pool.accRewardPerShare).div(1e12).sub(user.rewardDebt);\n            XVSStore(xvsStore).safeRewardTransfer(_rewardToken, msg.sender, pending);\n            user.amount = user.amount.sub(beforeUpgradeWithdrawalAmount);\n            user.rewardDebt = user.amount.mul(pool.accRewardPerShare).div(1e12);\n            pool.token.safeTransfer(address(msg.sender), beforeUpgradeWithdrawalAmount);\n        } else {\n            user.amount = user.amount.sub(afterUpgradeWithdrawalAmount);\n            totalPendingWithdrawals[_rewardToken][_pid] = totalPendingWithdrawals[_rewardToken][_pid].sub(\n                afterUpgradeWithdrawalAmount\n            );\n            pool.token.safeTransfer(address(msg.sender), afterUpgradeWithdrawalAmount);\n        }\n\n        emit ExecutedWithdrawal(\n            msg.sender,\n            _rewardToken,\n            _pid,\n            beforeUpgradeWithdrawalAmount.add(afterUpgradeWithdrawalAmount)\n        );\n    }\n\n    /**\n     * @notice Returns before and after upgrade pending withdrawal amount\n     * @param _requests The user's requests array storage pointer\n     * @return beforeUpgradeWithdrawalAmount The amount eligible for withdrawal before upgrade\n     * @return afterUpgradeWithdrawalAmount The amount eligible for withdrawal after upgrade\n     */\n    function getRequestedWithdrawalAmount(\n        WithdrawalRequest[] storage _requests\n    ) internal view returns (uint beforeUpgradeWithdrawalAmount, uint afterUpgradeWithdrawalAmount) {\n        for (uint i = _requests.length; i > 0; --i) {\n            if (_requests[i - 1].afterUpgrade == 1) {\n                afterUpgradeWithdrawalAmount = afterUpgradeWithdrawalAmount.add(_requests[i - 1].amount);\n            } else {\n                beforeUpgradeWithdrawalAmount = beforeUpgradeWithdrawalAmount.add(_requests[i - 1].amount);\n            }\n        }\n        return (beforeUpgradeWithdrawalAmount, afterUpgradeWithdrawalAmount);\n    }\n\n    /**\n     * @notice Request withdrawal to XVSVault for XVS allocation\n     * @param _rewardToken The Reward Token Address\n     * @param _pid The Pool Index\n     * @param _amount The amount to withdraw from the vault\n     */\n    function requestWithdrawal(address _rewardToken, uint256 _pid, uint256 _amount) external nonReentrant isActive {\n        _ensureValidPool(_rewardToken, _pid);\n        require(_amount > 0, \"requested amount cannot be zero\");\n        UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];\n        require(user.amount >= user.pendingWithdrawals.add(_amount), \"requested amount is invalid\");\n\n        PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n        WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][msg.sender];\n\n        uint beforeUpgradeWithdrawalAmount;\n\n        (beforeUpgradeWithdrawalAmount, ) = getRequestedWithdrawalAmount(requests);\n        require(beforeUpgradeWithdrawalAmount == 0, \"execute pending withdrawal\");\n\n        _updatePool(_rewardToken, _pid);\n        uint256 pending = _computeReward(user, pool);\n        _transferReward(_rewardToken, msg.sender, pending);\n\n        uint lockedUntil = pool.lockPeriod.add(block.timestamp);\n\n        pushWithdrawalRequest(user, requests, _amount, lockedUntil);\n        totalPendingWithdrawals[_rewardToken][_pid] = totalPendingWithdrawals[_rewardToken][_pid].add(_amount);\n        user.rewardDebt = _cumulativeReward(user, pool);\n\n        // Update Delegate Amount\n        if (address(pool.token) == xvsAddress) {\n            _moveDelegates(\n                delegates[msg.sender],\n                address(0),\n                safe96(_amount, \"XVSVault::requestWithdrawal: votes overflow\")\n            );\n        }\n\n        if (primeRewardToken == _rewardToken && _pid == primePoolId) {\n            primeToken.xvsUpdated(msg.sender);\n        }\n\n        emit Claim(msg.sender, _rewardToken, _pid, pending);\n        emit RequestedWithdrawal(msg.sender, _rewardToken, _pid, _amount);\n    }\n\n    /**\n     * @notice Get unlocked withdrawal amount\n     * @param _rewardToken The Reward Token Address\n     * @param _pid The Pool Index\n     * @param _user The User Address\n     * @return withdrawalAmount Amount that the user can withdraw\n     */\n    function getEligibleWithdrawalAmount(\n        address _rewardToken,\n        uint256 _pid,\n        address _user\n    ) external view returns (uint withdrawalAmount) {\n        _ensureValidPool(_rewardToken, _pid);\n        WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][_user];\n        // Since the requests are sorted by their unlock time, we can take\n        // the entries from the end of the array and stop at the first\n        // not-yet-eligible one\n        for (uint i = requests.length; i > 0 && isUnlocked(requests[i - 1]); --i) {\n            withdrawalAmount = withdrawalAmount.add(requests[i - 1].amount);\n        }\n        return withdrawalAmount;\n    }\n\n    /**\n     * @notice Get requested amount\n     * @param _rewardToken The Reward Token Address\n     * @param _pid The Pool Index\n     * @param _user The User Address\n     * @return Total amount of requested but not yet executed withdrawals (including both executable and locked ones)\n     */\n    function getRequestedAmount(address _rewardToken, uint256 _pid, address _user) external view returns (uint256) {\n        _ensureValidPool(_rewardToken, _pid);\n        UserInfo storage user = userInfos[_rewardToken][_pid][_user];\n        return user.pendingWithdrawals;\n    }\n\n    /**\n     * @notice Returns the array of withdrawal requests that have not been executed yet\n     * @param _rewardToken The Reward Token Address\n     * @param _pid The Pool Index\n     * @param _user The User Address\n     * @return An array of withdrawal requests\n     */\n    function getWithdrawalRequests(\n        address _rewardToken,\n        uint256 _pid,\n        address _user\n    ) external view returns (WithdrawalRequest[] memory) {\n        _ensureValidPool(_rewardToken, _pid);\n        return withdrawalRequests[_rewardToken][_pid][_user];\n    }\n\n    /**\n     * @notice View function to see pending XVSs on frontend\n     * @param _rewardToken Reward token address\n     * @param _pid Pool index\n     * @param _user User address\n     * @return Reward the user is eligible for in this pool, in terms of _rewardToken\n     */\n    function pendingReward(address _rewardToken, uint256 _pid, address _user) external view returns (uint256) {\n        _ensureValidPool(_rewardToken, _pid);\n        PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n        UserInfo storage user = userInfos[_rewardToken][_pid][_user];\n        uint256 accRewardPerShare = pool.accRewardPerShare;\n        uint256 supply = pool.token.balanceOf(address(this)).sub(totalPendingWithdrawals[_rewardToken][_pid]);\n        uint256 curBlockNumberOrSecond = getBlockNumberOrTimestamp();\n        uint256 rewardTokenPerBlockOrSecond = rewardTokenAmountsPerBlockOrSecond[_rewardToken];\n        if (curBlockNumberOrSecond > pool.lastRewardBlockOrSecond && supply != 0) {\n            uint256 multiplier = curBlockNumberOrSecond.sub(pool.lastRewardBlockOrSecond);\n            uint256 reward = multiplier.mul(rewardTokenPerBlockOrSecond).mul(pool.allocPoint).div(\n                totalAllocPoints[_rewardToken]\n            );\n            accRewardPerShare = accRewardPerShare.add(reward.mul(1e12).div(supply));\n        }\n        WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][_user];\n        (, uint256 afterUpgradeWithdrawalAmount) = getRequestedWithdrawalAmount(requests);\n        return user.amount.sub(afterUpgradeWithdrawalAmount).mul(accRewardPerShare).div(1e12).sub(user.rewardDebt);\n    }\n\n    // Update reward variables for all pools. Be careful of gas spending!\n    function massUpdatePools(address _rewardToken) internal {\n        uint256 length = poolInfos[_rewardToken].length;\n        for (uint256 pid = 0; pid < length; ++pid) {\n            _updatePool(_rewardToken, pid);\n        }\n    }\n\n    /**\n     * @notice Update reward variables of the given pool to be up-to-date\n     * @param _rewardToken Reward token address\n     * @param _pid Pool index\n     */\n    function updatePool(address _rewardToken, uint256 _pid) external isActive {\n        _ensureValidPool(_rewardToken, _pid);\n        _updatePool(_rewardToken, _pid);\n    }\n\n    // Update reward variables of the given pool to be up-to-date.\n    function _updatePool(address _rewardToken, uint256 _pid) internal {\n        PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n        if (getBlockNumberOrTimestamp() <= pool.lastRewardBlockOrSecond) {\n            return;\n        }\n        uint256 supply = pool.token.balanceOf(address(this));\n        supply = supply.sub(totalPendingWithdrawals[_rewardToken][_pid]);\n        if (supply == 0) {\n            pool.lastRewardBlockOrSecond = getBlockNumberOrTimestamp();\n            return;\n        }\n        uint256 curBlockNumberOrSecond = getBlockNumberOrTimestamp();\n        uint256 multiplier = curBlockNumberOrSecond.sub(pool.lastRewardBlockOrSecond);\n        uint256 reward = multiplier.mul(rewardTokenAmountsPerBlockOrSecond[_rewardToken]).mul(pool.allocPoint).div(\n            totalAllocPoints[_rewardToken]\n        );\n        pool.accRewardPerShare = pool.accRewardPerShare.add(reward.mul(1e12).div(supply));\n        pool.lastRewardBlockOrSecond = getBlockNumberOrTimestamp();\n    }\n\n    function _ensureValidPool(address rewardToken, uint256 pid) internal view {\n        require(pid < poolInfos[rewardToken].length, \"vault: pool exists?\");\n    }\n\n    /**\n     * @notice Get user info with reward token address and pid\n     * @param _rewardToken Reward token address\n     * @param _pid Pool index\n     * @param _user User address\n     * @return amount Deposited amount\n     * @return rewardDebt Reward debt (technical value used to track past payouts)\n     * @return pendingWithdrawals Requested but not yet executed withdrawals\n     */\n    function getUserInfo(\n        address _rewardToken,\n        uint256 _pid,\n        address _user\n    ) external view returns (uint256 amount, uint256 rewardDebt, uint256 pendingWithdrawals) {\n        _ensureValidPool(_rewardToken, _pid);\n        UserInfo storage user = userInfos[_rewardToken][_pid][_user];\n        amount = user.amount;\n        rewardDebt = user.rewardDebt;\n        pendingWithdrawals = user.pendingWithdrawals;\n    }\n\n    /**\n     * @notice Gets the total pending withdrawal amount of a user before upgrade\n     * @param _rewardToken The Reward Token Address\n     * @param _pid The Pool Index\n     * @param _user The address of the user\n     * @return beforeUpgradeWithdrawalAmount Total pending withdrawal amount in requests made before the vault upgrade\n     */\n    function pendingWithdrawalsBeforeUpgrade(\n        address _rewardToken,\n        uint256 _pid,\n        address _user\n    ) public view returns (uint256 beforeUpgradeWithdrawalAmount) {\n        WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][_user];\n        (beforeUpgradeWithdrawalAmount, ) = getRequestedWithdrawalAmount(requests);\n        return beforeUpgradeWithdrawalAmount;\n    }\n\n    /**\n     * @notice Get the XVS stake balance of an account (excluding the pending withdrawals)\n     * @param account The address of the account to check\n     * @return The balance that user staked\n     */\n    function getStakeAmount(address account) internal view returns (uint96) {\n        require(xvsAddress != address(0), \"XVSVault::getStakeAmount: xvs address is not set\");\n\n        PoolInfo[] storage poolInfo = poolInfos[xvsAddress];\n\n        uint256 length = poolInfo.length;\n        for (uint256 pid = 0; pid < length; ++pid) {\n            if (address(poolInfo[pid].token) == address(xvsAddress)) {\n                UserInfo storage user = userInfos[xvsAddress][pid][account];\n                return safe96(user.amount.sub(user.pendingWithdrawals), \"XVSVault::getStakeAmount: votes overflow\");\n            }\n        }\n        return uint96(0);\n    }\n\n    /**\n     * @notice Delegate votes from `msg.sender` to `delegatee`\n     * @param delegatee The address to delegate votes to\n     */\n    function delegate(address delegatee) external isActive {\n        return _delegate(msg.sender, delegatee);\n    }\n\n    /**\n     * @notice Delegates votes from signatory to `delegatee`\n     * @param delegatee The address to delegate votes to\n     * @param nonce The contract state required to match the signature\n     * @param expiry The time at which to expire the signature\n     * @param v The recovery byte of the signature\n     * @param r Half of the ECDSA signature pair\n     * @param s Half of the ECDSA signature pair\n     */\n    function delegateBySig(\n        address delegatee,\n        uint nonce,\n        uint expiry,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external isActive {\n        bytes32 domainSeparator = keccak256(\n            abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(\"XVSVault\")), getChainId(), address(this))\n        );\n        bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\n        bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n        address signatory = ECDSA.recover(digest, v, r, s);\n        require(nonce == nonces[signatory]++, \"XVSVault::delegateBySig: invalid nonce\");\n        require(block.timestamp <= expiry, \"XVSVault::delegateBySig: signature expired\");\n        return _delegate(signatory, delegatee);\n    }\n\n    /**\n     * @notice Gets the current votes balance for `account`\n     * @param account The address to get votes balance\n     * @return The number of current votes for `account`\n     */\n    function getCurrentVotes(address account) external view returns (uint96) {\n        uint32 nCheckpoints = numCheckpoints[account];\n        return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\n    }\n\n    function _delegate(address delegator, address delegatee) internal {\n        address currentDelegate = delegates[delegator];\n        uint96 delegatorBalance = getStakeAmount(delegator);\n        delegates[delegator] = delegatee;\n\n        emit DelegateChangedV2(delegator, currentDelegate, delegatee);\n\n        _moveDelegates(currentDelegate, delegatee, delegatorBalance);\n    }\n\n    function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal {\n        if (srcRep != dstRep && amount > 0) {\n            if (srcRep != address(0)) {\n                uint32 srcRepNum = numCheckpoints[srcRep];\n                uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\n                uint96 srcRepNew = sub96(srcRepOld, amount, \"XVSVault::_moveVotes: vote amount underflows\");\n                _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);\n            }\n\n            if (dstRep != address(0)) {\n                uint32 dstRepNum = numCheckpoints[dstRep];\n                uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\n                uint96 dstRepNew = add96(dstRepOld, amount, \"XVSVault::_moveVotes: vote amount overflows\");\n                _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\n            }\n        }\n    }\n\n    function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\n        uint32 blockNumberOrSecond = safe32(\n            getBlockNumberOrTimestamp(),\n            \"XVSVault::_writeCheckpoint: block number or second exceeds 32 bits\"\n        );\n\n        if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlockOrSecond == blockNumberOrSecond) {\n            checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\n        } else {\n            checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumberOrSecond, newVotes);\n            numCheckpoints[delegatee] = nCheckpoints + 1;\n        }\n\n        emit DelegateVotesChangedV2(delegatee, oldVotes, newVotes);\n    }\n\n    function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\n        require(n < 2 ** 32, errorMessage);\n        return uint32(n);\n    }\n\n    function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\n        require(n < 2 ** 96, errorMessage);\n        return uint96(n);\n    }\n\n    function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\n        uint96 c = a + b;\n        require(c >= a, errorMessage);\n        return c;\n    }\n\n    function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\n        require(b <= a, errorMessage);\n        return a - b;\n    }\n\n    function getChainId() internal pure returns (uint) {\n        uint256 chainId;\n        assembly {\n            chainId := chainid()\n        }\n        return chainId;\n    }\n\n    /**\n     * @notice Determine the xvs stake balance for an account\n     * @param account The address of the account to check\n     * @param blockNumberOrSecond The block number or second to get the vote balance at\n     * @return The balance that user staked\n     */\n    function getPriorVotes(address account, uint256 blockNumberOrSecond) external view returns (uint96) {\n        require(blockNumberOrSecond < getBlockNumberOrTimestamp(), \"XVSVault::getPriorVotes: not yet determined\");\n\n        uint32 nCheckpoints = numCheckpoints[account];\n        if (nCheckpoints == 0) {\n            return 0;\n        }\n\n        // First check most recent balance\n        if (checkpoints[account][nCheckpoints - 1].fromBlockOrSecond <= blockNumberOrSecond) {\n            return checkpoints[account][nCheckpoints - 1].votes;\n        }\n\n        // Next check implicit zero balance\n        if (checkpoints[account][0].fromBlockOrSecond > blockNumberOrSecond) {\n            return 0;\n        }\n\n        uint32 lower = 0;\n        uint32 upper = nCheckpoints - 1;\n        while (upper > lower) {\n            uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n            Checkpoint memory cp = checkpoints[account][center];\n            if (cp.fromBlockOrSecond == blockNumberOrSecond) {\n                return cp.votes;\n            } else if (cp.fromBlockOrSecond < blockNumberOrSecond) {\n                lower = center;\n            } else {\n                upper = center - 1;\n            }\n        }\n        return checkpoints[account][lower].votes;\n    }\n\n    /*** Admin Functions ***/\n\n    function _become(XVSVaultProxy xvsVaultProxy) external {\n        require(msg.sender == xvsVaultProxy.admin(), \"only proxy admin can change brains\");\n        require(xvsVaultProxy._acceptImplementation() == 0, \"change not authorized\");\n    }\n\n    function setXvsStore(address _xvs, address _xvsStore) external onlyAdmin {\n        _ensureNonzeroAddress(_xvs);\n        _ensureNonzeroAddress(_xvsStore);\n\n        address oldXvsContract = xvsAddress;\n        address oldStore = xvsStore;\n        require(oldXvsContract == address(0), \"already initialized\");\n\n        xvsAddress = _xvs;\n        xvsStore = _xvsStore;\n\n        _notEntered = true;\n\n        emit StoreUpdated(oldXvsContract, oldStore, _xvs, _xvsStore);\n    }\n\n    /**\n     * @notice Sets the address of the prime token contract\n     * @param _primeToken address of the prime token contract\n     * @param _primeRewardToken address of reward token\n     * @param _primePoolId pool id for reward\n     */\n    function setPrimeToken(IPrime _primeToken, address _primeRewardToken, uint256 _primePoolId) external onlyAdmin {\n        require(address(_primeToken) != address(0), \"prime token cannot be zero address\");\n        require(_primeRewardToken != address(0), \"reward cannot be zero address\");\n\n        _ensureValidPool(_primeRewardToken, _primePoolId);\n\n        emit NewPrimeToken(primeToken, _primeToken, primeRewardToken, _primeRewardToken, primePoolId, _primePoolId);\n\n        primeToken = _primeToken;\n        primeRewardToken = _primeRewardToken;\n        primePoolId = _primePoolId;\n    }\n\n    /**\n     * @dev Initializes the contract to use either blocks or seconds\n     * @param timeBased_ A boolean indicating whether the contract is based on time or block\n     * If timeBased is true than blocksPerYear_ param is ignored as blocksOrSecondsPerYear is set to SECONDS_PER_YEAR\n     * @param blocksPerYear_ The number of blocks per year\n     */\n    function initializeTimeManager(bool timeBased_, uint256 blocksPerYear_) external onlyAdmin {\n        _initializeTimeManager(timeBased_, blocksPerYear_);\n    }\n\n    /**\n     * @notice Sets the address of the access control of this contract\n     * @dev Admin function to set the access control address\n     * @param newAccessControlAddress New address for the access control\n     */\n    function setAccessControl(address newAccessControlAddress) external onlyAdmin {\n        _setAccessControlManager(newAccessControlAddress);\n    }\n\n    /**\n     * @dev Reverts if the provided address is a zero address\n     * @param address_ Address to check\n     */\n    function _ensureNonzeroAddress(address address_) internal pure {\n        require(address_ != address(0), \"zero address not allowed\");\n    }\n\n    /**\n     * @dev Transfers the reward to the user, taking into account the rewards store\n     *   balance and the previous debt. If there are not enough rewards in the store,\n     *   transfers the available funds and records the debt amount in pendingRewardTransfers.\n     * @param rewardToken Reward token address\n     * @param userAddress User address\n     * @param amount Reward amount, in reward tokens\n     */\n    function _transferReward(address rewardToken, address userAddress, uint256 amount) internal {\n        address xvsStore_ = xvsStore;\n        uint256 storeBalance = IBEP20(rewardToken).balanceOf(xvsStore_);\n        uint256 debtDueToFailedTransfers = pendingRewardTransfers[rewardToken][userAddress];\n        uint256 fullAmount = amount.add(debtDueToFailedTransfers);\n\n        if (fullAmount <= storeBalance) {\n            if (debtDueToFailedTransfers != 0) {\n                pendingRewardTransfers[rewardToken][userAddress] = 0;\n                emit VaultDebtUpdated(rewardToken, userAddress, debtDueToFailedTransfers, 0);\n            }\n            XVSStore(xvsStore_).safeRewardTransfer(rewardToken, userAddress, fullAmount);\n            return;\n        }\n        // Overflow isn't possible due to the check above\n        uint256 newOwedAmount = fullAmount - storeBalance;\n        pendingRewardTransfers[rewardToken][userAddress] = newOwedAmount;\n        emit VaultDebtUpdated(rewardToken, userAddress, debtDueToFailedTransfers, newOwedAmount);\n        XVSStore(xvsStore_).safeRewardTransfer(rewardToken, userAddress, storeBalance);\n    }\n\n    /**\n     * @dev Computes cumulative reward for all user's shares\n     * @param user UserInfo storage struct\n     * @param pool PoolInfo storage struct\n     */\n    function _cumulativeReward(UserInfo storage user, PoolInfo storage pool) internal view returns (uint256) {\n        return user.amount.sub(user.pendingWithdrawals).mul(pool.accRewardPerShare).div(1e12);\n    }\n\n    /**\n     * @dev Computes the reward for all user's shares\n     * @param user UserInfo storage struct\n     * @param pool PoolInfo storage struct\n     */\n    function _computeReward(UserInfo storage user, PoolInfo storage pool) internal view returns (uint256) {\n        return _cumulativeReward(user, pool).sub(user.rewardDebt);\n    }\n}\n"
      },
      "contracts/XVSVault/XVSVaultErrorReporter.sol": {
        "content": "pragma solidity ^0.5.16;\n\ncontract XVSVaultErrorReporter {\n    enum Error {\n        NO_ERROR,\n        UNAUTHORIZED\n    }\n\n    enum FailureInfo {\n        ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n        ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\n        SET_PENDING_ADMIN_OWNER_CHECK,\n        SET_PENDING_IMPLEMENTATION_OWNER_CHECK\n    }\n\n    /**\n     * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n     * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n     **/\n    event Failure(uint error, uint info, uint detail);\n\n    /**\n     * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n     */\n    function fail(Error err, FailureInfo info) internal returns (uint) {\n        emit Failure(uint(err), uint(info), 0);\n\n        return uint(err);\n    }\n\n    /**\n     * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n     */\n    function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n        emit Failure(uint(err), uint(info), opaqueError);\n\n        return uint(err);\n    }\n}\n"
      },
      "contracts/XVSVault/XVSVaultProxy.sol": {
        "content": "pragma solidity ^0.5.16;\n\nimport \"./XVSVaultStorage.sol\";\nimport \"./XVSVaultErrorReporter.sol\";\n\n/**\n * @title XVS Vault Proxy\n * @author Venus\n * @notice XVS Vault Proxy contract\n */\ncontract XVSVaultProxy is XVSVaultAdminStorage, XVSVaultErrorReporter {\n    /**\n     * @notice Emitted when pendingXVSVaultImplementation is changed\n     */\n    event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n    /**\n     * @notice Emitted when pendingXVSVaultImplementation is accepted, which means XVS Vault implementation is updated\n     */\n    event NewImplementation(address oldImplementation, address newImplementation);\n\n    /**\n     * @notice Emitted when pendingAdmin is changed\n     */\n    event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n    /**\n     * @notice Emitted when pendingAdmin is accepted, which means admin is updated\n     */\n    event NewAdmin(address oldAdmin, address newAdmin);\n\n    constructor() public {\n        // Set admin to caller\n        admin = msg.sender;\n    }\n\n    /*** Admin Functions ***/\n    function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\n        if (msg.sender != admin) {\n            return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\n        }\n\n        address oldPendingImplementation = pendingXVSVaultImplementation;\n\n        pendingXVSVaultImplementation = newPendingImplementation;\n\n        emit NewPendingImplementation(oldPendingImplementation, pendingXVSVaultImplementation);\n\n        return uint(Error.NO_ERROR);\n    }\n\n    /**\n     * @notice Accepts new implementation of XVS Vault. msg.sender must be pendingImplementation\n     * @dev Admin function for new implementation to accept it's role as implementation\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function _acceptImplementation() public returns (uint) {\n        // Check caller is pendingImplementation\n        if (msg.sender != pendingXVSVaultImplementation) {\n            return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\n        }\n\n        // Save current values for inclusion in log\n        address oldImplementation = implementation;\n        address oldPendingImplementation = pendingXVSVaultImplementation;\n\n        implementation = pendingXVSVaultImplementation;\n\n        pendingXVSVaultImplementation = address(0);\n\n        emit NewImplementation(oldImplementation, implementation);\n        emit NewPendingImplementation(oldPendingImplementation, pendingXVSVaultImplementation);\n\n        return uint(Error.NO_ERROR);\n    }\n\n    /**\n     * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n     * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n     * @param newPendingAdmin New pending admin.\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\n        // Check caller = admin\n        if (msg.sender != admin) {\n            return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\n        }\n\n        // Save current value, if any, for inclusion in log\n        address oldPendingAdmin = pendingAdmin;\n\n        // Store pendingAdmin with value newPendingAdmin\n        pendingAdmin = newPendingAdmin;\n\n        // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n        emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n        return uint(Error.NO_ERROR);\n    }\n\n    /**\n     * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n     * @dev Admin function for pending admin to accept role and update admin\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function _acceptAdmin() public returns (uint) {\n        // Check caller is pendingAdmin\n        if (msg.sender != pendingAdmin) {\n            return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n        }\n\n        // Save current values for inclusion in log\n        address oldAdmin = admin;\n        address oldPendingAdmin = pendingAdmin;\n\n        // Store admin with value pendingAdmin\n        admin = pendingAdmin;\n\n        // Clear the pending value\n        pendingAdmin = address(0);\n\n        emit NewAdmin(oldAdmin, admin);\n        emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n        return uint(Error.NO_ERROR);\n    }\n\n    /**\n     * @dev Delegates execution to an implementation contract.\n     * It returns to the external caller whatever the implementation returns\n     * or forwards reverts.\n     */\n    function() external payable {\n        // delegate all other functions to current implementation\n        (bool success, ) = implementation.delegatecall(msg.data);\n\n        assembly {\n            let free_mem_ptr := mload(0x40)\n            returndatacopy(free_mem_ptr, 0, returndatasize)\n\n            switch success\n            case 0 {\n                revert(free_mem_ptr, returndatasize)\n            }\n            default {\n                return(free_mem_ptr, returndatasize)\n            }\n        }\n    }\n}\n"
      },
      "contracts/XVSVault/XVSVaultStorage.sol": {
        "content": "pragma solidity ^0.5.16;\n\nimport \"../Utils/SafeMath.sol\";\nimport \"../Utils/IBEP20.sol\";\nimport \"../Tokens/Prime/IPrime.sol\";\n\ncontract XVSVaultAdminStorage {\n    /**\n     * @notice Administrator for this contract\n     */\n    address public admin;\n\n    /**\n     * @notice Pending administrator for this contract\n     */\n    address public pendingAdmin;\n\n    /**\n     * @notice Active brains of XVS Vault\n     */\n    address public implementation;\n\n    /**\n     * @notice Pending brains of XVS Vault\n     */\n    address public pendingXVSVaultImplementation;\n}\n\ncontract XVSVaultStorageV1 is XVSVaultAdminStorage {\n    /// @notice Guard variable for re-entrancy checks\n    bool internal _notEntered;\n\n    /// @notice The reward token store\n    address public xvsStore;\n\n    /// @notice The xvs token address\n    address public xvsAddress;\n\n    // Reward tokens created per block or second indentified by reward token address.\n    mapping(address => uint256) public rewardTokenAmountsPerBlockOrSecond;\n\n    /// @notice Info of each user.\n    struct UserInfo {\n        uint256 amount;\n        uint256 rewardDebt;\n        uint256 pendingWithdrawals;\n    }\n\n    // Info of each pool.\n    struct PoolInfo {\n        IBEP20 token; // Address of token contract to stake.\n        uint256 allocPoint; // How many allocation points assigned to this pool.\n        uint256 lastRewardBlockOrSecond; // Last block number or second that reward tokens distribution occurs.\n        uint256 accRewardPerShare; // Accumulated per share, times 1e12. See below.\n        uint256 lockPeriod; // Min time between withdrawal request and its execution.\n    }\n\n    // Infomation about a withdrawal request\n    struct WithdrawalRequest {\n        uint256 amount;\n        uint128 lockedUntil;\n        uint128 afterUpgrade;\n    }\n\n    // Info of each user that stakes tokens.\n    mapping(address => mapping(uint256 => mapping(address => UserInfo))) internal userInfos;\n\n    // Info of each pool.\n    mapping(address => PoolInfo[]) public poolInfos;\n\n    // Total allocation points. Must be the sum of all allocation points in all pools.\n    mapping(address => uint256) public totalAllocPoints;\n\n    // Info of requested but not yet executed withdrawals\n    mapping(address => mapping(uint256 => mapping(address => WithdrawalRequest[]))) internal withdrawalRequests;\n\n    /// @notice DEPRECATED A record of each accounts delegate (before the voting power fix)\n    mapping(address => address) private __oldDelegatesSlot;\n\n    /// @notice A checkpoint for marking number of votes from a given block or second\n    struct Checkpoint {\n        uint32 fromBlockOrSecond;\n        uint96 votes;\n    }\n\n    /// @notice DEPRECATED A record of votes checkpoints for each account, by index (before the voting power fix)\n    mapping(address => mapping(uint32 => Checkpoint)) private __oldCheckpointsSlot;\n\n    /// @notice DEPRECATED The number of checkpoints for each account (before the voting power fix)\n    mapping(address => uint32) private __oldNumCheckpointsSlot;\n\n    /// @notice A record of states for signing / validating signatures\n    mapping(address => uint) public nonces;\n\n    /// @notice The EIP-712 typehash for the contract's domain\n    bytes32 public constant DOMAIN_TYPEHASH =\n        keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n    /// @notice The EIP-712 typehash for the delegation struct used by the contract\n    bytes32 public constant DELEGATION_TYPEHASH =\n        keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n}\n\ncontract XVSVaultStorage is XVSVaultStorageV1 {\n    /// @notice A record of each accounts delegate\n    mapping(address => address) public delegates;\n\n    /// @notice A record of votes checkpoints for each account, by index\n    mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n    /// @notice The number of checkpoints for each account\n    mapping(address => uint32) public numCheckpoints;\n\n    /// @notice Tracks pending withdrawals for all users for a particular reward token and pool id\n    mapping(address => mapping(uint256 => uint256)) public totalPendingWithdrawals;\n\n    /// @notice pause indicator for Vault\n    bool public vaultPaused;\n\n    /// @notice if the token is added to any of the pools\n    mapping(address => bool) public isStakedToken;\n\n    /// @notice Amount we owe to users because of failed transfer attempts\n    mapping(address => mapping(address => uint256)) public pendingRewardTransfers;\n\n    /// @notice Prime token contract address\n    IPrime public primeToken;\n\n    /// @notice Reward token for which prime token is issued for staking\n    address public primeRewardToken;\n\n    /// @notice Pool ID for which prime token is issued for staking\n    uint256 public primePoolId;\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[46] private __gap;\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}