creation_sourcecode: {{
    "language": "Solidity",
    "settings": {
      "viaIR": false,
      "optimizer": {
        "runs": 10000,
        "enabled": true
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "none",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "libraries": {},
      "remappings": [
        "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
        "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/",
        "@prb/test/=node_modules/@prb/test/",
        "forge-std/=node_modules/forge-std/",
        "@sphinx-labs/contracts/=node_modules/@sphinx-labs/contracts/contracts/foundry/",
        "@eth-optimism/=node_modules/@eth-optimism/",
        "hardhat/=node_modules/hardhat/",
        "solmate/=node_modules/solmate/"
      ]
    },
    "sources": {
      "node_modules/@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"
      },
      "node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IERC20Metadata} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {ContextUpgradeable} from \"../../utils/ContextUpgradeable.sol\";\nimport {IERC20Errors} from \"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n */\nabstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors {\n    /// @custom:storage-location erc7201:openzeppelin.storage.ERC20\n    struct ERC20Storage {\n        mapping(address account => uint256) _balances;\n\n        mapping(address account => mapping(address spender => uint256)) _allowances;\n\n        uint256 _totalSupply;\n\n        string _name;\n        string _symbol;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ERC20\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00;\n\n    function _getERC20Storage() private pure returns (ERC20Storage storage $) {\n        assembly {\n            $.slot := ERC20StorageLocation\n        }\n    }\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n        __ERC20_init_unchained(name_, symbol_);\n    }\n\n    function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n        ERC20Storage storage $ = _getERC20Storage();\n        $._name = name_;\n        $._symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual returns (string memory) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual returns (string memory) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `value`.\n     */\n    function transfer(address to, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, value);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, value);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `value`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `value`.\n     */\n    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, value);\n        _transfer(from, to, value);\n        return true;\n    }\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _transfer(address from, address to, uint256 value) internal {\n        if (from == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        if (to == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(from, to, value);\n    }\n\n    /**\n     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n     * this function.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _update(address from, address to, uint256 value) internal virtual {\n        ERC20Storage storage $ = _getERC20Storage();\n        if (from == address(0)) {\n            // Overflow check required: The rest of the code assumes that totalSupply never overflows\n            $._totalSupply += value;\n        } else {\n            uint256 fromBalance = $._balances[from];\n            if (fromBalance < value) {\n                revert ERC20InsufficientBalance(from, fromBalance, value);\n            }\n            unchecked {\n                // Overflow not possible: value <= fromBalance <= totalSupply.\n                $._balances[from] = fromBalance - value;\n            }\n        }\n\n        if (to == address(0)) {\n            unchecked {\n                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n                $._totalSupply -= value;\n            }\n        } else {\n            unchecked {\n                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n                $._balances[to] += value;\n            }\n        }\n\n        emit Transfer(from, to, value);\n    }\n\n    /**\n     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n     * Relies on the `_update` mechanism\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _mint(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(address(0), account, value);\n    }\n\n    /**\n     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n     * Relies on the `_update` mechanism.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead\n     */\n    function _burn(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        _update(account, address(0), value);\n    }\n\n    /**\n     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address owner, address spender, uint256 value) internal {\n        _approve(owner, spender, value, true);\n    }\n\n    /**\n     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n     *\n     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any\n     * `Approval` event during `transferFrom` operations.\n     *\n     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to\n     * true using the following override:\n     * ```\n     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n     *     super._approve(owner, spender, value, true);\n     * }\n     * ```\n     *\n     * Requirements are the same as {_approve}.\n     */\n    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n        ERC20Storage storage $ = _getERC20Storage();\n        if (owner == address(0)) {\n            revert ERC20InvalidApprover(address(0));\n        }\n        if (spender == address(0)) {\n            revert ERC20InvalidSpender(address(0));\n        }\n        $._allowances[owner][spender] = value;\n        if (emitEvent) {\n            emit Approval(owner, spender, value);\n        }\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `value`.\n     *\n     * Does not update the allowance value in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Does not emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            if (currentAllowance < value) {\n                revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n            }\n            unchecked {\n                _approve(owner, spender, currentAllowance - value, false);\n            }\n        }\n    }\n}\n"
      },
      "node_modules/@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"
      },
      "node_modules/@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard\n    struct ReentrancyGuardStorage {\n        uint256 _status;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) {\n        assembly {\n            $.slot := ReentrancyGuardStorageLocation\n        }\n    }\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        $._status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if ($._status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        $._status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        $._status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        return $._status == ENTERED;\n    }\n}\n"
      },
      "node_modules/@openzeppelin/contracts/interfaces/draft-IERC6093.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard ERC20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     * @param allowance Amount of tokens a `spender` is allowed to operate with.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"
      },
      "node_modules/@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"
      },
      "node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "node_modules/@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"
      },
      "node_modules/@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"
      },
      "node_modules/@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"
      },
      "src/VestingToken.sol": {
        "content": "// SPDX-License-Identifier: None\n// Unvest Contracts (last updated v3.0.0) (VestingToken.sol)\npragma solidity ^0.8.24;\n\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { ERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\n\nimport { Errors } from \"./libraries/Errors.sol\";\nimport { Arrays } from \"./libraries/Arrays.sol\";\nimport { IFeeManager } from \"./interfaces/IFeeManager.sol\";\nimport { IVestingToken } from \"./interfaces/IVestingToken.sol\";\n\n/*\n\n _   _  _   _ __     __ _____  ____  _____ \n| | | || \\ | |\\ \\   / /| ____|/ ___||_   _|\n| | | ||  \\| | \\ \\ / / |  _|  \\___ \\  | |  \n| |_| || |\\  |  \\ V /  | |___  ___) | | |  \n \\___/ |_| \\_|   \\_/   |_____||____/  |_|  \n                                           \n */\n\n/// @title VestingToken\n/// @notice VestingToken locks ERC20 and contains the logic for tokens to be partially unlocked based on milestones.\n/// @author JA (@ubinatus) v3\n/// @author Klaus Hott (@Janther) v2\ncontract VestingToken is ERC20Upgradeable, ReentrancyGuardUpgradeable, IVestingToken {\n    using SafeERC20 for ERC20Upgradeable;\n\n    /// @dev `claimedAmountAfterTransfer` is used to calculate the `_claimableAmount` of an account. It's value is\n    /// updated on every `transfer`, `transferFrom`, and `claim` calls.\n    /// @dev While `claimedAmountAfterTransfer` contains a fraction of the `claimedAmountAfterTransfer`s of every token\n    /// transfer the owner of account receives, `claimedBalance` works as a counter for tokens claimed by this account.\n    struct Metadata {\n        uint256 claimedAmountAfterTransfer;\n        uint256 claimedBalance;\n    }\n\n    /// @param account Address that will receive the `amount` of `underlyingToken`.\n    /// @param amount  Amount of tokens that will be sent to the `account`.\n    event Claim(address indexed account, uint256 amount);\n\n    /// @param account Address that will burn the `amount` of `underlyingToken`.\n    /// @param amount  Amount of tokens that will be sent to the dead address.\n    event Burn(address indexed account, uint256 amount);\n\n    /// @param milestoneIndex Index of the Milestone reached.\n    event MilestoneReached(uint256 indexed milestoneIndex);\n\n    /// @dev Percentages and fees are calculated using 18 decimals where 1 ether is 100%.\n    uint256 internal constant ONE = 1 ether;\n\n    /// @notice The ERC20 token that this contract will be vesting.\n    ERC20Upgradeable public underlyingToken;\n\n    /// @notice The manager that deployed this contract which controls the values for `fee` and `feeCollector`.\n    IFeeManager public manager;\n\n    /// @dev The `decimals` value that is fetched from `underlyingToken`.\n    uint8 internal _decimals;\n\n    /// @dev The initial supply used for calculating the `claimableSupply`, `claimedSupply`, and `lockedSupply`.\n    uint256 internal _startingSupply;\n\n    /// @dev The imported claimed supply is necessary for an accurate `claimableSupply` but leads to an improper offset\n    /// in `claimedSupply`, so we keep track of this to account for it.\n    uint256 internal _importedClaimedSupply;\n\n    /// @notice An array of Milestones describing the times and behaviour of the rules to release the vested tokens.\n    Milestone[] internal _milestones;\n\n    /// @notice Keep track of the last reached Milestone to minimize the iterations over the milestones and save gas.\n    uint256 internal _lastReachedMilestone;\n\n    /// @dev Maps a an address to the metadata needed to calculate `claimableBalance` and `lockedBalanceOf`.\n    mapping(address => Metadata) internal _metadata;\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor() {\n        _disableInitializers();\n    }\n\n    /**\n     * @notice Initializes the contract by setting up the ERC20 variables, the `underlyingToken`, and the\n     * `milestonesArray` information.\n     *\n     * @dev The Ramp of the first Milestone in the `milestonesArray` will always act as a Cliff since it doesn't have\n     * a previous milestone.\n     *\n     * Requirements:\n     *\n     * - `underlyingTokenAddress` cannot be the zero address.\n     * - `timestamps` must be given in ascending order.\n     * - `percentages` must be given in ascending order and the last one must always be 1 eth, where 1 eth equals to\n     * 100%.\n     * - 2 `percentages` may have the same value as long as they are followed by a `Ramp.Linear` Milestone.\n     *\n     * @param name                   This ERC20 token name.\n     * @param symbol                 This ERC20 token symbol.\n     * @param underlyingTokenAddress The ERC20 token that will be held by this contract.\n     * @param milestonesArray        Array of all `Milestone`s for this contract's lifetime.\n     */\n    function initialize(\n        string calldata name,\n        string calldata symbol,\n        address underlyingTokenAddress,\n        Milestone[] calldata milestonesArray\n    )\n        external\n        override\n        initializer\n    {\n        __ERC20_init(name, symbol);\n        __ReentrancyGuard_init();\n\n        manager = IFeeManager(msg.sender);\n\n        _setupMilestones(milestonesArray);\n\n        underlyingToken = ERC20Upgradeable(underlyingTokenAddress);\n        _decimals = _tryFetchDecimals();\n    }\n\n    /// @dev Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`,\n    /// a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`).\n    ///\n    /// Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. Since we can't predict\n    /// the decimals the `underlyingToken` will have, we need to provide our own implementation which is setup at\n    /// initialization.\n    ///\n    /// NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the\n    /// contract.\n    function decimals() public view virtual override returns (uint8) {\n        return _decimals;\n    }\n\n    /// @notice Vests an `amount` of `underlyingToken` and mints LVTs for a `recipient`.\n    ///\n    /// Requirements:\n    ///\n    /// - `msg.sender` must have approved this contract an amount of `underlyingToken` greater or equal than `amount`.\n    ///\n    /// @param recipient The address that will receive the newly minted LVT.\n    /// @param amount    The amount of `underlyingToken` to be vested.\n    function addRecipient(address recipient, uint256 amount) external nonReentrant {\n        uint256 currentBalance = _getBalanceOfThis();\n\n        underlyingToken.safeTransferFrom(msg.sender, address(this), amount);\n        uint256 transferredAmount = _getBalanceOfThis() - currentBalance;\n\n        _startingSupply = _startingSupply + transferredAmount;\n        _mint(recipient, transferredAmount);\n    }\n\n    /// @notice Vests multiple `amounts` of `underlyingToken` and mints LVTs for multiple `recipients`.\n    ///\n    /// Requirements:\n    ///\n    /// - `recipients` and `amounts` must have the same length.\n    /// - `msg.sender` must have approved this contract an amount of `underlyingToken` greater or equal than the sum of\n    /// all of the `amounts`.\n    ///\n    /// @param recipients Array of addresses that will receive the newly minted LVTs.\n    /// @param amounts    Array of amounts of `underlyingToken` to be vested.\n    function addRecipients(\n        address[] calldata recipients,\n        uint256[] calldata amounts,\n        uint256 totalAmount\n    )\n        external\n        nonReentrant\n    {\n        if (recipients.length != amounts.length) revert Errors.InputArraysMustHaveSameLength();\n        uint256 currentBalance = _getBalanceOfThis();\n\n        underlyingToken.safeTransferFrom(msg.sender, address(this), totalAmount);\n        uint256 transferredAmount = _getBalanceOfThis() - currentBalance;\n\n        _startingSupply = _startingSupply + transferredAmount;\n\n        uint256 _totalAmount;\n        uint256 recipientsLen = recipients.length;\n        for (uint256 i = recipientsLen; i != 0;) {\n            unchecked {\n                --i;\n            }\n\n            address recipient = Arrays.unsafeMemoryAccess(recipients, i);\n            uint256 curAmount = Arrays.unsafeMemoryAccess(amounts, i);\n            _totalAmount += Arrays.unsafeMemoryAccess(amounts, i);\n            uint256 amount =\n                transferredAmount == totalAmount ? curAmount : (curAmount * transferredAmount) / totalAmount;\n            _mint(recipient, amount);\n        }\n\n        if (_totalAmount != totalAmount) revert Errors.InvalidTotalAmount();\n    }\n\n    /**\n     * @notice Behaves as `addRecipient` but provides the ability to set the initial state of the recipient's metadata.\n     * @notice This functionality is included in order to allow users to restart an allocation on a different chain and\n     * keeping the inner state as close as possible to the original.\n     *\n     * @dev The `Metadata.claimedAmountAfterTransfer` for the recipient is inferred from the parameters.\n     * @dev The `Metadata.claimedBalance` is lost in the transfer, the closest value will be\n     * `claimedAmountAfterTransfer`.\n     * @dev In the rare case where the contract and it's users are migrated after the last milestone has been reached,\n     * the `claimedAmountAfterTransfer` can't be inferred and the `claimedSupply` value for the whole contract is lost\n     * in the transfer.\n     * @dev The decision to do this is to minimize the altering of metadata to the amount that is being transferred and\n     * protect an attack that would render the contract unusable.\n     *\n     * Requirements:\n     *\n     * - `unlocked` must be less than or equal to this contracts `unlockedPercentage`.\n     * - `claimableAmountOfImport` must be less than or equal than the amount that would be claimable given the values\n     *  of `amount` and `percentage`.\n     * - `msg.sender` must have approved this contract an amount of `underlyingToken` greater or equal than `amount`.\n     *\n     * @param recipient               The address that will receive the newly minted LVT.\n     * @param amount                  The amount of `underlyingToken` to be vested.\n     * @param claimableAmountOfImport The amount of `underlyingToken` from this transaction that should be considered\n     *                                claimable.\n     * @param unlocked                The unlocked percentage value at the time of the export of this transaction.\n     */\n    function importRecipient(\n        address recipient,\n        uint256 amount,\n        uint256 claimableAmountOfImport,\n        uint256 unlocked\n    )\n        external\n        nonReentrant\n    {\n        if (unlocked > unlockedPercentage()) revert Errors.UnlockedIsGreaterThanExpected();\n        uint256 currentBalance = _getBalanceOfThis();\n\n        underlyingToken.safeTransferFrom(msg.sender, address(this), amount);\n        uint256 transferredAmount = _getBalanceOfThis() - currentBalance;\n\n        uint256 claimedAmount = _claimedAmount(transferredAmount, claimableAmountOfImport, unlocked);\n\n        _metadata[recipient].claimedAmountAfterTransfer =\n            _metadata[recipient].claimedAmountAfterTransfer + claimedAmount;\n\n        _importedClaimedSupply = _importedClaimedSupply + claimedAmount;\n        _startingSupply = _startingSupply + transferredAmount + claimedAmount;\n        _mint(recipient, transferredAmount);\n    }\n\n    /**\n     *  @notice Behaves as `addRecipients` but provides the ability to set the initial state of the recipient's\n     *  metadata.\n     *  @notice This functionality is included in order to allow users to restart an allocation on a different chain and\n     *  keeping the inner state as close as possible to the original.\n     *\n     *  @dev The `Metadata.claimedAmountAfterTransfer` for each recipient is inferred from the parameters.\n     *  @dev The `Metadata.claimedBalance` is lost in the transfer, the closest value will be\n     *  `claimedAmountAfterTransfer`.\n     *  @dev In the rare case where the contract and it's users are migrated after the last milestone has been reached,\n     *  the `claimedAmountAfterTransfer` can't be inferred and the `claimedSupply` value for the whole contract is lost\n     *  in the transfer.\n     *  @dev The decision to do this to minimize the altering of metadata to the amount that is being transferred and\n     *  protect an attack that would render the contract unusable.\n     *\n     *  @dev The Metadata for the recipient is inferred from the parameters. The decision to do this to minimize the\n     *  altering of metadata to the amount that is being transferred.\n     *\n     *  Requirements:\n     *\n     *  - `recipients`, `amounts`, and `claimableAmountsOfImport` must have the same length.\n     *  - `unlocked` must be less than or equal to this contracts `unlockedPercentage`.\n     *  - each value in `claimableAmountsOfImport` must be less than or equal than the amount that would be claimable\n     *  given the values in `amounts` and `percentages`.\n     *  - `msg.sender` must have approved this contract an amount of `underlyingToken` greater or equal than the sum of\n     *  all of the `amounts`.\n     *\n     *  @param recipients               Array of addresses that will receive the newly minted LVTs.\n     *  @param amounts                  Array of amounts of `underlyingToken` to be vested.\n     *  @param claimableAmountsOfImport Array of amounts of `underlyingToken` from this transaction that should be\n     * considered claimable.\n     *  @param unlocked                 The unlocked percentage value at the time of the export of this transaction.\n     */\n    function importRecipients(\n        address[] calldata recipients,\n        uint256[] calldata amounts,\n        uint256[] calldata claimableAmountsOfImport,\n        uint256 totalAmount,\n        uint256 unlocked\n    )\n        external\n        nonReentrant\n    {\n        if (unlocked > unlockedPercentage()) revert Errors.UnlockedIsGreaterThanExpected();\n\n        uint256 recipientsLen = recipients.length;\n        if (recipientsLen != amounts.length || claimableAmountsOfImport.length != amounts.length) {\n            revert Errors.InputArraysMustHaveSameLength();\n        }\n\n        uint256 currentBalance = _getBalanceOfThis();\n        underlyingToken.safeTransferFrom(msg.sender, address(this), totalAmount);\n        uint256 transferredAmount = _getBalanceOfThis() - currentBalance;\n\n        uint256 totalClaimed;\n\n        uint256 _totalAmount;\n        for (uint256 i = recipientsLen; i != 0;) {\n            unchecked {\n                --i;\n            }\n\n            uint256 curAmount = Arrays.unsafeMemoryAccess(amounts, i);\n\n            _totalAmount += curAmount;\n\n            address recipient = recipients[i];\n            uint256 amount =\n                transferredAmount == totalAmount ? curAmount : (curAmount * transferredAmount) / totalAmount;\n\n            uint256 claimableAmountOfImport = Arrays.unsafeMemoryAccess(claimableAmountsOfImport, i);\n\n            uint256 claimedAmount = _claimedAmount(amount, claimableAmountOfImport, unlocked);\n            _mint(recipient, amount);\n\n            _metadata[recipient].claimedAmountAfterTransfer =\n                _metadata[recipient].claimedAmountAfterTransfer + claimedAmount;\n\n            totalClaimed += claimedAmount;\n        }\n\n        if (_totalAmount != totalAmount) revert Errors.InvalidTotalAmount();\n\n        _importedClaimedSupply = _importedClaimedSupply + totalClaimed;\n        _startingSupply = _startingSupply + transferredAmount + totalClaimed;\n    }\n\n    /// @param recipient The address that will be exported.\n    ///\n    /// @return The arguments to use in a call `importRecipient` on a different contract to migrate the `recipient`'s\n    /// metadata.\n    function exportRecipient(address recipient) external view returns (address, uint256, uint256, uint256) {\n        return (recipient, balanceOf(recipient), claimableBalanceOf(recipient), unlockedPercentage());\n    }\n\n    /// @param recipients Array of addresses that will be exported.\n    ///\n    /// @return The arguments to use in a call `importRecipients` on a different contract to migrate the `recipients`'\n    /// metadata.\n    function exportRecipients(address[] calldata recipients)\n        external\n        view\n        returns (address[] calldata, uint256[] memory, uint256[] memory, uint256)\n    {\n        uint256 recipientsLen = recipients.length;\n        uint256[] memory balances = new uint256[](recipientsLen);\n        uint256[] memory claimableBalances = new uint256[](recipientsLen);\n\n        for (uint256 i = recipientsLen; i != 0;) {\n            unchecked {\n                --i;\n            }\n\n            address recipient = Arrays.unsafeMemoryAccess(recipients, i);\n            balances[i] = balanceOf(recipient);\n            claimableBalances[i] = claimableBalanceOf(recipient);\n        }\n\n        return (recipients, balances, claimableBalances, unlockedPercentage());\n    }\n\n    /// @notice This function will check and update the `_lastReachedMilestone` so the gas usage will be minimal in\n    /// calls to `unlockedPercentage`.\n    ///\n    /// @dev This function is called by claim with a value of `startIndex` equal to the previous value of\n    /// `_lastReachedMilestone`, but can be called externally with a more accurate value in case multiple Milestones\n    /// have been reached without anyone claiming.\n    ///\n    /// @param startIndex Index of the Milestone we want the loop to start checking.\n    function updateLastReachedMilestone(uint256 startIndex) public {\n        if (_milestones[startIndex].timestamp > block.timestamp) return;\n\n        uint256 lastReachedMilestone = _lastReachedMilestone;\n        uint256 len = _milestones.length;\n        Milestone storage previous = _milestones[startIndex];\n\n        for (uint256 i = startIndex; i < len;) {\n            Milestone storage current = _milestones[i];\n            if (current.timestamp <= block.timestamp) {\n                previous = current;\n\n                unchecked {\n                    ++i;\n                }\n\n                continue;\n            }\n\n            if (i > lastReachedMilestone + 1) {\n                unchecked {\n                    lastReachedMilestone = i - 1;\n                }\n                emit MilestoneReached(lastReachedMilestone);\n            }\n            return;\n        }\n\n        if (lastReachedMilestone < len - 1) {\n            unchecked {\n                lastReachedMilestone = len - 1;\n            }\n            emit MilestoneReached(lastReachedMilestone);\n        }\n\n        if (lastReachedMilestone != _lastReachedMilestone) {\n            unchecked {\n                _lastReachedMilestone = lastReachedMilestone;\n            }\n        }\n    }\n\n    /// @return The percentage of `underlyingToken` that users could claim.\n    function unlockedPercentage() public view returns (uint256) {\n        Milestone storage previous = _milestones[_lastReachedMilestone];\n        // If the first Milestone is still pending, the contract hasn't started unlocking tokens\n        if (previous.timestamp > block.timestamp) return 0;\n\n        uint256 percentage = previous.percentage;\n        uint256 milestonesLen = _milestones.length;\n        for (uint256 i = _lastReachedMilestone + 1; i < milestonesLen;) {\n            Milestone storage current = _milestones[i];\n            // If `current` Milestone has expired, `percentage` is at least `current` Milestone's percentage\n            if (current.timestamp <= block.timestamp) {\n                percentage = current.percentage;\n                previous = current;\n\n                unchecked {\n                    ++i;\n                }\n\n                continue;\n            }\n            // If `current` Milestone has a `Linear` ramp, `percentage` is between `previous` and `current`\n            // Milestone's percentage\n            if (current.ramp == Ramp.Linear) {\n                percentage += ((block.timestamp - previous.timestamp) * (current.percentage - previous.percentage))\n                    / (current.timestamp - previous.timestamp);\n            }\n            // `percentage` won't change after this\n            break;\n        }\n        return percentage;\n    }\n\n    /// @return The amount of `underlyingToken` that were held in this contract and have been claimed.\n    function claimedSupply() external view returns (uint256) {\n        return _startingSupply - totalSupply() - _importedClaimedSupply;\n    }\n\n    /// @return The amount of `underlyingToken` being held in this contract and that can be claimed.\n    function claimableSupply() public view returns (uint256) {\n        return _claimableAmount(_startingSupply, _startingSupply - totalSupply());\n    }\n\n    /// @return The amount of `underlyingToken` being held in this contract that can't be claimed yet.\n    function lockedSupply() external view returns (uint256) {\n        return totalSupply() - claimableSupply();\n    }\n\n    /// @param account The address whose tokens are being queried.\n    /// @return The amount of `underlyingToken` that were held in this contract and this `account` already claimed.\n    function claimedBalanceOf(address account) external view returns (uint256) {\n        return _metadata[account].claimedBalance;\n    }\n\n    /// @param account The address whose tokens are being queried.\n    /// @return The amount of `underlyingToken` that this `account` owns and can claim.\n    function claimableBalanceOf(address account) public view returns (uint256) {\n        uint256 claimedAmountAfterTransfer = _metadata[account].claimedAmountAfterTransfer;\n        return _claimableAmount(claimedAmountAfterTransfer + balanceOf(account), claimedAmountAfterTransfer);\n    }\n\n    /// @param account The address whose tokens are being queried.\n    /// @return The amount of `underlyingToken` that this `account` owns but can't claim yet.\n    function lockedBalanceOf(address account) external view returns (uint256) {\n        return balanceOf(account) - claimableBalanceOf(account);\n    }\n\n    /// @notice Claims available unlocked `underlyingToken` for the caller.\n    /// @dev Transfers claimable amount to `msg.sender` and requires a claim fee (`msg.value`).\n    /// Reverts if there's no claimable amount. Protected against re-entrancy.\n    function claim() external payable nonReentrant {\n        address account = msg.sender;\n        Metadata storage accountMetadata = _metadata[account];\n\n        updateLastReachedMilestone(_lastReachedMilestone);\n\n        uint256 claimableAmount = _claimableAmount(\n            accountMetadata.claimedAmountAfterTransfer + balanceOf(account), accountMetadata.claimedAmountAfterTransfer\n        );\n\n        if (claimableAmount == 0) {\n            revert Errors.NoClaimableAmount();\n        }\n\n        _burn(account, claimableAmount);\n\n        accountMetadata.claimedAmountAfterTransfer = accountMetadata.claimedAmountAfterTransfer + claimableAmount;\n        accountMetadata.claimedBalance = accountMetadata.claimedBalance + claimableAmount;\n\n        emit Claim(account, claimableAmount);\n        underlyingToken.safeTransfer(account, claimableAmount);\n\n        _processClaimFee();\n    }\n\n    /// @notice Allows an investor to burn their vested and underlying tokens.\n    /// @dev First attempts to burn the underlying tokens. If unsuccessful, these are sent to address '0xdead'. This\n    /// operation is followed by the burning of the equivalent vested tokens.\n    /// Assumes the underlying token has a burn function with the selector '0x42966c68'.\n    /// @param amount Amount of tokens to be burnt. The investor's locked balance must be greater or equal than this\n    /// amount.\n    function burn(uint256 amount) public payable {\n        uint256 currentBalance = _getBalanceOfThis();\n\n        address account = msg.sender;\n        address underlyingAddress = address(underlyingToken);\n\n        emit Burn(account, amount);\n\n        // Selector for \"burn(uint256)\"\n        bytes4 burnSelector = 0x42966c68;\n\n        // Encoding calldata for burn function\n        (bool burnSuccess,) = underlyingAddress.call(abi.encodeWithSelector(burnSelector, amount));\n        if (!burnSuccess) {\n            underlyingToken.safeTransfer(address(0xdead), amount);\n        }\n\n        uint256 transferredAmount = currentBalance - _getBalanceOfThis();\n\n        _startingSupply = _startingSupply - transferredAmount;\n\n        _burn(account, amount);\n    }\n\n    /// @notice Calculates and transfers the fee before executing a normal ERC20 transfer.\n    ///\n    /// @dev This method also updates the metadata in `msg.sender`, `to`, and `feeCollector`.\n    ///\n    /// @param to     Address of recipient.\n    /// @param amount Amount of tokens.\n    function transfer(address to, uint256 amount) public override returns (bool) {\n        _updateMetadataAndTransfer(msg.sender, to, amount, true);\n        return true;\n    }\n\n    /// @notice Calculates and transfers the fee before executing a normal ERC20 transferFrom.\n    ///\n    /// @dev This method also updates the metadata in `from`, `to`, and `feeCollector`.\n    ///\n    /// @param from   Address of sender.\n    /// @param to     Address of recipient.\n    /// @param amount Amount of tokens.\n    function transferFrom(address from, address to, uint256 amount) public override returns (bool) {\n        _updateMetadataAndTransfer(from, to, amount, false);\n        return true;\n    }\n\n    /// @notice Exposes the whole array of `_milestones`.\n    function milestones() external view returns (Milestone[] memory) {\n        return _milestones;\n    }\n\n    /// @notice Exposes the inner metadata for a given account.\n    /// @param account The address whose tokens are being queried.\n    function metadataOf(address account) external view returns (Metadata memory metadata) {\n        metadata = _metadata[account];\n    }\n\n    /// @notice Returns the current transfer fee associated to this `VestingToken`.\n    function transferFeeData() external view returns (address, uint64) {\n        return manager.transferFeeData(address(underlyingToken));\n    }\n\n    /// @notice Returns the current claim fee associated to this `VestingToken`.\n    function claimFeeData() external view returns (address, uint64) {\n        return manager.claimFeeData(address(underlyingToken));\n    }\n\n    /**\n     * @dev This function updates the metadata on the `sender`, the `receiver`, and the `feeCollector` if there's any\n     * fee involved. The changes on the metadata are on the value `claimedAmountAfterTransfer` which is used to\n     * calculate `_claimableAmount`.\n     *\n     * @dev The math behind these changes can be explained by the following logic:\n     *\n     *     1) claimableAmount = (unlockedPercentage * startingAmount) / ONE - claimedAmount\n     *\n     * When there's a transfer of an amount, we transfer both locked and unlocked tokens so the\n     * `claimableAmountAfterTransfer` will look like:\n     *\n     *     2) claimableAmountAfterTransfer = claimableAmount ± claimableAmountOfTransfer\n     *\n     * Notice the ± symbol is because the `sender`'s `claimableAmount` is reduced while the `receiver`'s\n     * `claimableAmount` is increased.\n     *\n     *     3) claimableAmountOfTransfer = claimableAmountOfSender * amountOfTransfer / balanceOfSender\n     *\n     * We can expand 3) into:\n     *\n     *     4) claimableAmountOfTransfer =\n     *            (unlockedPercentage * ((startingAmountOfSender * amountOfTransfer) / balanceOfSender)) / ONE) -\n     *            ((claimedAmountOfSender * amountOfTransfer) / balanceOfSender)\n     *\n     * Notice how the structure of the equation is the same as 1) and 2 new variables can be created to calculate\n     * `claimableAmountOfTransfer`\n     *\n     *     a) startingAmountOfTransfer = (startingAmountOfSender * amountOfTransfer) / balanceOfSender\n     *     b) claimedAmountOfTransfer = (claimedAmountOfSender * amountOfTransfer) / balanceOfSender\n     *\n     * Replacing `claimableAmountOfTransfer` in equation 2) and expanding it, we get:\n     *\n     *     5) claimableAmountAfterTransfer =\n     *            ((unlockedPercentage * startingAmount) / ONE - claimedAmount) ±\n     *            ((unlockedPercentage * startingAmountOfTransfer) / ONE - claimedAmountOfTransfer)\n     *\n     * We can group similar variables like this:\n     *\n     *     6) claimableAmountAfterTransfer =\n     *            (unlockedPercentage * (startingAmount - startingAmountOfTransfer)) / ONE -\n     *            (claimedAmount - claimedAmountOfTransfer)\n     *\n     * This shows that the new values to calculate `claimableAmountAfterTransfer` if we want to continue using the\n     * equation 1) are:\n     *\n     *     c) startingAmountAfterTransfer =\n     *            startingAmount ±\n     *            (startingAmountOfSender * amountOfTransfer) / balanceOfSender\n     *     d) claimedAmountAfterTransfer =\n     *            claimedAmount ±\n     *            (claimedAmountOfSender * amountOfTransfer) / balanceOfSender\n     *\n     * Since these values depend linearly on the value of `amountOfTransfer`, and the fee is a fraction of the amount,\n     * we can just factor in the `transferFeePercentage` to get the values for the transfer to the `feeCollector`.\n     *\n     *     e) startingAmountOfFee = (startingAmountOfTransfer * transferFeePercentage) / ONE;\n     *     f) claimedAmountOfFee = (claimedAmountOfTransfer * transferFeePercentage) / ONE;\n     *\n     * If we look at equation 1) and set `unlockedPercentage` to ONE, then `claimableAmount` must equal to the\n     * `balance`. Therefore the relation between `startingAmount`, `claimedAmount`, and `balance` should be:\n     *\n     *     g) startingAmount = claimedAmount + balance\n     *\n     * Since we want to minimize independent rounding in all of the `startingAmount`s, and `claimedAmount`s we will\n     * calculate the `claimedAmount` using multiplication and division as shown in b) and f), and the `startingAmount`\n     * can be derived using a simple subtraction.\n     * With this we ensure that if there's a rounding down in the divisions, we won't be leaving any token locked.\n     *\n     * @param from       Address of sender.\n     * @param to         Address of recipient.\n     * @param amount     Amount of tokens.\n     * @param isTransfer If a fee is charged, this will let the function know whether to use `transfer` or\n     *                   `transferFrom` to collect the fee.\n     */\n    function _updateMetadataAndTransfer(address from, address to, uint256 amount, bool isTransfer) internal {\n        Metadata storage accountMetadata = _metadata[from];\n\n        // Calculate `claimedAmountOfTransfer` as described on equation b)\n        // uint256 can handle 78 digits well. Normally token transactions have 18 decimals that gives us 43 digits of\n        // wiggle room in the multiplication `(accountMetadata.claimedAmountAfterTransfer * amount)` without\n        // overflowing.\n        uint256 claimedAmountOfTransfer = (accountMetadata.claimedAmountAfterTransfer * amount) / balanceOf(from);\n\n        // Modify `claimedAmountAfterTransfer` of the sender following equation d)\n        // Notice in this case we are reducing the value\n        accountMetadata.claimedAmountAfterTransfer =\n            accountMetadata.claimedAmountAfterTransfer - claimedAmountOfTransfer;\n\n        if (to != from) {\n            (address feeCollector, uint64 transferFeePercentage) = manager.transferFeeData(address(underlyingToken));\n\n            if (transferFeePercentage != 0) {\n                // The values of `fee` and `claimedAmountOfFee` are calculated using the `transferFeePercentage` shown\n                // in equation f)\n                uint256 fee = (amount * transferFeePercentage);\n                unchecked {\n                    fee /= ONE;\n                }\n\n                uint256 claimedAmountOfFee = (claimedAmountOfTransfer * transferFeePercentage);\n                unchecked {\n                    claimedAmountOfFee /= ONE;\n                }\n\n                // The values for the receiver need to be updated accordingly\n                amount -= fee;\n                claimedAmountOfTransfer -= claimedAmountOfFee;\n\n                // Modify `claimedAmountAfterTransfer` of the feeCollector following equation d)\n                // Notice in this case we are increasing the value\n                _metadata[feeCollector].claimedAmountAfterTransfer =\n                    _metadata[feeCollector].claimedAmountAfterTransfer + claimedAmountOfFee;\n\n                if (isTransfer) {\n                    super.transfer(feeCollector, fee);\n                } else {\n                    super.transferFrom(from, feeCollector, fee);\n                }\n            }\n        }\n\n        // Modify `claimedAmountAfterTransfer` of the receiver following equation d)\n        // Notice in this case we are increasing the value\n        // The next line triggers the linter because it's not aware that super.transfer does not call an external\n        // contract, nor does trigger a fallback function.\n        // solhint-disable-next-line reentrancy\n        _metadata[to].claimedAmountAfterTransfer = _metadata[to].claimedAmountAfterTransfer + claimedAmountOfTransfer;\n\n        if (isTransfer) {\n            super.transfer(to, amount);\n        } else {\n            super.transferFrom(from, to, amount);\n        }\n    }\n\n    /// @notice Validates and initializes the VestingToken milestones.\n    /// @dev It will perform validations on the calldata:\n    /// @dev - Milestones have percentages and timestamps sorted in ascending order.\n    /// @dev - No more than 2 consecutive Milestones can have the same percentage.\n    /// @dev - 2 Milestones may have the same percentage as long as they are followed by a Milestone with a\n    /// `Ramp.Linear`.\n    /// @dev - Only the last Milestone should have 100% percentage.\n    function _setupMilestones(Milestone[] calldata milestonesArray) internal {\n        if (milestonesArray.length == 0) revert Errors.MinMilestonesNotReached();\n        if (milestonesArray.length > 826) revert Errors.MaxAllowedMilestonesHit();\n\n        Milestone calldata current = milestonesArray[0];\n        bool twoInARow;\n        uint256 milestonesLen = milestonesArray.length;\n        for (uint256 i; i < milestonesLen;) {\n            if (i != 0) {\n                Milestone calldata previous = current;\n                current = milestonesArray[i];\n\n                if (previous.timestamp >= current.timestamp) revert Errors.MilestoneTimestampsNotSorted();\n                if (previous.percentage > current.percentage) revert Errors.MilestonePercentagesNotSorted();\n\n                if (twoInARow) {\n                    if (previous.percentage == current.percentage) revert Errors.MoreThanTwoEqualPercentages();\n                    if (current.ramp != Ramp.Linear) revert Errors.EqualPercentagesOnlyAllowedBeforeLinear();\n                }\n\n                twoInARow = previous.percentage == current.percentage;\n            }\n\n            if (i == milestonesLen - 1) {\n                if (current.percentage != ONE) revert Errors.LastPercentageMustBe100();\n            } else {\n                if (current.percentage == ONE) revert Errors.OnlyLastPercentageCanBe100();\n            }\n\n            _milestones.push(current);\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /// @dev Perform a staticcall to attempt to fetch `underlyingToken`'s decimals. In case of an error, we default to\n    /// 18.\n    function _tryFetchDecimals() internal view returns (uint8) {\n        (bool success, bytes memory encodedDecimals) =\n            address(underlyingToken).staticcall(abi.encodeWithSelector(ERC20Upgradeable.decimals.selector));\n\n        if (success && encodedDecimals.length >= 32) {\n            uint256 returnedDecimals;\n            assembly {\n                // Since `encodedDecimals` is a dynamic array, its first 32 bytes store the data's length\n                returnedDecimals := mload(add(encodedDecimals, 32))\n            }\n\n            // type(uint8).max => 255\n            if (returnedDecimals <= 255) {\n                return uint8(returnedDecimals);\n            }\n        }\n\n        return 18;\n    }\n\n    /// @dev Perform a staticcall to attempt to fetch `underlyingToken`'s balance of this contract. In case of an error,\n    /// reverts with custom `UnsuccessfulFetchOfTokenBalance` error.\n    function _getBalanceOfThis() internal view returns (uint256 returnedBalance) {\n        (bool success, bytes memory encodedBalance) = address(underlyingToken).staticcall(\n            abi.encodeWithSelector(ERC20Upgradeable.balanceOf.selector, address(this))\n        );\n\n        if (success && encodedBalance.length >= 32) {\n            assembly {\n                // Since `encodedBalance` is a dynamic array, its first 32 bytes store the data's length\n                returnedBalance := mload(add(encodedBalance, 32))\n            }\n            return returnedBalance;\n        }\n\n        revert Errors.UnsuccessfulFetchOfTokenBalance();\n    }\n\n    /// @notice This method is used to infer the value of claimed amounts.\n    ///\n    /// @dev If the unlocked percentage has already reached 100%, there's no way to infer the claimed amount.\n    ///\n    /// @param amount                  Amount of `underlyingToken` in the transaction.\n    /// @param claimableAmountOfImport Amount of `underlyingToken` from this transaction that should be considered\n    /// claimable.\n    /// @param unlocked                The unlocked percentage value at the time of the export of this transaction.\n    ///\n    /// @return Amount of `underlyingToken` that has been claimed based on the arguments given.\n    function _claimedAmount(\n        uint256 amount,\n        uint256 claimableAmountOfImport,\n        uint256 unlocked\n    )\n        internal\n        pure\n        returns (uint256)\n    {\n        if (unlocked == ONE) return 0;\n\n        uint256 a = unlocked * amount;\n        uint256 b = ONE * claimableAmountOfImport;\n        // If `a - b` underflows, we display a better error message.\n        if (b > a) revert Errors.ClaimableAmountOfImportIsGreaterThanExpected();\n        return (a - b) / (ONE - unlocked);\n    }\n\n    /// @param startingAmount Amount of `underlyingToken` originally held.\n    /// @param claimedAmount  Amount of `underlyingToken` already claimed.\n    ///\n    /// @return Amount of `underlyingToken` that can be claimed based on the milestones reached and initial amounts\n    /// given.\n    function _claimableAmount(uint256 startingAmount, uint256 claimedAmount) internal view returns (uint256) {\n        uint256 unlocked = (unlockedPercentage() * startingAmount);\n        unchecked {\n            unlocked /= ONE;\n        }\n\n        return unlocked < claimedAmount ? 0 : unlocked - claimedAmount;\n    }\n\n    /// @notice Processes the claim fee for a transaction.\n    /// @dev This function retrieves the claim fee data from the manager contract and, if the claim fee is greater than\n    /// zero, sends the `msg.value` to the fee collector address. Reverts if the transferred value is less than the\n    /// required claim fee or if the transfer fails.\n    function _processClaimFee() private {\n        (address feeCollector, uint64 claimFeeValue) = manager.claimFeeData(address(underlyingToken));\n\n        if (claimFeeValue != 0) {\n            if (msg.value != claimFeeValue) revert Errors.IncorrectClaimFee();\n\n            bytes4 unsuccessfulClaimFeeTransfer = Errors.UnsuccessfulClaimFeeTransfer.selector;\n\n            assembly {\n                let ptr := mload(0x40)\n                let sendSuccess := call(gas(), feeCollector, callvalue(), 0x00, 0x00, 0x00, 0x00)\n                if iszero(sendSuccess) {\n                    mstore(ptr, unsuccessfulClaimFeeTransfer)\n                    revert(ptr, 0x04)\n                }\n            }\n        }\n    }\n}\n"
      },
      "src/interfaces/IFeeManager.sol": {
        "content": "// SPDX-License-Identifier: None\n// Unvest Contracts (last updated v3.0.0) (interfaces/IFeeManager.sol)\npragma solidity ^0.8.24;\n\n/// @title IFeeManager\n/// @dev Interface that describes the struct and accessor function for the data related to the collection of fees.\ninterface IFeeManager {\n    /// @dev The `FeeData` struct is used to store fee configurations such as the collection address and fee amounts for\n    /// various transaction types in the contract.\n    struct FeeData {\n        /// @notice The address designated to collect fees.\n        /// @dev This address is responsible for receiving fees generated from various sources.\n        address feeCollector;\n        /// @notice The fixed fee amount required to be sent as value with each `createVestingToken` operation.\n        /// @dev `creationFee` is denominated in the smallest unit of the token. It must be sent as the transaction\n        /// value during the execution of the payable `createVestingToken` function.\n        uint64 creationFee;\n        /// @notice The transfer fee expressed in ether, where 0.01 ether corresponds to a 1% fee.\n        /// @dev `transferFeePercentage` is not in basis points but in ether units, with each ether unit representing a\n        /// percentage of the transaction value to be collected as a fee. This structure allows for flexible and easily\n        /// understandable fee calculations for `transfer` and `transferFrom` operations.\n        uint64 transferFeePercentage;\n        /// @notice The fixed fee amount required to be sent as value with each `claim` operation.\n        /// @dev `claimFee` is denominated in the smallest unit of the token. It must be sent as the transaction value\n        /// during the execution of the payable `claim` function.\n        uint64 claimFee;\n    }\n\n    /// @dev Stores global fee data upcoming change and timestamp for that change.\n    struct UpcomingFeeData {\n        /// @notice The new fee value in wei to be applied at `valueChangeAt`.\n        uint64 nextValue;\n        /// @notice Timestamp at which a new fee value becomes effective.\n        uint64 valueChangeAt;\n    }\n\n    /// @dev Stores custom fee data, including its current state, upcoming changes, and the timestamps for those\n    /// changes.\n    struct CustomFeeData {\n        /// @notice Indicates if the custom fee is currently enabled.\n        bool isEnabled;\n        /// @notice The current fee value in wei.\n        uint64 value;\n        /// @notice The new fee value in wei to be applied at `valueChangeAt`.\n        uint64 nextValue;\n        /// @notice Timestamp at which a new fee value becomes effective.\n        uint64 valueChangeAt;\n        /// @notice Indicates the future state of `isEnabled` after `statusChangeAt`.\n        bool nextEnableState;\n        /// @notice Timestamp at which the change to `isEnabled` becomes effective.\n        uint64 statusChangeAt;\n    }\n\n    /// @notice Exposes the creation fee for new `VestingToken`s deployments.\n    /// @param underlyingToken Address of the `underlyingToken`.\n    /// @dev Enabled custom fees overrides the global creation fee.\n    function creationFeeData(address underlyingToken)\n        external\n        view\n        returns (address feeCollector, uint64 creationFeeValue);\n\n    /// @notice Exposes the transfer fee for `VestingToken`s to consume.\n    /// @param underlyingToken Address of the `underlyingToken`.\n    /// @dev Enabled custom fees overrides the global transfer fee.\n    function transferFeeData(address underlyingToken)\n        external\n        view\n        returns (address feeCollector, uint64 transferFeePercentage);\n\n    /// @notice Exposes the claim fee for `VestingToken`s to consume.\n    /// @param underlyingToken Address of the `underlyingToken`.\n    /// @dev Enabled custom fees overrides the global claim fee.\n    function claimFeeData(address underlyingToken) external view returns (address feeCollector, uint64 claimFeeValue);\n}\n"
      },
      "src/interfaces/IVestingToken.sol": {
        "content": "// SPDX-License-Identifier: None\n// Unvest Contracts (last updated v3.0.0) (interfaces/IVestingToken.sol)\npragma solidity ^0.8.24;\n\n/// @title IVestingToken\n/// @dev Interface that describes the Milestone struct and initialize function so the `VestingTokenFactory` knows how to\n/// initialize the `VestingToken`.\ninterface IVestingToken {\n    /// @dev Ramps describes how the periods between release tokens.\n    ///     - Cliff releases nothing until the end of the period.\n    ///     - Linear releases tokens every second according to a linear slope.\n    ///\n    /// (0) Cliff             (1) Linear\n    ///  |                     |\n    ///  |        _____        |        _____\n    ///  |       |             |       /\n    ///  |       |             |      /\n    ///  |_______|_____        |_____/_______\n    ///      T0   T1               T0   T1\n    ///\n    enum Ramp {\n        Cliff,\n        Linear\n    }\n\n    /// @dev `timestamp` represents a moment in time when this Milestone is considered expired.\n    /// @dev `ramp` defines the behaviour of the release of tokens in period between the previous Milestone and the\n    /// current one.\n    /// @dev `percentage` is the percentage of tokens that should be released once this Milestone has expired.\n    struct Milestone {\n        uint64 timestamp;\n        Ramp ramp;\n        uint64 percentage;\n    }\n\n    /// @notice Initializes the contract by setting up the ERC20 variables, the `underlyingToken`, and the\n    /// `milestonesArray` information.\n    ///\n    /// @param name                   The token collection name.\n    /// @param symbol                 The token collection symbol.\n    /// @param underlyingTokenAddress The ERC20 token that will be held by this contract.\n    /// @param milestonesArray        Array of all Milestones for this Contract's lifetime.\n    function initialize(\n        string memory name,\n        string memory symbol,\n        address underlyingTokenAddress,\n        Milestone[] calldata milestonesArray\n    )\n        external;\n}\n"
      },
      "src/libraries/Arrays.sol": {
        "content": "// SPDX-License-Identifier: None\n// Unvest Contracts (last updated v3.0.0) (libraries/Arrays.sol)\npragma solidity ^0.8.24;\n\n/**\n * @dev Collection of functions related to array types.\n * @dev This is an extract from OpenZeppelin Arrays util contract.\n */\nlibrary Arrays {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    /// @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n    function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /// @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n    function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /// @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n    function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n}\n"
      },
      "src/libraries/Errors.sol": {
        "content": "// SPDX-License-Identifier: None\n// Unvest Contracts (last updated v3.0.0) (libraries/Errors.sol)\npragma solidity ^0.8.24;\n\n/// @title Errors Library\n/// @notice Provides custom errors for VestingTokenFactory and VestingToken contracts.\nlibrary Errors {\n    /*//////////////////////////////////////////////////////\n                      VestingTokenFactory\n    //////////////////////////////////////////////////////*/\n\n    /// @notice Error to indicate that an address cannot be the zero address.\n    error AddressCanNotBeZero();\n\n    /// @notice Error to indicate that deployment of a contract failed.\n    error FailedToDeploy();\n\n    /// @notice Error to indicate that a fee is out of the accepted range.\n    error FeeOutOfRange();\n\n    /// @notice Error to indicate that the creation fee is insufficient.\n    error InsufficientCreationFee();\n\n    /// @notice Error to indicate an unsuccessful transfer of the creation fee.\n    error UnsuccessfulCreationFeeTransfer();\n\n    /*//////////////////////////////////////////////////////\n                      VestingToken\n    //////////////////////////////////////////////////////*/\n\n    /// @notice Error to indicate that the minimum number of milestones has not been reached.\n    error MinMilestonesNotReached();\n\n    /// @notice Error to indicate that the maximum number of milestones has been exceeded.\n    error MaxAllowedMilestonesHit();\n\n    /// @notice Error to indicate that the claimable amount of an import is greater than expected.\n    error ClaimableAmountOfImportIsGreaterThanExpected();\n\n    /// @notice Error to indicate that equal percentages are only allowed before setting up linear milestones.\n    error EqualPercentagesOnlyAllowedBeforeLinear();\n\n    /// @notice Error to indicate that the sum of all individual amounts is not equal to the `totalAmount`.\n    error InvalidTotalAmount();\n\n    /// @notice Error to indicate that input arrays must have the same length.\n    error InputArraysMustHaveSameLength();\n\n    /// @notice Error to indicate that the last percentage in a milestone must be 100.\n    error LastPercentageMustBe100();\n\n    /// @notice Error to indicate that milestone percentages are not sorted in ascending order.\n    error MilestonePercentagesNotSorted();\n\n    /// @notice Error to indicate that milestone timestamps are not sorted in ascending chronological order.\n    error MilestoneTimestampsNotSorted();\n\n    /// @notice Error to indicate that there are more than two equal percentages, which is not allowed.\n    error MoreThanTwoEqualPercentages();\n\n    /// @notice Error to indicate that only the last percentage in a series can be 100.\n    error OnlyLastPercentageCanBe100();\n\n    /// @notice Error to indicate that the amount unlocked is greater than expected.\n    error UnlockedIsGreaterThanExpected();\n\n    /// @notice Error to indicate an unsuccessful fetch of token balance.\n    error UnsuccessfulFetchOfTokenBalance();\n\n    /// @notice Error to indicate that the claim fee provided does not match the expected claim fee.\n    error IncorrectClaimFee();\n\n    /// @notice Error to indicate an unsuccessful transfer of the claim fee.\n    error UnsuccessfulClaimFeeTransfer();\n\n    /// @notice Error to indicate that there is no balance available to claim.\n    error NoClaimableAmount();\n}\n"
      }
    }
  }}