creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n    struct OwnableStorage {\n        address _owner;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n    function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n        assembly {\n            $.slot := OwnableStorageLocation\n        }\n    }\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    function __Ownable_init(address initialOwner) internal onlyInitializing {\n        __Ownable_init_unchained(initialOwner);\n    }\n\n    function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        OwnableStorage storage $ = _getOwnableStorage();\n        return $._owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        OwnableStorage storage $ = _getOwnableStorage();\n        address oldOwner = $._owner;\n        $._owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Storage of the initializable contract.\n     *\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n     * when using with upgradeable contracts.\n     *\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n     */\n    struct InitializableStorage {\n        /**\n         * @dev Indicates that the contract has been initialized.\n         */\n        uint64 _initialized;\n        /**\n         * @dev Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n    /**\n     * @dev The contract is already initialized.\n     */\n    error InvalidInitialization();\n\n    /**\n     * @dev The contract is not initializing.\n     */\n    error NotInitializing();\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint64 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n     * production.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        // Cache values to avoid duplicated sloads\n        bool isTopLevelCall = !$._initializing;\n        uint64 initialized = $._initialized;\n\n        // Allowed calls:\n        // - initialSetup: the contract is not in the initializing state and no previous version was\n        //                 initialized\n        // - construction: the contract is initialized at version 1 (no reininitialization) and the\n        //                 current contract is just being deployed\n        bool initialSetup = initialized == 0 && isTopLevelCall;\n        bool construction = initialized == 1 && address(this).code.length == 0;\n\n        if (!initialSetup && !construction) {\n            revert InvalidInitialization();\n        }\n        $._initialized = 1;\n        if (isTopLevelCall) {\n            $._initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            $._initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint64 version) {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing || $._initialized >= version) {\n            revert InvalidInitialization();\n        }\n        $._initialized = version;\n        $._initializing = true;\n        _;\n        $._initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        _checkInitializing();\n        _;\n    }\n\n    /**\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n     */\n    function _checkInitializing() internal view virtual {\n        if (!_isInitializing()) {\n            revert NotInitializing();\n        }\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing) {\n            revert InvalidInitialization();\n        }\n        if ($._initialized != type(uint64).max) {\n            $._initialized = type(uint64).max;\n            emit Initialized(type(uint64).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint64) {\n        return _getInitializableStorage()._initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _getInitializableStorage()._initializing;\n    }\n\n    /**\n     * @dev Returns a pointer to the storage namespace.\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n        assembly {\n            $.slot := INITIALIZABLE_STORAGE\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Pausable\n    struct PausableStorage {\n        bool _paused;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Pausable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;\n\n    function _getPausableStorage() private pure returns (PausableStorage storage $) {\n        assembly {\n            $.slot := PausableStorageLocation\n        }\n    }\n\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    /**\n     * @dev The operation failed because the contract is paused.\n     */\n    error EnforcedPause();\n\n    /**\n     * @dev The operation failed because the contract is not paused.\n     */\n    error ExpectedPause();\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    function __Pausable_init() internal onlyInitializing {\n        __Pausable_init_unchained();\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n        PausableStorage storage $ = _getPausableStorage();\n        $._paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        PausableStorage storage $ = _getPausableStorage();\n        return $._paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (paused()) {\n            revert EnforcedPause();\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        if (!paused()) {\n            revert ExpectedPause();\n        }\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        PausableStorage storage $ = _getPausableStorage();\n        $._paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        PausableStorage storage $ = _getPausableStorage();\n        $._paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     *\n     * CAUTION: See Security Considerations above.\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\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    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) 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 a `value` amount of tokens as the allowance of `spender` over the\n     * 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 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` 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 from, address to, uint256 value) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC20Permit} from \"../extensions/IERC20Permit.sol\";\nimport {Address} from \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 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 SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev An operation with an ERC20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\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(IERC20 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. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data);\n        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {\n            revert SafeERC20FailedOperation(address(token));\n        }\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     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\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. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert FailedInnerCall();\n        }\n    }\n}\n"
      },
      "contracts/Incentives/VeTokenChef.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.23;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { OwnableUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { PausableUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport { RecoverERC20 } from \"../libraries/RecoverERC20.sol\";\nimport { IEligibilityDataProvider } from \"../interfaces/IIncentive/IEligibilityDataProvider.sol\";\nimport { IChefIncentivesController, ICICUserDefinedTypes } from \"../interfaces/IIncentive/IChefIncentivesController.sol\";\n\n/// @title ChefIncentivesController Contract\n/// @author Airpuff\n/// based on Radiant and Sushi MasterChef\n///\thttps://github.com/sushiswap/sushiswap/blob/master/contracts/MasterChef.sol\n/// https://github.com/radiant-capital/v2/blob/main/contracts/radiant/staking/ChefIncentivesController.sol\n\ncontract VeTokenChef is\n    IChefIncentivesController,\n    ICICUserDefinedTypes,\n    Initializable,\n    PausableUpgradeable,\n    OwnableUpgradeable,\n    RecoverERC20\n{\n    using SafeERC20 for IERC20;\n    // multiplier for reward calc\n    uint256 private constant ACC_REWARD_PRECISION = 1e12;\n    /********************** Emission Info ***********************/\n    // Array of tokens for reward\n    address[] public registeredTokens;\n\n    // Current reward per second\n    uint256 public rewardsPerSecond;\n\n    // last RPS, used during refill after reserve empty\n    uint256 public lastRPS;\n\n    // Info of each pool.\n    mapping(address => PoolInfo) public poolInfo;\n\n    // valid pool tokens(?)\n    mapping(address => bool) private vaildPODToken;\n\n    // Total allocation points. Must be the sum of all allocation points in all pools.\n\n    uint256 public totalAllocPoint;\n    // token => user => Info of each user that stakes LP tokens.\n    mapping(address => mapping(address => UserInfo)) public userInfo;\n\n    // user => base claimable balance\n    mapping(address => uint256) public userBaseClaimable;\n\n    // MFD, bounties, AC\n    mapping(address => bool) public eligibilityExempt;\n\n    // The block number when reward mining starts.\n    uint256 public startTime;\n\n    // Option for eligibility\n    EligibilityModes public eligibilityMode;\n\n    // Amount of deposited rewards\n    uint256 public depositedRewards;\n\n    // Amount of accumulated rewards\n    uint256 public accountedRewards;\n\n    // Timestamp when all pools updated\n    uint256 public lastAllPoolUpdate;\n    //use the mainchain / sidechain\n    address public veContract;\n    // Info of reward emission end time\n    EndingTime public endingTime;\n\n    // Contracts that are authorized to handle r/vdToken actions without triggering elgiibility checks\n    mapping(address => bool) public authorizedContracts;\n\n    // Mapping of addresses that are whitelisted to perform\n    mapping(address => bool) public whitelist;\n    // Flag to quickly enable/disable whitelisting\n    bool public whitelistActive;\n\n    // The one and only APUFF token\n    address public APUFFToken;\n\n    uint256[50] private __gap;\n\n    modifier onlyWhitelisted() {\n        if (!whitelist[msg.sender]) revert NotWhitelisted();\n        _;\n    }\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor() {\n        _disableInitializers();\n    }\n\n    /**\n     * @notice Initializer\n     * @param _rewardsPerSecond RPS\n     */\n    function initialize(\n        uint256 _rewardsPerSecond,\n        address _APUFFToken,\n        address _veContract,\n        uint256 _endingTimeCadence\n    ) public initializer {\n        if (_APUFFToken == address(0)) revert AddressZero();\n        if (_veContract == address(0)) revert AddressZero();\n\n        endingTime.updateCadence = _endingTimeCadence;\n        APUFFToken = _APUFFToken;\n        veContract = _veContract;\n        rewardsPerSecond = _rewardsPerSecond;\n\n        eligibilityMode = EligibilityModes.FULL;\n\n        __Ownable_init(msg.sender);\n        __Pausable_init();\n    }\n\n    /**\n     * @dev Returns length of reward pools.\n     */\n    function poolLength() public view returns (uint256) {\n        return registeredTokens.length;\n    }\n\n    /**\n     * @dev Enable/Disable eligibility\n     * @param _newVal New value.\n     */\n    function setEligibilityMode(EligibilityModes _newVal) external onlyOwner {\n        eligibilityMode = _newVal;\n        emit EligibilityModeUpdated(_newVal);\n    }\n\n    /********************** Pool Setup + Admin ***********************/\n\n    /**\n     * @dev Starts APUFF emission.\n     */\n    function start() public onlyOwner {\n        if (startTime != 0) revert AlreadyStarted();\n        startTime = block.timestamp;\n    }\n\n    /**\n     * @dev Add a new lp to the pool. Can only be called by the owner.\n     * @param _token for reward pool\n     * @param _allocPoint allocation point of the pool\n     */\n    function addPool(address _token, uint256 _allocPoint) public onlyWhitelisted {\n        if (poolInfo[_token].lastRewardTime != 0) revert PoolExists();\n        _updateEmissions();\n        totalAllocPoint = totalAllocPoint + _allocPoint;\n        registeredTokens.push(_token);\n        PoolInfo storage pool = poolInfo[_token];\n        pool.allocPoint = _allocPoint;\n        pool.lastRewardTime = block.timestamp;\n        vaildPODToken[_token] = true;\n    }\n\n    /**\n     * @dev Update the given pool's allocation point. Can only be called by the owner.\n     * @param _tokens for reward pools\n     * @param _allocPoints allocation points of the pools\n     */\n    function batchUpdateAllocPoint(address[] calldata _tokens, uint256[] calldata _allocPoints) external onlyWhitelisted {\n        if (_tokens.length != _allocPoints.length) revert ArrayLengthMismatch();\n        _massUpdatePools();\n        uint256 _totalAllocPoint = totalAllocPoint;\n        uint256 length = _tokens.length;\n        for (uint256 i; i < length; ) {\n            PoolInfo storage pool = poolInfo[_tokens[i]];\n            if (pool.lastRewardTime == 0) revert UnknownPool();\n            _totalAllocPoint = _totalAllocPoint - pool.allocPoint + _allocPoints[i];\n            pool.allocPoint = _allocPoints[i];\n            unchecked {\n                i++;\n            }\n        }\n        totalAllocPoint = _totalAllocPoint;\n        emit BatchAllocPointsUpdated(_tokens, _allocPoints);\n    }\n\n    /**\n     * @notice Sets the reward per second to be distributed. Can only be called by the owner.\n     * @dev Its decimals count is ACC_REWARD_PRECISION\n     * @param _rewardsPerSecond The amount of reward to be distributed per second.\n     */\n    function setRewardsPerSecond(uint256 _rewardsPerSecond) external onlyWhitelisted {\n        _massUpdatePools();\n        rewardsPerSecond = _rewardsPerSecond;\n        emit RewardsPerSecondUpdated(_rewardsPerSecond);\n    }\n\n    /**\n     * @notice Recover tokens in this contract. Callable by owner.\n     * @param tokenAddress Token address for recover\n     * @param tokenAmount Amount to recover\n     */\n    function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner {\n        _recoverERC20(tokenAddress, tokenAmount);\n    }\n\n    /********************** Pool State Changers ***********************/\n\n    /**\n     * @dev Update emission params of CIC.\n     */\n    function _updateEmissions() internal {\n        if (block.timestamp > endRewardTime()) {\n            _massUpdatePools();\n            lastRPS = rewardsPerSecond;\n            rewardsPerSecond = 0;\n            return;\n        }\n    }\n\n    /**\n     * @dev Update reward variables for all pools.\n     */\n    function _massUpdatePools() internal {\n        uint256 totalAP = totalAllocPoint;\n        uint256 length = poolLength();\n        for (uint256 i; i < length; ) {\n            _updatePool(poolInfo[registeredTokens[i]], totalAP);\n            unchecked {\n                i++;\n            }\n        }\n        lastAllPoolUpdate = block.timestamp;\n    }\n\n    /**\n     * @dev Update reward variables of the given pool to be up-to-date.\n     * @param pool pool info\n     * @param _totalAllocPoint allocation point of the pool\n     */\n    function _updatePool(PoolInfo storage pool, uint256 _totalAllocPoint) internal {\n        uint256 timestamp = block.timestamp;\n        uint256 endReward = endRewardTime();\n        if (endReward <= timestamp) {\n            timestamp = endReward;\n        }\n        if (timestamp <= pool.lastRewardTime) {\n            return;\n        }\n\n        (uint256 reward, uint256 newAccRewardPerShare) = _newRewards(pool, _totalAllocPoint);\n        accountedRewards = accountedRewards + reward;\n        pool.accRewardPerShare = pool.accRewardPerShare + newAccRewardPerShare;\n        pool.lastRewardTime = timestamp;\n    }\n\n    /********************** Emission Calc + Transfer ***********************/\n    /**\n     * @notice Claim rewards.\n     * @param _user address for claim\n     * @param _tokens array of reward-bearing tokens\n     */\n    function claim(address _user, address[] memory _tokens) public whenNotPaused {\n        _updateEmissions();\n        uint256 currentTimestamp = block.timestamp;\n        uint256 pending = userBaseClaimable[_user];\n        userBaseClaimable[_user] = 0;\n        uint256 _totalAllocPoint = totalAllocPoint;\n        uint256 length = _tokens.length;\n        for (uint256 i; i < length; ) {\n            if (!vaildPODToken[_tokens[i]]) revert InvalidRToken();\n            PoolInfo storage pool = poolInfo[_tokens[i]];\n            if (pool.lastRewardTime == 0) revert UnknownPool();\n            _updatePool(pool, _totalAllocPoint);\n            UserInfo storage user = userInfo[_tokens[i]][_user];\n            uint256 rewardDebt = (user.amount * pool.accRewardPerShare) / ACC_REWARD_PRECISION;\n            pending = pending + rewardDebt - user.rewardDebt;\n            user.rewardDebt = rewardDebt;\n            user.lastClaimTime = currentTimestamp;\n            unchecked {\n                i++;\n            }\n        }\n        _sendAPUFF(_user, pending);\n    }\n\n    /**\n     * @notice Claim rewards entitled to all registered tokens.\n     * @param _user address of the user\n     */\n    function claimAll(address _user) external {\n        claim(_user, registeredTokens);\n    }\n\n    /**\n     * @notice Pending rewards of a user for each pool (not total).\n     * @param _user address for claim\n     * @param _tokens array of reward-bearing tokens\n     * @return claimable rewards array\n     */\n    function pendingRewards(address _user, address[] memory _tokens) public view returns (uint256[] memory) {\n        uint256[] memory claimable = new uint256[](_tokens.length);\n        uint256 length = _tokens.length;\n        for (uint256 i; i < length; ) {\n            address token = _tokens[i];\n            PoolInfo storage pool = poolInfo[token];\n            UserInfo storage user = userInfo[token][_user];\n            uint256 accRewardPerShare = pool.accRewardPerShare;\n            if (block.timestamp > pool.lastRewardTime) {\n                (, uint256 newAccRewardPerShare) = _newRewards(pool, totalAllocPoint);\n                accRewardPerShare = accRewardPerShare + newAccRewardPerShare;\n            }\n            claimable[i] = (user.amount * accRewardPerShare) / ACC_REWARD_PRECISION - user.rewardDebt;\n            unchecked {\n                i++;\n            }\n        }\n        return claimable;\n    }\n\n    /**\n     * @notice Sum of all pending APUFF rewards.\n     * @param _user address of the user\n     * @return pending reward amount\n     */\n    function allPendingRewards(address _user) public view returns (uint256 pending) {\n        pending = userBaseClaimable[_user];\n        uint256[] memory claimable = pendingRewards(_user, registeredTokens);\n        uint256 length = claimable.length;\n        for (uint256 i; i < length; ) {\n            pending += claimable[i];\n            unchecked {\n                i++;\n            }\n        }\n    }\n\n    /**\n     * @notice Exempt a contract / user from eligibility check.\n     * @dev Can be called by owner or authorized contracts\n     * @param _contract address to exempt\n     * @param _value flag for exempt\n     */\n    function setEligibilityExempt(address _contract, bool _value) public {\n        // skip this if not processing eligibilty all the time\n        if (eligibilityMode != EligibilityModes.FULL) return;\n        if (msg.sender != owner() && !authorizedContracts[msg.sender]) revert InsufficientPermission();\n        eligibilityExempt[_contract] = _value;\n    }\n\n    /**\n     * @notice Updates whether the provided address is authorized to call setEligibilityExempt(), only callable by owner.\n     * @param _address address of the user or contract whose authorization level is being changed\n     */\n    function setContractAuthorization(address _address, bool _authorize) external onlyOwner {\n        if (authorizedContracts[_address] == _authorize) revert AuthorizationAlreadySet();\n        authorizedContracts[_address] = _authorize;\n        emit AuthorizedContractUpdated(_address, _authorize);\n    }\n\n    /********************** Eligibility + Disqualification ***********************/\n    /**\n     * @notice `after` Hook for deposit and borrow update.\n     * @dev important! eligible status can be updated here, for intergration with pools for withdrawal\n     * @param _user address\n     * @param _balance balance of token\n     */\n\n    function handleWithdrawAfter(address _user, uint256 _balance) external {\n        if (!vaildPODToken[msg.sender]) revert NotValidPool();\n        _handleActionAfterForToken(msg.sender, _user, _balance);\n    }\n\n    /**\n     * @notice `after` Hook for deposit and borrow update.\n     * @dev important! eligible status can be updated here\n     * @param _token address\n     * @param _user address\n     * @param _balance new amount\n    \n     */\n    function _handleActionAfterForToken(address _token, address _user, uint256 _balance) internal {\n        PoolInfo storage pool = poolInfo[_token];\n        if (pool.lastRewardTime == 0) revert UnknownPool();\n        // Although we would want the pools to be as up to date as possible when users\n        // transfer rTokens or dTokens, updating all pools on every r-/d-Token interaction would be too gas intensive.\n        // _updateEmissions();\n        _updatePool(pool, totalAllocPoint);\n        UserInfo storage user = userInfo[_token][_user];\n        uint256 amount = user.amount;\n        uint256 accRewardPerShare = pool.accRewardPerShare;\n        if (amount != 0) {\n            uint256 pending = (amount * accRewardPerShare) / ACC_REWARD_PRECISION - user.rewardDebt;\n            if (pending != 0) {\n                //@update user's claimable balance before actions\n                userBaseClaimable[_user] = userBaseClaimable[_user] + pending;\n            }\n        }\n        pool.totalSupply = pool.totalSupply - user.amount;\n        //@note updating user's balances\n        user.amount = _balance;\n        user.rewardDebt = (_balance * accRewardPerShare) / ACC_REWARD_PRECISION;\n        pool.totalSupply = pool.totalSupply + _balance;\n\n        emit BalanceUpdated(_token, _user, _balance);\n    }\n\n    /**\n     * @notice `after` Hook for deposit and borrow update.\n     * @dev important! eligible status can be updated here\n     * @param _user address\n     * @param _balance balance of token\n     */\n    function handleActionAfter(address _user, uint256 _balance) external {\n        if (!vaildPODToken[msg.sender]) revert NotValidPool();\n        _handleActionAfterForToken(msg.sender, _user, _balance);\n    }\n\n    /**\n     * @notice `before` Hook for deposit and borrow update.\n     * @param _user address\n     */\n    function handleActionBefore(address _user) external {}\n\n    /**\n     * @notice Hook for lock update.\n     * @dev Called by the locking contracts before locking or unlocking happens\n     * @param _user address\n     */\n    function beforeLockUpdate(address _user) external {}\n\n    /**\n     * @notice Hook for lock update.\n     * @dev Called by the locking contracts after locking or unlocking happens\n     * @param _user address\n     */\n    function afterLockUpdate(address _user) external {}\n\n    function refreshUserBalance(address _user) external onlyWhitelisted {\n        _updateRegisteredBalance(_user);\n    }\n\n    function refreshUserBalance(address _user, uint256 amount) external onlyWhitelisted {\n        userBaseClaimable[_user] = amount;\n    }\n\n    /**\n     * @notice Update balance if there are any unregistered.\n     * @param _user address of the user whose balances will be updated\n     */\n    function _updateRegisteredBalance(address _user) internal {\n        uint256 length = poolLength();\n        for (uint256 i; i < length; ) {\n            uint256 newBal = IERC20(registeredTokens[i]).balanceOf(_user);\n            uint256 registeredBal = userInfo[registeredTokens[i]][_user].amount;\n            if (newBal != registeredBal) {\n                _handleActionAfterForToken(registeredTokens[i], _user, newBal);\n            }\n            unchecked {\n                i++;\n            }\n        }\n    }\n\n    /********************** Eligibility + Disqualification ***********************/\n\n    /**\n     * @dev Returns true if `_user` has some reward eligible tokens.\n     * @param _user address of recipient\n     */\n    function hasEligibleDeposits(address _user) public view returns (bool hasDeposits) {\n        uint256 length = poolLength();\n        for (uint256 i; i < length; ) {\n            if (userInfo[registeredTokens[i]][_user].amount != 0) {\n                hasDeposits = true;\n                break;\n            }\n            unchecked {\n                i++;\n            }\n        }\n    }\n\n    /**\n     * @dev Stop APUFF emissions for specific users\n     * @param _user address of recipient\n     */\n    function stopEmissionsFor(address _user) internal {\n        if (eligibilityMode == EligibilityModes.DISABLED) revert NotEligible();\n        // lastEligibleStatus will be fresh from refresh before this call\n        uint256 length = poolLength();\n        for (uint256 i; i < length; ) {\n            address token = registeredTokens[i];\n            UserInfo storage user = userInfo[token][_user];\n\n            if (user.amount != 0) {\n                _handleActionAfterForToken(token, _user, 0);\n            }\n            unchecked {\n                i++;\n            }\n        }\n    }\n\n    /**\n     * @notice function to stop user emissions\n     * @param _user address of user to stop emissions for\n     */\n    function manualStopEmissionsFor(address _user, address[] memory _tokens) public onlyWhitelisted {\n        if (_user == address(0)) revert AddressZero();\n        uint256 length = _tokens.length;\n        for (uint256 i; i < length; ) {\n            address token = _tokens[i];\n            PoolInfo storage pool = poolInfo[token];\n            UserInfo storage user = userInfo[token][_user];\n\n            if (pool.lastRewardTime == 0) revert UnknownPool();\n\n            uint256 amount = user.amount;\n            if (amount != 0) {\n                uint256 accRewardPerShare = pool.accRewardPerShare;\n                uint256 pending = (amount * accRewardPerShare) / ACC_REWARD_PRECISION - user.rewardDebt;\n                if (pending != 0) {\n                    userBaseClaimable[_user] = userBaseClaimable[_user] + pending;\n                }\n                uint256 newTotalSupply = pool.totalSupply - amount;\n                user.amount = 0;\n                user.rewardDebt = 0;\n                pool.totalSupply = newTotalSupply;\n\n                emit BalanceUpdated(token, _user, 0);\n            }\n            unchecked {\n                i++;\n            }\n        }\n    }\n\n    function manualStopAllEmissionsFor(address _user) external onlyWhitelisted {\n        manualStopEmissionsFor(_user, registeredTokens);\n    }\n\n    /**\n     * @dev Send APUFF rewards to user.\n     * @param _user address of recipient\n     * @param _amount of APUFF\n     */\n    function _sendAPUFF(address _user, uint256 _amount) internal {\n        if (_amount == 0) {\n            return;\n        }\n\n        address APUFFToken_ = APUFFToken;\n        uint256 chefReserve = IERC20(APUFFToken_).balanceOf(address(this));\n        if (_amount > chefReserve) {\n            revert OutOfRewards();\n        } else {\n            IERC20(APUFFToken_).safeTransfer(_user, _amount);\n        }\n    }\n\n    /********************** APUFF Reserve Management ***********************/\n\n    /**\n     * @notice Ending reward distribution time.\n     */\n    function endRewardTime() public returns (uint256) {\n        if (endingTime.lastUpdatedTime + endingTime.updateCadence > block.timestamp) {\n            return endingTime.estimatedTime;\n        }\n\n        uint256 unclaimedRewards = availableRewards();\n        uint256 extra = 0;\n        uint256 length = poolLength();\n        for (uint256 i; i < length; ) {\n            PoolInfo storage pool = poolInfo[registeredTokens[i]];\n\n            if (pool.lastRewardTime > lastAllPoolUpdate) {\n                extra += ((pool.lastRewardTime - lastAllPoolUpdate) * pool.allocPoint * rewardsPerSecond) / totalAllocPoint;\n            }\n            unchecked {\n                i++;\n            }\n        }\n        endingTime.lastUpdatedTime = block.timestamp;\n\n        if (rewardsPerSecond == 0) {\n            endingTime.estimatedTime = type(uint256).max;\n            return type(uint256).max;\n        } else {\n            uint256 newEndTime = (unclaimedRewards + extra) / rewardsPerSecond + lastAllPoolUpdate;\n            endingTime.estimatedTime = newEndTime;\n            return newEndTime;\n        }\n    }\n\n    /**\n     * @notice Updates cadence duration of ending time.\n     * @dev Only callable by owner.\n     * @param _lapse new cadence\n     */\n\n    //@note (i.e. frequency of how often the estimated end time will be checked)\n    function setEndingTimeUpdateCadence(uint256 _lapse) external onlyOwner {\n        if (_lapse > 1 weeks) revert CadenceTooLong();\n        endingTime.updateCadence = _lapse;\n        emit EndingTimeUpdateCadence(_lapse);\n    }\n\n    /**\n     * @notice Add new rewards.\n     * @dev Only callable by owner.\n     * @param _amount new deposit amount\n     */\n    function registerRewardDeposit(uint256 _amount) external onlyWhitelisted {\n        depositedRewards = depositedRewards + _amount;\n        _massUpdatePools();\n        if (rewardsPerSecond == 0 && lastRPS > 0) {\n            rewardsPerSecond = lastRPS;\n        }\n        emit RewardDeposit(_amount);\n    }\n\n    /**\n     * @notice Available reward amount for future distribution.\n     * @dev This value is equal to `depositedRewards` - `accountedRewards`.\n     * @return amount available\n     */\n    function availableRewards() internal view returns (uint256 amount) {\n        return depositedRewards - accountedRewards;\n    }\n\n    /**\n     * @notice Pause the claim operations.\n     */\n    function pause() external onlyOwner {\n        _pause();\n    }\n\n    /**\n     * @notice Unpause the claim operations.\n     */\n    function unpause() external onlyOwner {\n        _unpause();\n    }\n\n    /**\n     * @dev Returns new rewards since last reward time.\n     * @param pool pool info\n     * @param _totalAllocPoint allocation point of the pool\n     */\n    function _newRewards(\n        PoolInfo memory pool,\n        uint256 _totalAllocPoint\n    ) internal view returns (uint256 newReward, uint256 newAccRewardPerShare) {\n        uint256 lpSupply = pool.totalSupply;\n        if (lpSupply > 0) {\n            uint256 duration = block.timestamp - pool.lastRewardTime;\n            uint256 rawReward = duration * rewardsPerSecond;\n\n            uint256 rewards = availableRewards();\n            if (rewards < rawReward) {\n                rawReward = rewards;\n            }\n            newReward = (rawReward * pool.allocPoint) / _totalAllocPoint;\n            newAccRewardPerShare = (newReward * ACC_REWARD_PRECISION) / lpSupply;\n        }\n    }\n\n    /**\n     * @notice Add new address to whitelist.\n     * @param user address\n     * @param status for whitelist\n     */\n    function setAddressWLstatus(address user, bool status) external onlyOwner {\n        whitelist[user] = status;\n    }\n\n    /**\n     * @notice Toggle whitelist to be either active or inactive\n     */\n    function toggleWhitelist() external onlyOwner {\n        whitelistActive = !whitelistActive;\n    }\n\n    //function using .call to allow keeper withdraw eth from contact\n    function withdrawEth(uint256 amount) external onlyOwner {\n        (bool success, ) = payable(owner()).call{ value: amount }(\"\");\n        if (!success) revert EthTransferFailed();\n    }\n}\n"
      },
      "contracts/interfaces/IIncentive/IChefIncentivesController.sol": {
        "content": "// SPDX-License-Identifier: agpl-3.0\npragma solidity ^0.8.23;\npragma experimental ABIEncoderV2;\n\ninterface ICICUserDefinedTypes {\n    // Info of each user.\n    // reward = user.`amount` * pool.`accRewardPerShare` - `rewardDebt`\n    struct UserInfo {\n        uint256 amount;\n        uint256 rewardDebt;\n        uint256 lastClaimTime;\n    }\n\n    // Info of each pool.\n    struct PoolInfo {\n        uint256 totalSupply;\n        uint256 allocPoint; // How many allocation points assigned to this pool.\n        uint256 lastRewardTime; // Last second that reward distribution occurs.\n        uint256 accRewardPerShare; // Accumulated rewards per share, times ACC_REWARD_PRECISION. See below.\n    }\n    // Info about token emissions for a given time period.\n    struct EmissionPoint {\n        uint128 startTimeOffset;\n        uint128 rewardsPerSecond;\n    }\n    // Info about ending time of reward emissions\n    struct EndingTime {\n        uint256 estimatedTime;\n        uint256 lastUpdatedTime;\n        uint256 updateCadence;\n    }\n\n    enum EligibilityModes {\n        // check on all rToken transfers\n        FULL,\n        // only check on Claim\n        LIMITED,\n        // 0 eligibility functions run\n        DISABLED\n    }\n\n    /********************** Events ***********************/\n    // Emitted when rewardPerSecond is updated\n    event RewardsPerSecondUpdated(uint256 indexed rewardsPerSecond);\n\n    event BalanceUpdated(address indexed token, address indexed user, uint256 balance);\n\n    event EmissionScheduleAppended(uint256[] startTimeOffsets, uint256[] rewardsPerSeconds);\n\n    event Disqualified(address indexed user);\n\n    event EligibilityModeUpdated(EligibilityModes indexed _newVal);\n\n    event BatchAllocPointsUpdated(address[] _tokens, uint256[] _allocPoints);\n\n    event AuthorizedContractUpdated(address _contract, bool _authorized);\n\n    event EndingTimeUpdateCadence(uint256 indexed _lapse);\n\n    event RewardDeposit(uint256 indexed _amount);\n\n    event UpdateRequested(address indexed _user, uint256 feePaid);\n\n    event KeeperConfigSet(address indexed keeper, uint256 executionGasLimit);\n\n    event EmissionStarted(uint256 _startTime);\n\n    event PoolAdded(address indexed _token, uint256 indexed _allocPoint);\n\n    event WhitelistUpdated(address indexed _user, bool _status);\n\n    event WhitelistToggled(bool _status);\n\n    /********************** Errors ***********************/\n    error AddressZero();\n\n    error UnknownPool();\n\n    error PoolExists();\n\n    error AlreadyStarted();\n\n    error NotAllowed();\n\n    error ArrayLengthMismatch();\n\n    error InvalidStart();\n\n    error InvalidRToken();\n\n    error InsufficientPermission();\n\n    error AuthorizationAlreadySet();\n\n    error NotVeContract();\n\n    error NotWhitelisted();\n\n    error NotEligible();\n\n    error CadenceTooLong();\n\n    error EligibleRequired();\n\n    error NotValidPool();\n\n    error OutOfRewards();\n\n    error DuplicateSchedule();\n\n    error ValueZero();\n\n    error NotKeeper();\n\n    error InsufficientFee();\n\n    error TransferFailed();\n\n    error UpdateInProgress();\n\n    error ExemptedUser();\n\n    error EthTransferFailed();\n\n    error InvalidToken();\n}\n\ninterface IChefIncentivesController {\n    /**\n     * @dev Called by the corresponding asset on any update that affects the rewards distribution\n     * @param user The address of the user\n     **/\n    function handleActionBefore(address user) external;\n\n    /**\n     * @dev Called by the corresponding asset on any update that affects the rewards distribution\n     * @param user The address of the user\n     * @param userBalance The balance of the user of the asset in the lending pool\n     **/\n    function handleWithdrawAfter(address user, uint256 userBalance) external;\n\n    /**\n     * @dev Called by the locking contracts after locking or unlocking happens\n     * @param user The address of the user\n     **/\n    function beforeLockUpdate(address user) external;\n\n    /**\n     * @notice Hook for lock update.\n     * @dev Called by the locking contracts after locking or unlocking happens\n     */\n    function afterLockUpdate(address _user) external;\n\n    function addPool(address _token, uint256 _allocPoint) external;\n\n    function claim(address _user, address[] calldata _tokens) external;\n\n    // function disqualifyUser(address _user, address _hunter) external returns (uint256 bounty);\n\n    // function bountyForUser(address _user) external view returns (uint256 bounty);\n\n    function allPendingRewards(address _user) external view returns (uint256 pending);\n\n    function claimAll(address _user) external;\n\n    // function claimBounty(address _user, bool _execute) external returns (bool issueBaseBounty);\n\n    function setEligibilityExempt(address _address, bool _value) external;\n\n    function manualStopEmissionsFor(address _user, address[] memory _tokens) external;\n\n    function manualStopAllEmissionsFor(address _user) external;\n\n    function setAddressWLstatus(address user, bool status) external;\n\n    function toggleWhitelist() external;\n\n}\n"
      },
      "contracts/interfaces/IIncentive/IEligibilityDataProvider.sol": {
        "content": "// SPDX-License-Identifier: agpl-3.0\npragma solidity ^0.8.23;\n\nimport { IChefIncentivesController } from \"./IChefIncentivesController.sol\";\n\ninterface IEDPUserDefinedTypes {\n    /********************** Events ***********************/\n    /// @notice Emitted when CIC is set\n    event ChefIncentivesControllerUpdated(IChefIncentivesController indexed _chef);\n\n    /// @notice Emitted when LP token is set\n    event VeTokenUpdated(address indexed _lpToken);\n\n    /// @notice Emitted when required TVL ratio is updated\n    event RequiredDepositRatioUpdated(uint256 indexed requiredDepositRatio);\n\n    /// @notice Emitted when price tolerance ratio is updated\n    event PriceToleranceRatioUpdated(uint256 indexed priceToleranceRatio);\n\n    /// @notice Emitted when DQ time is set\n    event DqTimeUpdated(address indexed _user, uint256 _time);\n\n    /********************** Errors ***********************/\n    error AddressZero();\n\n    error LPTokenSet(address currentVeToken);\n\n    error InvalidRatio();\n\n    error OnlyCIC();\n}\n\ninterface IEligibilityDataProvider {\n    function refreshByKeeper(address user, bool isEligible) external returns (bool currentEligibility);\n\n    function isEligibleForRewards(address _user) external view returns (bool isEligible);\n\n    function lockedVeTokenUsdcValue(address user) external view returns (uint256);\n\n    function requiredUsdcValue(address user) external view returns (uint256 required);\n\n    function lastEligibleStatus(address user) external view returns (bool);\n\n    function setDqTime(address _user, uint256 _time) external;\n\n    function getDqTime(address _user) external view returns (uint256);\n\n    function requiredDepositRatio() external view returns (uint256);\n\n    function RATIO_DIVISOR() external view returns (uint256);\n}\n"
      },
      "contracts/libraries/RecoverERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.23;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/// @title RecoverERC20 contract\n/// @author Radiant Devs\n/// @dev All function calls are currently implemented without side effects\ncontract RecoverERC20 {\n    using SafeERC20 for IERC20;\n\n    /// @notice Emitted when ERC20 token is recovered\n    event Recovered(address indexed token, uint256 amount);\n\n    /**\n     * @notice Added to support recovering LP Rewards from other systems such as BAL to be distributed to holders\n     */\n    function _recoverERC20(address tokenAddress, uint256 tokenAmount) internal {\n        IERC20(tokenAddress).safeTransfer(msg.sender, tokenAmount);\n        emit Recovered(tokenAddress, tokenAmount);\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}