creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControlUpgradeable {\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     *\n     * _Available since v3.1._\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) external;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\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 Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 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 functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\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 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\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        require(_initializing, \"Initializable: contract is not initializing\");\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        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _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 _initializing;\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../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    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\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        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\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        return _status == _ENTERED;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\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"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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 amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `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 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\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, it is bubbled up by this\n     * function (like regular Solidity function calls).\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     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\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     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../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    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMathUpgradeable {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/MathUpgradeable.sol\";\nimport \"./math/SignedMathUpgradeable.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n    uint8 private constant _ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = MathUpgradeable.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toString(int256 value) internal pure returns (string memory) {\n        return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMathUpgradeable.abs(value))));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, MathUpgradeable.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\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 amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `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 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/utils/introspection/ERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "contracts/interfaces/ethena/ISUSDe.sol": {
        "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.17;\n\ninterface ISUSDe {\n    function convertToAssets(uint256 shares) external view returns (uint256);\n}\n"
      },
      "contracts/interfaces/IChainlinkV3Aggregator.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.17;\n\ninterface IChainlinkV3Aggregator {\n    function decimals() external view returns (uint8);\n\n    function latestRoundData()\n        external\n        view\n        returns (\n            uint80 roundId,\n            int256 answer,\n            uint256 startedAt,\n            uint256 updatedAt,\n            uint80 answeredInRound\n        );\n}\n"
      },
      "contracts/interfaces/pendle/IPendlePtOracle.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\r\npragma solidity 0.8.17;\r\n\r\ninterface IPendlePtOracle {\r\n    function getOracleState(\r\n        address market,\r\n        uint32 duration\r\n    )\r\n        external\r\n        view\r\n        returns (\r\n            bool increaseCardinalityRequired,\r\n            uint16 cardinalityRequired,\r\n            bool oldestObservationSatisfied\r\n        );\r\n\r\n    function getPtToAssetRate(\r\n        address market,\r\n        uint32 duration\r\n    ) external view returns (uint256 ptToAssetRate);\r\n\r\n    function getLpToAssetRate(\r\n        address market,\r\n        uint32 duration\r\n    ) external view returns (uint256 ptToAssetRate);\r\n}\r\n"
      },
      "contracts/interfaces/pendle/IPMarket.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\r\npragma solidity 0.8.17;\r\n\r\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\r\n\r\nimport '../../libraries/pendle/MarketMathCore.sol';\r\nimport {IPPrincipalToken} from './IPPrincipalToken.sol';\r\nimport {IPYieldToken} from './IPYieldToken.sol';\r\nimport {IStandardizedYield} from './IStandardizedYield.sol';\r\n\r\ninterface IPMarket is IERC20 {\r\n    event Mint(\r\n        address indexed receiver,\r\n        uint256 netLpMinted,\r\n        uint256 netSyUsed,\r\n        uint256 netPtUsed\r\n    );\r\n\r\n    event Burn(\r\n        address indexed receiverSy,\r\n        address indexed receiverPt,\r\n        uint256 netLpBurned,\r\n        uint256 netSyOut,\r\n        uint256 netPtOut\r\n    );\r\n\r\n    event Swap(\r\n        address indexed caller,\r\n        address indexed receiver,\r\n        int256 netPtOut,\r\n        int256 netSyOut,\r\n        uint256 netSyFee,\r\n        uint256 netSyToReserve\r\n    );\r\n\r\n    event UpdateImpliedRate(\r\n        uint256 indexed timestamp,\r\n        uint256 lnLastImpliedRate\r\n    );\r\n\r\n    event IncreaseObservationCardinalityNext(\r\n        uint16 observationCardinalityNextOld,\r\n        uint16 observationCardinalityNextNew\r\n    );\r\n\r\n    function mint(\r\n        address receiver,\r\n        uint256 netSyDesired,\r\n        uint256 netPtDesired\r\n    ) external returns (uint256 netLpOut, uint256 netSyUsed, uint256 netPtUsed);\r\n\r\n    function burn(\r\n        address receiverSy,\r\n        address receiverPt,\r\n        uint256 netLpToBurn\r\n    ) external returns (uint256 netSyOut, uint256 netPtOut);\r\n\r\n    function swapExactPtForSy(\r\n        address receiver,\r\n        uint256 exactPtIn,\r\n        bytes calldata data\r\n    ) external returns (uint256 netSyOut, uint256 netSyFee);\r\n\r\n    function swapSyForExactPt(\r\n        address receiver,\r\n        uint256 exactPtOut,\r\n        bytes calldata data\r\n    ) external returns (uint256 netSyIn, uint256 netSyFee);\r\n\r\n    function redeemRewards(address user) external returns (uint256[] memory);\r\n\r\n    function readState(\r\n        address router\r\n    ) external view returns (MarketState memory market);\r\n\r\n    function observe(\r\n        uint32[] memory secondsAgos\r\n    ) external view returns (uint216[] memory lnImpliedRateCumulative);\r\n\r\n    function increaseObservationsCardinalityNext(\r\n        uint16 cardinalityNext\r\n    ) external;\r\n\r\n    function readTokens()\r\n        external\r\n        view\r\n        returns (\r\n            IStandardizedYield _SY,\r\n            IPPrincipalToken _PT,\r\n            IPYieldToken _YT\r\n        );\r\n\r\n    function getRewardTokens() external view returns (address[] memory);\r\n\r\n    function isExpired() external view returns (bool);\r\n\r\n    function expiry() external view returns (uint256);\r\n\r\n    function observations(\r\n        uint256 index\r\n    )\r\n        external\r\n        view\r\n        returns (\r\n            uint32 blockTimestamp,\r\n            uint216 lnImpliedRateCumulative,\r\n            bool initialized\r\n        );\r\n\r\n    function _storage()\r\n        external\r\n        view\r\n        returns (\r\n            int128 totalPt,\r\n            int128 totalSy,\r\n            uint96 lastLnImpliedRate,\r\n            uint16 observationIndex,\r\n            uint16 observationCardinality,\r\n            uint16 observationCardinalityNext\r\n        );\r\n}\r\n"
      },
      "contracts/interfaces/pendle/IPPrincipalToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\r\npragma solidity 0.8.17;\r\n\r\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\r\n\r\ninterface IPPrincipalToken is IERC20 {\r\n    function burnByYT(address user, uint256 amount) external;\r\n\r\n    function mintByYT(address user, uint256 amount) external;\r\n\r\n    function initialize(address _YT) external;\r\n\r\n    function SY() external view returns (address);\r\n\r\n    function YT() external view returns (address);\r\n\r\n    function factory() external view returns (address);\r\n\r\n    function expiry() external view returns (uint256);\r\n\r\n    function isExpired() external view returns (bool);\r\n}\r\n"
      },
      "contracts/interfaces/pendle/IPYieldToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\r\npragma solidity 0.8.17;\r\n\r\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\r\n\r\ninterface IPYieldToken is IERC20 {\r\n    event NewInterestIndex(uint256 indexed newIndex);\r\n\r\n    event Mint(\r\n        address indexed caller,\r\n        address indexed receiverPT,\r\n        address indexed receiverYT,\r\n        uint256 amountSyToMint,\r\n        uint256 amountPYOut\r\n    );\r\n\r\n    event Burn(\r\n        address indexed caller,\r\n        address indexed receiver,\r\n        uint256 amountPYToRedeem,\r\n        uint256 amountSyOut\r\n    );\r\n\r\n    event RedeemRewards(address indexed user, uint256[] amountRewardsOut);\r\n\r\n    event RedeemInterest(address indexed user, uint256 interestOut);\r\n\r\n    event WithdrawFeeToTreasury(uint256[] amountRewardsOut, uint256 syOut);\r\n\r\n    function mintPY(\r\n        address receiverPT,\r\n        address receiverYT\r\n    ) external returns (uint256 amountPYOut);\r\n\r\n    function redeemPY(address receiver) external returns (uint256 amountSyOut);\r\n\r\n    function redeemPYMulti(\r\n        address[] calldata receivers,\r\n        uint256[] calldata amountPYToRedeems\r\n    ) external returns (uint256[] memory amountSyOuts);\r\n\r\n    function redeemDueInterestAndRewards(\r\n        address user,\r\n        bool redeemInterest,\r\n        bool redeemRewards\r\n    ) external returns (uint256 interestOut, uint256[] memory rewardsOut);\r\n\r\n    function rewardIndexesCurrent() external returns (uint256[] memory);\r\n\r\n    function pyIndexCurrent() external returns (uint256);\r\n\r\n    function pyIndexStored() external view returns (uint256);\r\n\r\n    function getRewardTokens() external view returns (address[] memory);\r\n\r\n    function SY() external view returns (address);\r\n\r\n    function PT() external view returns (address);\r\n\r\n    function factory() external view returns (address);\r\n\r\n    function expiry() external view returns (uint256);\r\n\r\n    function isExpired() external view returns (bool);\r\n\r\n    function doCacheIndexSameBlock() external view returns (bool);\r\n\r\n    function pyIndexLastUpdatedBlock() external view returns (uint128);\r\n}\r\n"
      },
      "contracts/interfaces/pendle/IStandardizedYield.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\r\npragma solidity 0.8.17;\r\n\r\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\r\n\r\ninterface IStandardizedYield is IERC20 {\r\n    /// @dev Emitted when any base tokens is deposited to mint shares\r\n    event Deposit(\r\n        address indexed caller,\r\n        address indexed receiver,\r\n        address indexed tokenIn,\r\n        uint256 amountDeposited,\r\n        uint256 amountSyOut\r\n    );\r\n\r\n    /// @dev Emitted when any shares are redeemed for base tokens\r\n    event Redeem(\r\n        address indexed caller,\r\n        address indexed receiver,\r\n        address indexed tokenOut,\r\n        uint256 amountSyToRedeem,\r\n        uint256 amountTokenOut\r\n    );\r\n\r\n    /// @dev check `assetInfo()` for more information\r\n    enum AssetType {\r\n        TOKEN,\r\n        LIQUIDITY\r\n    }\r\n\r\n    /// @dev Emitted when (`user`) claims their rewards\r\n    event ClaimRewards(\r\n        address indexed user,\r\n        address[] rewardTokens,\r\n        uint256[] rewardAmounts\r\n    );\r\n\r\n    /**\r\n     * @notice mints an amount of shares by depositing a base token.\r\n     * @param receiver shares recipient address\r\n     * @param tokenIn address of the base tokens to mint shares\r\n     * @param amountTokenToDeposit amount of base tokens to be transferred from (`msg.sender`)\r\n     * @param minSharesOut reverts if amount of shares minted is lower than this\r\n     * @return amountSharesOut amount of shares minted\r\n     * @dev Emits a {Deposit} event\r\n     *\r\n     * Requirements:\r\n     * - (`tokenIn`) must be a valid base token.\r\n     */\r\n    function deposit(\r\n        address receiver,\r\n        address tokenIn,\r\n        uint256 amountTokenToDeposit,\r\n        uint256 minSharesOut\r\n    ) external payable returns (uint256 amountSharesOut);\r\n\r\n    /**\r\n     * @notice redeems an amount of base tokens by burning some shares\r\n     * @param receiver recipient address\r\n     * @param amountSharesToRedeem amount of shares to be burned\r\n     * @param tokenOut address of the base token to be redeemed\r\n     * @param minTokenOut reverts if amount of base token redeemed is lower than this\r\n     * @param burnFromInternalBalance if true, burns from balance of `address(this)`, otherwise burns from `msg.sender`\r\n     * @return amountTokenOut amount of base tokens redeemed\r\n     * @dev Emits a {Redeem} event\r\n     *\r\n     * Requirements:\r\n     * - (`tokenOut`) must be a valid base token.\r\n     */\r\n    function redeem(\r\n        address receiver,\r\n        uint256 amountSharesToRedeem,\r\n        address tokenOut,\r\n        uint256 minTokenOut,\r\n        bool burnFromInternalBalance\r\n    ) external returns (uint256 amountTokenOut);\r\n\r\n    /**\r\n     * @notice exchangeRate * syBalance / 1e18 must return the asset balance of the account\r\n     * @notice vice-versa, if a user uses some amount of tokens equivalent to X asset, the amount of sy\r\n     he can mint must be X * exchangeRate / 1e18\r\n     * @dev SYUtils's assetToSy & syToAsset should be used instead of raw multiplication\r\n     & division\r\n     */\r\n    function exchangeRate() external view returns (uint256 res);\r\n\r\n    /**\r\n     * @notice claims reward for (`user`)\r\n     * @param user the user receiving their rewards\r\n     * @return rewardAmounts an array of reward amounts in the same order as `getRewardTokens`\r\n     * @dev\r\n     * Emits a `ClaimRewards` event\r\n     * See {getRewardTokens} for list of reward tokens\r\n     */\r\n    function claimRewards(\r\n        address user\r\n    ) external returns (uint256[] memory rewardAmounts);\r\n\r\n    /**\r\n     * @notice get the amount of unclaimed rewards for (`user`)\r\n     * @param user the user to check for\r\n     * @return rewardAmounts an array of reward amounts in the same order as `getRewardTokens`\r\n     */\r\n    function accruedRewards(\r\n        address user\r\n    ) external view returns (uint256[] memory rewardAmounts);\r\n\r\n    function rewardIndexesCurrent() external returns (uint256[] memory indexes);\r\n\r\n    function rewardIndexesStored()\r\n        external\r\n        view\r\n        returns (uint256[] memory indexes);\r\n\r\n    /**\r\n     * @notice returns the list of reward token addresses\r\n     */\r\n    function getRewardTokens() external view returns (address[] memory);\r\n\r\n    /**\r\n     * @notice returns the address of the underlying yield token\r\n     */\r\n    function yieldToken() external view returns (address);\r\n\r\n    /**\r\n     * @notice returns all tokens that can mint this SY\r\n     */\r\n    function getTokensIn() external view returns (address[] memory res);\r\n\r\n    /**\r\n     * @notice returns all tokens that can be redeemed by this SY\r\n     */\r\n    function getTokensOut() external view returns (address[] memory res);\r\n\r\n    function isValidTokenIn(address token) external view returns (bool);\r\n\r\n    function isValidTokenOut(address token) external view returns (bool);\r\n\r\n    function previewDeposit(\r\n        address tokenIn,\r\n        uint256 amountTokenToDeposit\r\n    ) external view returns (uint256 amountSharesOut);\r\n\r\n    function previewRedeem(\r\n        address tokenOut,\r\n        uint256 amountSharesToRedeem\r\n    ) external view returns (uint256 amountTokenOut);\r\n\r\n    /**\r\n     * @notice This function contains information to interpret what the asset is\r\n     * @return assetType the type of the asset (0 for ERC20 tokens, 1 for AMM liquidity tokens,\r\n        2 for bridged yield bearing tokens like wstETH, rETH on Arbi whose the underlying asset doesn't exist on the chain)\r\n     * @return assetAddress the address of the asset\r\n     * @return assetDecimals the decimals of the asset\r\n     */\r\n    function assetInfo()\r\n        external\r\n        view\r\n        returns (\r\n            AssetType assetType,\r\n            address assetAddress,\r\n            uint8 assetDecimals\r\n        );\r\n}\r\n"
      },
      "contracts/interfaces/uniswapV3/IUniswapV3StaticOracle.sol": {
        "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.17;\n\ninterface IUniswapV3StaticOracle {\n    function quoteSpecificFeeTiersWithTimePeriod(\n        uint128 _baseAmount,\n        address _baseToken,\n        address _quoteToken,\n        uint24[] calldata _feeTiers,\n        uint32 _period\n    )\n        external\n        view\n        returns (uint256 _quoteAmount, address[] memory _queriedPools);\n}\n"
      },
      "contracts/libraries/pendle/Errors.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\r\npragma solidity 0.8.17;\r\n\r\nlibrary Errors {\r\n    // BulkSeller\r\n    error BulkInsufficientSyForTrade(\r\n        uint256 currentAmount,\r\n        uint256 requiredAmount\r\n    );\r\n    error BulkInsufficientTokenForTrade(\r\n        uint256 currentAmount,\r\n        uint256 requiredAmount\r\n    );\r\n    error BulkInSufficientSyOut(uint256 actualSyOut, uint256 requiredSyOut);\r\n    error BulkInSufficientTokenOut(\r\n        uint256 actualTokenOut,\r\n        uint256 requiredTokenOut\r\n    );\r\n    error BulkInsufficientSyReceived(\r\n        uint256 actualBalance,\r\n        uint256 requiredBalance\r\n    );\r\n    error BulkNotMaintainer();\r\n    error BulkNotAdmin();\r\n    error BulkSellerAlreadyExisted(address token, address SY, address bulk);\r\n    error BulkSellerInvalidToken(address token, address SY);\r\n    error BulkBadRateTokenToSy(\r\n        uint256 actualRate,\r\n        uint256 currentRate,\r\n        uint256 eps\r\n    );\r\n    error BulkBadRateSyToToken(\r\n        uint256 actualRate,\r\n        uint256 currentRate,\r\n        uint256 eps\r\n    );\r\n\r\n    // APPROX\r\n    error ApproxFail();\r\n    error ApproxParamsInvalid(uint256 guessMin, uint256 guessMax, uint256 eps);\r\n    error ApproxBinarySearchInputInvalid(\r\n        uint256 approxGuessMin,\r\n        uint256 approxGuessMax,\r\n        uint256 minGuessMin,\r\n        uint256 maxGuessMax\r\n    );\r\n\r\n    // MARKET + MARKET MATH CORE\r\n    error MarketExpired();\r\n    error MarketZeroAmountsInput();\r\n    error MarketZeroAmountsOutput();\r\n    error MarketZeroLnImpliedRate();\r\n    error MarketInsufficientPtForTrade(\r\n        int256 currentAmount,\r\n        int256 requiredAmount\r\n    );\r\n    error MarketInsufficientPtReceived(\r\n        uint256 actualBalance,\r\n        uint256 requiredBalance\r\n    );\r\n    error MarketInsufficientSyReceived(\r\n        uint256 actualBalance,\r\n        uint256 requiredBalance\r\n    );\r\n    error MarketZeroTotalPtOrTotalAsset(int256 totalPt, int256 totalAsset);\r\n    error MarketExchangeRateBelowOne(int256 exchangeRate);\r\n    error MarketProportionMustNotEqualOne();\r\n    error MarketRateScalarBelowZero(int256 rateScalar);\r\n    error MarketScalarRootBelowZero(int256 scalarRoot);\r\n    error MarketProportionTooHigh(int256 proportion, int256 maxProportion);\r\n\r\n    error OracleUninitialized();\r\n    error OracleTargetTooOld(uint32 target, uint32 oldest);\r\n    error OracleZeroCardinality();\r\n\r\n    error MarketFactoryExpiredPt();\r\n    error MarketFactoryInvalidPt();\r\n    error MarketFactoryMarketExists();\r\n\r\n    error MarketFactoryLnFeeRateRootTooHigh(\r\n        uint80 lnFeeRateRoot,\r\n        uint256 maxLnFeeRateRoot\r\n    );\r\n    error MarketFactoryReserveFeePercentTooHigh(\r\n        uint8 reserveFeePercent,\r\n        uint8 maxReserveFeePercent\r\n    );\r\n    error MarketFactoryZeroTreasury();\r\n    error MarketFactoryInitialAnchorTooLow(\r\n        int256 initialAnchor,\r\n        int256 minInitialAnchor\r\n    );\r\n\r\n    // ROUTER\r\n    error RouterInsufficientLpOut(uint256 actualLpOut, uint256 requiredLpOut);\r\n    error RouterInsufficientSyOut(uint256 actualSyOut, uint256 requiredSyOut);\r\n    error RouterInsufficientPtOut(uint256 actualPtOut, uint256 requiredPtOut);\r\n    error RouterInsufficientYtOut(uint256 actualYtOut, uint256 requiredYtOut);\r\n    error RouterInsufficientPYOut(uint256 actualPYOut, uint256 requiredPYOut);\r\n    error RouterInsufficientTokenOut(\r\n        uint256 actualTokenOut,\r\n        uint256 requiredTokenOut\r\n    );\r\n    error RouterExceededLimitSyIn(uint256 actualSyIn, uint256 limitSyIn);\r\n    error RouterExceededLimitPtIn(uint256 actualPtIn, uint256 limitPtIn);\r\n    error RouterExceededLimitYtIn(uint256 actualYtIn, uint256 limitYtIn);\r\n    error RouterInsufficientSyRepay(\r\n        uint256 actualSyRepay,\r\n        uint256 requiredSyRepay\r\n    );\r\n    error RouterInsufficientPtRepay(\r\n        uint256 actualPtRepay,\r\n        uint256 requiredPtRepay\r\n    );\r\n    error RouterNotAllSyUsed(uint256 netSyDesired, uint256 netSyUsed);\r\n\r\n    error RouterTimeRangeZero();\r\n    error RouterCallbackNotPendleMarket(address caller);\r\n    error RouterInvalidAction(bytes4 selector);\r\n    error RouterInvalidFacet(address facet);\r\n\r\n    error RouterKyberSwapDataZero();\r\n\r\n    // YIELD CONTRACT\r\n    error YCExpired();\r\n    error YCNotExpired();\r\n    error YieldContractInsufficientSy(uint256 actualSy, uint256 requiredSy);\r\n    error YCNothingToRedeem();\r\n    error YCPostExpiryDataNotSet();\r\n    error YCNoFloatingSy();\r\n\r\n    // YieldFactory\r\n    error YCFactoryInvalidExpiry();\r\n    error YCFactoryYieldContractExisted();\r\n    error YCFactoryZeroExpiryDivisor();\r\n    error YCFactoryZeroTreasury();\r\n    error YCFactoryInterestFeeRateTooHigh(\r\n        uint256 interestFeeRate,\r\n        uint256 maxInterestFeeRate\r\n    );\r\n    error YCFactoryRewardFeeRateTooHigh(\r\n        uint256 newRewardFeeRate,\r\n        uint256 maxRewardFeeRate\r\n    );\r\n\r\n    // SY\r\n    error SYInvalidTokenIn(address token);\r\n    error SYInvalidTokenOut(address token);\r\n    error SYZeroDeposit();\r\n    error SYZeroRedeem();\r\n    error SYInsufficientSharesOut(\r\n        uint256 actualSharesOut,\r\n        uint256 requiredSharesOut\r\n    );\r\n    error SYInsufficientTokenOut(\r\n        uint256 actualTokenOut,\r\n        uint256 requiredTokenOut\r\n    );\r\n\r\n    // SY-specific\r\n    error SYQiTokenMintFailed(uint256 errCode);\r\n    error SYQiTokenRedeemFailed(uint256 errCode);\r\n    error SYQiTokenRedeemRewardsFailed(\r\n        uint256 rewardAccruedType0,\r\n        uint256 rewardAccruedType1\r\n    );\r\n    error SYQiTokenBorrowRateTooHigh(uint256 borrowRate, uint256 borrowRateMax);\r\n\r\n    error SYCurveInvalidPid();\r\n    error SYCurve3crvPoolNotFound();\r\n\r\n    error SYApeDepositAmountTooSmall(uint256 amountDeposited);\r\n    error SYBalancerInvalidPid();\r\n    error SYInvalidRewardToken(address token);\r\n\r\n    error SYStargateRedeemCapExceeded(\r\n        uint256 amountLpDesired,\r\n        uint256 amountLpRedeemable\r\n    );\r\n\r\n    error SYBalancerReentrancy();\r\n\r\n    // Liquidity Mining\r\n    error VCInactivePool(address pool);\r\n    error VCPoolAlreadyActive(address pool);\r\n    error VCZeroVePendle(address user);\r\n    error VCExceededMaxWeight(uint256 totalWeight, uint256 maxWeight);\r\n    error VCEpochNotFinalized(uint256 wTime);\r\n    error VCPoolAlreadyAddAndRemoved(address pool);\r\n\r\n    error VEInvalidNewExpiry(uint256 newExpiry);\r\n    error VEExceededMaxLockTime();\r\n    error VEInsufficientLockTime();\r\n    error VENotAllowedReduceExpiry();\r\n    error VEZeroAmountLocked();\r\n    error VEPositionNotExpired();\r\n    error VEZeroPosition();\r\n    error VEZeroSlope(uint128 bias, uint128 slope);\r\n    error VEReceiveOldSupply(uint256 msgTime);\r\n\r\n    error GCNotPendleMarket(address caller);\r\n    error GCNotVotingController(address caller);\r\n\r\n    error InvalidWTime(uint256 wTime);\r\n    error ExpiryInThePast(uint256 expiry);\r\n    error ChainNotSupported(uint256 chainId);\r\n\r\n    error FDTotalAmountFundedNotMatch(\r\n        uint256 actualTotalAmount,\r\n        uint256 expectedTotalAmount\r\n    );\r\n    error FDEpochLengthMismatch();\r\n    error FDInvalidPool(address pool);\r\n    error FDPoolAlreadyExists(address pool);\r\n    error FDInvalidNewFinishedEpoch(\r\n        uint256 oldFinishedEpoch,\r\n        uint256 newFinishedEpoch\r\n    );\r\n    error FDInvalidStartEpoch(uint256 startEpoch);\r\n    error FDInvalidWTimeFund(uint256 lastFunded, uint256 wTime);\r\n    error FDFutureFunding(uint256 lastFunded, uint256 currentWTime);\r\n\r\n    error BDInvalidEpoch(uint256 epoch, uint256 startTime);\r\n\r\n    // Cross-Chain\r\n    error MsgNotFromSendEndpoint(uint16 srcChainId, bytes path);\r\n    error MsgNotFromReceiveEndpoint(address sender);\r\n    error InsufficientFeeToSendMsg(uint256 currentFee, uint256 requiredFee);\r\n    error ApproxDstExecutionGasNotSet();\r\n    error InvalidRetryData();\r\n\r\n    // GENERIC MSG\r\n    error ArrayLengthMismatch();\r\n    error ArrayEmpty();\r\n    error ArrayOutOfBounds();\r\n    error ZeroAddress();\r\n    error FailedToSendEther();\r\n    error InvalidMerkleProof();\r\n\r\n    error OnlyLayerZeroEndpoint();\r\n    error OnlyYT();\r\n    error OnlyYCFactory();\r\n    error OnlyWhitelisted();\r\n\r\n    // Swap Aggregator\r\n    error SAInsufficientTokenIn(\r\n        address tokenIn,\r\n        uint256 amountExpected,\r\n        uint256 amountActual\r\n    );\r\n    error UnsupportedSelector(uint256 aggregatorType, bytes4 selector);\r\n}\r\n"
      },
      "contracts/libraries/pendle/LogExpMath.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\r\n// documentation files (the “Software”), to deal in the Software without restriction, including without limitation the\r\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\r\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\r\n// Software.\r\n\r\n// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\r\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\r\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n\r\npragma solidity 0.8.17;\r\n\r\n/* solhint-disable */\r\n\r\n/**\r\n * @dev Exponentiation and logarithm functions for 18 decimal fixed point numbers (both base and exponent/argument).\r\n *\r\n * Exponentiation and logarithm with arbitrary bases (x^y and log_x(y)) are implemented by conversion to natural\r\n * exponentiation and logarithm (where the base is Euler's number).\r\n *\r\n * @author Fernando Martinelli - @fernandomartinelli\r\n * @author Sergio Yuhjtman - @sergioyuhjtman\r\n * @author Daniel Fernandez - @dmf7z\r\n */\r\nlibrary LogExpMath {\r\n    // All fixed point multiplications and divisions are inlined. This means we need to divide by ONE when multiplying\r\n    // two numbers, and multiply by ONE when dividing them.\r\n\r\n    // All arguments and return values are 18 decimal fixed point numbers.\r\n    int256 constant ONE_18 = 1e18;\r\n\r\n    // Internally, intermediate values are computed with higher precision as 20 decimal fixed point numbers, and in the\r\n    // case of ln36, 36 decimals.\r\n    int256 constant ONE_20 = 1e20;\r\n    int256 constant ONE_36 = 1e36;\r\n\r\n    // The domain of natural exponentiation is bound by the word size and number of decimals used.\r\n    //\r\n    // Because internally the result will be stored using 20 decimals, the largest possible result is\r\n    // (2^255 - 1) / 10^20, which makes the largest exponent ln((2^255 - 1) / 10^20) = 130.700829182905140221.\r\n    // The smallest possible result is 10^(-18), which makes largest negative argument\r\n    // ln(10^(-18)) = -41.446531673892822312.\r\n    // We use 130.0 and -41.0 to have some safety margin.\r\n    int256 constant MAX_NATURAL_EXPONENT = 130e18;\r\n    int256 constant MIN_NATURAL_EXPONENT = -41e18;\r\n\r\n    // Bounds for ln_36's argument. Both ln(0.9) and ln(1.1) can be represented with 36 decimal places in a fixed point\r\n    // 256 bit integer.\r\n    int256 constant LN_36_LOWER_BOUND = ONE_18 - 1e17;\r\n    int256 constant LN_36_UPPER_BOUND = ONE_18 + 1e17;\r\n\r\n    uint256 constant MILD_EXPONENT_BOUND = 2 ** 254 / uint256(ONE_20);\r\n\r\n    // 18 decimal constants\r\n    int256 constant x0 = 128000000000000000000; // 2ˆ7\r\n    int256 constant a0 =\r\n        38877084059945950922200000000000000000000000000000000000; // eˆ(x0) (no decimals)\r\n    int256 constant x1 = 64000000000000000000; // 2ˆ6\r\n    int256 constant a1 = 6235149080811616882910000000; // eˆ(x1) (no decimals)\r\n\r\n    // 20 decimal constants\r\n    int256 constant x2 = 3200000000000000000000; // 2ˆ5\r\n    int256 constant a2 = 7896296018268069516100000000000000; // eˆ(x2)\r\n    int256 constant x3 = 1600000000000000000000; // 2ˆ4\r\n    int256 constant a3 = 888611052050787263676000000; // eˆ(x3)\r\n    int256 constant x4 = 800000000000000000000; // 2ˆ3\r\n    int256 constant a4 = 298095798704172827474000; // eˆ(x4)\r\n    int256 constant x5 = 400000000000000000000; // 2ˆ2\r\n    int256 constant a5 = 5459815003314423907810; // eˆ(x5)\r\n    int256 constant x6 = 200000000000000000000; // 2ˆ1\r\n    int256 constant a6 = 738905609893065022723; // eˆ(x6)\r\n    int256 constant x7 = 100000000000000000000; // 2ˆ0\r\n    int256 constant a7 = 271828182845904523536; // eˆ(x7)\r\n    int256 constant x8 = 50000000000000000000; // 2ˆ-1\r\n    int256 constant a8 = 164872127070012814685; // eˆ(x8)\r\n    int256 constant x9 = 25000000000000000000; // 2ˆ-2\r\n    int256 constant a9 = 128402541668774148407; // eˆ(x9)\r\n    int256 constant x10 = 12500000000000000000; // 2ˆ-3\r\n    int256 constant a10 = 113314845306682631683; // eˆ(x10)\r\n    int256 constant x11 = 6250000000000000000; // 2ˆ-4\r\n    int256 constant a11 = 106449445891785942956; // eˆ(x11)\r\n\r\n    /**\r\n     * @dev Natural exponentiation (e^x) with signed 18 decimal fixed point exponent.\r\n     *\r\n     * Reverts if `x` is smaller than MIN_NATURAL_EXPONENT, or larger than `MAX_NATURAL_EXPONENT`.\r\n     */\r\n    function exp(int256 x) internal pure returns (int256) {\r\n        unchecked {\r\n            require(\r\n                x >= MIN_NATURAL_EXPONENT && x <= MAX_NATURAL_EXPONENT,\r\n                'Invalid exponent'\r\n            );\r\n\r\n            if (x < 0) {\r\n                // We only handle positive exponents: e^(-x) is computed as 1 / e^x. We can safely make x positive since it\r\n                // fits in the signed 256 bit range (as it is larger than MIN_NATURAL_EXPONENT).\r\n                // Fixed point division requires multiplying by ONE_18.\r\n                return ((ONE_18 * ONE_18) / exp(-x));\r\n            }\r\n\r\n            // First, we use the fact that e^(x+y) = e^x * e^y to decompose x into a sum of powers of two, which we call x_n,\r\n            // where x_n == 2^(7 - n), and e^x_n = a_n has been precomputed. We choose the first x_n, x0, to equal 2^7\r\n            // because all larger powers are larger than MAX_NATURAL_EXPONENT, and therefore not present in the\r\n            // decomposition.\r\n            // At the end of this process we will have the product of all e^x_n = a_n that apply, and the remainder of this\r\n            // decomposition, which will be lower than the smallest x_n.\r\n            // exp(x) = k_0 * a_0 * k_1 * a_1 * ... + k_n * a_n * exp(remainder), where each k_n equals either 0 or 1.\r\n            // We mutate x by subtracting x_n, making it the remainder of the decomposition.\r\n\r\n            // The first two a_n (e^(2^7) and e^(2^6)) are too large if stored as 18 decimal numbers, and could cause\r\n            // intermediate overflows. Instead we store them as plain integers, with 0 decimals.\r\n            // Additionally, x0 + x1 is larger than MAX_NATURAL_EXPONENT, which means they will not both be present in the\r\n            // decomposition.\r\n\r\n            // For each x_n, we test if that term is present in the decomposition (if x is larger than it), and if so deduct\r\n            // it and compute the accumulated product.\r\n\r\n            int256 firstAN;\r\n            if (x >= x0) {\r\n                x -= x0;\r\n                firstAN = a0;\r\n            } else if (x >= x1) {\r\n                x -= x1;\r\n                firstAN = a1;\r\n            } else {\r\n                firstAN = 1; // One with no decimal places\r\n            }\r\n\r\n            // We now transform x into a 20 decimal fixed point number, to have enhanced precision when computing the\r\n            // smaller terms.\r\n            x *= 100;\r\n\r\n            // `product` is the accumulated product of all a_n (except a0 and a1), which starts at 20 decimal fixed point\r\n            // one. Recall that fixed point multiplication requires dividing by ONE_20.\r\n            int256 product = ONE_20;\r\n\r\n            if (x >= x2) {\r\n                x -= x2;\r\n                product = (product * a2) / ONE_20;\r\n            }\r\n            if (x >= x3) {\r\n                x -= x3;\r\n                product = (product * a3) / ONE_20;\r\n            }\r\n            if (x >= x4) {\r\n                x -= x4;\r\n                product = (product * a4) / ONE_20;\r\n            }\r\n            if (x >= x5) {\r\n                x -= x5;\r\n                product = (product * a5) / ONE_20;\r\n            }\r\n            if (x >= x6) {\r\n                x -= x6;\r\n                product = (product * a6) / ONE_20;\r\n            }\r\n            if (x >= x7) {\r\n                x -= x7;\r\n                product = (product * a7) / ONE_20;\r\n            }\r\n            if (x >= x8) {\r\n                x -= x8;\r\n                product = (product * a8) / ONE_20;\r\n            }\r\n            if (x >= x9) {\r\n                x -= x9;\r\n                product = (product * a9) / ONE_20;\r\n            }\r\n\r\n            // x10 and x11 are unnecessary here since we have high enough precision already.\r\n\r\n            // Now we need to compute e^x, where x is small (in particular, it is smaller than x9). We use the Taylor series\r\n            // expansion for e^x: 1 + x + (x^2 / 2!) + (x^3 / 3!) + ... + (x^n / n!).\r\n\r\n            int256 seriesSum = ONE_20; // The initial one in the sum, with 20 decimal places.\r\n            int256 term; // Each term in the sum, where the nth term is (x^n / n!).\r\n\r\n            // The first term is simply x.\r\n            term = x;\r\n            seriesSum += term;\r\n\r\n            // Each term (x^n / n!) equals the previous one times x, divided by n. Since x is a fixed point number,\r\n            // multiplying by it requires dividing by ONE_20, but dividing by the non-fixed point n values does not.\r\n\r\n            term = ((term * x) / ONE_20) / 2;\r\n            seriesSum += term;\r\n\r\n            term = ((term * x) / ONE_20) / 3;\r\n            seriesSum += term;\r\n\r\n            term = ((term * x) / ONE_20) / 4;\r\n            seriesSum += term;\r\n\r\n            term = ((term * x) / ONE_20) / 5;\r\n            seriesSum += term;\r\n\r\n            term = ((term * x) / ONE_20) / 6;\r\n            seriesSum += term;\r\n\r\n            term = ((term * x) / ONE_20) / 7;\r\n            seriesSum += term;\r\n\r\n            term = ((term * x) / ONE_20) / 8;\r\n            seriesSum += term;\r\n\r\n            term = ((term * x) / ONE_20) / 9;\r\n            seriesSum += term;\r\n\r\n            term = ((term * x) / ONE_20) / 10;\r\n            seriesSum += term;\r\n\r\n            term = ((term * x) / ONE_20) / 11;\r\n            seriesSum += term;\r\n\r\n            term = ((term * x) / ONE_20) / 12;\r\n            seriesSum += term;\r\n\r\n            // 12 Taylor terms are sufficient for 18 decimal precision.\r\n\r\n            // We now have the first a_n (with no decimals), and the product of all other a_n present, and the Taylor\r\n            // approximation of the exponentiation of the remainder (both with 20 decimals). All that remains is to multiply\r\n            // all three (one 20 decimal fixed point multiplication, dividing by ONE_20, and one integer multiplication),\r\n            // and then drop two digits to return an 18 decimal value.\r\n\r\n            return (((product * seriesSum) / ONE_20) * firstAN) / 100;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Natural logarithm (ln(a)) with signed 18 decimal fixed point argument.\r\n     */\r\n    function ln(int256 a) internal pure returns (int256) {\r\n        unchecked {\r\n            // The real natural logarithm is not defined for negative numbers or zero.\r\n            require(a > 0, 'out of bounds');\r\n            if (LN_36_LOWER_BOUND < a && a < LN_36_UPPER_BOUND) {\r\n                return _ln_36(a) / ONE_18;\r\n            } else {\r\n                return _ln(a);\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Exponentiation (x^y) with unsigned 18 decimal fixed point base and exponent.\r\n     *\r\n     * Reverts if ln(x) * y is smaller than `MIN_NATURAL_EXPONENT`, or larger than `MAX_NATURAL_EXPONENT`.\r\n     */\r\n    function pow(uint256 x, uint256 y) internal pure returns (uint256) {\r\n        unchecked {\r\n            if (y == 0) {\r\n                // We solve the 0^0 indetermination by making it equal one.\r\n                return uint256(ONE_18);\r\n            }\r\n\r\n            if (x == 0) {\r\n                return 0;\r\n            }\r\n\r\n            // Instead of computing x^y directly, we instead rely on the properties of logarithms and exponentiation to\r\n            // arrive at that r`esult. In particular, exp(ln(x)) = x, and ln(x^y) = y * ln(x). This means\r\n            // x^y = exp(y * ln(x)).\r\n\r\n            // The ln function takes a signed value, so we need to make sure x fits in the signed 256 bit range.\r\n            require(x < 2 ** 255, 'x out of bounds');\r\n            int256 x_int256 = int256(x);\r\n\r\n            // We will compute y * ln(x) in a single step. Depending on the value of x, we can either use ln or ln_36. In\r\n            // both cases, we leave the division by ONE_18 (due to fixed point multiplication) to the end.\r\n\r\n            // This prevents y * ln(x) from overflowing, and at the same time guarantees y fits in the signed 256 bit range.\r\n            require(y < MILD_EXPONENT_BOUND, 'y out of bounds');\r\n            int256 y_int256 = int256(y);\r\n\r\n            int256 logx_times_y;\r\n            if (LN_36_LOWER_BOUND < x_int256 && x_int256 < LN_36_UPPER_BOUND) {\r\n                int256 ln_36_x = _ln_36(x_int256);\r\n\r\n                // ln_36_x has 36 decimal places, so multiplying by y_int256 isn't as straightforward, since we can't just\r\n                // bring y_int256 to 36 decimal places, as it might overflow. Instead, we perform two 18 decimal\r\n                // multiplications and add the results: one with the first 18 decimals of ln_36_x, and one with the\r\n                // (downscaled) last 18 decimals.\r\n                logx_times_y = ((ln_36_x / ONE_18) *\r\n                    y_int256 +\r\n                    ((ln_36_x % ONE_18) * y_int256) /\r\n                    ONE_18);\r\n            } else {\r\n                logx_times_y = _ln(x_int256) * y_int256;\r\n            }\r\n            logx_times_y /= ONE_18;\r\n\r\n            // Finally, we compute exp(y * ln(x)) to arrive at x^y\r\n            require(\r\n                MIN_NATURAL_EXPONENT <= logx_times_y &&\r\n                    logx_times_y <= MAX_NATURAL_EXPONENT,\r\n                'product out of bounds'\r\n            );\r\n\r\n            return uint256(exp(logx_times_y));\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Internal natural logarithm (ln(a)) with signed 18 decimal fixed point argument.\r\n     */\r\n    function _ln(int256 a) private pure returns (int256) {\r\n        unchecked {\r\n            if (a < ONE_18) {\r\n                // Since ln(a^k) = k * ln(a), we can compute ln(a) as ln(a) = ln((1/a)^(-1)) = - ln((1/a)). If a is less\r\n                // than one, 1/a will be greater than one, and this if statement will not be entered in the recursive call.\r\n                // Fixed point division requires multiplying by ONE_18.\r\n                return (-_ln((ONE_18 * ONE_18) / a));\r\n            }\r\n\r\n            // First, we use the fact that ln^(a * b) = ln(a) + ln(b) to decompose ln(a) into a sum of powers of two, which\r\n            // we call x_n, where x_n == 2^(7 - n), which are the natural logarithm of precomputed quantities a_n (that is,\r\n            // ln(a_n) = x_n). We choose the first x_n, x0, to equal 2^7 because the exponential of all larger powers cannot\r\n            // be represented as 18 fixed point decimal numbers in 256 bits, and are therefore larger than a.\r\n            // At the end of this process we will have the sum of all x_n = ln(a_n) that apply, and the remainder of this\r\n            // decomposition, which will be lower than the smallest a_n.\r\n            // ln(a) = k_0 * x_0 + k_1 * x_1 + ... + k_n * x_n + ln(remainder), where each k_n equals either 0 or 1.\r\n            // We mutate a by subtracting a_n, making it the remainder of the decomposition.\r\n\r\n            // For reasons related to how `exp` works, the first two a_n (e^(2^7) and e^(2^6)) are not stored as fixed point\r\n            // numbers with 18 decimals, but instead as plain integers with 0 decimals, so we need to multiply them by\r\n            // ONE_18 to convert them to fixed point.\r\n            // For each a_n, we test if that term is present in the decomposition (if a is larger than it), and if so divide\r\n            // by it and compute the accumulated sum.\r\n\r\n            int256 sum = 0;\r\n            if (a >= a0 * ONE_18) {\r\n                a /= a0; // Integer, not fixed point division\r\n                sum += x0;\r\n            }\r\n\r\n            if (a >= a1 * ONE_18) {\r\n                a /= a1; // Integer, not fixed point division\r\n                sum += x1;\r\n            }\r\n\r\n            // All other a_n and x_n are stored as 20 digit fixed point numbers, so we convert the sum and a to this format.\r\n            sum *= 100;\r\n            a *= 100;\r\n\r\n            // Because further a_n are  20 digit fixed point numbers, we multiply by ONE_20 when dividing by them.\r\n\r\n            if (a >= a2) {\r\n                a = (a * ONE_20) / a2;\r\n                sum += x2;\r\n            }\r\n\r\n            if (a >= a3) {\r\n                a = (a * ONE_20) / a3;\r\n                sum += x3;\r\n            }\r\n\r\n            if (a >= a4) {\r\n                a = (a * ONE_20) / a4;\r\n                sum += x4;\r\n            }\r\n\r\n            if (a >= a5) {\r\n                a = (a * ONE_20) / a5;\r\n                sum += x5;\r\n            }\r\n\r\n            if (a >= a6) {\r\n                a = (a * ONE_20) / a6;\r\n                sum += x6;\r\n            }\r\n\r\n            if (a >= a7) {\r\n                a = (a * ONE_20) / a7;\r\n                sum += x7;\r\n            }\r\n\r\n            if (a >= a8) {\r\n                a = (a * ONE_20) / a8;\r\n                sum += x8;\r\n            }\r\n\r\n            if (a >= a9) {\r\n                a = (a * ONE_20) / a9;\r\n                sum += x9;\r\n            }\r\n\r\n            if (a >= a10) {\r\n                a = (a * ONE_20) / a10;\r\n                sum += x10;\r\n            }\r\n\r\n            if (a >= a11) {\r\n                a = (a * ONE_20) / a11;\r\n                sum += x11;\r\n            }\r\n\r\n            // a is now a small number (smaller than a_11, which roughly equals 1.06). This means we can use a Taylor series\r\n            // that converges rapidly for values of `a` close to one - the same one used in ln_36.\r\n            // Let z = (a - 1) / (a + 1).\r\n            // ln(a) = 2 * (z + z^3 / 3 + z^5 / 5 + z^7 / 7 + ... + z^(2 * n + 1) / (2 * n + 1))\r\n\r\n            // Recall that 20 digit fixed point division requires multiplying by ONE_20, and multiplication requires\r\n            // division by ONE_20.\r\n            int256 z = ((a - ONE_20) * ONE_20) / (a + ONE_20);\r\n            int256 z_squared = (z * z) / ONE_20;\r\n\r\n            // num is the numerator of the series: the z^(2 * n + 1) term\r\n            int256 num = z;\r\n\r\n            // seriesSum holds the accumulated sum of each term in the series, starting with the initial z\r\n            int256 seriesSum = num;\r\n\r\n            // In each step, the numerator is multiplied by z^2\r\n            num = (num * z_squared) / ONE_20;\r\n            seriesSum += num / 3;\r\n\r\n            num = (num * z_squared) / ONE_20;\r\n            seriesSum += num / 5;\r\n\r\n            num = (num * z_squared) / ONE_20;\r\n            seriesSum += num / 7;\r\n\r\n            num = (num * z_squared) / ONE_20;\r\n            seriesSum += num / 9;\r\n\r\n            num = (num * z_squared) / ONE_20;\r\n            seriesSum += num / 11;\r\n\r\n            // 6 Taylor terms are sufficient for 36 decimal precision.\r\n\r\n            // Finally, we multiply by 2 (non fixed point) to compute ln(remainder)\r\n            seriesSum *= 2;\r\n\r\n            // We now have the sum of all x_n present, and the Taylor approximation of the logarithm of the remainder (both\r\n            // with 20 decimals). All that remains is to sum these two, and then drop two digits to return a 18 decimal\r\n            // value.\r\n\r\n            return (sum + seriesSum) / 100;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @dev Intrnal high precision (36 decimal places) natural logarithm (ln(x)) with signed 18 decimal fixed point argument,\r\n     * for x close to one.\r\n     *\r\n     * Should only be used if x is between LN_36_LOWER_BOUND and LN_36_UPPER_BOUND.\r\n     */\r\n    function _ln_36(int256 x) private pure returns (int256) {\r\n        unchecked {\r\n            // Since ln(1) = 0, a value of x close to one will yield a very small result, which makes using 36 digits\r\n            // worthwhile.\r\n\r\n            // First, we transform x to a 36 digit fixed point value.\r\n            x *= ONE_18;\r\n\r\n            // We will use the following Taylor expansion, which converges very rapidly. Let z = (x - 1) / (x + 1).\r\n            // ln(x) = 2 * (z + z^3 / 3 + z^5 / 5 + z^7 / 7 + ... + z^(2 * n + 1) / (2 * n + 1))\r\n\r\n            // Recall that 36 digit fixed point division requires multiplying by ONE_36, and multiplication requires\r\n            // division by ONE_36.\r\n            int256 z = ((x - ONE_36) * ONE_36) / (x + ONE_36);\r\n            int256 z_squared = (z * z) / ONE_36;\r\n\r\n            // num is the numerator of the series: the z^(2 * n + 1) term\r\n            int256 num = z;\r\n\r\n            // seriesSum holds the accumulated sum of each term in the series, starting with the initial z\r\n            int256 seriesSum = num;\r\n\r\n            // In each step, the numerator is multiplied by z^2\r\n            num = (num * z_squared) / ONE_36;\r\n            seriesSum += num / 3;\r\n\r\n            num = (num * z_squared) / ONE_36;\r\n            seriesSum += num / 5;\r\n\r\n            num = (num * z_squared) / ONE_36;\r\n            seriesSum += num / 7;\r\n\r\n            num = (num * z_squared) / ONE_36;\r\n            seriesSum += num / 9;\r\n\r\n            num = (num * z_squared) / ONE_36;\r\n            seriesSum += num / 11;\r\n\r\n            num = (num * z_squared) / ONE_36;\r\n            seriesSum += num / 13;\r\n\r\n            num = (num * z_squared) / ONE_36;\r\n            seriesSum += num / 15;\r\n\r\n            // 8 Taylor terms are sufficient for 36 decimal precision.\r\n\r\n            // All that remains is multiplying by 2 (non fixed point).\r\n            return seriesSum * 2;\r\n        }\r\n    }\r\n}\r\n"
      },
      "contracts/libraries/pendle/MarketMathCore.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\r\npragma solidity 0.8.17;\r\n\r\nimport './PMath.sol';\r\nimport './LogExpMath.sol';\r\n\r\nimport './PYIndex.sol';\r\nimport './MiniHelpers.sol';\r\nimport './Errors.sol';\r\n\r\nstruct MarketState {\r\n    int256 totalPt;\r\n    int256 totalSy;\r\n    int256 totalLp;\r\n    address treasury;\r\n    /// immutable variables ///\r\n    int256 scalarRoot;\r\n    uint256 expiry;\r\n    /// fee data ///\r\n    uint256 lnFeeRateRoot;\r\n    uint256 reserveFeePercent; // base 100\r\n    /// last trade data ///\r\n    uint256 lastLnImpliedRate;\r\n}\r\n\r\n// params that are expensive to compute, therefore we pre-compute them\r\nstruct MarketPreCompute {\r\n    int256 rateScalar;\r\n    int256 totalAsset;\r\n    int256 rateAnchor;\r\n    int256 feeRate;\r\n}\r\n\r\n// solhint-disable ordering\r\nlibrary MarketMathCore {\r\n    using PMath for uint256;\r\n    using PMath for int256;\r\n    using LogExpMath for int256;\r\n    using PYIndexLib for PYIndex;\r\n\r\n    int256 internal constant MINIMUM_LIQUIDITY = 10 ** 3;\r\n    int256 internal constant PERCENTAGE_DECIMALS = 100;\r\n    uint256 internal constant DAY = 86400;\r\n    uint256 internal constant IMPLIED_RATE_TIME = 365 * DAY;\r\n\r\n    int256 internal constant MAX_MARKET_PROPORTION = (1e18 * 96) / 100;\r\n\r\n    using PMath for uint256;\r\n    using PMath for int256;\r\n\r\n    /*///////////////////////////////////////////////////////////////\r\n                UINT FUNCTIONS TO PROXY TO CORE FUNCTIONS\r\n    //////////////////////////////////////////////////////////////*/\r\n\r\n    function addLiquidity(\r\n        MarketState memory market,\r\n        uint256 syDesired,\r\n        uint256 ptDesired,\r\n        uint256 blockTime\r\n    )\r\n        internal\r\n        pure\r\n        returns (\r\n            uint256 lpToReserve,\r\n            uint256 lpToAccount,\r\n            uint256 syUsed,\r\n            uint256 ptUsed\r\n        )\r\n    {\r\n        (\r\n            int256 _lpToReserve,\r\n            int256 _lpToAccount,\r\n            int256 _syUsed,\r\n            int256 _ptUsed\r\n        ) = addLiquidityCore(\r\n                market,\r\n                syDesired.Int(),\r\n                ptDesired.Int(),\r\n                blockTime\r\n            );\r\n\r\n        lpToReserve = _lpToReserve.Uint();\r\n        lpToAccount = _lpToAccount.Uint();\r\n        syUsed = _syUsed.Uint();\r\n        ptUsed = _ptUsed.Uint();\r\n    }\r\n\r\n    function removeLiquidity(\r\n        MarketState memory market,\r\n        uint256 lpToRemove\r\n    ) internal pure returns (uint256 netSyToAccount, uint256 netPtToAccount) {\r\n        (int256 _syToAccount, int256 _ptToAccount) = removeLiquidityCore(\r\n            market,\r\n            lpToRemove.Int()\r\n        );\r\n\r\n        netSyToAccount = _syToAccount.Uint();\r\n        netPtToAccount = _ptToAccount.Uint();\r\n    }\r\n\r\n    function swapExactPtForSy(\r\n        MarketState memory market,\r\n        PYIndex index,\r\n        uint256 exactPtToMarket,\r\n        uint256 blockTime\r\n    )\r\n        internal\r\n        pure\r\n        returns (\r\n            uint256 netSyToAccount,\r\n            uint256 netSyFee,\r\n            uint256 netSyToReserve\r\n        )\r\n    {\r\n        (\r\n            int256 _netSyToAccount,\r\n            int256 _netSyFee,\r\n            int256 _netSyToReserve\r\n        ) = executeTradeCore(market, index, exactPtToMarket.neg(), blockTime);\r\n\r\n        netSyToAccount = _netSyToAccount.Uint();\r\n        netSyFee = _netSyFee.Uint();\r\n        netSyToReserve = _netSyToReserve.Uint();\r\n    }\r\n\r\n    function swapSyForExactPt(\r\n        MarketState memory market,\r\n        PYIndex index,\r\n        uint256 exactPtToAccount,\r\n        uint256 blockTime\r\n    )\r\n        internal\r\n        pure\r\n        returns (\r\n            uint256 netSyToMarket,\r\n            uint256 netSyFee,\r\n            uint256 netSyToReserve\r\n        )\r\n    {\r\n        (\r\n            int256 _netSyToAccount,\r\n            int256 _netSyFee,\r\n            int256 _netSyToReserve\r\n        ) = executeTradeCore(market, index, exactPtToAccount.Int(), blockTime);\r\n\r\n        netSyToMarket = _netSyToAccount.neg().Uint();\r\n        netSyFee = _netSyFee.Uint();\r\n        netSyToReserve = _netSyToReserve.Uint();\r\n    }\r\n\r\n    /*///////////////////////////////////////////////////////////////\r\n                    CORE FUNCTIONS\r\n    //////////////////////////////////////////////////////////////*/\r\n\r\n    function addLiquidityCore(\r\n        MarketState memory market,\r\n        int256 syDesired,\r\n        int256 ptDesired,\r\n        uint256 blockTime\r\n    )\r\n        internal\r\n        pure\r\n        returns (\r\n            int256 lpToReserve,\r\n            int256 lpToAccount,\r\n            int256 syUsed,\r\n            int256 ptUsed\r\n        )\r\n    {\r\n        /// ------------------------------------------------------------\r\n        /// CHECKS\r\n        /// ------------------------------------------------------------\r\n        if (syDesired == 0 || ptDesired == 0)\r\n            revert Errors.MarketZeroAmountsInput();\r\n        if (MiniHelpers.isExpired(market.expiry, blockTime))\r\n            revert Errors.MarketExpired();\r\n\r\n        /// ------------------------------------------------------------\r\n        /// MATH\r\n        /// ------------------------------------------------------------\r\n        if (market.totalLp == 0) {\r\n            lpToAccount =\r\n                PMath.sqrt((syDesired * ptDesired).Uint()).Int() -\r\n                MINIMUM_LIQUIDITY;\r\n            lpToReserve = MINIMUM_LIQUIDITY;\r\n            syUsed = syDesired;\r\n            ptUsed = ptDesired;\r\n        } else {\r\n            int256 netLpByPt = (ptDesired * market.totalLp) / market.totalPt;\r\n            int256 netLpBySy = (syDesired * market.totalLp) / market.totalSy;\r\n            if (netLpByPt < netLpBySy) {\r\n                lpToAccount = netLpByPt;\r\n                ptUsed = ptDesired;\r\n                syUsed = (market.totalSy * lpToAccount) / market.totalLp;\r\n            } else {\r\n                lpToAccount = netLpBySy;\r\n                syUsed = syDesired;\r\n                ptUsed = (market.totalPt * lpToAccount) / market.totalLp;\r\n            }\r\n        }\r\n\r\n        if (lpToAccount <= 0) revert Errors.MarketZeroAmountsOutput();\r\n\r\n        /// ------------------------------------------------------------\r\n        /// WRITE\r\n        /// ------------------------------------------------------------\r\n        market.totalSy += syUsed;\r\n        market.totalPt += ptUsed;\r\n        market.totalLp += lpToAccount + lpToReserve;\r\n    }\r\n\r\n    function removeLiquidityCore(\r\n        MarketState memory market,\r\n        int256 lpToRemove\r\n    ) internal pure returns (int256 netSyToAccount, int256 netPtToAccount) {\r\n        /// ------------------------------------------------------------\r\n        /// CHECKS\r\n        /// ------------------------------------------------------------\r\n        if (lpToRemove == 0) revert Errors.MarketZeroAmountsInput();\r\n\r\n        /// ------------------------------------------------------------\r\n        /// MATH\r\n        /// ------------------------------------------------------------\r\n        netSyToAccount = (lpToRemove * market.totalSy) / market.totalLp;\r\n        netPtToAccount = (lpToRemove * market.totalPt) / market.totalLp;\r\n\r\n        if (netSyToAccount == 0 && netPtToAccount == 0)\r\n            revert Errors.MarketZeroAmountsOutput();\r\n\r\n        /// ------------------------------------------------------------\r\n        /// WRITE\r\n        /// ------------------------------------------------------------\r\n        market.totalLp = market.totalLp.subNoNeg(lpToRemove);\r\n        market.totalPt = market.totalPt.subNoNeg(netPtToAccount);\r\n        market.totalSy = market.totalSy.subNoNeg(netSyToAccount);\r\n    }\r\n\r\n    function executeTradeCore(\r\n        MarketState memory market,\r\n        PYIndex index,\r\n        int256 netPtToAccount,\r\n        uint256 blockTime\r\n    )\r\n        internal\r\n        pure\r\n        returns (int256 netSyToAccount, int256 netSyFee, int256 netSyToReserve)\r\n    {\r\n        /// ------------------------------------------------------------\r\n        /// CHECKS\r\n        /// ------------------------------------------------------------\r\n        if (MiniHelpers.isExpired(market.expiry, blockTime))\r\n            revert Errors.MarketExpired();\r\n        if (market.totalPt <= netPtToAccount)\r\n            revert Errors.MarketInsufficientPtForTrade(\r\n                market.totalPt,\r\n                netPtToAccount\r\n            );\r\n\r\n        /// ------------------------------------------------------------\r\n        /// MATH\r\n        /// ------------------------------------------------------------\r\n        MarketPreCompute memory comp = getMarketPreCompute(\r\n            market,\r\n            index,\r\n            blockTime\r\n        );\r\n\r\n        (netSyToAccount, netSyFee, netSyToReserve) = calcTrade(\r\n            market,\r\n            comp,\r\n            index,\r\n            netPtToAccount\r\n        );\r\n\r\n        /// ------------------------------------------------------------\r\n        /// WRITE\r\n        /// ------------------------------------------------------------\r\n        _setNewMarketStateTrade(\r\n            market,\r\n            comp,\r\n            index,\r\n            netPtToAccount,\r\n            netSyToAccount,\r\n            netSyToReserve,\r\n            blockTime\r\n        );\r\n    }\r\n\r\n    function getMarketPreCompute(\r\n        MarketState memory market,\r\n        PYIndex index,\r\n        uint256 blockTime\r\n    ) internal pure returns (MarketPreCompute memory res) {\r\n        if (MiniHelpers.isExpired(market.expiry, blockTime))\r\n            revert Errors.MarketExpired();\r\n\r\n        uint256 timeToExpiry = market.expiry - blockTime;\r\n\r\n        res.rateScalar = _getRateScalar(market, timeToExpiry);\r\n        res.totalAsset = index.syToAsset(market.totalSy);\r\n\r\n        if (market.totalPt == 0 || res.totalAsset == 0)\r\n            revert Errors.MarketZeroTotalPtOrTotalAsset(\r\n                market.totalPt,\r\n                res.totalAsset\r\n            );\r\n\r\n        res.rateAnchor = _getRateAnchor(\r\n            market.totalPt,\r\n            market.lastLnImpliedRate,\r\n            res.totalAsset,\r\n            res.rateScalar,\r\n            timeToExpiry\r\n        );\r\n        res.feeRate = _getExchangeRateFromImpliedRate(\r\n            market.lnFeeRateRoot,\r\n            timeToExpiry\r\n        );\r\n    }\r\n\r\n    function calcTrade(\r\n        MarketState memory market,\r\n        MarketPreCompute memory comp,\r\n        PYIndex index,\r\n        int256 netPtToAccount\r\n    )\r\n        internal\r\n        pure\r\n        returns (int256 netSyToAccount, int256 netSyFee, int256 netSyToReserve)\r\n    {\r\n        int256 preFeeExchangeRate = _getExchangeRate(\r\n            market.totalPt,\r\n            comp.totalAsset,\r\n            comp.rateScalar,\r\n            comp.rateAnchor,\r\n            netPtToAccount\r\n        );\r\n\r\n        int256 preFeeAssetToAccount = netPtToAccount\r\n            .divDown(preFeeExchangeRate)\r\n            .neg();\r\n        int256 fee = comp.feeRate;\r\n\r\n        if (netPtToAccount > 0) {\r\n            int256 postFeeExchangeRate = preFeeExchangeRate.divDown(fee);\r\n            if (postFeeExchangeRate < PMath.IONE)\r\n                revert Errors.MarketExchangeRateBelowOne(postFeeExchangeRate);\r\n\r\n            fee = preFeeAssetToAccount.mulDown(PMath.IONE - fee);\r\n        } else {\r\n            fee = ((preFeeAssetToAccount * (PMath.IONE - fee)) / fee).neg();\r\n        }\r\n\r\n        int256 netAssetToReserve = (fee * market.reserveFeePercent.Int()) /\r\n            PERCENTAGE_DECIMALS;\r\n        int256 netAssetToAccount = preFeeAssetToAccount - fee;\r\n\r\n        netSyToAccount = netAssetToAccount < 0\r\n            ? index.assetToSyUp(netAssetToAccount)\r\n            : index.assetToSy(netAssetToAccount);\r\n        netSyFee = index.assetToSy(fee);\r\n        netSyToReserve = index.assetToSy(netAssetToReserve);\r\n    }\r\n\r\n    function _setNewMarketStateTrade(\r\n        MarketState memory market,\r\n        MarketPreCompute memory comp,\r\n        PYIndex index,\r\n        int256 netPtToAccount,\r\n        int256 netSyToAccount,\r\n        int256 netSyToReserve,\r\n        uint256 blockTime\r\n    ) internal pure {\r\n        uint256 timeToExpiry = market.expiry - blockTime;\r\n\r\n        market.totalPt = market.totalPt.subNoNeg(netPtToAccount);\r\n        market.totalSy = market.totalSy.subNoNeg(\r\n            netSyToAccount + netSyToReserve\r\n        );\r\n\r\n        market.lastLnImpliedRate = _getLnImpliedRate(\r\n            market.totalPt,\r\n            index.syToAsset(market.totalSy),\r\n            comp.rateScalar,\r\n            comp.rateAnchor,\r\n            timeToExpiry\r\n        );\r\n\r\n        if (market.lastLnImpliedRate == 0)\r\n            revert Errors.MarketZeroLnImpliedRate();\r\n    }\r\n\r\n    function _getRateAnchor(\r\n        int256 totalPt,\r\n        uint256 lastLnImpliedRate,\r\n        int256 totalAsset,\r\n        int256 rateScalar,\r\n        uint256 timeToExpiry\r\n    ) internal pure returns (int256 rateAnchor) {\r\n        int256 newExchangeRate = _getExchangeRateFromImpliedRate(\r\n            lastLnImpliedRate,\r\n            timeToExpiry\r\n        );\r\n\r\n        if (newExchangeRate < PMath.IONE)\r\n            revert Errors.MarketExchangeRateBelowOne(newExchangeRate);\r\n\r\n        {\r\n            int256 proportion = totalPt.divDown(totalPt + totalAsset);\r\n\r\n            int256 lnProportion = _logProportion(proportion);\r\n\r\n            rateAnchor = newExchangeRate - lnProportion.divDown(rateScalar);\r\n        }\r\n    }\r\n\r\n    /// @notice Calculates the current market implied rate.\r\n    /// @return lnImpliedRate the implied rate\r\n    function _getLnImpliedRate(\r\n        int256 totalPt,\r\n        int256 totalAsset,\r\n        int256 rateScalar,\r\n        int256 rateAnchor,\r\n        uint256 timeToExpiry\r\n    ) internal pure returns (uint256 lnImpliedRate) {\r\n        // This will check for exchange rates < PMath.IONE\r\n        int256 exchangeRate = _getExchangeRate(\r\n            totalPt,\r\n            totalAsset,\r\n            rateScalar,\r\n            rateAnchor,\r\n            0\r\n        );\r\n\r\n        // exchangeRate >= 1 so its ln >= 0\r\n        uint256 lnRate = exchangeRate.ln().Uint();\r\n\r\n        lnImpliedRate = (lnRate * IMPLIED_RATE_TIME) / timeToExpiry;\r\n    }\r\n\r\n    /// @notice Converts an implied rate to an exchange rate given a time to expiry. The\r\n    /// formula is E = e^rt\r\n    function _getExchangeRateFromImpliedRate(\r\n        uint256 lnImpliedRate,\r\n        uint256 timeToExpiry\r\n    ) internal pure returns (int256 exchangeRate) {\r\n        uint256 rt = (lnImpliedRate * timeToExpiry) / IMPLIED_RATE_TIME;\r\n\r\n        exchangeRate = LogExpMath.exp(rt.Int());\r\n    }\r\n\r\n    function _getExchangeRate(\r\n        int256 totalPt,\r\n        int256 totalAsset,\r\n        int256 rateScalar,\r\n        int256 rateAnchor,\r\n        int256 netPtToAccount\r\n    ) internal pure returns (int256 exchangeRate) {\r\n        int256 numerator = totalPt.subNoNeg(netPtToAccount);\r\n\r\n        int256 proportion = (numerator.divDown(totalPt + totalAsset));\r\n\r\n        if (proportion > MAX_MARKET_PROPORTION)\r\n            revert Errors.MarketProportionTooHigh(\r\n                proportion,\r\n                MAX_MARKET_PROPORTION\r\n            );\r\n\r\n        int256 lnProportion = _logProportion(proportion);\r\n\r\n        exchangeRate = lnProportion.divDown(rateScalar) + rateAnchor;\r\n\r\n        if (exchangeRate < PMath.IONE)\r\n            revert Errors.MarketExchangeRateBelowOne(exchangeRate);\r\n    }\r\n\r\n    function _logProportion(\r\n        int256 proportion\r\n    ) internal pure returns (int256 res) {\r\n        if (proportion == PMath.IONE)\r\n            revert Errors.MarketProportionMustNotEqualOne();\r\n\r\n        int256 logitP = proportion.divDown(PMath.IONE - proportion);\r\n\r\n        res = logitP.ln();\r\n    }\r\n\r\n    function _getRateScalar(\r\n        MarketState memory market,\r\n        uint256 timeToExpiry\r\n    ) internal pure returns (int256 rateScalar) {\r\n        rateScalar =\r\n            (market.scalarRoot * IMPLIED_RATE_TIME.Int()) /\r\n            timeToExpiry.Int();\r\n        if (rateScalar <= 0)\r\n            revert Errors.MarketRateScalarBelowZero(rateScalar);\r\n    }\r\n\r\n    function setInitialLnImpliedRate(\r\n        MarketState memory market,\r\n        PYIndex index,\r\n        int256 initialAnchor,\r\n        uint256 blockTime\r\n    ) internal pure {\r\n        /// ------------------------------------------------------------\r\n        /// CHECKS\r\n        /// ------------------------------------------------------------\r\n        if (MiniHelpers.isExpired(market.expiry, blockTime))\r\n            revert Errors.MarketExpired();\r\n\r\n        /// ------------------------------------------------------------\r\n        /// MATH\r\n        /// ------------------------------------------------------------\r\n        int256 totalAsset = index.syToAsset(market.totalSy);\r\n        uint256 timeToExpiry = market.expiry - blockTime;\r\n        int256 rateScalar = _getRateScalar(market, timeToExpiry);\r\n\r\n        /// ------------------------------------------------------------\r\n        /// WRITE\r\n        /// ------------------------------------------------------------\r\n        market.lastLnImpliedRate = _getLnImpliedRate(\r\n            market.totalPt,\r\n            totalAsset,\r\n            rateScalar,\r\n            initialAnchor,\r\n            timeToExpiry\r\n        );\r\n    }\r\n}\r\n"
      },
      "contracts/libraries/pendle/MiniHelpers.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\r\npragma solidity 0.8.17;\r\n\r\nlibrary MiniHelpers {\r\n    function isCurrentlyExpired(uint256 expiry) internal view returns (bool) {\r\n        return (expiry <= block.timestamp);\r\n    }\r\n\r\n    function isExpired(\r\n        uint256 expiry,\r\n        uint256 blockTime\r\n    ) internal pure returns (bool) {\r\n        return (expiry <= blockTime);\r\n    }\r\n\r\n    function isTimeInThePast(uint256 timestamp) internal view returns (bool) {\r\n        return (timestamp <= block.timestamp); // same definition as isCurrentlyExpired\r\n    }\r\n}\r\n"
      },
      "contracts/libraries/pendle/PendlePtOracleLib.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.17;\r\n\r\nimport './PMath.sol';\r\nimport '../../interfaces/pendle/IPMarket.sol';\r\n\r\nlibrary PendlePtOracleLib {\r\n    using PMath for uint256;\r\n    using PMath for int256;\r\n\r\n    /**\r\n     * This function returns the twap rate PT/Asset on market, but take into account the current rate of SY\r\n     This is to account for special cases where underlying asset becomes insolvent and has decreasing exchangeRate\r\n     * @param market market to get rate from\r\n     * @param duration twap duration\r\n     */\r\n    function getPtToAssetRate(\r\n        IPMarket market,\r\n        uint32 duration\r\n    ) internal view returns (uint256) {\r\n        (uint256 syIndex, uint256 pyIndex) = getSYandPYIndexCurrent(market);\r\n        if (syIndex >= pyIndex) {\r\n            return getPtToAssetRateRaw(market, duration);\r\n        } else {\r\n            return (getPtToAssetRateRaw(market, duration) * syIndex) / pyIndex;\r\n        }\r\n    }\r\n\r\n    function getPtToAssetRateRaw(\r\n        IPMarket market,\r\n        uint32 duration\r\n    ) internal view returns (uint256) {\r\n        uint256 expiry = market.expiry();\r\n\r\n        if (expiry <= block.timestamp) {\r\n            return PMath.ONE;\r\n        } else {\r\n            uint256 lnImpliedRate = _getMarketLnImpliedRate(market, duration);\r\n            uint256 timeToExpiry = expiry - block.timestamp;\r\n            uint256 assetToPtRate = MarketMathCore\r\n                ._getExchangeRateFromImpliedRate(lnImpliedRate, timeToExpiry)\r\n                .Uint();\r\n            return PMath.ONE.divDown(assetToPtRate);\r\n        }\r\n    }\r\n\r\n    function getSYandPYIndexCurrent(\r\n        IPMarket market\r\n    ) internal view returns (uint256 syIndex, uint256 pyIndex) {\r\n        (IStandardizedYield SY, , IPYieldToken YT) = market.readTokens();\r\n\r\n        syIndex = SY.exchangeRate();\r\n        uint256 pyIndexStored = YT.pyIndexStored();\r\n\r\n        if (\r\n            YT.doCacheIndexSameBlock() &&\r\n            YT.pyIndexLastUpdatedBlock() == block.number\r\n        ) {\r\n            pyIndex = pyIndexStored;\r\n        } else {\r\n            pyIndex = PMath.max(syIndex, pyIndexStored);\r\n        }\r\n    }\r\n\r\n    function _getMarketLnImpliedRate(\r\n        IPMarket market,\r\n        uint32 duration\r\n    ) private view returns (uint256) {\r\n        uint32[] memory durations = new uint32[](2);\r\n        durations[0] = duration;\r\n\r\n        uint216[] memory lnImpliedRateCumulative = market.observe(durations);\r\n        return\r\n            (lnImpliedRateCumulative[1] - lnImpliedRateCumulative[0]) /\r\n            duration;\r\n    }\r\n}\r\n"
      },
      "contracts/libraries/pendle/PMath.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\r\n// This program is free software: you can redistribute it and/or modify\r\n// it under the terms of the GNU General Public License as published by\r\n// the Free Software Foundation, either version 3 of the License, or\r\n// (at your option) any later version.\r\n\r\n// This program is distributed in the hope that it will be useful,\r\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n// GNU General Public License for more details.\r\n\r\n// You should have received a copy of the GNU General Public License\r\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\r\n\r\npragma solidity 0.8.17;\r\n\r\n/* solhint-disable private-vars-leading-underscore, reason-string */\r\n\r\nlibrary PMath {\r\n    uint256 internal constant ONE = 1e18; // 18 decimal places\r\n    int256 internal constant IONE = 1e18; // 18 decimal places\r\n\r\n    function subMax0(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        unchecked {\r\n            return (a >= b ? a - b : 0);\r\n        }\r\n    }\r\n\r\n    function subNoNeg(int256 a, int256 b) internal pure returns (int256) {\r\n        require(a >= b, 'negative');\r\n        return a - b; // no unchecked since if b is very negative, a - b might overflow\r\n    }\r\n\r\n    function mulDown(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        uint256 product = a * b;\r\n        unchecked {\r\n            return product / ONE;\r\n        }\r\n    }\r\n\r\n    function mulDown(int256 a, int256 b) internal pure returns (int256) {\r\n        int256 product = a * b;\r\n        unchecked {\r\n            return product / IONE;\r\n        }\r\n    }\r\n\r\n    function divDown(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        uint256 aInflated = a * ONE;\r\n        unchecked {\r\n            return aInflated / b;\r\n        }\r\n    }\r\n\r\n    function divDown(int256 a, int256 b) internal pure returns (int256) {\r\n        int256 aInflated = a * IONE;\r\n        unchecked {\r\n            return aInflated / b;\r\n        }\r\n    }\r\n\r\n    function rawDivUp(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return (a + b - 1) / b;\r\n    }\r\n\r\n    // @author Uniswap\r\n    function sqrt(uint256 y) internal pure returns (uint256 z) {\r\n        if (y > 3) {\r\n            z = y;\r\n            uint256 x = y / 2 + 1;\r\n            while (x < z) {\r\n                z = x;\r\n                x = (y / x + x) / 2;\r\n            }\r\n        } else if (y != 0) {\r\n            z = 1;\r\n        }\r\n    }\r\n\r\n    function square(uint256 x) internal pure returns (uint256) {\r\n        return x * x;\r\n    }\r\n\r\n    function squareDown(uint256 x) internal pure returns (uint256) {\r\n        return mulDown(x, x);\r\n    }\r\n\r\n    function abs(int256 x) internal pure returns (uint256) {\r\n        return uint256(x > 0 ? x : -x);\r\n    }\r\n\r\n    function neg(int256 x) internal pure returns (int256) {\r\n        return x * (-1);\r\n    }\r\n\r\n    function neg(uint256 x) internal pure returns (int256) {\r\n        return Int(x) * (-1);\r\n    }\r\n\r\n    function max(uint256 x, uint256 y) internal pure returns (uint256) {\r\n        return (x > y ? x : y);\r\n    }\r\n\r\n    function max(int256 x, int256 y) internal pure returns (int256) {\r\n        return (x > y ? x : y);\r\n    }\r\n\r\n    function min(uint256 x, uint256 y) internal pure returns (uint256) {\r\n        return (x < y ? x : y);\r\n    }\r\n\r\n    function min(int256 x, int256 y) internal pure returns (int256) {\r\n        return (x < y ? x : y);\r\n    }\r\n\r\n    /*///////////////////////////////////////////////////////////////\r\n                               SIGNED CASTS\r\n    //////////////////////////////////////////////////////////////*/\r\n\r\n    function Int(uint256 x) internal pure returns (int256) {\r\n        require(x <= uint256(type(int256).max));\r\n        return int256(x);\r\n    }\r\n\r\n    function Int128(int256 x) internal pure returns (int128) {\r\n        require(type(int128).min <= x && x <= type(int128).max);\r\n        return int128(x);\r\n    }\r\n\r\n    function Int128(uint256 x) internal pure returns (int128) {\r\n        return Int128(Int(x));\r\n    }\r\n\r\n    /*///////////////////////////////////////////////////////////////\r\n                               UNSIGNED CASTS\r\n    //////////////////////////////////////////////////////////////*/\r\n\r\n    function Uint(int256 x) internal pure returns (uint256) {\r\n        require(x >= 0);\r\n        return uint256(x);\r\n    }\r\n\r\n    function Uint32(uint256 x) internal pure returns (uint32) {\r\n        require(x <= type(uint32).max);\r\n        return uint32(x);\r\n    }\r\n\r\n    function Uint64(uint256 x) internal pure returns (uint64) {\r\n        require(x <= type(uint64).max);\r\n        return uint64(x);\r\n    }\r\n\r\n    function Uint112(uint256 x) internal pure returns (uint112) {\r\n        require(x <= type(uint112).max);\r\n        return uint112(x);\r\n    }\r\n\r\n    function Uint96(uint256 x) internal pure returns (uint96) {\r\n        require(x <= type(uint96).max);\r\n        return uint96(x);\r\n    }\r\n\r\n    function Uint128(uint256 x) internal pure returns (uint128) {\r\n        require(x <= type(uint128).max);\r\n        return uint128(x);\r\n    }\r\n\r\n    function Uint192(uint256 x) internal pure returns (uint192) {\r\n        require(x <= type(uint192).max);\r\n        return uint192(x);\r\n    }\r\n\r\n    function isAApproxB(\r\n        uint256 a,\r\n        uint256 b,\r\n        uint256 eps\r\n    ) internal pure returns (bool) {\r\n        return mulDown(b, ONE - eps) <= a && a <= mulDown(b, ONE + eps);\r\n    }\r\n\r\n    function isAGreaterApproxB(\r\n        uint256 a,\r\n        uint256 b,\r\n        uint256 eps\r\n    ) internal pure returns (bool) {\r\n        return a >= b && a <= mulDown(b, ONE + eps);\r\n    }\r\n\r\n    function isASmallerApproxB(\r\n        uint256 a,\r\n        uint256 b,\r\n        uint256 eps\r\n    ) internal pure returns (bool) {\r\n        return a <= b && a >= mulDown(b, ONE - eps);\r\n    }\r\n}\r\n"
      },
      "contracts/libraries/pendle/PYIndex.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\r\npragma solidity 0.8.17;\r\n\r\nimport '../../interfaces/pendle/IPYieldToken.sol';\r\nimport '../../interfaces/pendle/IPPrincipalToken.sol';\r\n\r\nimport './SYUtils.sol';\r\nimport './PMath.sol';\r\n\r\ntype PYIndex is uint256;\r\n\r\nlibrary PYIndexLib {\r\n    using PMath for uint256;\r\n    using PMath for int256;\r\n\r\n    function newIndex(IPYieldToken YT) internal returns (PYIndex) {\r\n        return PYIndex.wrap(YT.pyIndexCurrent());\r\n    }\r\n\r\n    function syToAsset(\r\n        PYIndex index,\r\n        uint256 syAmount\r\n    ) internal pure returns (uint256) {\r\n        return SYUtils.syToAsset(PYIndex.unwrap(index), syAmount);\r\n    }\r\n\r\n    function assetToSy(\r\n        PYIndex index,\r\n        uint256 assetAmount\r\n    ) internal pure returns (uint256) {\r\n        return SYUtils.assetToSy(PYIndex.unwrap(index), assetAmount);\r\n    }\r\n\r\n    function assetToSyUp(\r\n        PYIndex index,\r\n        uint256 assetAmount\r\n    ) internal pure returns (uint256) {\r\n        return SYUtils.assetToSyUp(PYIndex.unwrap(index), assetAmount);\r\n    }\r\n\r\n    function syToAssetUp(\r\n        PYIndex index,\r\n        uint256 syAmount\r\n    ) internal pure returns (uint256) {\r\n        uint256 _index = PYIndex.unwrap(index);\r\n        return SYUtils.syToAssetUp(_index, syAmount);\r\n    }\r\n\r\n    function syToAsset(\r\n        PYIndex index,\r\n        int256 syAmount\r\n    ) internal pure returns (int256) {\r\n        int256 sign = syAmount < 0 ? int256(-1) : int256(1);\r\n        return\r\n            sign *\r\n            (SYUtils.syToAsset(PYIndex.unwrap(index), syAmount.abs())).Int();\r\n    }\r\n\r\n    function assetToSy(\r\n        PYIndex index,\r\n        int256 assetAmount\r\n    ) internal pure returns (int256) {\r\n        int256 sign = assetAmount < 0 ? int256(-1) : int256(1);\r\n        return\r\n            sign *\r\n            (SYUtils.assetToSy(PYIndex.unwrap(index), assetAmount.abs())).Int();\r\n    }\r\n\r\n    function assetToSyUp(\r\n        PYIndex index,\r\n        int256 assetAmount\r\n    ) internal pure returns (int256) {\r\n        int256 sign = assetAmount < 0 ? int256(-1) : int256(1);\r\n        return\r\n            sign *\r\n            (SYUtils.assetToSyUp(PYIndex.unwrap(index), assetAmount.abs()))\r\n                .Int();\r\n    }\r\n}\r\n"
      },
      "contracts/libraries/pendle/SYUtils.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\r\npragma solidity 0.8.17;\r\n\r\nlibrary SYUtils {\r\n    uint256 internal constant ONE = 1e18;\r\n\r\n    function syToAsset(\r\n        uint256 exchangeRate,\r\n        uint256 syAmount\r\n    ) internal pure returns (uint256) {\r\n        return (syAmount * exchangeRate) / ONE;\r\n    }\r\n\r\n    function syToAssetUp(\r\n        uint256 exchangeRate,\r\n        uint256 syAmount\r\n    ) internal pure returns (uint256) {\r\n        return (syAmount * exchangeRate + ONE - 1) / ONE;\r\n    }\r\n\r\n    function assetToSy(\r\n        uint256 exchangeRate,\r\n        uint256 assetAmount\r\n    ) internal pure returns (uint256) {\r\n        return (assetAmount * ONE) / exchangeRate;\r\n    }\r\n\r\n    function assetToSyUp(\r\n        uint256 exchangeRate,\r\n        uint256 assetAmount\r\n    ) internal pure returns (uint256) {\r\n        return (assetAmount * ONE + exchangeRate - 1) / exchangeRate;\r\n    }\r\n}\r\n"
      },
      "contracts/oasis/usd/ERC20ValueProvider.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity 0.8.17;\n\nimport '@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol';\nimport '@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol';\n\nimport '../../utils/AccessControlUpgradeable.sol';\nimport '../../utils/RateLib.sol';\nimport '../../interfaces/IChainlinkV3Aggregator.sol';\n\nabstract contract ERC20ValueProvider is\n    ReentrancyGuardUpgradeable,\n    AccessControlUpgradeable\n{\n    using RateLib for RateLib.Rate;\n\n    error InvalidAmount(uint256 amount);\n    error ZeroAddress();\n    error InvalidOracleResults();\n\n    event NewBaseCreditLimitRate(RateLib.Rate rate);\n    event NewBaseLiquidationLimitRate(RateLib.Rate rate);\n\n    /// @notice The token oracles aggregator\n    IChainlinkV3Aggregator public aggregator;\n\n    /// @notice The token address\n    IERC20MetadataUpgradeable public token;\n\n    RateLib.Rate public baseCreditLimitRate;\n    RateLib.Rate public baseLiquidationLimitRate;\n\n    /// @notice This function is only called once during deployment of the proxy contract. It's not called after upgrades.\n    /// @param _aggregator The token oracles aggregator\n    /// @param _token The token address\n    /// @param _baseCreditLimitRate The base credit limit rate\n    /// @param _baseLiquidationLimitRate The base liquidation limit rate\n    function __initialize(\n        IChainlinkV3Aggregator _aggregator,\n        IERC20MetadataUpgradeable _token,\n        RateLib.Rate calldata _baseCreditLimitRate,\n        RateLib.Rate calldata _baseLiquidationLimitRate\n    ) internal onlyInitializing {\n        __AccessControl_init();\n        __ReentrancyGuard_init();\n\n        if (address(_aggregator) == address(0)) revert ZeroAddress();\n\n        _validateRateBelowOne(_baseCreditLimitRate);\n        _validateRateBelowOne(_baseLiquidationLimitRate);\n\n        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n\n        aggregator = _aggregator;\n        token = _token;\n        baseCreditLimitRate = _baseCreditLimitRate;\n        baseLiquidationLimitRate = _baseLiquidationLimitRate;\n    }\n\n    /// @param _owner The owner address\n    /// @param _colAmount The collateral amount\n    /// @return The credit limit rate\n    function getCreditLimitRate(\n        address _owner,\n        uint256 _colAmount\n    ) public view returns (RateLib.Rate memory) {\n        return baseCreditLimitRate;\n    }\n\n    /// @param _owner The owner address\n    /// @param _colAmount The collateral amount\n    /// @return The liquidation limit rate\n    function getLiquidationLimitRate(\n        address _owner,\n        uint256 _colAmount\n    ) public view returns (RateLib.Rate memory) {\n        return baseLiquidationLimitRate;\n    }\n\n    /// @param _owner The owner address\n    /// @param _colAmount The collateral amount\n    /// @return The credit limit for collateral amount\n    function getCreditLimitUSD(\n        address _owner,\n        uint256 _colAmount\n    ) external view returns (uint256) {\n        RateLib.Rate memory _creditLimitRate = getCreditLimitRate(\n            _owner,\n            _colAmount\n        );\n        return _creditLimitRate.calculate(getPriceUSD(_colAmount));\n    }\n\n    /// @param _owner The owner address\n    /// @param _colAmount The collateral amount\n    /// @return The liquidation limit for collateral amount\n    function getLiquidationLimitUSD(\n        address _owner,\n        uint256 _colAmount\n    ) external view returns (uint256) {\n        RateLib.Rate memory _liquidationLimitRate = getLiquidationLimitRate(\n            _owner,\n            _colAmount\n        );\n        return _liquidationLimitRate.calculate(getPriceUSD(_colAmount));\n    }\n\n    /// @return The value for the collection, in USD.\n    function getPriceUSD(uint256 colAmount) public view returns (uint256) {\n        uint256 price = getPriceUSD();\n        return (price * colAmount) / (10 ** token.decimals());\n    }\n\n    /// @return The value for the collection, in USD.\n    function getPriceUSD() public view virtual returns (uint256) {\n        (, int256 answer, , uint256 timestamp, ) = aggregator.latestRoundData();\n\n        if (answer == 0 || timestamp == 0) revert InvalidOracleResults();\n\n        uint8 decimals = aggregator.decimals();\n\n        unchecked {\n            //converts the answer to have 18 decimals\n            return\n                decimals > 18\n                    ? uint256(answer) / 10 ** (decimals - 18)\n                    : uint256(answer) * 10 ** (18 - decimals);\n        }\n    }\n\n    function setBaseCreditLimitRate(\n        RateLib.Rate memory _baseCreditLimitRate\n    ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        _validateRateBelowOne(_baseCreditLimitRate);\n\n        baseCreditLimitRate = _baseCreditLimitRate;\n\n        emit NewBaseCreditLimitRate(_baseCreditLimitRate);\n    }\n\n    function setBaseLiquidationLimitRate(\n        RateLib.Rate memory _liquidationLimitRate\n    ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        _validateRateBelowOne(_liquidationLimitRate);\n\n        baseLiquidationLimitRate = _liquidationLimitRate;\n\n        emit NewBaseLiquidationLimitRate(_liquidationLimitRate);\n    }\n\n    /// @dev Validates a rate. The denominator must be greater than zero and greater than or equal to the numerator.\n    /// @param _rate The rate to validate\n    function _validateRateBelowOne(RateLib.Rate memory _rate) internal pure {\n        if (!_rate.isValid() || _rate.isAboveOne())\n            revert RateLib.InvalidRate();\n    }\n}\n"
      },
      "contracts/oasis/usd/valueProviders/PendlePTValueProviderForSusde.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity 0.8.17;\n\nimport './SUSDeValueProvider.sol';\nimport '../ERC20ValueProvider.sol';\nimport '../../../interfaces/pendle/IPMarket.sol';\nimport '../../../interfaces/pendle/IPendlePtOracle.sol';\nimport '../../../libraries/pendle/PendlePtOracleLib.sol';\n\ncontract PendlePTValueProviderForSusde is ERC20ValueProvider {\n    using PendlePtOracleLib for IPMarket;\n\n    error IncreaseCardinalityRequired();\n    error OldestObservationNotSatisfied();\n\n    struct PendlePtConfig {\n        IPMarket market;\n        uint32 twapDuration;\n    }\n\n    IPendlePtOracle public ptOracle;\n    PendlePtConfig public ptConfig;\n    address public susde;\n    SUSDeValueProvider public susdeValueProvider;\n\n    /// @notice This function is only called once during deployment of the proxy contract. It's not called after upgrades.\n    /// @param _aggregator The token oracles aggregator (ETH / USD)\n    /// @param _token The token address\n    /// @param _baseCreditLimitRate The base credit limit rate\n    /// @param _baseLiquidationLimitRate The base liquidation limit rate\n    function initialize(\n        PendlePtConfig memory _ptConfig,\n        IPendlePtOracle _ptOracle,\n        address _susde,\n        SUSDeValueProvider _susdeValueProvider,\n        IChainlinkV3Aggregator _aggregator,\n        IERC20MetadataUpgradeable _token,\n        RateLib.Rate calldata _baseCreditLimitRate,\n        RateLib.Rate calldata _baseLiquidationLimitRate\n    ) external initializer {\n        __initialize(\n            _aggregator,\n            _token,\n            _baseCreditLimitRate,\n            _baseLiquidationLimitRate\n        );\n\n        ptConfig = _ptConfig;\n        ptOracle = _ptOracle;\n        susde = _susde;\n        susdeValueProvider = _susdeValueProvider;\n    }\n\n    /// @return The value for the collection, in USD.\n    function getPriceUSD() public view override returns (uint256) {\n        // check PT twap\n        (\n            bool increaseCardinalityRequired,\n            ,\n            bool oldestObservationSatisfied\n        ) = ptOracle.getOracleState(\n                address(ptConfig.market),\n                ptConfig.twapDuration\n            );\n        if (increaseCardinalityRequired) {\n            revert IncreaseCardinalityRequired();\n        }\n        if (!oldestObservationSatisfied) {\n            revert OldestObservationNotSatisfied();\n        }\n\n        uint256 ptRate = ptConfig.market.getPtToAssetRate(\n            ptConfig.twapDuration\n        ); // 18 decimals\n\n        uint256 susdePrice = susdeValueProvider.getPriceUSD();\n\n        unchecked {\n            // converts the answer to have 18 decimals\n            return (ptRate * susdePrice) / 1e18;\n        }\n    }\n}\n"
      },
      "contracts/oasis/usd/valueProviders/SUSDeValueProvider.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity 0.8.17;\n\nimport '../ERC20ValueProvider.sol';\n\nimport '../../../interfaces/ethena/ISUSDe.sol';\nimport '../../../interfaces/uniswapV3/IUniswapV3StaticOracle.sol';\n\ncontract SUSDeValueProvider is ERC20ValueProvider {\n    struct USDePriceSetting {\n        address uniV3StaticOracle;\n        address usde;\n        address usdt;\n        uint24[] fees;\n        uint32 period;\n        uint256 minPrice; // 6 decimals\n        uint256 maxPrice; // 6 decimals\n    }\n\n    USDePriceSetting public usdePriceSetting;\n\n    /// @notice This function is only called once during deployment of the proxy contract. It's not called after upgrades.\n    /// @param _aggregator The token oracles aggregator\n    /// @param _token The token address\n    /// @param _baseCreditLimitRate The base credit limit rate\n    /// @param _baseLiquidationLimitRate The base liquidation limit rate\n    function initialize(\n        USDePriceSetting memory _usdePriceSetting,\n        IChainlinkV3Aggregator _aggregator,\n        IERC20MetadataUpgradeable _token,\n        RateLib.Rate calldata _baseCreditLimitRate,\n        RateLib.Rate calldata _baseLiquidationLimitRate\n    ) external initializer {\n        __initialize(\n            _aggregator,\n            _token,\n            _baseCreditLimitRate,\n            _baseLiquidationLimitRate\n        );\n        usdePriceSetting = _usdePriceSetting;\n    }\n\n    function setSetting(\n        USDePriceSetting memory _usdePriceSetting,\n        IChainlinkV3Aggregator _usdtAggregator\n    ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        aggregator = _usdtAggregator;\n        usdePriceSetting = _usdePriceSetting;\n    }\n\n    /// @return priceUSD The value for the collection, in USD.\n    function getPriceUSD() public view override returns (uint256 priceUSD) {\n        (, int256 usdtPrice, , uint256 usdtPriceTimestamp, ) = aggregator\n            .latestRoundData(); // 8 decimals\n\n        if (usdtPrice == 0 || usdtPriceTimestamp == 0) {\n            revert InvalidOracleResults();\n        }\n\n        (uint256 usdePrice, ) = IUniswapV3StaticOracle(\n            usdePriceSetting.uniV3StaticOracle\n        ).quoteSpecificFeeTiersWithTimePeriod(\n                1 ether,\n                usdePriceSetting.usde,\n                usdePriceSetting.usdt,\n                usdePriceSetting.fees,\n                usdePriceSetting.period\n            ); // 6 decimals\n\n        if (\n            usdePrice < usdePriceSetting.minPrice ||\n            usdePrice > usdePriceSetting.maxPrice\n        ) {\n            revert InvalidOracleResults();\n        }\n\n        priceUSD =\n            (uint256(usdtPrice) *\n                usdePrice *\n                ISUSDe(address(token)).convertToAssets(1 ether)) /\n            1e14;\n    }\n}\n"
      },
      "contracts/utils/AccessControlUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\";\nimport \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\n\n//copy paste of openzeppelin's {AccessControlUpgradeable} contract but instead of extending\n//{ERC165Upgradeable} it extends {ERC165} to have the storage layout match {OwnableUpgradeable}'s\n//and allow replacing it.\nabstract contract AccessControlUpgradeable is\n    Initializable,\n    ContextUpgradeable,\n    IAccessControlUpgradeable,\n    ERC165\n{\n    function __AccessControl_init() internal onlyInitializing {}\n\n    function __AccessControl_init_unchained() internal onlyInitializing {}\n\n    struct RoleData {\n        mapping(address => bool) members;\n        bytes32 adminRole;\n    }\n\n    mapping(bytes32 => RoleData) private _roles;\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with a standardized message including the required role.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     *\n     * _Available since v4.1._\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role, _msgSender());\n        _;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(\n        bytes4 interfaceId\n    ) public view virtual override returns (bool) {\n        return\n            interfaceId == type(IAccessControlUpgradeable).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(\n        bytes32 role,\n        address account\n    ) public view virtual override returns (bool) {\n        return _roles[role].members[account];\n    }\n\n    /**\n     * @dev Revert with a standard message if `account` is missing `role`.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!hasRole(role, account)) {\n            revert(\n                string(\n                    abi.encodePacked(\n                        \"AccessControl: account \",\n                        StringsUpgradeable.toHexString(uint160(account), 20),\n                        \" is missing role \",\n                        StringsUpgradeable.toHexString(uint256(role), 32)\n                    )\n                )\n            );\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(\n        bytes32 role\n    ) public view virtual override returns (bytes32) {\n        return _roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(\n        bytes32 role,\n        address account\n    ) public virtual override onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(\n        bytes32 role,\n        address account\n    ) public virtual override onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(\n        bytes32 role,\n        address account\n    ) public virtual override {\n        require(\n            account == _msgSender(),\n            \"AccessControl: can only renounce roles for self\"\n        );\n\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event. Note that unlike {grantRole}, this function doesn't perform any\n     * checks on the calling account.\n     *\n     * [WARNING]\n     * ====\n     * This function should only be called from the constructor when setting\n     * up the initial roles for the system.\n     *\n     * Using this function in any other way is effectively circumventing the admin\n     * system imposed by {AccessControl}.\n     * ====\n     *\n     * NOTE: This function is deprecated in favor of {_grantRole}.\n     */\n    function _setupRole(bytes32 role, address account) internal virtual {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        _roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * Internal function without access restriction.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual {\n        if (!hasRole(role, account)) {\n            _roles[role].members[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n        }\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * Internal function without access restriction.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual {\n        if (hasRole(role, account)) {\n            _roles[role].members[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n        }\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "contracts/utils/RateLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity 0.8.17;\n\nlibrary RateLib {\n    error InvalidRate();\n\n    struct Rate {\n        uint128 numerator;\n        uint128 denominator;\n    }\n\n    function isValid(Rate memory _rate) internal pure returns (bool) {\n        return _rate.denominator != 0;\n    }\n\n    function isZero(Rate memory _rate) internal pure returns (bool) {\n        return _rate.numerator == 0;\n    }\n\n    function isAboveOne(Rate memory _rate) internal pure returns (bool) {\n        return _rate.numerator > _rate.denominator;\n    }\n\n    function isBelowOne(Rate memory _rate) internal pure returns (bool) {\n        return _rate.denominator > _rate.numerator;\n    }\n\n    function isOne(Rate memory _rate) internal pure returns (bool) {\n        return _rate.numerator == _rate.denominator;\n    }\n\n    function greaterThan(\n        Rate memory _r1,\n        Rate memory _r2\n    ) internal pure returns (bool) {\n        return\n            _r1.numerator * _r2.denominator > _r2.numerator * _r1.denominator;\n    }\n\n    function sum(\n        Rate memory _r1,\n        Rate memory _r2\n    ) internal pure returns (Rate memory) {\n        return\n            Rate({\n                numerator: _r1.numerator *\n                    _r2.denominator +\n                    _r1.denominator *\n                    _r2.numerator,\n                denominator: _r1.denominator * _r2.denominator\n            });\n    }\n\n    function calculate(\n        Rate memory _rate,\n        uint256 _num\n    ) internal pure returns (uint256) {\n        return (_num * _rate.numerator) / _rate.denominator;\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}