creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/IAuthentication.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\ninterface IAuthentication {\n    /**\n     * @dev Returns the action identifier associated with the external function described by `selector`.\n     */\n    function getActionId(bytes4 selector) external view returns (bytes32);\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/ISignaturesValidator.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @dev Interface for the SignatureValidator helper, used to support meta-transactions.\n */\ninterface ISignaturesValidator {\n    /**\n     * @dev Returns the EIP712 domain separator.\n     */\n    function getDomainSeparator() external view returns (bytes32);\n\n    /**\n     * @dev Returns the next nonce used by an address to sign messages.\n     */\n    function getNextNonce(address user) external view returns (uint256);\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/ITemporarilyPausable.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @dev Interface for the TemporarilyPausable helper.\n */\ninterface ITemporarilyPausable {\n    /**\n     * @dev Emitted every time the pause state changes by `_setPaused`.\n     */\n    event PausedStateChanged(bool paused);\n\n    /**\n     * @dev Returns the current paused state.\n     */\n    function getPausedState()\n        external\n        view\n        returns (\n            bool paused,\n            uint256 pauseWindowEndTime,\n            uint256 bufferPeriodEndTime\n        );\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/solidity-utils/misc/IWETH.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\nimport \"../openzeppelin/IERC20.sol\";\n\n/**\n * @dev Interface for WETH9.\n * See https://github.com/gnosis/canonical-weth/blob/0dd1ea3e295eef916d0c6223ec63141137d22d67/contracts/WETH9.sol\n */\ninterface IWETH is IERC20 {\n    function deposit() external payable;\n\n    function withdraw(uint256 amount) external;\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/vault/IAsset.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @dev This is an empty interface used to represent either ERC20-conforming token contracts or ETH (using the zero\n * address sentinel value). We're just relying on the fact that `interface` can be used to declare new address-like\n * types.\n *\n * This concept is unrelated to a Pool's Asset Managers.\n */\ninterface IAsset {\n    // solhint-disable-previous-line no-empty-blocks\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/vault/IAuthorizer.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\ninterface IAuthorizer {\n    /**\n     * @dev Returns true if `account` can perform the action described by `actionId` in the contract `where`.\n     */\n    function canPerform(\n        bytes32 actionId,\n        address account,\n        address where\n    ) external view returns (bool);\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/vault/IFlashLoanRecipient.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\n\n// Inspired by Aave Protocol's IFlashLoanReceiver.\n\nimport \"../solidity-utils/openzeppelin/IERC20.sol\";\n\ninterface IFlashLoanRecipient {\n    /**\n     * @dev When `flashLoan` is called on the Vault, it invokes the `receiveFlashLoan` hook on the recipient.\n     *\n     * At the time of the call, the Vault will have transferred `amounts` for `tokens` to the recipient. Before this\n     * call returns, the recipient must have transferred `amounts` plus `feeAmounts` for each token back to the\n     * Vault, or else the entire flash loan will revert.\n     *\n     * `userData` is the same value passed in the `IVault.flashLoan` call.\n     */\n    function receiveFlashLoan(\n        IERC20[] memory tokens,\n        uint256[] memory amounts,\n        uint256[] memory feeAmounts,\n        bytes memory userData\n    ) external;\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/vault/IProtocolFeesCollector.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.7.0 <0.9.0;\npragma experimental ABIEncoderV2;\n\nimport \"../solidity-utils/openzeppelin/IERC20.sol\";\n\nimport \"./IVault.sol\";\nimport \"./IAuthorizer.sol\";\n\ninterface IProtocolFeesCollector {\n    event SwapFeePercentageChanged(uint256 newSwapFeePercentage);\n    event FlashLoanFeePercentageChanged(uint256 newFlashLoanFeePercentage);\n\n    function withdrawCollectedFees(\n        IERC20[] calldata tokens,\n        uint256[] calldata amounts,\n        address recipient\n    ) external;\n\n    function setSwapFeePercentage(uint256 newSwapFeePercentage) external;\n\n    function setFlashLoanFeePercentage(uint256 newFlashLoanFeePercentage) external;\n\n    function getSwapFeePercentage() external view returns (uint256);\n\n    function getFlashLoanFeePercentage() external view returns (uint256);\n\n    function getCollectedFeeAmounts(IERC20[] memory tokens) external view returns (uint256[] memory feeAmounts);\n\n    function getAuthorizer() external view returns (IAuthorizer);\n\n    function vault() external view returns (IVault);\n}\n"
      },
      "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma experimental ABIEncoderV2;\n\nimport \"../solidity-utils/openzeppelin/IERC20.sol\";\nimport \"../solidity-utils/helpers/IAuthentication.sol\";\nimport \"../solidity-utils/helpers/ISignaturesValidator.sol\";\nimport \"../solidity-utils/helpers/ITemporarilyPausable.sol\";\nimport \"../solidity-utils/misc/IWETH.sol\";\n\nimport \"./IAsset.sol\";\nimport \"./IAuthorizer.sol\";\nimport \"./IFlashLoanRecipient.sol\";\nimport \"./IProtocolFeesCollector.sol\";\n\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @dev Full external interface for the Vault core contract - no external or public methods exist in the contract that\n * don't override one of these declarations.\n */\ninterface IVault is ISignaturesValidator, ITemporarilyPausable, IAuthentication {\n    // Generalities about the Vault:\n    //\n    // - Whenever documentation refers to 'tokens', it strictly refers to ERC20-compliant token contracts. Tokens are\n    // transferred out of the Vault by calling the `IERC20.transfer` function, and transferred in by calling\n    // `IERC20.transferFrom`. In these cases, the sender must have previously allowed the Vault to use their tokens by\n    // calling `IERC20.approve`. The only deviation from the ERC20 standard that is supported is functions not returning\n    // a boolean value: in these scenarios, a non-reverting call is assumed to be successful.\n    //\n    // - All non-view functions in the Vault are non-reentrant: calling them while another one is mid-execution (e.g.\n    // while execution control is transferred to a token contract during a swap) will result in a revert. View\n    // functions can be called in a re-reentrant way, but doing so might cause them to return inconsistent results.\n    // Contracts calling view functions in the Vault must make sure the Vault has not already been entered.\n    //\n    // - View functions revert if referring to either unregistered Pools, or unregistered tokens for registered Pools.\n\n    // Authorizer\n    //\n    // Some system actions are permissioned, like setting and collecting protocol fees. This permissioning system exists\n    // outside of the Vault in the Authorizer contract: the Vault simply calls the Authorizer to check if the caller\n    // can perform a given action.\n\n    /**\n     * @dev Returns the Vault's Authorizer.\n     */\n    function getAuthorizer() external view returns (IAuthorizer);\n\n    /**\n     * @dev Sets a new Authorizer for the Vault. The caller must be allowed by the current Authorizer to do this.\n     *\n     * Emits an `AuthorizerChanged` event.\n     */\n    function setAuthorizer(IAuthorizer newAuthorizer) external;\n\n    /**\n     * @dev Emitted when a new authorizer is set by `setAuthorizer`.\n     */\n    event AuthorizerChanged(IAuthorizer indexed newAuthorizer);\n\n    // Relayers\n    //\n    // Additionally, it is possible for an account to perform certain actions on behalf of another one, using their\n    // Vault ERC20 allowance and Internal Balance. These accounts are said to be 'relayers' for these Vault functions,\n    // and are expected to be smart contracts with sound authentication mechanisms. For an account to be able to wield\n    // this power, two things must occur:\n    //  - The Authorizer must grant the account the permission to be a relayer for the relevant Vault function. This\n    //    means that Balancer governance must approve each individual contract to act as a relayer for the intended\n    //    functions.\n    //  - Each user must approve the relayer to act on their behalf.\n    // This double protection means users cannot be tricked into approving malicious relayers (because they will not\n    // have been allowed by the Authorizer via governance), nor can malicious relayers approved by a compromised\n    // Authorizer or governance drain user funds, since they would also need to be approved by each individual user.\n\n    /**\n     * @dev Returns true if `user` has approved `relayer` to act as a relayer for them.\n     */\n    function hasApprovedRelayer(address user, address relayer) external view returns (bool);\n\n    /**\n     * @dev Allows `relayer` to act as a relayer for `sender` if `approved` is true, and disallows it otherwise.\n     *\n     * Emits a `RelayerApprovalChanged` event.\n     */\n    function setRelayerApproval(\n        address sender,\n        address relayer,\n        bool approved\n    ) external;\n\n    /**\n     * @dev Emitted every time a relayer is approved or disapproved by `setRelayerApproval`.\n     */\n    event RelayerApprovalChanged(address indexed relayer, address indexed sender, bool approved);\n\n    // Internal Balance\n    //\n    // Users can deposit tokens into the Vault, where they are allocated to their Internal Balance, and later\n    // transferred or withdrawn. It can also be used as a source of tokens when joining Pools, as a destination\n    // when exiting them, and as either when performing swaps. This usage of Internal Balance results in greatly reduced\n    // gas costs when compared to relying on plain ERC20 transfers, leading to large savings for frequent users.\n    //\n    // Internal Balance management features batching, which means a single contract call can be used to perform multiple\n    // operations of different kinds, with different senders and recipients, at once.\n\n    /**\n     * @dev Returns `user`'s Internal Balance for a set of tokens.\n     */\n    function getInternalBalance(address user, IERC20[] memory tokens) external view returns (uint256[] memory);\n\n    /**\n     * @dev Performs a set of user balance operations, which involve Internal Balance (deposit, withdraw or transfer)\n     * and plain ERC20 transfers using the Vault's allowance. This last feature is particularly useful for relayers, as\n     * it lets integrators reuse a user's Vault allowance.\n     *\n     * For each operation, if the caller is not `sender`, it must be an authorized relayer for them.\n     */\n    function manageUserBalance(UserBalanceOp[] memory ops) external payable;\n\n    /**\n     * @dev Data for `manageUserBalance` operations, which include the possibility for ETH to be sent and received\n     without manual WETH wrapping or unwrapping.\n     */\n    struct UserBalanceOp {\n        UserBalanceOpKind kind;\n        IAsset asset;\n        uint256 amount;\n        address sender;\n        address payable recipient;\n    }\n\n    // There are four possible operations in `manageUserBalance`:\n    //\n    // - DEPOSIT_INTERNAL\n    // Increases the Internal Balance of the `recipient` account by transferring tokens from the corresponding\n    // `sender`. The sender must have allowed the Vault to use their tokens via `IERC20.approve()`.\n    //\n    // ETH can be used by passing the ETH sentinel value as the asset and forwarding ETH in the call: it will be wrapped\n    // and deposited as WETH. Any ETH amount remaining will be sent back to the caller (not the sender, which is\n    // relevant for relayers).\n    //\n    // Emits an `InternalBalanceChanged` event.\n    //\n    //\n    // - WITHDRAW_INTERNAL\n    // Decreases the Internal Balance of the `sender` account by transferring tokens to the `recipient`.\n    //\n    // ETH can be used by passing the ETH sentinel value as the asset. This will deduct WETH instead, unwrap it and send\n    // it to the recipient as ETH.\n    //\n    // Emits an `InternalBalanceChanged` event.\n    //\n    //\n    // - TRANSFER_INTERNAL\n    // Transfers tokens from the Internal Balance of the `sender` account to the Internal Balance of `recipient`.\n    //\n    // Reverts if the ETH sentinel value is passed.\n    //\n    // Emits an `InternalBalanceChanged` event.\n    //\n    //\n    // - TRANSFER_EXTERNAL\n    // Transfers tokens from `sender` to `recipient`, using the Vault's ERC20 allowance. This is typically used by\n    // relayers, as it lets them reuse a user's Vault allowance.\n    //\n    // Reverts if the ETH sentinel value is passed.\n    //\n    // Emits an `ExternalBalanceTransfer` event.\n\n    enum UserBalanceOpKind { DEPOSIT_INTERNAL, WITHDRAW_INTERNAL, TRANSFER_INTERNAL, TRANSFER_EXTERNAL }\n\n    /**\n     * @dev Emitted when a user's Internal Balance changes, either from calls to `manageUserBalance`, or through\n     * interacting with Pools using Internal Balance.\n     *\n     * Because Internal Balance works exclusively with ERC20 tokens, ETH deposits and withdrawals will use the WETH\n     * address.\n     */\n    event InternalBalanceChanged(address indexed user, IERC20 indexed token, int256 delta);\n\n    /**\n     * @dev Emitted when a user's Vault ERC20 allowance is used by the Vault to transfer tokens to an external account.\n     */\n    event ExternalBalanceTransfer(IERC20 indexed token, address indexed sender, address recipient, uint256 amount);\n\n    // Pools\n    //\n    // There are three specialization settings for Pools, which allow for cheaper swaps at the cost of reduced\n    // functionality:\n    //\n    //  - General: no specialization, suited for all Pools. IGeneralPool is used for swap request callbacks, passing the\n    // balance of all tokens in the Pool. These Pools have the largest swap costs (because of the extra storage reads),\n    // which increase with the number of registered tokens.\n    //\n    //  - Minimal Swap Info: IMinimalSwapInfoPool is used instead of IGeneralPool, which saves gas by only passing the\n    // balance of the two tokens involved in the swap. This is suitable for some pricing algorithms, like the weighted\n    // constant product one popularized by Balancer V1. Swap costs are smaller compared to general Pools, and are\n    // independent of the number of registered tokens.\n    //\n    //  - Two Token: only allows two tokens to be registered. This achieves the lowest possible swap gas cost. Like\n    // minimal swap info Pools, these are called via IMinimalSwapInfoPool.\n\n    enum PoolSpecialization { GENERAL, MINIMAL_SWAP_INFO, TWO_TOKEN }\n\n    /**\n     * @dev Registers the caller account as a Pool with a given specialization setting. Returns the Pool's ID, which\n     * is used in all Pool-related functions. Pools cannot be deregistered, nor can the Pool's specialization be\n     * changed.\n     *\n     * The caller is expected to be a smart contract that implements either `IGeneralPool` or `IMinimalSwapInfoPool`,\n     * depending on the chosen specialization setting. This contract is known as the Pool's contract.\n     *\n     * Note that the same contract may register itself as multiple Pools with unique Pool IDs, or in other words,\n     * multiple Pools may share the same contract.\n     *\n     * Emits a `PoolRegistered` event.\n     */\n    function registerPool(PoolSpecialization specialization) external returns (bytes32);\n\n    /**\n     * @dev Emitted when a Pool is registered by calling `registerPool`.\n     */\n    event PoolRegistered(bytes32 indexed poolId, address indexed poolAddress, PoolSpecialization specialization);\n\n    /**\n     * @dev Returns a Pool's contract address and specialization setting.\n     */\n    function getPool(bytes32 poolId) external view returns (address, PoolSpecialization);\n\n    /**\n     * @dev Registers `tokens` for the `poolId` Pool. Must be called by the Pool's contract.\n     *\n     * Pools can only interact with tokens they have registered. Users join a Pool by transferring registered tokens,\n     * exit by receiving registered tokens, and can only swap registered tokens.\n     *\n     * Each token can only be registered once. For Pools with the Two Token specialization, `tokens` must have a length\n     * of two, that is, both tokens must be registered in the same `registerTokens` call, and they must be sorted in\n     * ascending order.\n     *\n     * The `tokens` and `assetManagers` arrays must have the same length, and each entry in these indicates the Asset\n     * Manager for the corresponding token. Asset Managers can manage a Pool's tokens via `managePoolBalance`,\n     * depositing and withdrawing them directly, and can even set their balance to arbitrary amounts. They are therefore\n     * expected to be highly secured smart contracts with sound design principles, and the decision to register an\n     * Asset Manager should not be made lightly.\n     *\n     * Pools can choose not to assign an Asset Manager to a given token by passing in the zero address. Once an Asset\n     * Manager is set, it cannot be changed except by deregistering the associated token and registering again with a\n     * different Asset Manager.\n     *\n     * Emits a `TokensRegistered` event.\n     */\n    function registerTokens(\n        bytes32 poolId,\n        IERC20[] memory tokens,\n        address[] memory assetManagers\n    ) external;\n\n    /**\n     * @dev Emitted when a Pool registers tokens by calling `registerTokens`.\n     */\n    event TokensRegistered(bytes32 indexed poolId, IERC20[] tokens, address[] assetManagers);\n\n    /**\n     * @dev Deregisters `tokens` for the `poolId` Pool. Must be called by the Pool's contract.\n     *\n     * Only registered tokens (via `registerTokens`) can be deregistered. Additionally, they must have zero total\n     * balance. For Pools with the Two Token specialization, `tokens` must have a length of two, that is, both tokens\n     * must be deregistered in the same `deregisterTokens` call.\n     *\n     * A deregistered token can be re-registered later on, possibly with a different Asset Manager.\n     *\n     * Emits a `TokensDeregistered` event.\n     */\n    function deregisterTokens(bytes32 poolId, IERC20[] memory tokens) external;\n\n    /**\n     * @dev Emitted when a Pool deregisters tokens by calling `deregisterTokens`.\n     */\n    event TokensDeregistered(bytes32 indexed poolId, IERC20[] tokens);\n\n    /**\n     * @dev Returns detailed information for a Pool's registered token.\n     *\n     * `cash` is the number of tokens the Vault currently holds for the Pool. `managed` is the number of tokens\n     * withdrawn and held outside the Vault by the Pool's token Asset Manager. The Pool's total balance for `token`\n     * equals the sum of `cash` and `managed`.\n     *\n     * Internally, `cash` and `managed` are stored using 112 bits. No action can ever cause a Pool's token `cash`,\n     * `managed` or `total` balance to be greater than 2^112 - 1.\n     *\n     * `lastChangeBlock` is the number of the block in which `token`'s total balance was last modified (via either a\n     * join, exit, swap, or Asset Manager update). This value is useful to avoid so-called 'sandwich attacks', for\n     * example when developing price oracles. A change of zero (e.g. caused by a swap with amount zero) is considered a\n     * change for this purpose, and will update `lastChangeBlock`.\n     *\n     * `assetManager` is the Pool's token Asset Manager.\n     */\n    function getPoolTokenInfo(bytes32 poolId, IERC20 token)\n        external\n        view\n        returns (\n            uint256 cash,\n            uint256 managed,\n            uint256 lastChangeBlock,\n            address assetManager\n        );\n\n    /**\n     * @dev Returns a Pool's registered tokens, the total balance for each, and the latest block when *any* of\n     * the tokens' `balances` changed.\n     *\n     * The order of the `tokens` array is the same order that will be used in `joinPool`, `exitPool`, as well as in all\n     * Pool hooks (where applicable). Calls to `registerTokens` and `deregisterTokens` may change this order.\n     *\n     * If a Pool only registers tokens once, and these are sorted in ascending order, they will be stored in the same\n     * order as passed to `registerTokens`.\n     *\n     * Total balances include both tokens held by the Vault and those withdrawn by the Pool's Asset Managers. These are\n     * the amounts used by joins, exits and swaps. For a detailed breakdown of token balances, use `getPoolTokenInfo`\n     * instead.\n     */\n    function getPoolTokens(bytes32 poolId)\n        external\n        view\n        returns (\n            IERC20[] memory tokens,\n            uint256[] memory balances,\n            uint256 lastChangeBlock\n        );\n\n    /**\n     * @dev Called by users to join a Pool, which transfers tokens from `sender` into the Pool's balance. This will\n     * trigger custom Pool behavior, which will typically grant something in return to `recipient` - often tokenized\n     * Pool shares.\n     *\n     * If the caller is not `sender`, it must be an authorized relayer for them.\n     *\n     * The `assets` and `maxAmountsIn` arrays must have the same length, and each entry indicates the maximum amount\n     * to send for each asset. The amounts to send are decided by the Pool and not the Vault: it just enforces\n     * these maximums.\n     *\n     * If joining a Pool that holds WETH, it is possible to send ETH directly: the Vault will do the wrapping. To enable\n     * this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead of the\n     * WETH address. Note that it is not possible to combine ETH and WETH in the same join. Any excess ETH will be sent\n     * back to the caller (not the sender, which is important for relayers).\n     *\n     * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when\n     * interacting with Pools that register and deregister tokens frequently. If sending ETH however, the array must be\n     * sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the final\n     * `assets` array might not be sorted. Pools with no registered tokens cannot be joined.\n     *\n     * If `fromInternalBalance` is true, the caller's Internal Balance will be preferred: ERC20 transfers will only\n     * be made for the difference between the requested amount and Internal Balance (if any). Note that ETH cannot be\n     * withdrawn from Internal Balance: attempting to do so will trigger a revert.\n     *\n     * This causes the Vault to call the `IBasePool.onJoinPool` hook on the Pool's contract, where Pools implement\n     * their own custom logic. This typically requires additional information from the user (such as the expected number\n     * of Pool shares). This can be encoded in the `userData` argument, which is ignored by the Vault and passed\n     * directly to the Pool's contract, as is `recipient`.\n     *\n     * Emits a `PoolBalanceChanged` event.\n     */\n    function joinPool(\n        bytes32 poolId,\n        address sender,\n        address recipient,\n        JoinPoolRequest memory request\n    ) external payable;\n\n    struct JoinPoolRequest {\n        IAsset[] assets;\n        uint256[] maxAmountsIn;\n        bytes userData;\n        bool fromInternalBalance;\n    }\n\n    /**\n     * @dev Called by users to exit a Pool, which transfers tokens from the Pool's balance to `recipient`. This will\n     * trigger custom Pool behavior, which will typically ask for something in return from `sender` - often tokenized\n     * Pool shares. The amount of tokens that can be withdrawn is limited by the Pool's `cash` balance (see\n     * `getPoolTokenInfo`).\n     *\n     * If the caller is not `sender`, it must be an authorized relayer for them.\n     *\n     * The `tokens` and `minAmountsOut` arrays must have the same length, and each entry in these indicates the minimum\n     * token amount to receive for each token contract. The amounts to send are decided by the Pool and not the Vault:\n     * it just enforces these minimums.\n     *\n     * If exiting a Pool that holds WETH, it is possible to receive ETH directly: the Vault will do the unwrapping. To\n     * enable this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead\n     * of the WETH address. Note that it is not possible to combine ETH and WETH in the same exit.\n     *\n     * `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when\n     * interacting with Pools that register and deregister tokens frequently. If receiving ETH however, the array must\n     * be sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the\n     * final `assets` array might not be sorted. Pools with no registered tokens cannot be exited.\n     *\n     * If `toInternalBalance` is true, the tokens will be deposited to `recipient`'s Internal Balance. Otherwise,\n     * an ERC20 transfer will be performed. Note that ETH cannot be deposited to Internal Balance: attempting to\n     * do so will trigger a revert.\n     *\n     * `minAmountsOut` is the minimum amount of tokens the user expects to get out of the Pool, for each token in the\n     * `tokens` array. This array must match the Pool's registered tokens.\n     *\n     * This causes the Vault to call the `IBasePool.onExitPool` hook on the Pool's contract, where Pools implement\n     * their own custom logic. This typically requires additional information from the user (such as the expected number\n     * of Pool shares to return). This can be encoded in the `userData` argument, which is ignored by the Vault and\n     * passed directly to the Pool's contract.\n     *\n     * Emits a `PoolBalanceChanged` event.\n     */\n    function exitPool(\n        bytes32 poolId,\n        address sender,\n        address payable recipient,\n        ExitPoolRequest memory request\n    ) external;\n\n    struct ExitPoolRequest {\n        IAsset[] assets;\n        uint256[] minAmountsOut;\n        bytes userData;\n        bool toInternalBalance;\n    }\n\n    /**\n     * @dev Emitted when a user joins or exits a Pool by calling `joinPool` or `exitPool`, respectively.\n     */\n    event PoolBalanceChanged(\n        bytes32 indexed poolId,\n        address indexed liquidityProvider,\n        IERC20[] tokens,\n        int256[] deltas,\n        uint256[] protocolFeeAmounts\n    );\n\n    enum PoolBalanceChangeKind { JOIN, EXIT }\n\n    // Swaps\n    //\n    // Users can swap tokens with Pools by calling the `swap` and `batchSwap` functions. To do this,\n    // they need not trust Pool contracts in any way: all security checks are made by the Vault. They must however be\n    // aware of the Pools' pricing algorithms in order to estimate the prices Pools will quote.\n    //\n    // The `swap` function executes a single swap, while `batchSwap` can perform multiple swaps in sequence.\n    // In each individual swap, tokens of one kind are sent from the sender to the Pool (this is the 'token in'),\n    // and tokens of another kind are sent from the Pool to the recipient in exchange (this is the 'token out').\n    // More complex swaps, such as one token in to multiple tokens out can be achieved by batching together\n    // individual swaps.\n    //\n    // There are two swap kinds:\n    //  - 'given in' swaps, where the amount of tokens in (sent to the Pool) is known, and the Pool determines (via the\n    // `onSwap` hook) the amount of tokens out (to send to the recipient).\n    //  - 'given out' swaps, where the amount of tokens out (received from the Pool) is known, and the Pool determines\n    // (via the `onSwap` hook) the amount of tokens in (to receive from the sender).\n    //\n    // Additionally, it is possible to chain swaps using a placeholder input amount, which the Vault replaces with\n    // the calculated output of the previous swap. If the previous swap was 'given in', this will be the calculated\n    // tokenOut amount. If the previous swap was 'given out', it will use the calculated tokenIn amount. These extended\n    // swaps are known as 'multihop' swaps, since they 'hop' through a number of intermediate tokens before arriving at\n    // the final intended token.\n    //\n    // In all cases, tokens are only transferred in and out of the Vault (or withdrawn from and deposited into Internal\n    // Balance) after all individual swaps have been completed, and the net token balance change computed. This makes\n    // certain swap patterns, such as multihops, or swaps that interact with the same token pair in multiple Pools, cost\n    // much less gas than they would otherwise.\n    //\n    // It also means that under certain conditions it is possible to perform arbitrage by swapping with multiple\n    // Pools in a way that results in net token movement out of the Vault (profit), with no tokens being sent in (only\n    // updating the Pool's internal accounting).\n    //\n    // To protect users from front-running or the market changing rapidly, they supply a list of 'limits' for each token\n    // involved in the swap, where either the maximum number of tokens to send (by passing a positive value) or the\n    // minimum amount of tokens to receive (by passing a negative value) is specified.\n    //\n    // Additionally, a 'deadline' timestamp can also be provided, forcing the swap to fail if it occurs after\n    // this point in time (e.g. if the transaction failed to be included in a block promptly).\n    //\n    // If interacting with Pools that hold WETH, it is possible to both send and receive ETH directly: the Vault will do\n    // the wrapping and unwrapping. To enable this mechanism, the IAsset sentinel value (the zero address) must be\n    // passed in the `assets` array instead of the WETH address. Note that it is possible to combine ETH and WETH in the\n    // same swap. Any excess ETH will be sent back to the caller (not the sender, which is relevant for relayers).\n    //\n    // Finally, Internal Balance can be used when either sending or receiving tokens.\n\n    enum SwapKind { GIVEN_IN, GIVEN_OUT }\n\n    /**\n     * @dev Performs a swap with a single Pool.\n     *\n     * If the swap is 'given in' (the number of tokens to send to the Pool is known), it returns the amount of tokens\n     * taken from the Pool, which must be greater than or equal to `limit`.\n     *\n     * If the swap is 'given out' (the number of tokens to take from the Pool is known), it returns the amount of tokens\n     * sent to the Pool, which must be less than or equal to `limit`.\n     *\n     * Internal Balance usage and the recipient are determined by the `funds` struct.\n     *\n     * Emits a `Swap` event.\n     */\n    function swap(\n        SingleSwap memory singleSwap,\n        FundManagement memory funds,\n        uint256 limit,\n        uint256 deadline\n    ) external payable returns (uint256);\n\n    /**\n     * @dev Data for a single swap executed by `swap`. `amount` is either `amountIn` or `amountOut` depending on\n     * the `kind` value.\n     *\n     * `assetIn` and `assetOut` are either token addresses, or the IAsset sentinel value for ETH (the zero address).\n     * Note that Pools never interact with ETH directly: it will be wrapped to or unwrapped from WETH by the Vault.\n     *\n     * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be\n     * used to extend swap behavior.\n     */\n    struct SingleSwap {\n        bytes32 poolId;\n        SwapKind kind;\n        IAsset assetIn;\n        IAsset assetOut;\n        uint256 amount;\n        bytes userData;\n    }\n\n    /**\n     * @dev Performs a series of swaps with one or multiple Pools. In each individual swap, the caller determines either\n     * the amount of tokens sent to or received from the Pool, depending on the `kind` value.\n     *\n     * Returns an array with the net Vault asset balance deltas. Positive amounts represent tokens (or ETH) sent to the\n     * Vault, and negative amounts represent tokens (or ETH) sent by the Vault. Each delta corresponds to the asset at\n     * the same index in the `assets` array.\n     *\n     * Swaps are executed sequentially, in the order specified by the `swaps` array. Each array element describes a\n     * Pool, the token to be sent to this Pool, the token to receive from it, and an amount that is either `amountIn` or\n     * `amountOut` depending on the swap kind.\n     *\n     * Multihop swaps can be executed by passing an `amount` value of zero for a swap. This will cause the amount in/out\n     * of the previous swap to be used as the amount in for the current one. In a 'given in' swap, 'tokenIn' must equal\n     * the previous swap's `tokenOut`. For a 'given out' swap, `tokenOut` must equal the previous swap's `tokenIn`.\n     *\n     * The `assets` array contains the addresses of all assets involved in the swaps. These are either token addresses,\n     * or the IAsset sentinel value for ETH (the zero address). Each entry in the `swaps` array specifies tokens in and\n     * out by referencing an index in `assets`. Note that Pools never interact with ETH directly: it will be wrapped to\n     * or unwrapped from WETH by the Vault.\n     *\n     * Internal Balance usage, sender, and recipient are determined by the `funds` struct. The `limits` array specifies\n     * the minimum or maximum amount of each token the vault is allowed to transfer.\n     *\n     * `batchSwap` can be used to make a single swap, like `swap` does, but doing so requires more gas than the\n     * equivalent `swap` call.\n     *\n     * Emits `Swap` events.\n     */\n    function batchSwap(\n        SwapKind kind,\n        BatchSwapStep[] memory swaps,\n        IAsset[] memory assets,\n        FundManagement memory funds,\n        int256[] memory limits,\n        uint256 deadline\n    ) external payable returns (int256[] memory);\n\n    /**\n     * @dev Data for each individual swap executed by `batchSwap`. The asset in and out fields are indexes into the\n     * `assets` array passed to that function, and ETH assets are converted to WETH.\n     *\n     * If `amount` is zero, the multihop mechanism is used to determine the actual amount based on the amount in/out\n     * from the previous swap, depending on the swap kind.\n     *\n     * The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be\n     * used to extend swap behavior.\n     */\n    struct BatchSwapStep {\n        bytes32 poolId;\n        uint256 assetInIndex;\n        uint256 assetOutIndex;\n        uint256 amount;\n        bytes userData;\n    }\n\n    /**\n     * @dev Emitted for each individual swap performed by `swap` or `batchSwap`.\n     */\n    event Swap(\n        bytes32 indexed poolId,\n        IERC20 indexed tokenIn,\n        IERC20 indexed tokenOut,\n        uint256 amountIn,\n        uint256 amountOut\n    );\n\n    /**\n     * @dev All tokens in a swap are either sent from the `sender` account to the Vault, or from the Vault to the\n     * `recipient` account.\n     *\n     * If the caller is not `sender`, it must be an authorized relayer for them.\n     *\n     * If `fromInternalBalance` is true, the `sender`'s Internal Balance will be preferred, performing an ERC20\n     * transfer for the difference between the requested amount and the User's Internal Balance (if any). The `sender`\n     * must have allowed the Vault to use their tokens via `IERC20.approve()`. This matches the behavior of\n     * `joinPool`.\n     *\n     * If `toInternalBalance` is true, tokens will be deposited to `recipient`'s internal balance instead of\n     * transferred. This matches the behavior of `exitPool`.\n     *\n     * Note that ETH cannot be deposited to or withdrawn from Internal Balance: attempting to do so will trigger a\n     * revert.\n     */\n    struct FundManagement {\n        address sender;\n        bool fromInternalBalance;\n        address payable recipient;\n        bool toInternalBalance;\n    }\n\n    /**\n     * @dev Simulates a call to `batchSwap`, returning an array of Vault asset deltas. Calls to `swap` cannot be\n     * simulated directly, but an equivalent `batchSwap` call can and will yield the exact same result.\n     *\n     * Each element in the array corresponds to the asset at the same index, and indicates the number of tokens (or ETH)\n     * the Vault would take from the sender (if positive) or send to the recipient (if negative). The arguments it\n     * receives are the same that an equivalent `batchSwap` call would receive.\n     *\n     * Unlike `batchSwap`, this function performs no checks on the sender or recipient field in the `funds` struct.\n     * This makes it suitable to be called by off-chain applications via eth_call without needing to hold tokens,\n     * approve them for the Vault, or even know a user's address.\n     *\n     * Note that this function is not 'view' (due to implementation details): the client code must explicitly execute\n     * eth_call instead of eth_sendTransaction.\n     */\n    function queryBatchSwap(\n        SwapKind kind,\n        BatchSwapStep[] memory swaps,\n        IAsset[] memory assets,\n        FundManagement memory funds\n    ) external returns (int256[] memory assetDeltas);\n\n    // Flash Loans\n\n    /**\n     * @dev Performs a 'flash loan', sending tokens to `recipient`, executing the `receiveFlashLoan` hook on it,\n     * and then reverting unless the tokens plus a proportional protocol fee have been returned.\n     *\n     * The `tokens` and `amounts` arrays must have the same length, and each entry in these indicates the loan amount\n     * for each token contract. `tokens` must be sorted in ascending order.\n     *\n     * The 'userData' field is ignored by the Vault, and forwarded as-is to `recipient` as part of the\n     * `receiveFlashLoan` call.\n     *\n     * Emits `FlashLoan` events.\n     */\n    function flashLoan(\n        IFlashLoanRecipient recipient,\n        IERC20[] memory tokens,\n        uint256[] memory amounts,\n        bytes memory userData\n    ) external;\n\n    /**\n     * @dev Emitted for each individual flash loan performed by `flashLoan`.\n     */\n    event FlashLoan(IFlashLoanRecipient indexed recipient, IERC20 indexed token, uint256 amount, uint256 feeAmount);\n\n    // Asset Management\n    //\n    // Each token registered for a Pool can be assigned an Asset Manager, which is able to freely withdraw the Pool's\n    // tokens from the Vault, deposit them, or assign arbitrary values to its `managed` balance (see\n    // `getPoolTokenInfo`). This makes them extremely powerful and dangerous. Even if an Asset Manager only directly\n    // controls one of the tokens in a Pool, a malicious manager could set that token's balance to manipulate the\n    // prices of the other tokens, and then drain the Pool with swaps. The risk of using Asset Managers is therefore\n    // not constrained to the tokens they are managing, but extends to the entire Pool's holdings.\n    //\n    // However, a properly designed Asset Manager smart contract can be safely used for the Pool's benefit,\n    // for example by lending unused tokens out for interest, or using them to participate in voting protocols.\n    //\n    // This concept is unrelated to the IAsset interface.\n\n    /**\n     * @dev Performs a set of Pool balance operations, which may be either withdrawals, deposits or updates.\n     *\n     * Pool Balance management features batching, which means a single contract call can be used to perform multiple\n     * operations of different kinds, with different Pools and tokens, at once.\n     *\n     * For each operation, the caller must be registered as the Asset Manager for `token` in `poolId`.\n     */\n    function managePoolBalance(PoolBalanceOp[] memory ops) external;\n\n    struct PoolBalanceOp {\n        PoolBalanceOpKind kind;\n        bytes32 poolId;\n        IERC20 token;\n        uint256 amount;\n    }\n\n    /**\n     * Withdrawals decrease the Pool's cash, but increase its managed balance, leaving the total balance unchanged.\n     *\n     * Deposits increase the Pool's cash, but decrease its managed balance, leaving the total balance unchanged.\n     *\n     * Updates don't affect the Pool's cash balance, but because the managed balance changes, it does alter the total.\n     * The external amount can be either increased or decreased by this call (i.e., reporting a gain or a loss).\n     */\n    enum PoolBalanceOpKind { WITHDRAW, DEPOSIT, UPDATE }\n\n    /**\n     * @dev Emitted when a Pool's token Asset Manager alters its balance via `managePoolBalance`.\n     */\n    event PoolBalanceManaged(\n        bytes32 indexed poolId,\n        address indexed assetManager,\n        IERC20 indexed token,\n        int256 cashDelta,\n        int256 managedDelta\n    );\n\n    // Protocol Fees\n    //\n    // Some operations cause the Vault to collect tokens in the form of protocol fees, which can then be withdrawn by\n    // permissioned accounts.\n    //\n    // There are two kinds of protocol fees:\n    //\n    //  - flash loan fees: charged on all flash loans, as a percentage of the amounts lent.\n    //\n    //  - swap fees: a percentage of the fees charged by Pools when performing swaps. For a number of reasons, including\n    // swap gas costs and interface simplicity, protocol swap fees are not charged on each individual swap. Rather,\n    // Pools are expected to keep track of how much they have charged in swap fees, and pay any outstanding debts to the\n    // Vault when they are joined or exited. This prevents users from joining a Pool with unpaid debt, as well as\n    // exiting a Pool in debt without first paying their share.\n\n    /**\n     * @dev Returns the current protocol fee module.\n     */\n    function getProtocolFeesCollector() external view returns (IProtocolFeesCollector);\n\n    /**\n     * @dev Safety mechanism to pause most Vault operations in the event of an emergency - typically detection of an\n     * error in some part of the system.\n     *\n     * The Vault can only be paused during an initial time period, after which pausing is forever disabled.\n     *\n     * While the contract is paused, the following features are disabled:\n     * - depositing and transferring internal balance\n     * - transferring external balance (using the Vault's allowance)\n     * - swaps\n     * - joining Pools\n     * - Asset Manager interactions\n     *\n     * Internal Balance can still be withdrawn, and Pools exited.\n     */\n    function setPaused(bool paused) external;\n\n    /**\n     * @dev Returns the Vault's WETH instance.\n     */\n    function WETH() external view returns (IWETH);\n    // solhint-disable-previous-line func-name-mixedcase\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Storage of the initializable contract.\n     *\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n     * when using with upgradeable contracts.\n     *\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n     */\n    struct InitializableStorage {\n        /**\n         * @dev Indicates that the contract has been initialized.\n         */\n        uint64 _initialized;\n        /**\n         * @dev Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n    /**\n     * @dev The contract is already initialized.\n     */\n    error InvalidInitialization();\n\n    /**\n     * @dev The contract is not initializing.\n     */\n    error NotInitializing();\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint64 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n     * production.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        // Cache values to avoid duplicated sloads\n        bool isTopLevelCall = !$._initializing;\n        uint64 initialized = $._initialized;\n\n        // Allowed calls:\n        // - initialSetup: the contract is not in the initializing state and no previous version was\n        //                 initialized\n        // - construction: the contract is initialized at version 1 (no reininitialization) and the\n        //                 current contract is just being deployed\n        bool initialSetup = initialized == 0 && isTopLevelCall;\n        bool construction = initialized == 1 && address(this).code.length == 0;\n\n        if (!initialSetup && !construction) {\n            revert InvalidInitialization();\n        }\n        $._initialized = 1;\n        if (isTopLevelCall) {\n            $._initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            $._initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint64 version) {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing || $._initialized >= version) {\n            revert InvalidInitialization();\n        }\n        $._initialized = version;\n        $._initializing = true;\n        _;\n        $._initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        _checkInitializing();\n        _;\n    }\n\n    /**\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n     */\n    function _checkInitializing() internal view virtual {\n        if (!_isInitializing()) {\n            revert NotInitializing();\n        }\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing) {\n            revert InvalidInitialization();\n        }\n        if ($._initialized != type(uint64).max) {\n            $._initialized = type(uint64).max;\n            emit Initialized(type(uint64).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint64) {\n        return _getInitializableStorage()._initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _getInitializableStorage()._initializing;\n    }\n\n    /**\n     * @dev Returns a pointer to the storage namespace.\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n        assembly {\n            $.slot := INITIALIZABLE_STORAGE\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC1822Proxiable} from \"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\";\nimport {ERC1967Utils} from \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\";\nimport {Initializable} from \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {\n    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n    address private immutable __self = address(this);\n\n    /**\n     * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\n     * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\n     * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\n     * If the getter returns `\"5.0.0\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\n     * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\n     * during an upgrade.\n     */\n    string public constant UPGRADE_INTERFACE_VERSION = \"5.0.0\";\n\n    /**\n     * @dev The call is from an unauthorized context.\n     */\n    error UUPSUnauthorizedCallContext();\n\n    /**\n     * @dev The storage `slot` is unsupported as a UUID.\n     */\n    error UUPSUnsupportedProxiableUUID(bytes32 slot);\n\n    /**\n     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n     * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n     * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n     * fail.\n     */\n    modifier onlyProxy() {\n        _checkProxy();\n        _;\n    }\n\n    /**\n     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n     * callable on the implementing contract but not through proxies.\n     */\n    modifier notDelegated() {\n        _checkNotDelegated();\n        _;\n    }\n\n    function __UUPSUpgradeable_init() internal onlyInitializing {\n    }\n\n    function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n     * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n     */\n    function proxiableUUID() external view virtual notDelegated returns (bytes32) {\n        return ERC1967Utils.IMPLEMENTATION_SLOT;\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n     * encoded in `data`.\n     *\n     * Calls {_authorizeUpgrade}.\n     *\n     * Emits an {Upgraded} event.\n     *\n     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n     */\n    function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\n        _authorizeUpgrade(newImplementation);\n        _upgradeToAndCallUUPS(newImplementation, data);\n    }\n\n    /**\n     * @dev Reverts if the execution is not performed via delegatecall or the execution\n     * context is not of a proxy with an ERC1967-compliant implementation pointing to self.\n     * See {_onlyProxy}.\n     */\n    function _checkProxy() internal view virtual {\n        if (\n            address(this) == __self || // Must be called through delegatecall\n            ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\n        ) {\n            revert UUPSUnauthorizedCallContext();\n        }\n    }\n\n    /**\n     * @dev Reverts if the execution is performed via delegatecall.\n     * See {notDelegated}.\n     */\n    function _checkNotDelegated() internal view virtual {\n        if (address(this) != __self) {\n            // Must not be called through delegatecall\n            revert UUPSUnauthorizedCallContext();\n        }\n    }\n\n    /**\n     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n     * {upgradeToAndCall}.\n     *\n     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n     *\n     * ```solidity\n     * function _authorizeUpgrade(address) internal onlyOwner {}\n     * ```\n     */\n    function _authorizeUpgrade(address newImplementation) internal virtual;\n\n    /**\n     * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\n     *\n     * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\n     * is expected to be the implementation slot in ERC1967.\n     *\n     * Emits an {IERC1967-Upgraded} event.\n     */\n    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\n        try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n            if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\n                revert UUPSUnsupportedProxiableUUID(slot);\n            }\n            ERC1967Utils.upgradeToAndCall(newImplementation, data);\n        } catch {\n            // The implementation is not UUPS\n            revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/access/IAccessControl.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev The `account` is missing a role.\n     */\n    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n    /**\n     * @dev The caller of a function is not the expected one.\n     *\n     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n     */\n    error AccessControlBadConfirmation();\n\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    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 `callerConfirmation`.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n"
      },
      "@openzeppelin/contracts/interfaces/draft-IERC1822.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n    /**\n     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n     * address.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy.\n     */\n    function proxiableUUID() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n    /**\n     * @dev Must return an address that can be used as a delegate call target.\n     *\n     * {UpgradeableBeacon} will check that this address is a contract.\n     */\n    function implementation() external view returns (address);\n}\n"
      },
      "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol)\n\npragma solidity ^0.8.20;\n\nimport {IBeacon} from \"../beacon/IBeacon.sol\";\nimport {Address} from \"../../utils/Address.sol\";\nimport {StorageSlot} from \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n */\nlibrary ERC1967Utils {\n    // We re-declare ERC-1967 events here because they can't be used directly from IERC1967.\n    // This will be fixed in Solidity 0.8.21. At that point we should remove these events.\n    /**\n     * @dev Emitted when the implementation is upgraded.\n     */\n    event Upgraded(address indexed implementation);\n\n    /**\n     * @dev Emitted when the admin account has changed.\n     */\n    event AdminChanged(address previousAdmin, address newAdmin);\n\n    /**\n     * @dev Emitted when the beacon is changed.\n     */\n    event BeaconUpgraded(address indexed beacon);\n\n    /**\n     * @dev Storage slot with the address of the current implementation.\n     * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1.\n     */\n    // solhint-disable-next-line private-vars-leading-underscore\n    bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /**\n     * @dev The `implementation` of the proxy is invalid.\n     */\n    error ERC1967InvalidImplementation(address implementation);\n\n    /**\n     * @dev The `admin` of the proxy is invalid.\n     */\n    error ERC1967InvalidAdmin(address admin);\n\n    /**\n     * @dev The `beacon` of the proxy is invalid.\n     */\n    error ERC1967InvalidBeacon(address beacon);\n\n    /**\n     * @dev An upgrade function sees `msg.value > 0` that may be lost.\n     */\n    error ERC1967NonPayable();\n\n    /**\n     * @dev Returns the current implementation address.\n     */\n    function getImplementation() internal view returns (address) {\n        return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 implementation slot.\n     */\n    function _setImplementation(address newImplementation) private {\n        if (newImplementation.code.length == 0) {\n            revert ERC1967InvalidImplementation(newImplementation);\n        }\n        StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\n    }\n\n    /**\n     * @dev Performs implementation upgrade with additional setup call if data is nonempty.\n     * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n     * to avoid stuck value in the contract.\n     *\n     * Emits an {IERC1967-Upgraded} event.\n     */\n    function upgradeToAndCall(address newImplementation, bytes memory data) internal {\n        _setImplementation(newImplementation);\n        emit Upgraded(newImplementation);\n\n        if (data.length > 0) {\n            Address.functionDelegateCall(newImplementation, data);\n        } else {\n            _checkNonPayable();\n        }\n    }\n\n    /**\n     * @dev Storage slot with the admin of the contract.\n     * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1.\n     */\n    // solhint-disable-next-line private-vars-leading-underscore\n    bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /**\n     * @dev Returns the current admin.\n     *\n     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using\n     * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n     * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n     */\n    function getAdmin() internal view returns (address) {\n        return StorageSlot.getAddressSlot(ADMIN_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 admin slot.\n     */\n    function _setAdmin(address newAdmin) private {\n        if (newAdmin == address(0)) {\n            revert ERC1967InvalidAdmin(address(0));\n        }\n        StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\n    }\n\n    /**\n     * @dev Changes the admin of the proxy.\n     *\n     * Emits an {IERC1967-AdminChanged} event.\n     */\n    function changeAdmin(address newAdmin) internal {\n        emit AdminChanged(getAdmin(), newAdmin);\n        _setAdmin(newAdmin);\n    }\n\n    /**\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n     * This is the keccak-256 hash of \"eip1967.proxy.beacon\" subtracted by 1.\n     */\n    // solhint-disable-next-line private-vars-leading-underscore\n    bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n    /**\n     * @dev Returns the current beacon.\n     */\n    function getBeacon() internal view returns (address) {\n        return StorageSlot.getAddressSlot(BEACON_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new beacon in the EIP1967 beacon slot.\n     */\n    function _setBeacon(address newBeacon) private {\n        if (newBeacon.code.length == 0) {\n            revert ERC1967InvalidBeacon(newBeacon);\n        }\n\n        StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\n\n        address beaconImplementation = IBeacon(newBeacon).implementation();\n        if (beaconImplementation.code.length == 0) {\n            revert ERC1967InvalidImplementation(beaconImplementation);\n        }\n    }\n\n    /**\n     * @dev Change the beacon and trigger a setup call if data is nonempty.\n     * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n     * to avoid stuck value in the contract.\n     *\n     * Emits an {IERC1967-BeaconUpgraded} event.\n     *\n     * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\n     * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\n     * efficiency.\n     */\n    function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\n        _setBeacon(newBeacon);\n        emit BeaconUpgraded(newBeacon);\n\n        if (data.length > 0) {\n            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n        } else {\n            _checkNonPayable();\n        }\n    }\n\n    /**\n     * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\n     * if an upgrade doesn't perform an initialization call.\n     */\n    function _checkNonPayable() private {\n        if (msg.value > 0) {\n            revert ERC1967NonPayable();\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     *\n     * CAUTION: See Security Considerations above.\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC20Permit} from \"../extensions/IERC20Permit.sol\";\nimport {Address} from \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev An operation with an ERC20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data);\n        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert FailedInnerCall();\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    /**\n     * @dev Muldiv operation overflow.\n     */\n    error MathOverflowedMulDiv();\n\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\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 towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            return a / b;\n        }\n\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\n     * denominator == 0.\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * 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 = x * y; // 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                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            if (denominator <= prod1) {\n                revert MathOverflowedMulDiv();\n            }\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.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\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\n            // works 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 (unsignedRoundsUp(rounding) && 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\n     * towards zero.\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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\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 + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\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 + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/StorageSlot.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(newImplementation.code.length > 0);\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    struct StringSlot {\n        string value;\n    }\n\n    struct BytesSlot {\n        bytes value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n     */\n    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n     */\n    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := store.slot\n        }\n    }\n}\n"
      },
      "@pendle/core-v2/contracts/core/libraries/BoringOwnableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\ncontract BoringOwnableUpgradeableData {\n    address public owner;\n    address public pendingOwner;\n}\n\nabstract contract BoringOwnableUpgradeable is BoringOwnableUpgradeableData, Initializable {\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    function __BoringOwnable_init() internal onlyInitializing {\n        owner = msg.sender;\n    }\n\n    /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.\n    /// Can only be invoked by the current `owner`.\n    /// @param newOwner Address of the new owner.\n    /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.\n    /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.\n    function transferOwnership(address newOwner, bool direct, bool renounce) public onlyOwner {\n        if (direct) {\n            // Checks\n            require(newOwner != address(0) || renounce, \"Ownable: zero address\");\n\n            // Effects\n            emit OwnershipTransferred(owner, newOwner);\n            owner = newOwner;\n            pendingOwner = address(0);\n        } else {\n            // Effects\n            pendingOwner = newOwner;\n        }\n    }\n\n    /// @notice Needs to be called by `pendingOwner` to claim ownership.\n    function claimOwnership() public {\n        address _pendingOwner = pendingOwner;\n\n        // Checks\n        require(msg.sender == _pendingOwner, \"Ownable: caller != pending owner\");\n\n        // Effects\n        emit OwnershipTransferred(owner, _pendingOwner);\n        owner = _pendingOwner;\n        pendingOwner = address(0);\n    }\n\n    /// @notice Only allows the `owner` to execute the function.\n    modifier onlyOwner() {\n        require(msg.sender == owner, \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    uint256[48] private __gap;\n}\n"
      },
      "@pendle/core-v2/contracts/core/libraries/Errors.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nlibrary Errors {\n    // BulkSeller\n    error BulkInsufficientSyForTrade(uint256 currentAmount, uint256 requiredAmount);\n    error BulkInsufficientTokenForTrade(uint256 currentAmount, uint256 requiredAmount);\n    error BulkInSufficientSyOut(uint256 actualSyOut, uint256 requiredSyOut);\n    error BulkInSufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut);\n    error BulkInsufficientSyReceived(uint256 actualBalance, uint256 requiredBalance);\n    error BulkNotMaintainer();\n    error BulkNotAdmin();\n    error BulkSellerAlreadyExisted(address token, address SY, address bulk);\n    error BulkSellerInvalidToken(address token, address SY);\n    error BulkBadRateTokenToSy(uint256 actualRate, uint256 currentRate, uint256 eps);\n    error BulkBadRateSyToToken(uint256 actualRate, uint256 currentRate, uint256 eps);\n\n    // APPROX\n    error ApproxFail();\n    error ApproxParamsInvalid(uint256 guessMin, uint256 guessMax, uint256 eps);\n    error ApproxBinarySearchInputInvalid(\n        uint256 approxGuessMin,\n        uint256 approxGuessMax,\n        uint256 minGuessMin,\n        uint256 maxGuessMax\n    );\n\n    // MARKET + MARKET MATH CORE\n    error MarketExpired();\n    error MarketZeroAmountsInput();\n    error MarketZeroAmountsOutput();\n    error MarketZeroLnImpliedRate();\n    error MarketInsufficientPtForTrade(int256 currentAmount, int256 requiredAmount);\n    error MarketInsufficientPtReceived(uint256 actualBalance, uint256 requiredBalance);\n    error MarketInsufficientSyReceived(uint256 actualBalance, uint256 requiredBalance);\n    error MarketZeroTotalPtOrTotalAsset(int256 totalPt, int256 totalAsset);\n    error MarketExchangeRateBelowOne(int256 exchangeRate);\n    error MarketProportionMustNotEqualOne();\n    error MarketRateScalarBelowZero(int256 rateScalar);\n    error MarketScalarRootBelowZero(int256 scalarRoot);\n    error MarketProportionTooHigh(int256 proportion, int256 maxProportion);\n\n    error OracleUninitialized();\n    error OracleTargetTooOld(uint32 target, uint32 oldest);\n    error OracleZeroCardinality();\n\n    error MarketFactoryExpiredPt();\n    error MarketFactoryInvalidPt();\n    error MarketFactoryMarketExists();\n\n    error MarketFactoryLnFeeRateRootTooHigh(uint80 lnFeeRateRoot, uint256 maxLnFeeRateRoot);\n    error MarketFactoryOverriddenFeeTooHigh(uint80 overriddenFee, uint256 marketLnFeeRateRoot);\n    error MarketFactoryReserveFeePercentTooHigh(uint8 reserveFeePercent, uint8 maxReserveFeePercent);\n    error MarketFactoryZeroTreasury();\n    error MarketFactoryInitialAnchorTooLow(int256 initialAnchor, int256 minInitialAnchor);\n    error MFNotPendleMarket(address addr);\n\n    // ROUTER\n    error RouterInsufficientLpOut(uint256 actualLpOut, uint256 requiredLpOut);\n    error RouterInsufficientSyOut(uint256 actualSyOut, uint256 requiredSyOut);\n    error RouterInsufficientPtOut(uint256 actualPtOut, uint256 requiredPtOut);\n    error RouterInsufficientYtOut(uint256 actualYtOut, uint256 requiredYtOut);\n    error RouterInsufficientPYOut(uint256 actualPYOut, uint256 requiredPYOut);\n    error RouterInsufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut);\n    error RouterInsufficientSyRepay(uint256 actualSyRepay, uint256 requiredSyRepay);\n    error RouterInsufficientPtRepay(uint256 actualPtRepay, uint256 requiredPtRepay);\n    error RouterNotAllSyUsed(uint256 netSyDesired, uint256 netSyUsed);\n\n    error RouterTimeRangeZero();\n    error RouterCallbackNotPendleMarket(address caller);\n    error RouterInvalidAction(bytes4 selector);\n    error RouterInvalidFacet(address facet);\n\n    error RouterKyberSwapDataZero();\n\n    error SimulationResults(bool success, bytes res);\n\n    // YIELD CONTRACT\n    error YCExpired();\n    error YCNotExpired();\n    error YieldContractInsufficientSy(uint256 actualSy, uint256 requiredSy);\n    error YCNothingToRedeem();\n    error YCPostExpiryDataNotSet();\n    error YCNoFloatingSy();\n\n    // YieldFactory\n    error YCFactoryInvalidExpiry();\n    error YCFactoryYieldContractExisted();\n    error YCFactoryZeroExpiryDivisor();\n    error YCFactoryZeroTreasury();\n    error YCFactoryInterestFeeRateTooHigh(uint256 interestFeeRate, uint256 maxInterestFeeRate);\n    error YCFactoryRewardFeeRateTooHigh(uint256 newRewardFeeRate, uint256 maxRewardFeeRate);\n\n    // SY\n    error SYInvalidTokenIn(address token);\n    error SYInvalidTokenOut(address token);\n    error SYZeroDeposit();\n    error SYZeroRedeem();\n    error SYInsufficientSharesOut(uint256 actualSharesOut, uint256 requiredSharesOut);\n    error SYInsufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut);\n\n    // SY-specific\n    error SYQiTokenMintFailed(uint256 errCode);\n    error SYQiTokenRedeemFailed(uint256 errCode);\n    error SYQiTokenRedeemRewardsFailed(uint256 rewardAccruedType0, uint256 rewardAccruedType1);\n    error SYQiTokenBorrowRateTooHigh(uint256 borrowRate, uint256 borrowRateMax);\n\n    error SYCurveInvalidPid();\n    error SYCurve3crvPoolNotFound();\n\n    error SYApeDepositAmountTooSmall(uint256 amountDeposited);\n    error SYBalancerInvalidPid();\n    error SYInvalidRewardToken(address token);\n\n    error SYStargateRedeemCapExceeded(uint256 amountLpDesired, uint256 amountLpRedeemable);\n\n    error SYBalancerReentrancy();\n\n    error NotFromTrustedRemote(uint16 srcChainId, bytes path);\n\n    error ApxETHNotEnoughBuffer();\n\n    // Liquidity Mining\n    error VCInactivePool(address pool);\n    error VCPoolAlreadyActive(address pool);\n    error VCZeroVePendle(address user);\n    error VCExceededMaxWeight(uint256 totalWeight, uint256 maxWeight);\n    error VCEpochNotFinalized(uint256 wTime);\n    error VCPoolAlreadyAddAndRemoved(address pool);\n\n    error VEInvalidNewExpiry(uint256 newExpiry);\n    error VEExceededMaxLockTime();\n    error VEInsufficientLockTime();\n    error VENotAllowedReduceExpiry();\n    error VEZeroAmountLocked();\n    error VEPositionNotExpired();\n    error VEZeroPosition();\n    error VEZeroSlope(uint128 bias, uint128 slope);\n    error VEReceiveOldSupply(uint256 msgTime);\n\n    error GCNotPendleMarket(address caller);\n    error GCNotVotingController(address caller);\n\n    error InvalidWTime(uint256 wTime);\n    error ExpiryInThePast(uint256 expiry);\n    error ChainNotSupported(uint256 chainId);\n\n    error FDTotalAmountFundedNotMatch(uint256 actualTotalAmount, uint256 expectedTotalAmount);\n    error FDEpochLengthMismatch();\n    error FDInvalidPool(address pool);\n    error FDPoolAlreadyExists(address pool);\n    error FDInvalidNewFinishedEpoch(uint256 oldFinishedEpoch, uint256 newFinishedEpoch);\n    error FDInvalidStartEpoch(uint256 startEpoch);\n    error FDInvalidWTimeFund(uint256 lastFunded, uint256 wTime);\n    error FDFutureFunding(uint256 lastFunded, uint256 currentWTime);\n\n    error BDInvalidEpoch(uint256 epoch, uint256 startTime);\n\n    // Cross-Chain\n    error MsgNotFromSendEndpoint(uint16 srcChainId, bytes path);\n    error MsgNotFromReceiveEndpoint(address sender);\n    error InsufficientFeeToSendMsg(uint256 currentFee, uint256 requiredFee);\n    error ApproxDstExecutionGasNotSet();\n    error InvalidRetryData();\n\n    // GENERIC MSG\n    error ArrayLengthMismatch();\n    error ArrayEmpty();\n    error ArrayOutOfBounds();\n    error ZeroAddress();\n    error FailedToSendEther();\n    error InvalidMerkleProof();\n\n    error OnlyLayerZeroEndpoint();\n    error OnlyYT();\n    error OnlyYCFactory();\n    error OnlyWhitelisted();\n\n    // Swap Aggregator\n    error SAInsufficientTokenIn(address tokenIn, uint256 amountExpected, uint256 amountActual);\n    error UnsupportedSelector(uint256 aggregatorType, bytes4 selector);\n}\n"
      },
      "@pendle/core-v2/contracts/core/libraries/math/LogExpMath.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\n// documentation files (the “Software”), to deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the\n// Software.\n\n// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\npragma solidity ^0.8.0;\n\n/* solhint-disable */\n\n/**\n * @dev Exponentiation and logarithm functions for 18 decimal fixed point numbers (both base and exponent/argument).\n *\n * Exponentiation and logarithm with arbitrary bases (x^y and log_x(y)) are implemented by conversion to natural\n * exponentiation and logarithm (where the base is Euler's number).\n *\n * @author Fernando Martinelli - @fernandomartinelli\n * @author Sergio Yuhjtman - @sergioyuhjtman\n * @author Daniel Fernandez - @dmf7z\n */\nlibrary LogExpMath {\n    // All fixed point multiplications and divisions are inlined. This means we need to divide by ONE when multiplying\n    // two numbers, and multiply by ONE when dividing them.\n\n    // All arguments and return values are 18 decimal fixed point numbers.\n    int256 constant ONE_18 = 1e18;\n\n    // Internally, intermediate values are computed with higher precision as 20 decimal fixed point numbers, and in the\n    // case of ln36, 36 decimals.\n    int256 constant ONE_20 = 1e20;\n    int256 constant ONE_36 = 1e36;\n\n    // The domain of natural exponentiation is bound by the word size and number of decimals used.\n    //\n    // Because internally the result will be stored using 20 decimals, the largest possible result is\n    // (2^255 - 1) / 10^20, which makes the largest exponent ln((2^255 - 1) / 10^20) = 130.700829182905140221.\n    // The smallest possible result is 10^(-18), which makes largest negative argument\n    // ln(10^(-18)) = -41.446531673892822312.\n    // We use 130.0 and -41.0 to have some safety margin.\n    int256 constant MAX_NATURAL_EXPONENT = 130e18;\n    int256 constant MIN_NATURAL_EXPONENT = -41e18;\n\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\n    // 256 bit integer.\n    int256 constant LN_36_LOWER_BOUND = ONE_18 - 1e17;\n    int256 constant LN_36_UPPER_BOUND = ONE_18 + 1e17;\n\n    uint256 constant MILD_EXPONENT_BOUND = 2 ** 254 / uint256(ONE_20);\n\n    // 18 decimal constants\n    int256 constant x0 = 128000000000000000000; // 2ˆ7\n    int256 constant a0 = 38877084059945950922200000000000000000000000000000000000; // eˆ(x0) (no decimals)\n    int256 constant x1 = 64000000000000000000; // 2ˆ6\n    int256 constant a1 = 6235149080811616882910000000; // eˆ(x1) (no decimals)\n\n    // 20 decimal constants\n    int256 constant x2 = 3200000000000000000000; // 2ˆ5\n    int256 constant a2 = 7896296018268069516100000000000000; // eˆ(x2)\n    int256 constant x3 = 1600000000000000000000; // 2ˆ4\n    int256 constant a3 = 888611052050787263676000000; // eˆ(x3)\n    int256 constant x4 = 800000000000000000000; // 2ˆ3\n    int256 constant a4 = 298095798704172827474000; // eˆ(x4)\n    int256 constant x5 = 400000000000000000000; // 2ˆ2\n    int256 constant a5 = 5459815003314423907810; // eˆ(x5)\n    int256 constant x6 = 200000000000000000000; // 2ˆ1\n    int256 constant a6 = 738905609893065022723; // eˆ(x6)\n    int256 constant x7 = 100000000000000000000; // 2ˆ0\n    int256 constant a7 = 271828182845904523536; // eˆ(x7)\n    int256 constant x8 = 50000000000000000000; // 2ˆ-1\n    int256 constant a8 = 164872127070012814685; // eˆ(x8)\n    int256 constant x9 = 25000000000000000000; // 2ˆ-2\n    int256 constant a9 = 128402541668774148407; // eˆ(x9)\n    int256 constant x10 = 12500000000000000000; // 2ˆ-3\n    int256 constant a10 = 113314845306682631683; // eˆ(x10)\n    int256 constant x11 = 6250000000000000000; // 2ˆ-4\n    int256 constant a11 = 106449445891785942956; // eˆ(x11)\n\n    /**\n     * @dev Natural exponentiation (e^x) with signed 18 decimal fixed point exponent.\n     *\n     * Reverts if `x` is smaller than MIN_NATURAL_EXPONENT, or larger than `MAX_NATURAL_EXPONENT`.\n     */\n    function exp(int256 x) internal pure returns (int256) {\n        unchecked {\n            require(x >= MIN_NATURAL_EXPONENT && x <= MAX_NATURAL_EXPONENT, \"Invalid exponent\");\n\n            if (x < 0) {\n                // We only handle positive exponents: e^(-x) is computed as 1 / e^x. We can safely make x positive since it\n                // fits in the signed 256 bit range (as it is larger than MIN_NATURAL_EXPONENT).\n                // Fixed point division requires multiplying by ONE_18.\n                return ((ONE_18 * ONE_18) / exp(-x));\n            }\n\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,\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\n            // because all larger powers are larger than MAX_NATURAL_EXPONENT, and therefore not present in the\n            // decomposition.\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\n            // decomposition, which will be lower than the smallest x_n.\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.\n            // We mutate x by subtracting x_n, making it the remainder of the decomposition.\n\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\n            // intermediate overflows. Instead we store them as plain integers, with 0 decimals.\n            // Additionally, x0 + x1 is larger than MAX_NATURAL_EXPONENT, which means they will not both be present in the\n            // decomposition.\n\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\n            // it and compute the accumulated product.\n\n            int256 firstAN;\n            if (x >= x0) {\n                x -= x0;\n                firstAN = a0;\n            } else if (x >= x1) {\n                x -= x1;\n                firstAN = a1;\n            } else {\n                firstAN = 1; // One with no decimal places\n            }\n\n            // We now transform x into a 20 decimal fixed point number, to have enhanced precision when computing the\n            // smaller terms.\n            x *= 100;\n\n            // `product` is the accumulated product of all a_n (except a0 and a1), which starts at 20 decimal fixed point\n            // one. Recall that fixed point multiplication requires dividing by ONE_20.\n            int256 product = ONE_20;\n\n            if (x >= x2) {\n                x -= x2;\n                product = (product * a2) / ONE_20;\n            }\n            if (x >= x3) {\n                x -= x3;\n                product = (product * a3) / ONE_20;\n            }\n            if (x >= x4) {\n                x -= x4;\n                product = (product * a4) / ONE_20;\n            }\n            if (x >= x5) {\n                x -= x5;\n                product = (product * a5) / ONE_20;\n            }\n            if (x >= x6) {\n                x -= x6;\n                product = (product * a6) / ONE_20;\n            }\n            if (x >= x7) {\n                x -= x7;\n                product = (product * a7) / ONE_20;\n            }\n            if (x >= x8) {\n                x -= x8;\n                product = (product * a8) / ONE_20;\n            }\n            if (x >= x9) {\n                x -= x9;\n                product = (product * a9) / ONE_20;\n            }\n\n            // x10 and x11 are unnecessary here since we have high enough precision already.\n\n            // Now we need to compute e^x, where x is small (in particular, it is smaller than x9). We use the Taylor series\n            // expansion for e^x: 1 + x + (x^2 / 2!) + (x^3 / 3!) + ... + (x^n / n!).\n\n            int256 seriesSum = ONE_20; // The initial one in the sum, with 20 decimal places.\n            int256 term; // Each term in the sum, where the nth term is (x^n / n!).\n\n            // The first term is simply x.\n            term = x;\n            seriesSum += term;\n\n            // Each term (x^n / n!) equals the previous one times x, divided by n. Since x is a fixed point number,\n            // multiplying by it requires dividing by ONE_20, but dividing by the non-fixed point n values does not.\n\n            term = ((term * x) / ONE_20) / 2;\n            seriesSum += term;\n\n            term = ((term * x) / ONE_20) / 3;\n            seriesSum += term;\n\n            term = ((term * x) / ONE_20) / 4;\n            seriesSum += term;\n\n            term = ((term * x) / ONE_20) / 5;\n            seriesSum += term;\n\n            term = ((term * x) / ONE_20) / 6;\n            seriesSum += term;\n\n            term = ((term * x) / ONE_20) / 7;\n            seriesSum += term;\n\n            term = ((term * x) / ONE_20) / 8;\n            seriesSum += term;\n\n            term = ((term * x) / ONE_20) / 9;\n            seriesSum += term;\n\n            term = ((term * x) / ONE_20) / 10;\n            seriesSum += term;\n\n            term = ((term * x) / ONE_20) / 11;\n            seriesSum += term;\n\n            term = ((term * x) / ONE_20) / 12;\n            seriesSum += term;\n\n            // 12 Taylor terms are sufficient for 18 decimal precision.\n\n            // We now have the first a_n (with no decimals), and the product of all other a_n present, and the Taylor\n            // approximation of the exponentiation of the remainder (both with 20 decimals). All that remains is to multiply\n            // all three (one 20 decimal fixed point multiplication, dividing by ONE_20, and one integer multiplication),\n            // and then drop two digits to return an 18 decimal value.\n\n            return (((product * seriesSum) / ONE_20) * firstAN) / 100;\n        }\n    }\n\n    /**\n     * @dev Natural logarithm (ln(a)) with signed 18 decimal fixed point argument.\n     */\n    function ln(int256 a) internal pure returns (int256) {\n        unchecked {\n            // The real natural logarithm is not defined for negative numbers or zero.\n            require(a > 0, \"out of bounds\");\n            if (LN_36_LOWER_BOUND < a && a < LN_36_UPPER_BOUND) {\n                return _ln_36(a) / ONE_18;\n            } else {\n                return _ln(a);\n            }\n        }\n    }\n\n    /**\n     * @dev Exponentiation (x^y) with unsigned 18 decimal fixed point base and exponent.\n     *\n     * Reverts if ln(x) * y is smaller than `MIN_NATURAL_EXPONENT`, or larger than `MAX_NATURAL_EXPONENT`.\n     */\n    function pow(uint256 x, uint256 y) internal pure returns (uint256) {\n        unchecked {\n            if (y == 0) {\n                // We solve the 0^0 indetermination by making it equal one.\n                return uint256(ONE_18);\n            }\n\n            if (x == 0) {\n                return 0;\n            }\n\n            // Instead of computing x^y directly, we instead rely on the properties of logarithms and exponentiation to\n            // arrive at that r`esult. In particular, exp(ln(x)) = x, and ln(x^y) = y * ln(x). This means\n            // x^y = exp(y * ln(x)).\n\n            // The ln function takes a signed value, so we need to make sure x fits in the signed 256 bit range.\n            require(x < 2 ** 255, \"x out of bounds\");\n            int256 x_int256 = int256(x);\n\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\n            // both cases, we leave the division by ONE_18 (due to fixed point multiplication) to the end.\n\n            // This prevents y * ln(x) from overflowing, and at the same time guarantees y fits in the signed 256 bit range.\n            require(y < MILD_EXPONENT_BOUND, \"y out of bounds\");\n            int256 y_int256 = int256(y);\n\n            int256 logx_times_y;\n            if (LN_36_LOWER_BOUND < x_int256 && x_int256 < LN_36_UPPER_BOUND) {\n                int256 ln_36_x = _ln_36(x_int256);\n\n                // ln_36_x has 36 decimal places, so multiplying by y_int256 isn't as straightforward, since we can't just\n                // bring y_int256 to 36 decimal places, as it might overflow. Instead, we perform two 18 decimal\n                // multiplications and add the results: one with the first 18 decimals of ln_36_x, and one with the\n                // (downscaled) last 18 decimals.\n                logx_times_y = ((ln_36_x / ONE_18) * y_int256 + ((ln_36_x % ONE_18) * y_int256) / ONE_18);\n            } else {\n                logx_times_y = _ln(x_int256) * y_int256;\n            }\n            logx_times_y /= ONE_18;\n\n            // Finally, we compute exp(y * ln(x)) to arrive at x^y\n            require(\n                MIN_NATURAL_EXPONENT <= logx_times_y && logx_times_y <= MAX_NATURAL_EXPONENT,\n                \"product out of bounds\"\n            );\n\n            return uint256(exp(logx_times_y));\n        }\n    }\n\n    /**\n     * @dev Internal natural logarithm (ln(a)) with signed 18 decimal fixed point argument.\n     */\n    function _ln(int256 a) private pure returns (int256) {\n        unchecked {\n            if (a < ONE_18) {\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\n                // than one, 1/a will be greater than one, and this if statement will not be entered in the recursive call.\n                // Fixed point division requires multiplying by ONE_18.\n                return (-_ln((ONE_18 * ONE_18) / a));\n            }\n\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\n            // we call x_n, where x_n == 2^(7 - n), which are the natural logarithm of precomputed quantities a_n (that is,\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\n            // be represented as 18 fixed point decimal numbers in 256 bits, and are therefore larger than a.\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\n            // decomposition, which will be lower than the smallest a_n.\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.\n            // We mutate a by subtracting a_n, making it the remainder of the decomposition.\n\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\n            // numbers with 18 decimals, but instead as plain integers with 0 decimals, so we need to multiply them by\n            // ONE_18 to convert them to fixed point.\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\n            // by it and compute the accumulated sum.\n\n            int256 sum = 0;\n            if (a >= a0 * ONE_18) {\n                a /= a0; // Integer, not fixed point division\n                sum += x0;\n            }\n\n            if (a >= a1 * ONE_18) {\n                a /= a1; // Integer, not fixed point division\n                sum += x1;\n            }\n\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.\n            sum *= 100;\n            a *= 100;\n\n            // Because further a_n are  20 digit fixed point numbers, we multiply by ONE_20 when dividing by them.\n\n            if (a >= a2) {\n                a = (a * ONE_20) / a2;\n                sum += x2;\n            }\n\n            if (a >= a3) {\n                a = (a * ONE_20) / a3;\n                sum += x3;\n            }\n\n            if (a >= a4) {\n                a = (a * ONE_20) / a4;\n                sum += x4;\n            }\n\n            if (a >= a5) {\n                a = (a * ONE_20) / a5;\n                sum += x5;\n            }\n\n            if (a >= a6) {\n                a = (a * ONE_20) / a6;\n                sum += x6;\n            }\n\n            if (a >= a7) {\n                a = (a * ONE_20) / a7;\n                sum += x7;\n            }\n\n            if (a >= a8) {\n                a = (a * ONE_20) / a8;\n                sum += x8;\n            }\n\n            if (a >= a9) {\n                a = (a * ONE_20) / a9;\n                sum += x9;\n            }\n\n            if (a >= a10) {\n                a = (a * ONE_20) / a10;\n                sum += x10;\n            }\n\n            if (a >= a11) {\n                a = (a * ONE_20) / a11;\n                sum += x11;\n            }\n\n            // a is now a small number (smaller than a_11, which roughly equals 1.06). This means we can use a Taylor series\n            // that converges rapidly for values of `a` close to one - the same one used in ln_36.\n            // Let z = (a - 1) / (a + 1).\n            // ln(a) = 2 * (z + z^3 / 3 + z^5 / 5 + z^7 / 7 + ... + z^(2 * n + 1) / (2 * n + 1))\n\n            // Recall that 20 digit fixed point division requires multiplying by ONE_20, and multiplication requires\n            // division by ONE_20.\n            int256 z = ((a - ONE_20) * ONE_20) / (a + ONE_20);\n            int256 z_squared = (z * z) / ONE_20;\n\n            // num is the numerator of the series: the z^(2 * n + 1) term\n            int256 num = z;\n\n            // seriesSum holds the accumulated sum of each term in the series, starting with the initial z\n            int256 seriesSum = num;\n\n            // In each step, the numerator is multiplied by z^2\n            num = (num * z_squared) / ONE_20;\n            seriesSum += num / 3;\n\n            num = (num * z_squared) / ONE_20;\n            seriesSum += num / 5;\n\n            num = (num * z_squared) / ONE_20;\n            seriesSum += num / 7;\n\n            num = (num * z_squared) / ONE_20;\n            seriesSum += num / 9;\n\n            num = (num * z_squared) / ONE_20;\n            seriesSum += num / 11;\n\n            // 6 Taylor terms are sufficient for 36 decimal precision.\n\n            // Finally, we multiply by 2 (non fixed point) to compute ln(remainder)\n            seriesSum *= 2;\n\n            // We now have the sum of all x_n present, and the Taylor approximation of the logarithm of the remainder (both\n            // with 20 decimals). All that remains is to sum these two, and then drop two digits to return a 18 decimal\n            // value.\n\n            return (sum + seriesSum) / 100;\n        }\n    }\n\n    /**\n     * @dev Intrnal high precision (36 decimal places) natural logarithm (ln(x)) with signed 18 decimal fixed point argument,\n     * for x close to one.\n     *\n     * Should only be used if x is between LN_36_LOWER_BOUND and LN_36_UPPER_BOUND.\n     */\n    function _ln_36(int256 x) private pure returns (int256) {\n        unchecked {\n            // Since ln(1) = 0, a value of x close to one will yield a very small result, which makes using 36 digits\n            // worthwhile.\n\n            // First, we transform x to a 36 digit fixed point value.\n            x *= ONE_18;\n\n            // We will use the following Taylor expansion, which converges very rapidly. Let z = (x - 1) / (x + 1).\n            // ln(x) = 2 * (z + z^3 / 3 + z^5 / 5 + z^7 / 7 + ... + z^(2 * n + 1) / (2 * n + 1))\n\n            // Recall that 36 digit fixed point division requires multiplying by ONE_36, and multiplication requires\n            // division by ONE_36.\n            int256 z = ((x - ONE_36) * ONE_36) / (x + ONE_36);\n            int256 z_squared = (z * z) / ONE_36;\n\n            // num is the numerator of the series: the z^(2 * n + 1) term\n            int256 num = z;\n\n            // seriesSum holds the accumulated sum of each term in the series, starting with the initial z\n            int256 seriesSum = num;\n\n            // In each step, the numerator is multiplied by z^2\n            num = (num * z_squared) / ONE_36;\n            seriesSum += num / 3;\n\n            num = (num * z_squared) / ONE_36;\n            seriesSum += num / 5;\n\n            num = (num * z_squared) / ONE_36;\n            seriesSum += num / 7;\n\n            num = (num * z_squared) / ONE_36;\n            seriesSum += num / 9;\n\n            num = (num * z_squared) / ONE_36;\n            seriesSum += num / 11;\n\n            num = (num * z_squared) / ONE_36;\n            seriesSum += num / 13;\n\n            num = (num * z_squared) / ONE_36;\n            seriesSum += num / 15;\n\n            // 8 Taylor terms are sufficient for 36 decimal precision.\n\n            // All that remains is multiplying by 2 (non fixed point).\n            return seriesSum * 2;\n        }\n    }\n}\n"
      },
      "@pendle/core-v2/contracts/core/libraries/math/PMath.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.0;\n\n/* solhint-disable private-vars-leading-underscore, reason-string */\n\nlibrary PMath {\n    uint256 internal constant ONE = 1e18; // 18 decimal places\n    int256 internal constant IONE = 1e18; // 18 decimal places\n\n    function subMax0(uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            return (a >= b ? a - b : 0);\n        }\n    }\n\n    function subNoNeg(int256 a, int256 b) internal pure returns (int256) {\n        require(a >= b, \"negative\");\n        return a - b; // no unchecked since if b is very negative, a - b might overflow\n    }\n\n    function mulDown(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 product = a * b;\n        unchecked {\n            return product / ONE;\n        }\n    }\n\n    function mulDown(int256 a, int256 b) internal pure returns (int256) {\n        int256 product = a * b;\n        unchecked {\n            return product / IONE;\n        }\n    }\n\n    function divDown(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 aInflated = a * ONE;\n        unchecked {\n            return aInflated / b;\n        }\n    }\n\n    function divDown(int256 a, int256 b) internal pure returns (int256) {\n        int256 aInflated = a * IONE;\n        unchecked {\n            return aInflated / b;\n        }\n    }\n\n    function rawDivUp(uint256 a, uint256 b) internal pure returns (uint256) {\n        return (a + b - 1) / b;\n    }\n\n    // @author Uniswap\n    function sqrt(uint256 y) internal pure returns (uint256 z) {\n        if (y > 3) {\n            z = y;\n            uint256 x = y / 2 + 1;\n            while (x < z) {\n                z = x;\n                x = (y / x + x) / 2;\n            }\n        } else if (y != 0) {\n            z = 1;\n        }\n    }\n\n    function square(uint256 x) internal pure returns (uint256) {\n        return x * x;\n    }\n\n    function squareDown(uint256 x) internal pure returns (uint256) {\n        return mulDown(x, x);\n    }\n\n    function abs(int256 x) internal pure returns (uint256) {\n        return uint256(x > 0 ? x : -x);\n    }\n\n    function neg(int256 x) internal pure returns (int256) {\n        return x * (-1);\n    }\n\n    function neg(uint256 x) internal pure returns (int256) {\n        return Int(x) * (-1);\n    }\n\n    function max(uint256 x, uint256 y) internal pure returns (uint256) {\n        return (x > y ? x : y);\n    }\n\n    function max(int256 x, int256 y) internal pure returns (int256) {\n        return (x > y ? x : y);\n    }\n\n    function min(uint256 x, uint256 y) internal pure returns (uint256) {\n        return (x < y ? x : y);\n    }\n\n    function min(int256 x, int256 y) internal pure returns (int256) {\n        return (x < y ? x : y);\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                               SIGNED CASTS\n    //////////////////////////////////////////////////////////////*/\n\n    function Int(uint256 x) internal pure returns (int256) {\n        require(x <= uint256(type(int256).max));\n        return int256(x);\n    }\n\n    function Int128(int256 x) internal pure returns (int128) {\n        require(type(int128).min <= x && x <= type(int128).max);\n        return int128(x);\n    }\n\n    function Int128(uint256 x) internal pure returns (int128) {\n        return Int128(Int(x));\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                               UNSIGNED CASTS\n    //////////////////////////////////////////////////////////////*/\n\n    function Uint(int256 x) internal pure returns (uint256) {\n        require(x >= 0);\n        return uint256(x);\n    }\n\n    function Uint32(uint256 x) internal pure returns (uint32) {\n        require(x <= type(uint32).max);\n        return uint32(x);\n    }\n\n    function Uint64(uint256 x) internal pure returns (uint64) {\n        require(x <= type(uint64).max);\n        return uint64(x);\n    }\n\n    function Uint112(uint256 x) internal pure returns (uint112) {\n        require(x <= type(uint112).max);\n        return uint112(x);\n    }\n\n    function Uint96(uint256 x) internal pure returns (uint96) {\n        require(x <= type(uint96).max);\n        return uint96(x);\n    }\n\n    function Uint128(uint256 x) internal pure returns (uint128) {\n        require(x <= type(uint128).max);\n        return uint128(x);\n    }\n\n    function Uint192(uint256 x) internal pure returns (uint192) {\n        require(x <= type(uint192).max);\n        return uint192(x);\n    }\n\n    function isAApproxB(uint256 a, uint256 b, uint256 eps) internal pure returns (bool) {\n        return mulDown(b, ONE - eps) <= a && a <= mulDown(b, ONE + eps);\n    }\n\n    function isAGreaterApproxB(uint256 a, uint256 b, uint256 eps) internal pure returns (bool) {\n        return a >= b && a <= mulDown(b, ONE + eps);\n    }\n\n    function isASmallerApproxB(uint256 a, uint256 b, uint256 eps) internal pure returns (bool) {\n        return a <= b && a >= mulDown(b, ONE - eps);\n    }\n}\n"
      },
      "@pendle/core-v2/contracts/core/libraries/MiniHelpers.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nlibrary MiniHelpers {\n    function isCurrentlyExpired(uint256 expiry) internal view returns (bool) {\n        return (expiry <= block.timestamp);\n    }\n\n    function isExpired(uint256 expiry, uint256 blockTime) internal pure returns (bool) {\n        return (expiry <= blockTime);\n    }\n\n    function isTimeInThePast(uint256 timestamp) internal view returns (bool) {\n        return (timestamp <= block.timestamp); // same definition as isCurrentlyExpired\n    }\n}\n"
      },
      "@pendle/core-v2/contracts/core/Market/MarketMathCore.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport \"../libraries/math/PMath.sol\";\nimport \"../libraries/math/LogExpMath.sol\";\n\nimport \"../StandardizedYield/PYIndex.sol\";\nimport \"../libraries/MiniHelpers.sol\";\nimport \"../libraries/Errors.sol\";\n\nstruct MarketState {\n    int256 totalPt;\n    int256 totalSy;\n    int256 totalLp;\n    address treasury;\n    /// immutable variables ///\n    int256 scalarRoot;\n    uint256 expiry;\n    /// fee data ///\n    uint256 lnFeeRateRoot;\n    uint256 reserveFeePercent; // base 100\n    /// last trade data ///\n    uint256 lastLnImpliedRate;\n}\n\n// params that are expensive to compute, therefore we pre-compute them\nstruct MarketPreCompute {\n    int256 rateScalar;\n    int256 totalAsset;\n    int256 rateAnchor;\n    int256 feeRate;\n}\n\n// solhint-disable ordering\nlibrary MarketMathCore {\n    using PMath for uint256;\n    using PMath for int256;\n    using LogExpMath for int256;\n    using PYIndexLib for PYIndex;\n\n    int256 internal constant MINIMUM_LIQUIDITY = 10 ** 3;\n    int256 internal constant PERCENTAGE_DECIMALS = 100;\n    uint256 internal constant DAY = 86400;\n    uint256 internal constant IMPLIED_RATE_TIME = 365 * DAY;\n\n    int256 internal constant MAX_MARKET_PROPORTION = (1e18 * 96) / 100;\n\n    using PMath for uint256;\n    using PMath for int256;\n\n    /*///////////////////////////////////////////////////////////////\n                UINT FUNCTIONS TO PROXY TO CORE FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function addLiquidity(\n        MarketState memory market,\n        uint256 syDesired,\n        uint256 ptDesired,\n        uint256 blockTime\n    ) internal pure returns (uint256 lpToReserve, uint256 lpToAccount, uint256 syUsed, uint256 ptUsed) {\n        (int256 _lpToReserve, int256 _lpToAccount, int256 _syUsed, int256 _ptUsed) = addLiquidityCore(\n            market,\n            syDesired.Int(),\n            ptDesired.Int(),\n            blockTime\n        );\n\n        lpToReserve = _lpToReserve.Uint();\n        lpToAccount = _lpToAccount.Uint();\n        syUsed = _syUsed.Uint();\n        ptUsed = _ptUsed.Uint();\n    }\n\n    function removeLiquidity(\n        MarketState memory market,\n        uint256 lpToRemove\n    ) internal pure returns (uint256 netSyToAccount, uint256 netPtToAccount) {\n        (int256 _syToAccount, int256 _ptToAccount) = removeLiquidityCore(market, lpToRemove.Int());\n\n        netSyToAccount = _syToAccount.Uint();\n        netPtToAccount = _ptToAccount.Uint();\n    }\n\n    function swapExactPtForSy(\n        MarketState memory market,\n        PYIndex index,\n        uint256 exactPtToMarket,\n        uint256 blockTime\n    ) internal pure returns (uint256 netSyToAccount, uint256 netSyFee, uint256 netSyToReserve) {\n        (int256 _netSyToAccount, int256 _netSyFee, int256 _netSyToReserve) = executeTradeCore(\n            market,\n            index,\n            exactPtToMarket.neg(),\n            blockTime\n        );\n\n        netSyToAccount = _netSyToAccount.Uint();\n        netSyFee = _netSyFee.Uint();\n        netSyToReserve = _netSyToReserve.Uint();\n    }\n\n    function swapSyForExactPt(\n        MarketState memory market,\n        PYIndex index,\n        uint256 exactPtToAccount,\n        uint256 blockTime\n    ) internal pure returns (uint256 netSyToMarket, uint256 netSyFee, uint256 netSyToReserve) {\n        (int256 _netSyToAccount, int256 _netSyFee, int256 _netSyToReserve) = executeTradeCore(\n            market,\n            index,\n            exactPtToAccount.Int(),\n            blockTime\n        );\n\n        netSyToMarket = _netSyToAccount.neg().Uint();\n        netSyFee = _netSyFee.Uint();\n        netSyToReserve = _netSyToReserve.Uint();\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                    CORE FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function addLiquidityCore(\n        MarketState memory market,\n        int256 syDesired,\n        int256 ptDesired,\n        uint256 blockTime\n    ) internal pure returns (int256 lpToReserve, int256 lpToAccount, int256 syUsed, int256 ptUsed) {\n        /// ------------------------------------------------------------\n        /// CHECKS\n        /// ------------------------------------------------------------\n        if (syDesired == 0 || ptDesired == 0) revert Errors.MarketZeroAmountsInput();\n        if (MiniHelpers.isExpired(market.expiry, blockTime)) revert Errors.MarketExpired();\n\n        /// ------------------------------------------------------------\n        /// MATH\n        /// ------------------------------------------------------------\n        if (market.totalLp == 0) {\n            lpToAccount = PMath.sqrt((syDesired * ptDesired).Uint()).Int() - MINIMUM_LIQUIDITY;\n            lpToReserve = MINIMUM_LIQUIDITY;\n            syUsed = syDesired;\n            ptUsed = ptDesired;\n        } else {\n            int256 netLpByPt = (ptDesired * market.totalLp) / market.totalPt;\n            int256 netLpBySy = (syDesired * market.totalLp) / market.totalSy;\n            if (netLpByPt < netLpBySy) {\n                lpToAccount = netLpByPt;\n                ptUsed = ptDesired;\n                syUsed = (market.totalSy * lpToAccount) / market.totalLp;\n            } else {\n                lpToAccount = netLpBySy;\n                syUsed = syDesired;\n                ptUsed = (market.totalPt * lpToAccount) / market.totalLp;\n            }\n        }\n\n        if (lpToAccount <= 0) revert Errors.MarketZeroAmountsOutput();\n\n        /// ------------------------------------------------------------\n        /// WRITE\n        /// ------------------------------------------------------------\n        market.totalSy += syUsed;\n        market.totalPt += ptUsed;\n        market.totalLp += lpToAccount + lpToReserve;\n    }\n\n    function removeLiquidityCore(\n        MarketState memory market,\n        int256 lpToRemove\n    ) internal pure returns (int256 netSyToAccount, int256 netPtToAccount) {\n        /// ------------------------------------------------------------\n        /// CHECKS\n        /// ------------------------------------------------------------\n        if (lpToRemove == 0) revert Errors.MarketZeroAmountsInput();\n\n        /// ------------------------------------------------------------\n        /// MATH\n        /// ------------------------------------------------------------\n        netSyToAccount = (lpToRemove * market.totalSy) / market.totalLp;\n        netPtToAccount = (lpToRemove * market.totalPt) / market.totalLp;\n\n        if (netSyToAccount == 0 && netPtToAccount == 0) revert Errors.MarketZeroAmountsOutput();\n\n        /// ------------------------------------------------------------\n        /// WRITE\n        /// ------------------------------------------------------------\n        market.totalLp = market.totalLp.subNoNeg(lpToRemove);\n        market.totalPt = market.totalPt.subNoNeg(netPtToAccount);\n        market.totalSy = market.totalSy.subNoNeg(netSyToAccount);\n    }\n\n    function executeTradeCore(\n        MarketState memory market,\n        PYIndex index,\n        int256 netPtToAccount,\n        uint256 blockTime\n    ) internal pure returns (int256 netSyToAccount, int256 netSyFee, int256 netSyToReserve) {\n        /// ------------------------------------------------------------\n        /// CHECKS\n        /// ------------------------------------------------------------\n        if (MiniHelpers.isExpired(market.expiry, blockTime)) revert Errors.MarketExpired();\n        if (market.totalPt <= netPtToAccount)\n            revert Errors.MarketInsufficientPtForTrade(market.totalPt, netPtToAccount);\n\n        /// ------------------------------------------------------------\n        /// MATH\n        /// ------------------------------------------------------------\n        MarketPreCompute memory comp = getMarketPreCompute(market, index, blockTime);\n\n        (netSyToAccount, netSyFee, netSyToReserve) = calcTrade(market, comp, index, netPtToAccount);\n\n        /// ------------------------------------------------------------\n        /// WRITE\n        /// ------------------------------------------------------------\n        _setNewMarketStateTrade(market, comp, index, netPtToAccount, netSyToAccount, netSyToReserve, blockTime);\n    }\n\n    function getMarketPreCompute(\n        MarketState memory market,\n        PYIndex index,\n        uint256 blockTime\n    ) internal pure returns (MarketPreCompute memory res) {\n        if (MiniHelpers.isExpired(market.expiry, blockTime)) revert Errors.MarketExpired();\n\n        uint256 timeToExpiry = market.expiry - blockTime;\n\n        res.rateScalar = _getRateScalar(market, timeToExpiry);\n        res.totalAsset = index.syToAsset(market.totalSy);\n\n        if (market.totalPt == 0 || res.totalAsset == 0)\n            revert Errors.MarketZeroTotalPtOrTotalAsset(market.totalPt, res.totalAsset);\n\n        res.rateAnchor = _getRateAnchor(\n            market.totalPt,\n            market.lastLnImpliedRate,\n            res.totalAsset,\n            res.rateScalar,\n            timeToExpiry\n        );\n        res.feeRate = _getExchangeRateFromImpliedRate(market.lnFeeRateRoot, timeToExpiry);\n    }\n\n    function calcTrade(\n        MarketState memory market,\n        MarketPreCompute memory comp,\n        PYIndex index,\n        int256 netPtToAccount\n    ) internal pure returns (int256 netSyToAccount, int256 netSyFee, int256 netSyToReserve) {\n        int256 preFeeExchangeRate = _getExchangeRate(\n            market.totalPt,\n            comp.totalAsset,\n            comp.rateScalar,\n            comp.rateAnchor,\n            netPtToAccount\n        );\n\n        int256 preFeeAssetToAccount = netPtToAccount.divDown(preFeeExchangeRate).neg();\n        int256 fee = comp.feeRate;\n\n        if (netPtToAccount > 0) {\n            int256 postFeeExchangeRate = preFeeExchangeRate.divDown(fee);\n            if (postFeeExchangeRate < PMath.IONE) revert Errors.MarketExchangeRateBelowOne(postFeeExchangeRate);\n\n            fee = preFeeAssetToAccount.mulDown(PMath.IONE - fee);\n        } else {\n            fee = ((preFeeAssetToAccount * (PMath.IONE - fee)) / fee).neg();\n        }\n\n        int256 netAssetToReserve = (fee * market.reserveFeePercent.Int()) / PERCENTAGE_DECIMALS;\n        int256 netAssetToAccount = preFeeAssetToAccount - fee;\n\n        netSyToAccount = netAssetToAccount < 0\n            ? index.assetToSyUp(netAssetToAccount)\n            : index.assetToSy(netAssetToAccount);\n        netSyFee = index.assetToSy(fee);\n        netSyToReserve = index.assetToSy(netAssetToReserve);\n    }\n\n    function _setNewMarketStateTrade(\n        MarketState memory market,\n        MarketPreCompute memory comp,\n        PYIndex index,\n        int256 netPtToAccount,\n        int256 netSyToAccount,\n        int256 netSyToReserve,\n        uint256 blockTime\n    ) internal pure {\n        uint256 timeToExpiry = market.expiry - blockTime;\n\n        market.totalPt = market.totalPt.subNoNeg(netPtToAccount);\n        market.totalSy = market.totalSy.subNoNeg(netSyToAccount + netSyToReserve);\n\n        market.lastLnImpliedRate = _getLnImpliedRate(\n            market.totalPt,\n            index.syToAsset(market.totalSy),\n            comp.rateScalar,\n            comp.rateAnchor,\n            timeToExpiry\n        );\n\n        if (market.lastLnImpliedRate == 0) revert Errors.MarketZeroLnImpliedRate();\n    }\n\n    function _getRateAnchor(\n        int256 totalPt,\n        uint256 lastLnImpliedRate,\n        int256 totalAsset,\n        int256 rateScalar,\n        uint256 timeToExpiry\n    ) internal pure returns (int256 rateAnchor) {\n        int256 newExchangeRate = _getExchangeRateFromImpliedRate(lastLnImpliedRate, timeToExpiry);\n\n        if (newExchangeRate < PMath.IONE) revert Errors.MarketExchangeRateBelowOne(newExchangeRate);\n\n        {\n            int256 proportion = totalPt.divDown(totalPt + totalAsset);\n\n            int256 lnProportion = _logProportion(proportion);\n\n            rateAnchor = newExchangeRate - lnProportion.divDown(rateScalar);\n        }\n    }\n\n    /// @notice Calculates the current market implied rate.\n    /// @return lnImpliedRate the implied rate\n    function _getLnImpliedRate(\n        int256 totalPt,\n        int256 totalAsset,\n        int256 rateScalar,\n        int256 rateAnchor,\n        uint256 timeToExpiry\n    ) internal pure returns (uint256 lnImpliedRate) {\n        // This will check for exchange rates < PMath.IONE\n        int256 exchangeRate = _getExchangeRate(totalPt, totalAsset, rateScalar, rateAnchor, 0);\n\n        // exchangeRate >= 1 so its ln >= 0\n        uint256 lnRate = exchangeRate.ln().Uint();\n\n        lnImpliedRate = (lnRate * IMPLIED_RATE_TIME) / timeToExpiry;\n    }\n\n    /// @notice Converts an implied rate to an exchange rate given a time to expiry. The\n    /// formula is E = e^rt\n    function _getExchangeRateFromImpliedRate(\n        uint256 lnImpliedRate,\n        uint256 timeToExpiry\n    ) internal pure returns (int256 exchangeRate) {\n        uint256 rt = (lnImpliedRate * timeToExpiry) / IMPLIED_RATE_TIME;\n\n        exchangeRate = LogExpMath.exp(rt.Int());\n    }\n\n    function _getExchangeRate(\n        int256 totalPt,\n        int256 totalAsset,\n        int256 rateScalar,\n        int256 rateAnchor,\n        int256 netPtToAccount\n    ) internal pure returns (int256 exchangeRate) {\n        int256 numerator = totalPt.subNoNeg(netPtToAccount);\n\n        int256 proportion = (numerator.divDown(totalPt + totalAsset));\n\n        if (proportion > MAX_MARKET_PROPORTION)\n            revert Errors.MarketProportionTooHigh(proportion, MAX_MARKET_PROPORTION);\n\n        int256 lnProportion = _logProportion(proportion);\n\n        exchangeRate = lnProportion.divDown(rateScalar) + rateAnchor;\n\n        if (exchangeRate < PMath.IONE) revert Errors.MarketExchangeRateBelowOne(exchangeRate);\n    }\n\n    function _logProportion(int256 proportion) internal pure returns (int256 res) {\n        if (proportion == PMath.IONE) revert Errors.MarketProportionMustNotEqualOne();\n\n        int256 logitP = proportion.divDown(PMath.IONE - proportion);\n\n        res = logitP.ln();\n    }\n\n    function _getRateScalar(MarketState memory market, uint256 timeToExpiry) internal pure returns (int256 rateScalar) {\n        rateScalar = (market.scalarRoot * IMPLIED_RATE_TIME.Int()) / timeToExpiry.Int();\n        if (rateScalar <= 0) revert Errors.MarketRateScalarBelowZero(rateScalar);\n    }\n\n    function setInitialLnImpliedRate(\n        MarketState memory market,\n        PYIndex index,\n        int256 initialAnchor,\n        uint256 blockTime\n    ) internal pure {\n        /// ------------------------------------------------------------\n        /// CHECKS\n        /// ------------------------------------------------------------\n        if (MiniHelpers.isExpired(market.expiry, blockTime)) revert Errors.MarketExpired();\n\n        /// ------------------------------------------------------------\n        /// MATH\n        /// ------------------------------------------------------------\n        int256 totalAsset = index.syToAsset(market.totalSy);\n        uint256 timeToExpiry = market.expiry - blockTime;\n        int256 rateScalar = _getRateScalar(market, timeToExpiry);\n\n        /// ------------------------------------------------------------\n        /// WRITE\n        /// ------------------------------------------------------------\n        market.lastLnImpliedRate = _getLnImpliedRate(\n            market.totalPt,\n            totalAsset,\n            rateScalar,\n            initialAnchor,\n            timeToExpiry\n        );\n    }\n}\n"
      },
      "@pendle/core-v2/contracts/core/StandardizedYield/PYIndex.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\nimport \"../../interfaces/IPYieldToken.sol\";\nimport \"../../interfaces/IPPrincipalToken.sol\";\n\nimport \"./SYUtils.sol\";\nimport \"../libraries/math/PMath.sol\";\n\ntype PYIndex is uint256;\n\nlibrary PYIndexLib {\n    using PMath for uint256;\n    using PMath for int256;\n\n    function newIndex(IPYieldToken YT) internal returns (PYIndex) {\n        return PYIndex.wrap(YT.pyIndexCurrent());\n    }\n\n    function syToAsset(PYIndex index, uint256 syAmount) internal pure returns (uint256) {\n        return SYUtils.syToAsset(PYIndex.unwrap(index), syAmount);\n    }\n\n    function assetToSy(PYIndex index, uint256 assetAmount) internal pure returns (uint256) {\n        return SYUtils.assetToSy(PYIndex.unwrap(index), assetAmount);\n    }\n\n    function assetToSyUp(PYIndex index, uint256 assetAmount) internal pure returns (uint256) {\n        return SYUtils.assetToSyUp(PYIndex.unwrap(index), assetAmount);\n    }\n\n    function syToAssetUp(PYIndex index, uint256 syAmount) internal pure returns (uint256) {\n        uint256 _index = PYIndex.unwrap(index);\n        return SYUtils.syToAssetUp(_index, syAmount);\n    }\n\n    function syToAsset(PYIndex index, int256 syAmount) internal pure returns (int256) {\n        int256 sign = syAmount < 0 ? int256(-1) : int256(1);\n        return sign * (SYUtils.syToAsset(PYIndex.unwrap(index), syAmount.abs())).Int();\n    }\n\n    function assetToSy(PYIndex index, int256 assetAmount) internal pure returns (int256) {\n        int256 sign = assetAmount < 0 ? int256(-1) : int256(1);\n        return sign * (SYUtils.assetToSy(PYIndex.unwrap(index), assetAmount.abs())).Int();\n    }\n\n    function assetToSyUp(PYIndex index, int256 assetAmount) internal pure returns (int256) {\n        int256 sign = assetAmount < 0 ? int256(-1) : int256(1);\n        return sign * (SYUtils.assetToSyUp(PYIndex.unwrap(index), assetAmount.abs())).Int();\n    }\n}\n"
      },
      "@pendle/core-v2/contracts/core/StandardizedYield/SYUtils.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nlibrary SYUtils {\n    uint256 internal constant ONE = 1e18;\n\n    function syToAsset(uint256 exchangeRate, uint256 syAmount) internal pure returns (uint256) {\n        return (syAmount * exchangeRate) / ONE;\n    }\n\n    function syToAssetUp(uint256 exchangeRate, uint256 syAmount) internal pure returns (uint256) {\n        return (syAmount * exchangeRate + ONE - 1) / ONE;\n    }\n\n    function assetToSy(uint256 exchangeRate, uint256 assetAmount) internal pure returns (uint256) {\n        return (assetAmount * ONE) / exchangeRate;\n    }\n\n    function assetToSyUp(uint256 exchangeRate, uint256 assetAmount) internal pure returns (uint256) {\n        return (assetAmount * ONE + exchangeRate - 1) / exchangeRate;\n    }\n}\n"
      },
      "@pendle/core-v2/contracts/interfaces/IPActionAddRemoveLiqV3.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport \"../router/base/MarketApproxLib.sol\";\nimport \"./IPAllActionTypeV3.sol\";\n\n/*\n *******************************************************************************************************************\n *******************************************************************************************************************\n * NOTICE *\n * Refer to https://docs.pendle.finance/Developers/Contracts/PendleRouter for more information on\n * TokenInput, TokenOutput, ApproxParams, LimitOrderData\n * It's recommended to use Pendle's Hosted SDK to generate the params\n *******************************************************************************************************************\n *******************************************************************************************************************\n */\n\ninterface IPActionAddRemoveLiqV3 {\n    event AddLiquidityDualSyAndPt(\n        address indexed caller,\n        address indexed market,\n        address indexed receiver,\n        uint256 netSyUsed,\n        uint256 netPtUsed,\n        uint256 netLpOut\n    );\n\n    event AddLiquidityDualTokenAndPt(\n        address indexed caller,\n        address indexed market,\n        address indexed tokenIn,\n        address receiver,\n        uint256 netTokenUsed,\n        uint256 netPtUsed,\n        uint256 netLpOut,\n        uint256 netSyInterm\n    );\n\n    event AddLiquiditySinglePt(\n        address indexed caller,\n        address indexed market,\n        address indexed receiver,\n        uint256 netPtIn,\n        uint256 netLpOut\n    );\n\n    event AddLiquiditySingleSy(\n        address indexed caller,\n        address indexed market,\n        address indexed receiver,\n        uint256 netSyIn,\n        uint256 netLpOut\n    );\n\n    event AddLiquiditySingleToken(\n        address indexed caller,\n        address indexed market,\n        address indexed token,\n        address receiver,\n        uint256 netTokenIn,\n        uint256 netLpOut,\n        uint256 netSyInterm\n    );\n\n    event AddLiquiditySingleSyKeepYt(\n        address indexed caller,\n        address indexed market,\n        address indexed receiver,\n        uint256 netSyIn,\n        uint256 netSyMintPy,\n        uint256 netLpOut,\n        uint256 netYtOut\n    );\n\n    event AddLiquiditySingleTokenKeepYt(\n        address indexed caller,\n        address indexed market,\n        address indexed token,\n        address receiver,\n        uint256 netTokenIn,\n        uint256 netLpOut,\n        uint256 netYtOut,\n        uint256 netSyMintPy,\n        uint256 netSyInterm\n    );\n\n    event RemoveLiquidityDualSyAndPt(\n        address indexed caller,\n        address indexed market,\n        address indexed receiver,\n        uint256 netLpToRemove,\n        uint256 netPtOut,\n        uint256 netSyOut\n    );\n\n    event RemoveLiquidityDualTokenAndPt(\n        address indexed caller,\n        address indexed market,\n        address indexed tokenOut,\n        address receiver,\n        uint256 netLpToRemove,\n        uint256 netPtOut,\n        uint256 netTokenOut,\n        uint256 netSyInterm\n    );\n\n    event RemoveLiquiditySinglePt(\n        address indexed caller,\n        address indexed market,\n        address indexed receiver,\n        uint256 netLpToRemove,\n        uint256 netPtOut\n    );\n\n    event RemoveLiquiditySingleSy(\n        address indexed caller,\n        address indexed market,\n        address indexed receiver,\n        uint256 netLpToRemove,\n        uint256 netSyOut\n    );\n\n    event RemoveLiquiditySingleToken(\n        address indexed caller,\n        address indexed market,\n        address indexed token,\n        address receiver,\n        uint256 netLpToRemove,\n        uint256 netTokenOut,\n        uint256 netSyInterm\n    );\n\n    function addLiquidityDualTokenAndPt(\n        address receiver,\n        address market,\n        TokenInput calldata input,\n        uint256 netPtDesired,\n        uint256 minLpOut\n    ) external payable returns (uint256 netLpOut, uint256 netPtUsed, uint256 netSyInterm);\n\n    function addLiquidityDualSyAndPt(\n        address receiver,\n        address market,\n        uint256 netSyDesired,\n        uint256 netPtDesired,\n        uint256 minLpOut\n    ) external returns (uint256 netLpOut, uint256 netSyUsed, uint256 netPtUsed);\n\n    function addLiquiditySinglePt(\n        address receiver,\n        address market,\n        uint256 netPtIn,\n        uint256 minLpOut,\n        ApproxParams calldata guessPtSwapToSy,\n        LimitOrderData calldata limit\n    ) external returns (uint256 netLpOut, uint256 netSyFee);\n\n    function addLiquiditySingleToken(\n        address receiver,\n        address market,\n        uint256 minLpOut,\n        ApproxParams calldata guessPtReceivedFromSy,\n        TokenInput calldata input,\n        LimitOrderData calldata limit\n    ) external payable returns (uint256 netLpOut, uint256 netSyFee, uint256 netSyInterm);\n\n    function addLiquiditySingleSy(\n        address receiver,\n        address market,\n        uint256 netSyIn,\n        uint256 minLpOut,\n        ApproxParams calldata guessPtReceivedFromSy,\n        LimitOrderData calldata limit\n    ) external returns (uint256 netLpOut, uint256 netSyFee);\n\n    function addLiquiditySingleTokenKeepYt(\n        address receiver,\n        address market,\n        uint256 minLpOut,\n        uint256 minYtOut,\n        TokenInput calldata input\n    ) external payable returns (uint256 netLpOut, uint256 netYtOut, uint256 netSyMintPy, uint256 netSyInterm);\n\n    function addLiquiditySingleSyKeepYt(\n        address receiver,\n        address market,\n        uint256 netSyIn,\n        uint256 minLpOut,\n        uint256 minYtOut\n    ) external returns (uint256 netLpOut, uint256 netYtOut, uint256 netSyMintPy);\n\n    function removeLiquidityDualTokenAndPt(\n        address receiver,\n        address market,\n        uint256 netLpToRemove,\n        TokenOutput calldata output,\n        uint256 minPtOut\n    ) external returns (uint256 netTokenOut, uint256 netPtOut, uint256 netSyInterm);\n\n    function removeLiquidityDualSyAndPt(\n        address receiver,\n        address market,\n        uint256 netLpToRemove,\n        uint256 minSyOut,\n        uint256 minPtOut\n    ) external returns (uint256 netSyOut, uint256 netPtOut);\n\n    function removeLiquiditySinglePt(\n        address receiver,\n        address market,\n        uint256 netLpToRemove,\n        uint256 minPtOut,\n        ApproxParams calldata guessPtReceivedFromSy,\n        LimitOrderData calldata limit\n    ) external returns (uint256 netPtOut, uint256 netSyFee);\n\n    function removeLiquiditySingleToken(\n        address receiver,\n        address market,\n        uint256 netLpToRemove,\n        TokenOutput calldata output,\n        LimitOrderData calldata limit\n    ) external returns (uint256 netTokenOut, uint256 netSyFee, uint256 netSyInterm);\n\n    function removeLiquiditySingleSy(\n        address receiver,\n        address market,\n        uint256 netLpToRemove,\n        uint256 minSyOut,\n        LimitOrderData calldata limit\n    ) external returns (uint256 netSyOut, uint256 netSyFee);\n}\n"
      },
      "@pendle/core-v2/contracts/interfaces/IPAllActionTypeV3.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity ^0.8.0;\n\nimport \"../router/swap-aggregator/IPSwapAggregator.sol\";\nimport \"./IPLimitRouter.sol\";\n\n/*\n *******************************************************************************************************************\n *******************************************************************************************************************\n * NOTICE *\n * Refer to https://docs.pendle.finance/Developers/Contracts/PendleRouter for more information on\n * TokenInput, TokenOutput, ApproxParams, LimitOrderData\n * It's recommended to use Pendle's Hosted SDK to generate the params\n *******************************************************************************************************************\n *******************************************************************************************************************\n */\n\nstruct TokenInput {\n    // TOKEN DATA\n    address tokenIn;\n    uint256 netTokenIn;\n    address tokenMintSy;\n    // AGGREGATOR DATA\n    address pendleSwap;\n    SwapData swapData;\n}\n\nstruct TokenOutput {\n    // TOKEN DATA\n    address tokenOut;\n    uint256 minTokenOut;\n    address tokenRedeemSy;\n    // AGGREGATOR DATA\n    address pendleSwap;\n    SwapData swapData;\n}\n\nstruct LimitOrderData {\n    address limitRouter;\n    uint256 epsSkipMarket; // only used for swap operations, will be ignored otherwise\n    FillOrderParams[] normalFills;\n    FillOrderParams[] flashFills;\n    bytes optData;\n}\n"
      },
      "@pendle/core-v2/contracts/interfaces/IPGauge.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\ninterface IPGauge {\n    function totalActiveSupply() external view returns (uint256);\n\n    function activeBalance(address user) external view returns (uint256);\n\n    // only available for newer factories. please check the verified contracts\n    event RedeemRewards(address indexed user, uint256[] rewardsOut);\n}\n"
      },
      "@pendle/core-v2/contracts/interfaces/IPInterestManagerYT.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\ninterface IPInterestManagerYT {\n    event CollectInterestFee(uint256 amountInterestFee);\n\n    function userInterest(address user) external view returns (uint128 lastPYIndex, uint128 accruedInterest);\n}\n"
      },
      "@pendle/core-v2/contracts/interfaces/IPLimitRouter.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport \"../core/StandardizedYield/PYIndex.sol\";\n\ninterface IPLimitOrderType {\n    enum OrderType {\n        SY_FOR_PT,\n        PT_FOR_SY,\n        SY_FOR_YT,\n        YT_FOR_SY\n    }\n\n    // Fixed-size order part with core information\n    struct StaticOrder {\n        uint256 salt;\n        uint256 expiry;\n        uint256 nonce;\n        OrderType orderType;\n        address token;\n        address YT;\n        address maker;\n        address receiver;\n        uint256 makingAmount;\n        uint256 lnImpliedRate;\n        uint256 failSafeRate;\n    }\n\n    struct FillResults {\n        uint256 totalMaking;\n        uint256 totalTaking;\n        uint256 totalFee;\n        uint256 totalNotionalVolume;\n        uint256[] netMakings;\n        uint256[] netTakings;\n        uint256[] netFees;\n        uint256[] notionalVolumes;\n    }\n}\n\nstruct Order {\n    uint256 salt;\n    uint256 expiry;\n    uint256 nonce;\n    IPLimitOrderType.OrderType orderType;\n    address token;\n    address YT;\n    address maker;\n    address receiver;\n    uint256 makingAmount;\n    uint256 lnImpliedRate;\n    uint256 failSafeRate;\n    bytes permit;\n}\n\nstruct FillOrderParams {\n    Order order;\n    bytes signature;\n    uint256 makingAmount;\n}\n\ninterface IPLimitRouterCallback is IPLimitOrderType {\n    function limitRouterCallback(\n        uint256 actualMaking,\n        uint256 actualTaking,\n        uint256 totalFee,\n        bytes memory data\n    ) external returns (bytes memory);\n}\n\ninterface IPLimitRouter is IPLimitOrderType {\n    struct OrderStatus {\n        uint128 filledAmount;\n        uint128 remaining;\n    }\n\n    event OrderCanceled(address indexed maker, bytes32 indexed orderHash);\n\n    event OrderFilledV2(\n        bytes32 indexed orderHash,\n        OrderType indexed orderType,\n        address indexed YT,\n        address token,\n        uint256 netInputFromMaker,\n        uint256 netOutputToMaker,\n        uint256 feeAmount,\n        uint256 notionalVolume,\n        address maker,\n        address taker\n    );\n\n    // @dev actualMaking, actualTaking are in the SY form\n    function fill(\n        FillOrderParams[] memory params,\n        address receiver,\n        uint256 maxTaking,\n        bytes calldata optData,\n        bytes calldata callback\n    ) external returns (uint256 actualMaking, uint256 actualTaking, uint256 totalFee, bytes memory callbackReturn);\n\n    function feeRecipient() external view returns (address);\n\n    function hashOrder(Order memory order) external view returns (bytes32);\n\n    function cancelSingle(Order calldata order) external;\n\n    function cancelBatch(Order[] calldata orders) external;\n\n    function orderStatusesRaw(\n        bytes32[] memory orderHashes\n    ) external view returns (uint256[] memory remainingsRaw, uint256[] memory filledAmounts);\n\n    function orderStatuses(\n        bytes32[] memory orderHashes\n    ) external view returns (uint256[] memory remainings, uint256[] memory filledAmounts);\n\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n\n    function simulate(address target, bytes calldata data) external payable;\n\n    /* --- Deprecated events --- */\n\n    // deprecate on 7/1/2024, prior to official launch\n    event OrderFilled(\n        bytes32 indexed orderHash,\n        OrderType indexed orderType,\n        address indexed YT,\n        address token,\n        uint256 netInputFromMaker,\n        uint256 netOutputToMaker,\n        uint256 feeAmount,\n        uint256 notionalVolume\n    );\n}\n"
      },
      "@pendle/core-v2/contracts/interfaces/IPMarket.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"./IPPrincipalToken.sol\";\nimport \"./IPYieldToken.sol\";\nimport \"./IStandardizedYield.sol\";\nimport \"./IPGauge.sol\";\nimport \"../core/Market/MarketMathCore.sol\";\n\ninterface IPMarket is IERC20Metadata, IPGauge {\n    event Mint(address indexed receiver, uint256 netLpMinted, uint256 netSyUsed, uint256 netPtUsed);\n\n    event Burn(\n        address indexed receiverSy,\n        address indexed receiverPt,\n        uint256 netLpBurned,\n        uint256 netSyOut,\n        uint256 netPtOut\n    );\n\n    event Swap(\n        address indexed caller,\n        address indexed receiver,\n        int256 netPtOut,\n        int256 netSyOut,\n        uint256 netSyFee,\n        uint256 netSyToReserve\n    );\n\n    event UpdateImpliedRate(uint256 indexed timestamp, uint256 lnLastImpliedRate);\n\n    event IncreaseObservationCardinalityNext(\n        uint16 observationCardinalityNextOld,\n        uint16 observationCardinalityNextNew\n    );\n\n    function mint(\n        address receiver,\n        uint256 netSyDesired,\n        uint256 netPtDesired\n    ) external returns (uint256 netLpOut, uint256 netSyUsed, uint256 netPtUsed);\n\n    function burn(\n        address receiverSy,\n        address receiverPt,\n        uint256 netLpToBurn\n    ) external returns (uint256 netSyOut, uint256 netPtOut);\n\n    function swapExactPtForSy(\n        address receiver,\n        uint256 exactPtIn,\n        bytes calldata data\n    ) external returns (uint256 netSyOut, uint256 netSyFee);\n\n    function swapSyForExactPt(\n        address receiver,\n        uint256 exactPtOut,\n        bytes calldata data\n    ) external returns (uint256 netSyIn, uint256 netSyFee);\n\n    function redeemRewards(address user) external returns (uint256[] memory);\n\n    function readState(address router) external view returns (MarketState memory market);\n\n    function observe(uint32[] memory secondsAgos) external view returns (uint216[] memory lnImpliedRateCumulative);\n\n    function increaseObservationsCardinalityNext(uint16 cardinalityNext) external;\n\n    function readTokens() external view returns (IStandardizedYield _SY, IPPrincipalToken _PT, IPYieldToken _YT);\n\n    function getRewardTokens() external view returns (address[] memory);\n\n    function isExpired() external view returns (bool);\n\n    function expiry() external view returns (uint256);\n\n    function observations(\n        uint256 index\n    ) external view returns (uint32 blockTimestamp, uint216 lnImpliedRateCumulative, bool initialized);\n\n    function _storage()\n        external\n        view\n        returns (\n            int128 totalPt,\n            int128 totalSy,\n            uint96 lastLnImpliedRate,\n            uint16 observationIndex,\n            uint16 observationCardinality,\n            uint16 observationCardinalityNext\n        );\n}\n"
      },
      "@pendle/core-v2/contracts/interfaces/IPPrincipalToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface IPPrincipalToken is IERC20Metadata {\n    function burnByYT(address user, uint256 amount) external;\n\n    function mintByYT(address user, uint256 amount) external;\n\n    function initialize(address _YT) external;\n\n    function SY() external view returns (address);\n\n    function YT() external view returns (address);\n\n    function factory() external view returns (address);\n\n    function expiry() external view returns (uint256);\n\n    function isExpired() external view returns (bool);\n}\n"
      },
      "@pendle/core-v2/contracts/interfaces/IPPtLpOracle.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\ninterface IPPtLpOracle {\n    event SetBlockCycleNumerator(uint16 newBlockCycleNumerator);\n\n    function getPtToAssetRate(address market, uint32 duration) external view returns (uint256);\n\n    function getLpToAssetRate(address market, uint32 duration) external view returns (uint256);\n\n    function getPtToSyRate(address market, uint32 duration) external view returns (uint256);\n\n    function getLpToSyRate(address market, uint32 duration) external view returns (uint256);\n\n    function getOracleState(\n        address market,\n        uint32 duration\n    )\n        external\n        view\n        returns (bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied);\n}\n"
      },
      "@pendle/core-v2/contracts/interfaces/IPYieldToken.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"./IRewardManager.sol\";\nimport \"./IPInterestManagerYT.sol\";\n\ninterface IPYieldToken is IERC20Metadata, IRewardManager, IPInterestManagerYT {\n    event NewInterestIndex(uint256 indexed newIndex);\n\n    event Mint(\n        address indexed caller,\n        address indexed receiverPT,\n        address indexed receiverYT,\n        uint256 amountSyToMint,\n        uint256 amountPYOut\n    );\n\n    event Burn(address indexed caller, address indexed receiver, uint256 amountPYToRedeem, uint256 amountSyOut);\n\n    event RedeemRewards(address indexed user, uint256[] amountRewardsOut);\n\n    event RedeemInterest(address indexed user, uint256 interestOut);\n\n    event CollectRewardFee(address indexed rewardToken, uint256 amountRewardFee);\n\n    function mintPY(address receiverPT, address receiverYT) external returns (uint256 amountPYOut);\n\n    function redeemPY(address receiver) external returns (uint256 amountSyOut);\n\n    function redeemPYMulti(\n        address[] calldata receivers,\n        uint256[] calldata amountPYToRedeems\n    ) external returns (uint256[] memory amountSyOuts);\n\n    function redeemDueInterestAndRewards(\n        address user,\n        bool redeemInterest,\n        bool redeemRewards\n    ) external returns (uint256 interestOut, uint256[] memory rewardsOut);\n\n    function rewardIndexesCurrent() external returns (uint256[] memory);\n\n    function pyIndexCurrent() external returns (uint256);\n\n    function pyIndexStored() external view returns (uint256);\n\n    function getRewardTokens() external view returns (address[] memory);\n\n    function SY() external view returns (address);\n\n    function PT() external view returns (address);\n\n    function factory() external view returns (address);\n\n    function expiry() external view returns (uint256);\n\n    function isExpired() external view returns (bool);\n\n    function doCacheIndexSameBlock() external view returns (bool);\n\n    function pyIndexLastUpdatedBlock() external view returns (uint128);\n}\n"
      },
      "@pendle/core-v2/contracts/interfaces/IRewardManager.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\ninterface IRewardManager {\n    function userReward(address token, address user) external view returns (uint128 index, uint128 accrued);\n}\n"
      },
      "@pendle/core-v2/contracts/interfaces/IStandardizedYield.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n/*\n * MIT License\n * ===========\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n */\n\npragma solidity ^0.8.0;\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface IStandardizedYield is IERC20Metadata {\n    /// @dev Emitted when any base tokens is deposited to mint shares\n    event Deposit(\n        address indexed caller,\n        address indexed receiver,\n        address indexed tokenIn,\n        uint256 amountDeposited,\n        uint256 amountSyOut\n    );\n\n    /// @dev Emitted when any shares are redeemed for base tokens\n    event Redeem(\n        address indexed caller,\n        address indexed receiver,\n        address indexed tokenOut,\n        uint256 amountSyToRedeem,\n        uint256 amountTokenOut\n    );\n\n    /// @dev check `assetInfo()` for more information\n    enum AssetType {\n        TOKEN,\n        LIQUIDITY\n    }\n\n    /// @dev Emitted when (`user`) claims their rewards\n    event ClaimRewards(address indexed user, address[] rewardTokens, uint256[] rewardAmounts);\n\n    /**\n     * @notice mints an amount of shares by depositing a base token.\n     * @param receiver shares recipient address\n     * @param tokenIn address of the base tokens to mint shares\n     * @param amountTokenToDeposit amount of base tokens to be transferred from (`msg.sender`)\n     * @param minSharesOut reverts if amount of shares minted is lower than this\n     * @return amountSharesOut amount of shares minted\n     * @dev Emits a {Deposit} event\n     *\n     * Requirements:\n     * - (`tokenIn`) must be a valid base token.\n     */\n    function deposit(\n        address receiver,\n        address tokenIn,\n        uint256 amountTokenToDeposit,\n        uint256 minSharesOut\n    ) external payable returns (uint256 amountSharesOut);\n\n    /**\n     * @notice redeems an amount of base tokens by burning some shares\n     * @param receiver recipient address\n     * @param amountSharesToRedeem amount of shares to be burned\n     * @param tokenOut address of the base token to be redeemed\n     * @param minTokenOut reverts if amount of base token redeemed is lower than this\n     * @param burnFromInternalBalance if true, burns from balance of `address(this)`, otherwise burns from `msg.sender`\n     * @return amountTokenOut amount of base tokens redeemed\n     * @dev Emits a {Redeem} event\n     *\n     * Requirements:\n     * - (`tokenOut`) must be a valid base token.\n     */\n    function redeem(\n        address receiver,\n        uint256 amountSharesToRedeem,\n        address tokenOut,\n        uint256 minTokenOut,\n        bool burnFromInternalBalance\n    ) external returns (uint256 amountTokenOut);\n\n    /**\n     * @notice exchangeRate * syBalance / 1e18 must return the asset balance of the account\n     * @notice vice-versa, if a user uses some amount of tokens equivalent to X asset, the amount of sy\n     he can mint must be X * exchangeRate / 1e18\n     * @dev SYUtils's assetToSy & syToAsset should be used instead of raw multiplication\n     & division\n     */\n    function exchangeRate() external view returns (uint256 res);\n\n    /**\n     * @notice claims reward for (`user`)\n     * @param user the user receiving their rewards\n     * @return rewardAmounts an array of reward amounts in the same order as `getRewardTokens`\n     * @dev\n     * Emits a `ClaimRewards` event\n     * See {getRewardTokens} for list of reward tokens\n     */\n    function claimRewards(address user) external returns (uint256[] memory rewardAmounts);\n\n    /**\n     * @notice get the amount of unclaimed rewards for (`user`)\n     * @param user the user to check for\n     * @return rewardAmounts an array of reward amounts in the same order as `getRewardTokens`\n     */\n    function accruedRewards(address user) external view returns (uint256[] memory rewardAmounts);\n\n    function rewardIndexesCurrent() external returns (uint256[] memory indexes);\n\n    function rewardIndexesStored() external view returns (uint256[] memory indexes);\n\n    /**\n     * @notice returns the list of reward token addresses\n     */\n    function getRewardTokens() external view returns (address[] memory);\n\n    /**\n     * @notice returns the address of the underlying yield token\n     */\n    function yieldToken() external view returns (address);\n\n    /**\n     * @notice returns all tokens that can mint this SY\n     */\n    function getTokensIn() external view returns (address[] memory res);\n\n    /**\n     * @notice returns all tokens that can be redeemed by this SY\n     */\n    function getTokensOut() external view returns (address[] memory res);\n\n    function isValidTokenIn(address token) external view returns (bool);\n\n    function isValidTokenOut(address token) external view returns (bool);\n\n    function previewDeposit(\n        address tokenIn,\n        uint256 amountTokenToDeposit\n    ) external view returns (uint256 amountSharesOut);\n\n    function previewRedeem(\n        address tokenOut,\n        uint256 amountSharesToRedeem\n    ) external view returns (uint256 amountTokenOut);\n\n    /**\n     * @notice This function contains information to interpret what the asset is\n     * @return assetType the type of the asset (0 for ERC20 tokens, 1 for AMM liquidity tokens,\n        2 for bridged yield bearing tokens like wstETH, rETH on Arbi whose the underlying asset doesn't exist on the chain)\n     * @return assetAddress the address of the asset\n     * @return assetDecimals the decimals of the asset\n     */\n    function assetInfo() external view returns (AssetType assetType, address assetAddress, uint8 assetDecimals);\n}\n"
      },
      "@pendle/core-v2/contracts/oracles/PendleLpOracleLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport \"./PendlePtOracleLib.sol\";\n\nlibrary PendleLpOracleLib {\n    using PendlePtOracleLib for IPMarket;\n    using PMath for uint256;\n    using PMath for int256;\n    using MarketMathCore for MarketState;\n\n    /**\n      * This function returns the approximated twap rate LP/asset on market, but take into account the current rate of SY\n     This is to account for special cases where underlying asset becomes insolvent and has decreasing exchangeRate\n     * @param market market to get rate from\n     * @param duration twap duration\n     */\n    function getLpToAssetRate(IPMarket market, uint32 duration) internal view returns (uint256) {\n        (uint256 syIndex, uint256 pyIndex) = PendlePtOracleLib.getSYandPYIndexCurrent(market);\n        uint256 lpToAssetRateRaw = _getLpToAssetRateRaw(market, duration, pyIndex);\n        if (syIndex >= pyIndex) {\n            return lpToAssetRateRaw;\n        } else {\n            return (lpToAssetRateRaw * syIndex) / pyIndex;\n        }\n    }\n\n    /**\n      * This function returns the approximated twap rate LP/asset on market, but take into account the current rate of SY\n     This is to account for special cases where underlying asset becomes insolvent and has decreasing exchangeRate\n     * @param market market to get rate from\n     * @param duration twap duration\n     */\n    function getLpToSyRate(IPMarket market, uint32 duration) internal view returns (uint256) {\n        (uint256 syIndex, uint256 pyIndex) = PendlePtOracleLib.getSYandPYIndexCurrent(market);\n        uint256 lpToAssetRateRaw = _getLpToAssetRateRaw(market, duration, pyIndex);\n        if (syIndex >= pyIndex) {\n            return lpToAssetRateRaw.divDown(syIndex);\n        } else {\n            return lpToAssetRateRaw.divDown(pyIndex);\n        }\n    }\n\n    function _getLpToAssetRateRaw(\n        IPMarket market,\n        uint32 duration,\n        uint256 pyIndex\n    ) private view returns (uint256 lpToAssetRateRaw) {\n        MarketState memory state = market.readState(address(0));\n\n        int256 totalHypotheticalAsset;\n        if (state.expiry <= block.timestamp) {\n            // 1 PT = 1 Asset post-expiry\n            totalHypotheticalAsset = state.totalPt + PYIndexLib.syToAsset(PYIndex.wrap(pyIndex), state.totalSy);\n        } else {\n            MarketPreCompute memory comp = state.getMarketPreCompute(PYIndex.wrap(pyIndex), block.timestamp);\n\n            (int256 rateOracle, int256 rateHypTrade) = _getPtRatesRaw(market, state, duration);\n            int256 cParam = LogExpMath.exp(comp.rateScalar.mulDown((rateOracle - comp.rateAnchor)));\n\n            int256 tradeSize = (cParam.mulDown(comp.totalAsset) - state.totalPt).divDown(\n                PMath.IONE + cParam.divDown(rateHypTrade)\n            );\n\n            totalHypotheticalAsset =\n                comp.totalAsset -\n                tradeSize.divDown(rateHypTrade) +\n                (state.totalPt + tradeSize).divDown(rateOracle);\n        }\n\n        lpToAssetRateRaw = totalHypotheticalAsset.divDown(state.totalLp).Uint();\n    }\n\n    function _getPtRatesRaw(\n        IPMarket market,\n        MarketState memory state,\n        uint32 duration\n    ) private view returns (int256 rateOracle, int256 rateHypTrade) {\n        rateOracle = PMath.IONE.divDown(market.getPtToAssetRateRaw(duration).Int());\n        int256 rateLastTrade = MarketMathCore._getExchangeRateFromImpliedRate(\n            state.lastLnImpliedRate,\n            state.expiry - block.timestamp\n        );\n        rateHypTrade = (rateLastTrade + rateOracle) / 2;\n    }\n}\n"
      },
      "@pendle/core-v2/contracts/oracles/PendlePtLpOracle.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.17;\n\nimport \"./PendlePtOracleLib.sol\";\nimport \"./PendleLpOracleLib.sol\";\nimport \"../interfaces/IPPtLpOracle.sol\";\nimport \"../core/libraries/BoringOwnableUpgradeable.sol\";\n\n// This is a pre-deployed version of PendlePtOracleLib & PendleLpOracleLib with additional utility functions.\n// Use of this contract rather than direct library integration resulting in a smaller bytecode size and simpler structure\n// but slightly higher gas usage (~ 4000 gas, 2 external calls & 1 cold code load)\ncontract PendlePtLpOracle is BoringOwnableUpgradeable, IPPtLpOracle {\n    using PendlePtOracleLib for IPMarket;\n    using PendleLpOracleLib for IPMarket;\n\n    error InvalidBlockRate(uint256 blockCycleNumerator);\n    error TwapDurationTooLarge(uint32 duration, uint32 cardinalityRequired);\n\n    /// @notice Oracles will be created ensuring a lowerbound in PendleMarket oracle's cardinality\n    /// @dev Cardinality lowerbound will be calculated as twap_duration * 1000 / blockCycleNumerator\n    /// @dev blockCycleNumerator should be configured so that blockCycleNumerator / 1000 < actual block cycle\n    /// @dev blockCycleNumerator should be greater or equal to 1000 since the oracle only records one\n    /// rate per timestamp\n    /// For example, on Ethereum blockCycleNumerator = 11000, where 11000/1000 = 11 < 12\n    ///                 Arbitrum blockCycleNumerator = 1000, since we can't do better than this\n    uint16 public blockCycleNumerator;\n    uint16 public constant BLOCK_CYCLE_DENOMINATOR = 1000;\n\n    constructor(uint16 _blockCycleNumerator) initializer {\n        __BoringOwnable_init();\n        setBlockCycleNumerator(_blockCycleNumerator);\n    }\n\n    function setBlockCycleNumerator(uint16 newBlockCycleNumerator) public onlyOwner {\n        if (newBlockCycleNumerator < BLOCK_CYCLE_DENOMINATOR) {\n            revert InvalidBlockRate(newBlockCycleNumerator);\n        }\n\n        blockCycleNumerator = newBlockCycleNumerator;\n        emit SetBlockCycleNumerator(newBlockCycleNumerator);\n    }\n\n    function getPtToAssetRate(address market, uint32 duration) external view returns (uint256) {\n        return IPMarket(market).getPtToAssetRate(duration);\n    }\n\n    /// @notice make sure you have taken into account the risk of not being able to withdraw from SY to Asset\n    /// More info in StandardizedYield\n    function getLpToAssetRate(address market, uint32 duration) external view returns (uint256) {\n        return IPMarket(market).getLpToAssetRate(duration);\n    }\n\n    function getPtToSyRate(address market, uint32 duration) external view returns (uint256) {\n        return IPMarket(market).getPtToSyRate(duration);\n    }\n\n    function getLpToSyRate(address market, uint32 duration) external view returns (uint256) {\n        return IPMarket(market).getLpToSyRate(duration);\n    }\n\n    /**\n     * A check function for the cardinality status of the market\n     * @param market PendleMarket address\n     * @param duration twap duration\n     * @return increaseCardinalityRequired a boolean indicates whether the cardinality should be increased to serve the duration\n     * @return cardinalityRequired the amount of cardinality required for the twap duration\n     */\n    function getOracleState(\n        address market,\n        uint32 duration\n    )\n        external\n        view\n        returns (bool increaseCardinalityRequired, uint16 cardinalityRequired, bool oldestObservationSatisfied)\n    {\n        (, , , uint16 observationIndex, uint16 observationCardinality, uint16 cardinalityReserved) = IPMarket(market)\n            ._storage();\n\n        // checkIncreaseCardinalityRequired\n        cardinalityRequired = _calcCardinalityRequiredRequired(duration);\n        increaseCardinalityRequired = cardinalityReserved < cardinalityRequired;\n\n        // check oldestObservationSatisfied\n        (uint32 oldestTimestamp, , bool initialized) = IPMarket(market).observations(\n            (observationIndex + 1) % observationCardinality\n        );\n        if (!initialized) {\n            (oldestTimestamp, , ) = IPMarket(market).observations(0);\n        }\n        oldestObservationSatisfied = oldestTimestamp < block.timestamp - duration;\n    }\n\n    function _calcCardinalityRequiredRequired(uint32 duration) internal view returns (uint16) {\n        uint32 cardinalityRequired = (duration * BLOCK_CYCLE_DENOMINATOR + blockCycleNumerator - 1) /\n            blockCycleNumerator +\n            1;\n        if (cardinalityRequired > type(uint16).max) {\n            revert TwapDurationTooLarge(duration, cardinalityRequired);\n        }\n        return uint16(cardinalityRequired);\n    }\n}\n"
      },
      "@pendle/core-v2/contracts/oracles/PendlePtOracleLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport \"../interfaces/IPMarket.sol\";\nimport \"../core/libraries/math/PMath.sol\";\n\n// This library can & should be integrated directly for optimal gas usage.\n// If you prefer not to integrate it directly, the PendlePtOracle contract (a pre-deployed version of this contract) can be used.\nlibrary PendlePtOracleLib {\n    using PMath for uint256;\n    using PMath for int256;\n\n    /**\n     * This function returns the twap rate PT/Asset on market, but take into account the current rate of SY\n     This is to account for special cases where underlying asset becomes insolvent and has decreasing exchangeRate\n     * @param market market to get rate from\n     * @param duration twap duration\n     */\n    function getPtToAssetRate(IPMarket market, uint32 duration) internal view returns (uint256) {\n        (uint256 syIndex, uint256 pyIndex) = getSYandPYIndexCurrent(market);\n        if (syIndex >= pyIndex) {\n            return getPtToAssetRateRaw(market, duration);\n        } else {\n            return (getPtToAssetRateRaw(market, duration) * syIndex) / pyIndex;\n        }\n    }\n\n    /// @notice Similar to getPtToAsset but returns the rate in SY instead\n    function getPtToSyRate(IPMarket market, uint32 duration) internal view returns (uint256) {\n        (uint256 syIndex, uint256 pyIndex) = getSYandPYIndexCurrent(market);\n        if (syIndex >= pyIndex) {\n            return getPtToAssetRateRaw(market, duration).divDown(syIndex);\n        } else {\n            return getPtToAssetRateRaw(market, duration).divDown(pyIndex);\n        }\n    }\n\n    /// @notice returns the raw rate without taking into account whether SY is solvent\n    function getPtToAssetRateRaw(IPMarket market, uint32 duration) internal view returns (uint256) {\n        uint256 expiry = market.expiry();\n\n        if (expiry <= block.timestamp) {\n            return PMath.ONE;\n        } else {\n            uint256 lnImpliedRate = _getMarketLnImpliedRate(market, duration);\n            uint256 timeToExpiry = expiry - block.timestamp;\n            uint256 assetToPtRate = MarketMathCore._getExchangeRateFromImpliedRate(lnImpliedRate, timeToExpiry).Uint();\n            return PMath.ONE.divDown(assetToPtRate);\n        }\n    }\n\n    function getSYandPYIndexCurrent(IPMarket market) internal view returns (uint256 syIndex, uint256 pyIndex) {\n        (IStandardizedYield SY, , IPYieldToken YT) = market.readTokens();\n\n        syIndex = SY.exchangeRate();\n        uint256 pyIndexStored = YT.pyIndexStored();\n\n        if (YT.doCacheIndexSameBlock() && YT.pyIndexLastUpdatedBlock() == block.number) {\n            pyIndex = pyIndexStored;\n        } else {\n            pyIndex = PMath.max(syIndex, pyIndexStored);\n        }\n    }\n\n    function _getMarketLnImpliedRate(IPMarket market, uint32 duration) private view returns (uint256) {\n        uint32[] memory durations = new uint32[](2);\n        durations[0] = duration;\n\n        uint216[] memory lnImpliedRateCumulative = market.observe(durations);\n        return (lnImpliedRateCumulative[1] - lnImpliedRateCumulative[0]) / duration;\n    }\n}\n"
      },
      "@pendle/core-v2/contracts/router/base/MarketApproxLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport \"../../core/libraries/math/PMath.sol\";\nimport \"../../core/Market/MarketMathCore.sol\";\n\nstruct ApproxParams {\n    uint256 guessMin;\n    uint256 guessMax;\n    uint256 guessOffchain; // pass 0 in to skip this variable\n    uint256 maxIteration; // every iteration, the diff between guessMin and guessMax will be divided by 2\n    uint256 eps; // the max eps between the returned result & the correct result, base 1e18. Normally this number will be set\n    // to 1e15 (1e18/1000 = 0.1%)\n}\n\n/// Further explanation of the eps. Take swapExactSyForPt for example. To calc the corresponding amount of Pt to swap out,\n/// it's necessary to run an approximation algorithm, because by default there only exists the Pt to Sy formula\n/// To approx, the 5 values above will have to be provided, and the approx process will run as follows:\n/// mid = (guessMin + guessMax) / 2 // mid here is the current guess of the amount of Pt out\n/// netSyNeed = calcSwapSyForExactPt(mid)\n/// if (netSyNeed > exactSyIn) guessMax = mid - 1 // since the maximum Sy in can't exceed the exactSyIn\n/// else guessMin = mid (1)\n/// For the (1), since netSyNeed <= exactSyIn, the result might be usable. If the netSyNeed is within eps of\n/// exactSyIn (ex eps=0.1% => we have used 99.9% the amount of Sy specified), mid will be chosen as the final guess result\n\n/// for guessOffchain, this is to provide a shortcut to guessing. The offchain SDK can precalculate the exact result\n/// before the tx is sent. When the tx reaches the contract, the guessOffchain will be checked first, and if it satisfies the\n/// approximation, it will be used (and save all the guessing). It's expected that this shortcut will be used in most cases\n/// except in cases that there is a trade in the same market right before the tx\n\nlibrary MarketApproxPtInLib {\n    using MarketMathCore for MarketState;\n    using PYIndexLib for PYIndex;\n    using PMath for uint256;\n    using PMath for int256;\n    using LogExpMath for int256;\n\n    /**\n     * @dev algorithm:\n     *     - Bin search the amount of PT to swap in\n     *     - Try swapping & get netSyOut\n     *     - Stop when netSyOut greater & approx minSyOut\n     *     - guess & approx is for netPtIn\n     */\n    function approxSwapPtForExactSy(\n        MarketState memory market,\n        PYIndex index,\n        uint256 minSyOut,\n        uint256 blockTime,\n        ApproxParams memory approx\n    ) internal pure returns (uint256, /*netPtIn*/ uint256, /*netSyOut*/ uint256 /*netSyFee*/) {\n        MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);\n        if (approx.guessOffchain == 0) {\n            // no limit on min\n            approx.guessMax = PMath.min(approx.guessMax, calcMaxPtIn(market, comp));\n            validateApprox(approx);\n        }\n\n        for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {\n            uint256 guess = nextGuess(approx, iter);\n            (uint256 netSyOut, uint256 netSyFee, ) = calcSyOut(market, comp, index, guess);\n\n            if (netSyOut >= minSyOut) {\n                if (PMath.isAGreaterApproxB(netSyOut, minSyOut, approx.eps)) {\n                    return (guess, netSyOut, netSyFee);\n                }\n                approx.guessMax = guess;\n            } else {\n                approx.guessMin = guess;\n            }\n        }\n        revert Errors.ApproxFail();\n    }\n\n    /**\n     * @dev algorithm:\n     *     - Bin search the amount of PT to swap in\n     *     - Flashswap the corresponding amount of SY out\n     *     - Pair those amount with exactSyIn SY to tokenize into PT & YT\n     *     - PT to repay the flashswap, YT transferred to user\n     *     - Stop when the amount of SY to be pulled to tokenize PT to repay loan approx the exactSyIn\n     *     - guess & approx is for netYtOut (also netPtIn)\n     */\n    function approxSwapExactSyForYt(\n        MarketState memory market,\n        PYIndex index,\n        uint256 exactSyIn,\n        uint256 blockTime,\n        ApproxParams memory approx\n    ) internal pure returns (uint256, /*netYtOut*/ uint256 /*netSyFee*/) {\n        MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);\n        if (approx.guessOffchain == 0) {\n            approx.guessMin = PMath.max(approx.guessMin, index.syToAsset(exactSyIn));\n            approx.guessMax = PMath.min(approx.guessMax, calcMaxPtIn(market, comp));\n            validateApprox(approx);\n        }\n\n        // at minimum we will flashswap exactSyIn since we have enough SY to payback the PT loan\n\n        for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {\n            uint256 guess = nextGuess(approx, iter);\n\n            (uint256 netSyOut, uint256 netSyFee, ) = calcSyOut(market, comp, index, guess);\n\n            uint256 netSyToTokenizePt = index.assetToSyUp(guess);\n\n            // for sure netSyToTokenizePt >= netSyOut since we are swapping PT to SY\n            uint256 netSyToPull = netSyToTokenizePt - netSyOut;\n\n            if (netSyToPull <= exactSyIn) {\n                if (PMath.isASmallerApproxB(netSyToPull, exactSyIn, approx.eps)) {\n                    return (guess, netSyFee);\n                }\n                approx.guessMin = guess;\n            } else {\n                approx.guessMax = guess - 1;\n            }\n        }\n        revert Errors.ApproxFail();\n    }\n\n    struct Args5 {\n        MarketState market;\n        PYIndex index;\n        uint256 totalPtIn;\n        uint256 netSyHolding;\n        uint256 blockTime;\n        ApproxParams approx;\n    }\n\n    /**\n     * @dev algorithm:\n     *     - Bin search the amount of PT to swap to SY\n     *     - Swap PT to SY\n     *     - Pair the remaining PT with the SY to add liquidity\n     *     - Stop when the ratio of PT / totalPt & SY / totalSy is approx\n     *     - guess & approx is for netPtSwap\n     */\n    function approxSwapPtToAddLiquidity(\n        MarketState memory _market,\n        PYIndex _index,\n        uint256 _totalPtIn,\n        uint256 _netSyHolding,\n        uint256 _blockTime,\n        ApproxParams memory approx\n    ) internal pure returns (uint256, /*netPtSwap*/ uint256, /*netSyFromSwap*/ uint256 /*netSyFee*/) {\n        Args5 memory a = Args5(_market, _index, _totalPtIn, _netSyHolding, _blockTime, approx);\n        MarketPreCompute memory comp = a.market.getMarketPreCompute(a.index, a.blockTime);\n        if (approx.guessOffchain == 0) {\n            // no limit on min\n            approx.guessMax = PMath.min(approx.guessMax, calcMaxPtIn(a.market, comp));\n            approx.guessMax = PMath.min(approx.guessMax, a.totalPtIn);\n            validateApprox(approx);\n            require(a.market.totalLp != 0, \"no existing lp\");\n        }\n\n        for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {\n            uint256 guess = nextGuess(approx, iter);\n\n            (uint256 syNumerator, uint256 ptNumerator, uint256 netSyOut, uint256 netSyFee, ) = calcNumerators(\n                a.market,\n                a.index,\n                a.totalPtIn,\n                a.netSyHolding,\n                comp,\n                guess\n            );\n\n            if (PMath.isAApproxB(syNumerator, ptNumerator, approx.eps)) {\n                return (guess, netSyOut, netSyFee);\n            }\n\n            if (syNumerator <= ptNumerator) {\n                // needs more SY --> swap more PT\n                approx.guessMin = guess + 1;\n            } else {\n                // needs less SY --> swap less PT\n                approx.guessMax = guess - 1;\n            }\n        }\n        revert Errors.ApproxFail();\n    }\n\n    function calcNumerators(\n        MarketState memory market,\n        PYIndex index,\n        uint256 totalPtIn,\n        uint256 netSyHolding,\n        MarketPreCompute memory comp,\n        uint256 guess\n    )\n        internal\n        pure\n        returns (uint256 syNumerator, uint256 ptNumerator, uint256 netSyOut, uint256 netSyFee, uint256 netSyToReserve)\n    {\n        (netSyOut, netSyFee, netSyToReserve) = calcSyOut(market, comp, index, guess);\n\n        uint256 newTotalPt = uint256(market.totalPt) + guess;\n        uint256 newTotalSy = (uint256(market.totalSy) - netSyOut - netSyToReserve);\n\n        // it is desired that\n        // (netSyOut + netSyHolding) / newTotalSy = netPtRemaining / newTotalPt\n        // which is equivalent to\n        // (netSyOut + netSyHolding) * newTotalPt = netPtRemaining * newTotalSy\n\n        syNumerator = (netSyOut + netSyHolding) * newTotalPt;\n        ptNumerator = (totalPtIn - guess) * newTotalSy;\n    }\n\n    /**\n     * @dev algorithm:\n     *     - Bin search the amount of PT to swap to SY\n     *     - Flashswap the corresponding amount of SY out\n     *     - Tokenize all the SY into PT + YT\n     *     - PT to repay the flashswap, YT transferred to user\n     *     - Stop when the additional amount of PT to pull to repay the loan approx the exactPtIn\n     *     - guess & approx is for totalPtToSwap\n     */\n    function approxSwapExactPtForYt(\n        MarketState memory market,\n        PYIndex index,\n        uint256 exactPtIn,\n        uint256 blockTime,\n        ApproxParams memory approx\n    ) internal pure returns (uint256, /*netYtOut*/ uint256, /*totalPtToSwap*/ uint256 /*netSyFee*/) {\n        MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);\n        if (approx.guessOffchain == 0) {\n            approx.guessMin = PMath.max(approx.guessMin, exactPtIn);\n            approx.guessMax = PMath.min(approx.guessMax, calcMaxPtIn(market, comp));\n            validateApprox(approx);\n        }\n\n        for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {\n            uint256 guess = nextGuess(approx, iter);\n\n            (uint256 netSyOut, uint256 netSyFee, ) = calcSyOut(market, comp, index, guess);\n\n            uint256 netAssetOut = index.syToAsset(netSyOut);\n\n            // guess >= netAssetOut since we are swapping PT to SY\n            uint256 netPtToPull = guess - netAssetOut;\n\n            if (netPtToPull <= exactPtIn) {\n                if (PMath.isASmallerApproxB(netPtToPull, exactPtIn, approx.eps)) {\n                    return (netAssetOut, guess, netSyFee);\n                }\n                approx.guessMin = guess;\n            } else {\n                approx.guessMax = guess - 1;\n            }\n        }\n        revert Errors.ApproxFail();\n    }\n\n    ////////////////////////////////////////////////////////////////////////////////\n\n    function calcSyOut(\n        MarketState memory market,\n        MarketPreCompute memory comp,\n        PYIndex index,\n        uint256 netPtIn\n    ) internal pure returns (uint256 netSyOut, uint256 netSyFee, uint256 netSyToReserve) {\n        (int256 _netSyOut, int256 _netSyFee, int256 _netSyToReserve) = market.calcTrade(comp, index, -int256(netPtIn));\n        netSyOut = uint256(_netSyOut);\n        netSyFee = uint256(_netSyFee);\n        netSyToReserve = uint256(_netSyToReserve);\n    }\n\n    function nextGuess(ApproxParams memory approx, uint256 iter) internal pure returns (uint256) {\n        if (iter == 0 && approx.guessOffchain != 0) return approx.guessOffchain;\n        if (approx.guessMin <= approx.guessMax) return (approx.guessMin + approx.guessMax) / 2;\n        revert Errors.ApproxFail();\n    }\n\n    /// INTENDED TO BE CALLED BY WHEN GUESS.OFFCHAIN == 0 ONLY ///\n\n    function validateApprox(ApproxParams memory approx) internal pure {\n        if (approx.guessMin > approx.guessMax || approx.eps > PMath.ONE) {\n            revert Errors.ApproxParamsInvalid(approx.guessMin, approx.guessMax, approx.eps);\n        }\n    }\n\n    function calcMaxPtIn(MarketState memory market, MarketPreCompute memory comp) internal pure returns (uint256) {\n        uint256 low = 0;\n        uint256 hi = uint256(comp.totalAsset) - 1;\n\n        while (low != hi) {\n            uint256 mid = (low + hi + 1) / 2;\n            if (calcSlope(comp, market.totalPt, int256(mid)) < 0) hi = mid - 1;\n            else low = mid;\n        }\n        return low;\n    }\n\n    function calcSlope(MarketPreCompute memory comp, int256 totalPt, int256 ptToMarket) internal pure returns (int256) {\n        int256 diffAssetPtToMarket = comp.totalAsset - ptToMarket;\n        int256 sumPt = ptToMarket + totalPt;\n\n        require(diffAssetPtToMarket > 0 && sumPt > 0, \"invalid ptToMarket\");\n\n        int256 part1 = (ptToMarket * (totalPt + comp.totalAsset)).divDown(sumPt * diffAssetPtToMarket);\n\n        int256 part2 = sumPt.divDown(diffAssetPtToMarket).ln();\n        int256 part3 = PMath.IONE.divDown(comp.rateScalar);\n\n        return comp.rateAnchor - (part1 - part2).mulDown(part3);\n    }\n}\n\nlibrary MarketApproxPtOutLib {\n    using MarketMathCore for MarketState;\n    using PYIndexLib for PYIndex;\n    using PMath for uint256;\n    using PMath for int256;\n    using LogExpMath for int256;\n\n    /**\n     * @dev algorithm:\n     *     - Bin search the amount of PT to swapExactOut\n     *     - Calculate the amount of SY needed\n     *     - Stop when the netSyIn is smaller approx exactSyIn\n     *     - guess & approx is for netSyIn\n     */\n    function approxSwapExactSyForPt(\n        MarketState memory market,\n        PYIndex index,\n        uint256 exactSyIn,\n        uint256 blockTime,\n        ApproxParams memory approx\n    ) internal pure returns (uint256, /*netPtOut*/ uint256 /*netSyFee*/) {\n        MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);\n        if (approx.guessOffchain == 0) {\n            // no limit on min\n            approx.guessMax = PMath.min(approx.guessMax, calcMaxPtOut(comp, market.totalPt));\n            validateApprox(approx);\n        }\n\n        for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {\n            uint256 guess = nextGuess(approx, iter);\n\n            (uint256 netSyIn, uint256 netSyFee, ) = calcSyIn(market, comp, index, guess);\n\n            if (netSyIn <= exactSyIn) {\n                if (PMath.isASmallerApproxB(netSyIn, exactSyIn, approx.eps)) {\n                    return (guess, netSyFee);\n                }\n                approx.guessMin = guess;\n            } else {\n                approx.guessMax = guess - 1;\n            }\n        }\n\n        revert Errors.ApproxFail();\n    }\n\n    /**\n     * @dev algorithm:\n     *     - Bin search the amount of PT to swapExactOut\n     *     - Flashswap that amount of PT & pair with YT to redeem SY\n     *     - Use the SY to repay the flashswap debt and the remaining is transferred to user\n     *     - Stop when the netSyOut is greater approx the minSyOut\n     *     - guess & approx is for netSyOut\n     */\n    function approxSwapYtForExactSy(\n        MarketState memory market,\n        PYIndex index,\n        uint256 minSyOut,\n        uint256 blockTime,\n        ApproxParams memory approx\n    ) internal pure returns (uint256, /*netYtIn*/ uint256, /*netSyOut*/ uint256 /*netSyFee*/) {\n        MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);\n        if (approx.guessOffchain == 0) {\n            // no limit on min\n            approx.guessMax = PMath.min(approx.guessMax, calcMaxPtOut(comp, market.totalPt));\n            validateApprox(approx);\n        }\n\n        for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {\n            uint256 guess = nextGuess(approx, iter);\n\n            (uint256 netSyOwed, uint256 netSyFee, ) = calcSyIn(market, comp, index, guess);\n\n            uint256 netAssetToRepay = index.syToAssetUp(netSyOwed);\n            uint256 netSyOut = index.assetToSy(guess - netAssetToRepay);\n\n            if (netSyOut >= minSyOut) {\n                if (PMath.isAGreaterApproxB(netSyOut, minSyOut, approx.eps)) {\n                    return (guess, netSyOut, netSyFee);\n                }\n                approx.guessMax = guess;\n            } else {\n                approx.guessMin = guess + 1;\n            }\n        }\n        revert Errors.ApproxFail();\n    }\n\n    struct Args6 {\n        MarketState market;\n        PYIndex index;\n        uint256 totalSyIn;\n        uint256 netPtHolding;\n        uint256 blockTime;\n        ApproxParams approx;\n    }\n\n    /**\n     * @dev algorithm:\n     *     - Bin search the amount of PT to swapExactOut\n     *     - Swap that amount of PT out\n     *     - Pair the remaining PT with the SY to add liquidity\n     *     - Stop when the ratio of PT / totalPt & SY / totalSy is approx\n     *     - guess & approx is for netPtFromSwap\n     */\n    function approxSwapSyToAddLiquidity(\n        MarketState memory _market,\n        PYIndex _index,\n        uint256 _totalSyIn,\n        uint256 _netPtHolding,\n        uint256 _blockTime,\n        ApproxParams memory _approx\n    ) internal pure returns (uint256, /*netPtFromSwap*/ uint256, /*netSySwap*/ uint256 /*netSyFee*/) {\n        Args6 memory a = Args6(_market, _index, _totalSyIn, _netPtHolding, _blockTime, _approx);\n\n        MarketPreCompute memory comp = a.market.getMarketPreCompute(a.index, a.blockTime);\n        if (a.approx.guessOffchain == 0) {\n            // no limit on min\n            a.approx.guessMax = PMath.min(a.approx.guessMax, calcMaxPtOut(comp, a.market.totalPt));\n            validateApprox(a.approx);\n            require(a.market.totalLp != 0, \"no existing lp\");\n        }\n\n        for (uint256 iter = 0; iter < a.approx.maxIteration; ++iter) {\n            uint256 guess = nextGuess(a.approx, iter);\n\n            (uint256 netSyIn, uint256 netSyFee, uint256 netSyToReserve) = calcSyIn(a.market, comp, a.index, guess);\n\n            if (netSyIn > a.totalSyIn) {\n                a.approx.guessMax = guess - 1;\n                continue;\n            }\n\n            uint256 syNumerator;\n            uint256 ptNumerator;\n\n            {\n                uint256 newTotalPt = uint256(a.market.totalPt) - guess;\n                uint256 netTotalSy = uint256(a.market.totalSy) + netSyIn - netSyToReserve;\n\n                // it is desired that\n                // (netPtFromSwap + netPtHolding) / newTotalPt = netSyRemaining / netTotalSy\n                // which is equivalent to\n                // (netPtFromSwap + netPtHolding) * netTotalSy = netSyRemaining * newTotalPt\n\n                ptNumerator = (guess + a.netPtHolding) * netTotalSy;\n                syNumerator = (a.totalSyIn - netSyIn) * newTotalPt;\n            }\n\n            if (PMath.isAApproxB(ptNumerator, syNumerator, a.approx.eps)) {\n                return (guess, netSyIn, netSyFee);\n            }\n\n            if (ptNumerator <= syNumerator) {\n                // needs more PT\n                a.approx.guessMin = guess + 1;\n            } else {\n                // needs less PT\n                a.approx.guessMax = guess - 1;\n            }\n        }\n        revert Errors.ApproxFail();\n    }\n\n    /**\n     * @dev algorithm:\n     *     - Bin search the amount of PT to swapExactOut\n     *     - Flashswap that amount of PT out\n     *     - Pair all the PT with the YT to redeem SY\n     *     - Use the SY to repay the flashswap debt\n     *     - Stop when the amount of YT required to pair with PT is approx exactYtIn\n     *     - guess & approx is for netPtFromSwap\n     */\n    function approxSwapExactYtForPt(\n        MarketState memory market,\n        PYIndex index,\n        uint256 exactYtIn,\n        uint256 blockTime,\n        ApproxParams memory approx\n    ) internal pure returns (uint256, /*netPtOut*/ uint256, /*totalPtSwapped*/ uint256 /*netSyFee*/) {\n        MarketPreCompute memory comp = market.getMarketPreCompute(index, blockTime);\n        if (approx.guessOffchain == 0) {\n            approx.guessMin = PMath.max(approx.guessMin, exactYtIn);\n            approx.guessMax = PMath.min(approx.guessMax, calcMaxPtOut(comp, market.totalPt));\n            validateApprox(approx);\n        }\n\n        for (uint256 iter = 0; iter < approx.maxIteration; ++iter) {\n            uint256 guess = nextGuess(approx, iter);\n\n            (uint256 netSyOwed, uint256 netSyFee, ) = calcSyIn(market, comp, index, guess);\n\n            uint256 netYtToPull = index.syToAssetUp(netSyOwed);\n\n            if (netYtToPull <= exactYtIn) {\n                if (PMath.isASmallerApproxB(netYtToPull, exactYtIn, approx.eps)) {\n                    return (guess - netYtToPull, guess, netSyFee);\n                }\n                approx.guessMin = guess;\n            } else {\n                approx.guessMax = guess - 1;\n            }\n        }\n        revert Errors.ApproxFail();\n    }\n\n    ////////////////////////////////////////////////////////////////////////////////\n\n    function calcSyIn(\n        MarketState memory market,\n        MarketPreCompute memory comp,\n        PYIndex index,\n        uint256 netPtOut\n    ) internal pure returns (uint256 netSyIn, uint256 netSyFee, uint256 netSyToReserve) {\n        (int256 _netSyIn, int256 _netSyFee, int256 _netSyToReserve) = market.calcTrade(comp, index, int256(netPtOut));\n\n        // all safe since totalPt and totalSy is int128\n        netSyIn = uint256(-_netSyIn);\n        netSyFee = uint256(_netSyFee);\n        netSyToReserve = uint256(_netSyToReserve);\n    }\n\n    function calcMaxPtOut(MarketPreCompute memory comp, int256 totalPt) internal pure returns (uint256) {\n        int256 logitP = (comp.feeRate - comp.rateAnchor).mulDown(comp.rateScalar).exp();\n        int256 proportion = logitP.divDown(logitP + PMath.IONE);\n        int256 numerator = proportion.mulDown(totalPt + comp.totalAsset);\n        int256 maxPtOut = totalPt - numerator;\n        // only get 99.9% of the theoretical max to accommodate some precision issues\n        return (uint256(maxPtOut) * 999) / 1000;\n    }\n\n    function nextGuess(ApproxParams memory approx, uint256 iter) internal pure returns (uint256) {\n        if (iter == 0 && approx.guessOffchain != 0) return approx.guessOffchain;\n        if (approx.guessMin <= approx.guessMax) return (approx.guessMin + approx.guessMax) / 2;\n        revert Errors.ApproxFail();\n    }\n\n    function validateApprox(ApproxParams memory approx) internal pure {\n        if (approx.guessMin > approx.guessMax || approx.eps > PMath.ONE) {\n            revert Errors.ApproxParamsInvalid(approx.guessMin, approx.guessMax, approx.eps);\n        }\n    }\n}\n"
      },
      "@pendle/core-v2/contracts/router/swap-aggregator/IPSwapAggregator.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nstruct SwapData {\n    SwapType swapType;\n    address extRouter;\n    bytes extCalldata;\n    bool needScale;\n}\n\nenum SwapType {\n    NONE,\n    KYBERSWAP,\n    ONE_INCH,\n    // ETH_WETH not used in Aggregator\n    ETH_WETH\n}\n\ninterface IPSwapAggregator {\n    function swap(address tokenIn, uint256 amountIn, SwapData calldata swapData) external payable;\n}\n"
      },
      "@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Callback for IUniswapV3PoolActions#swap\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\ninterface IUniswapV3SwapCallback {\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n    function uniswapV3SwapCallback(\n        int256 amount0Delta,\n        int256 amount1Delta,\n        bytes calldata data\n    ) external;\n}\n"
      },
      "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.7.5;\npragma abicoder v2;\n\nimport '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\n\n/// @title Router token swapping functionality\n/// @notice Functions for swapping tokens via Uniswap V3\ninterface ISwapRouter is IUniswapV3SwapCallback {\n    struct ExactInputSingleParams {\n        address tokenIn;\n        address tokenOut;\n        uint24 fee;\n        address recipient;\n        uint256 deadline;\n        uint256 amountIn;\n        uint256 amountOutMinimum;\n        uint160 sqrtPriceLimitX96;\n    }\n\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\n    /// @return amountOut The amount of the received token\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\n\n    struct ExactInputParams {\n        bytes path;\n        address recipient;\n        uint256 deadline;\n        uint256 amountIn;\n        uint256 amountOutMinimum;\n    }\n\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\n    /// @return amountOut The amount of the received token\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\n\n    struct ExactOutputSingleParams {\n        address tokenIn;\n        address tokenOut;\n        uint24 fee;\n        address recipient;\n        uint256 deadline;\n        uint256 amountOut;\n        uint256 amountInMaximum;\n        uint160 sqrtPriceLimitX96;\n    }\n\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\n    /// @return amountIn The amount of the input token\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\n\n    struct ExactOutputParams {\n        bytes path;\n        address recipient;\n        uint256 deadline;\n        uint256 amountOut;\n        uint256 amountInMaximum;\n    }\n\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\n    /// @return amountIn The amount of the input token\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\n}\n"
      },
      "contracts/interfaces/IStrategyBase.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\n\n/// @notice StrategyBase interface\ninterface IStrategyBase {\n    function depositCalldata(uint256 _amount) external view returns (address, bytes memory);\n\n    function addressToApprove() external view returns (address);\n\n    function withdraw(uint256 _amount) external returns (uint256);\n\n    function nav() external view returns (uint256);\n\n    function yieldToUnderlying(uint256 amount) external view returns (uint256);\n\n    function underlyingToYield(uint256 amount) external view returns (uint256);\n\n    function yieldBalance() external view returns (uint256);\n\n    function poolingManager() external view returns (address);\n\n    function underlyingToken() external view returns (address);\n\n    function yieldToken() external view returns (address);\n\n    function bridge() external view returns (address);\n}\n"
      },
      "contracts/interfaces/pendle/IMarketDepositHelper.sol": {
        "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.20;\n\ninterface IMarketDepositHelper {\n    function depositMarket(address market, uint256 amount) external;\n    function depositMarketFor(address market, address _for, uint256 amount) external;\n    function withdrawMarket(address market, uint256 amount) external;\n    function withdrawMarketWithClaim(address market, uint256 amount, bool doClaim) external;\n    function balance(address market, address user) external view returns (uint256);\n}\n"
      },
      "contracts/interfaces/pendle/IPenpie.sol": {
        "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.20;\n\ninterface IPenpie {\n    function multiclaim(address[] calldata _stakingTokens) external;\n}\n"
      },
      "contracts/lib/ErrorLib.sol": {
        "content": "// SPDX-License-Identifier: Apache-2.0.\npragma solidity ^0.8.20;\n\nlibrary ErrorLib {\n    error CallerIsNotPoolingManager();\n    error CallerIsNotAdmin();\n    error InvalidPoolingManager();\n    error NotPoolingManager();\n    error InvalidUnderlyingToken();\n    error InvalidSyUnderlyingToken();\n    error PoolNotExist();\n    error InvalidSlippage();\n    error ErrorStrategyNotExist(address strategy);\n    error ErrorBeforeProcessStrategy(address strategy);\n    error ErrorDepositStrategy(address strategy);\n    error ErrorWithdrawStrategy(address strategy);\n    error ErrorAfterWithdrawStrategy(address strategy);\n    error InvalidMarket();\n    error ZeroAmount();\n    error Expired();\n    error MinReceivedAmountExceeded();\n    error InvalidToken();\n    error InvalidSyToken();\n    error IncreaseCardinalityRequired();\n    error OldestObservationNotSatisfied();\n    error InvalidBalancerPool();\n    error InvalidUniswapPath();\n    error InvalidCurvePool();\n}\n"
      },
      "contracts/strategies/pendleLp/lrt/PendleLpStrategyLrt.sol": {
        "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.20;\n\nimport \"../PendleLpStrategyBase.sol\";\nimport {IERC20Metadata} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {IVault} from \"@balancer-labs/v2-interfaces/contracts/vault/IVault.sol\";\nimport {IAsset} from \"@balancer-labs/v2-interfaces/contracts/vault/IAsset.sol\";\nimport {ErrorLib} from \"../../../lib/ErrorLib.sol\";\n\n// all LRT have 2 major sources of liquidity, Uniswap V2, Balancer V2 or Curve\n\ninterface CurveFi {\n    function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external returns (uint256);\n}\n\ncontract PendleLpStrategyLrt is PendleLpStrategyBase {\n    using SafeERC20 for IERC20;\n    uint256 public pricefeedPrecision;\n    uint256 public syUnderlyingPrecision;\n    uint256 public underlyingPrecision;\n    uint256 public minReceivedAmountFactorUnderlyingSy;\n    bytes public uniswapPathUnderlyingToSyUnderlying;\n    bytes public uniswapPathSyUnderlyingToUnderlying;\n    bytes32 public balancerPoolId;\n    CurveFi public curvePool;\n    IVault internal constant BALANCER_VAULT = IVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);\n\n    enum Exchange {\n        Curve,\n        Uniswap,\n        Balancer\n    }\n    Exchange public selectedExchange;\n\n    struct ExchangeInitParams {\n        bytes uniswapPathUnderlyingToSyUnderlying;\n        bytes uniswapPathSyUnderlyingToUnderlying;\n        bytes32 balancerPoolId;\n        address curvePool;\n        Exchange selectedExchange;\n    }\n\n    constructor() initializer {}\n\n    function initialize(\n        address _poolingManager,\n        address _underlying,\n        address _yieldToken,\n        address _bridge,\n        address _syUnderlying,\n        ExchangeInitParams memory _exchangeParams,\n        uint256 _maxSingleTrade\n    ) external initializer {\n        _initExchange(_exchangeParams);\n        _initializePendleLpStrategy(_poolingManager, _underlying, _yieldToken, _bridge, _syUnderlying, _maxSingleTrade);\n        _setMinReceivedAmountFactorUnderlyingSy((WAD * 990) / 1000);\n    }\n\n    function setUniswapPathUnderlyingToSyUnderlying(bytes memory _uniswapPathUnderlyingToSyUnderlying) external {\n        _assertOnlyRoleOwner();\n        if (_uniswapPathUnderlyingToSyUnderlying.length == 0) revert ErrorLib.InvalidUniswapPath();\n        uniswapPathUnderlyingToSyUnderlying = _uniswapPathUnderlyingToSyUnderlying;\n    }\n\n    function setUniswapPathSyUnderlyingToUnderlying(bytes memory _uniswapPathSyUnderlyingToUnderlying) external {\n        _assertOnlyRoleOwner();\n        if (_uniswapPathSyUnderlyingToUnderlying.length == 0) revert ErrorLib.InvalidUniswapPath();\n        uniswapPathSyUnderlyingToUnderlying = _uniswapPathSyUnderlyingToUnderlying;\n    }\n\n    function setBalancerPoolId(bytes32 _balancerPoolId) external {\n        _assertOnlyRoleOwner();\n        if (_balancerPoolId == bytes32(0)) revert ErrorLib.InvalidBalancerPool();\n        balancerPoolId = _balancerPoolId;\n    }\n\n    function setCurvePool(address _curvePool) external {\n        _assertOnlyRoleOwner();\n        if (_curvePool == address(0)) revert ErrorLib.InvalidCurvePool();\n        curvePool = CurveFi(_curvePool);\n    }\n\n    function switchAmm(Exchange _selectedExchange) external {\n        _assertOnlyRoleOwner();\n        address currentSpender = _addressToApproveSyUnderlyingAndUnderlying();\n        IERC20 underlyingTokenDisp = IERC20(underlyingToken);\n        IERC20 syUnderlyingTokenDisp = IERC20(syUnderlying);\n        underlyingTokenDisp.forceApprove(address(currentSpender), 0);\n        syUnderlyingTokenDisp.forceApprove(address(currentSpender), 0);\n        if (_selectedExchange == Exchange.Uniswap) {\n            if (uniswapPathUnderlyingToSyUnderlying.length == 0) revert ErrorLib.InvalidUniswapPath();\n            if (uniswapPathSyUnderlyingToUnderlying.length == 0) revert ErrorLib.InvalidUniswapPath();\n        }\n        if (_selectedExchange == Exchange.Balancer) {\n            if (balancerPoolId == bytes32(0)) revert ErrorLib.InvalidBalancerPool();\n        }\n\n        if (_selectedExchange == Exchange.Curve) {\n            if (address(curvePool) == address(0)) revert ErrorLib.InvalidCurvePool();\n        }\n        selectedExchange = _selectedExchange;\n        currentSpender = _addressToApproveSyUnderlyingAndUnderlying();\n        underlyingTokenDisp.forceApprove(address(currentSpender), type(uint).max);\n        syUnderlyingTokenDisp.forceApprove(address(currentSpender), type(uint).max);\n    }\n\n    function setMinReceivedAmountFactorUnderlyingSy(uint256 _minReceivedAmountFactorUnderlyingSy) external {\n        _assertOnlyRoleOwner();\n        _setMinReceivedAmountFactorUnderlyingSy(_minReceivedAmountFactorUnderlyingSy);\n    }\n\n    /// @inheritdoc PendleLpStrategyBase\n    function _getSyUnderlyingFromUnderlying(uint256 _amount) internal override returns (uint256) {\n        uint256 syUnderlyingAmount = _underlyingToSyUnderlying(_amount);\n        uint256 amountOutMinimum = (minReceivedAmountFactorUnderlyingSy * syUnderlyingAmount) / (WAD);\n        if (selectedExchange == Exchange.Balancer) {\n            IVault.SingleSwap memory swapParams = IVault.SingleSwap({\n                poolId: balancerPoolId,\n                kind: IVault.SwapKind.GIVEN_IN,\n                assetIn: IAsset(underlyingToken),\n                assetOut: IAsset(syUnderlying),\n                amount: _amount,\n                userData: new bytes(0)\n            });\n            IVault.FundManagement memory fundsParams = IVault.FundManagement({\n                sender: address(this),\n                fromInternalBalance: false,\n                recipient: payable(address(this)),\n                toInternalBalance: false\n            });\n            return BALANCER_VAULT.swap(swapParams, fundsParams, amountOutMinimum, block.timestamp);\n        } else if (selectedExchange == Exchange.Curve) {\n            return curvePool.exchange(0, 1, _amount, amountOutMinimum);\n        } else {\n            ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({\n                path: uniswapPathUnderlyingToSyUnderlying,\n                recipient: address(this),\n                deadline: block.timestamp,\n                amountIn: _amount,\n                amountOutMinimum: amountOutMinimum\n            });\n            return UNI_V3_ROUTER.exactInput(params);\n        }\n    }\n\n    /// @inheritdoc PendleLpStrategyBase\n    function _getUnderlyingFromSyUnderlying(uint256 _shares) internal override returns (uint256) {\n        uint256 underlyingAmount = _syUnderlyingToUnderlying(_shares);\n        uint256 amountOutMinimum = (minReceivedAmountFactorUnderlyingSy * underlyingAmount) / (WAD);\n        if (selectedExchange == Exchange.Balancer) {\n            IVault.SingleSwap memory swapParams = IVault.SingleSwap({\n                poolId: balancerPoolId,\n                kind: IVault.SwapKind.GIVEN_IN,\n                assetIn: IAsset(syUnderlying),\n                assetOut: IAsset(underlyingToken),\n                amount: _shares,\n                userData: new bytes(0)\n            });\n            IVault.FundManagement memory fundsParams = IVault.FundManagement({\n                sender: address(this),\n                fromInternalBalance: false,\n                recipient: payable(address(this)),\n                toInternalBalance: false\n            });\n            return (BALANCER_VAULT.swap(swapParams, fundsParams, amountOutMinimum, block.timestamp));\n        } else if (selectedExchange == Exchange.Curve) {\n            return curvePool.exchange(1, 0, _shares, amountOutMinimum);\n        } else {\n            ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({\n                path: uniswapPathSyUnderlyingToUnderlying,\n                recipient: address(this),\n                deadline: block.timestamp,\n                amountIn: _shares,\n                amountOutMinimum: amountOutMinimum\n            });\n            return UNI_V3_ROUTER.exactInput(params);\n        }\n    }\n\n    function _syUnderlyingToUnderlying(uint256 _amount) internal view returns (uint256) {\n        return (_amount * sy.exchangeRate()) / (WAD);\n    }\n\n    function _underlyingToSyUnderlying(uint256 _amount) internal view returns (uint256) {\n        return (_amount * WAD) / (sy.exchangeRate());\n    }\n\n    function _addressToApproveUnderlyingToSyUnderlying() internal view override returns (address) {\n        return _addressToApproveSyUnderlyingAndUnderlying();\n    }\n\n    function _addressToApproveSyUnderlyingToUnderlying() internal view override returns (address) {\n        return _addressToApproveSyUnderlyingAndUnderlying();\n    }\n\n    function _addressToApproveSyUnderlyingAndUnderlying() internal view returns (address) {\n        if (selectedExchange == Exchange.Balancer) {\n            return address(BALANCER_VAULT);\n        } else if (selectedExchange == Exchange.Curve) {\n            return address(curvePool);\n        } else {\n            return address(UNI_V3_ROUTER);\n        }\n    }\n\n    function _setMinReceivedAmountFactorUnderlyingSy(uint256 _minReceivedAmountFactorUnderlyingSy) internal {\n        if (_minReceivedAmountFactorUnderlyingSy > WAD || _minReceivedAmountFactorUnderlyingSy < (WAD * 98) / 100)\n            revert ErrorLib.InvalidSlippage();\n        minReceivedAmountFactorUnderlyingSy = _minReceivedAmountFactorUnderlyingSy;\n    }\n\n    function _initExchange(ExchangeInitParams memory _params) internal {\n        selectedExchange = _params.selectedExchange;\n        if (_params.selectedExchange == Exchange.Balancer) {\n            if (_params.balancerPoolId == bytes32(0)) revert ErrorLib.InvalidBalancerPool();\n            balancerPoolId = _params.balancerPoolId;\n        } else if (_params.selectedExchange == Exchange.Uniswap) {\n            if (_params.uniswapPathUnderlyingToSyUnderlying.length == 0) revert ErrorLib.InvalidUniswapPath();\n            if (_params.uniswapPathSyUnderlyingToUnderlying.length == 0) revert ErrorLib.InvalidUniswapPath();\n            uniswapPathUnderlyingToSyUnderlying = _params.uniswapPathUnderlyingToSyUnderlying;\n            uniswapPathSyUnderlyingToUnderlying = _params.uniswapPathSyUnderlyingToUnderlying;\n        } else if (_params.selectedExchange == Exchange.Curve) {\n            if (_params.curvePool == address(0)) revert ErrorLib.InvalidCurvePool();\n            curvePool = CurveFi(_params.curvePool);\n        }\n    }\n}\n"
      },
      "contracts/strategies/pendleLp/PendleLpStrategyBase.sol": {
        "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {IPMarket} from \"@pendle/core-v2/contracts/interfaces/IPMarket.sol\";\nimport {IPActionAddRemoveLiqV3, LimitOrderData, ApproxParams} from \"@pendle/core-v2/contracts/interfaces/IPActionAddRemoveLiqV3.sol\";\nimport {PendleLpOracleLib, IStandardizedYield} from \"@pendle/core-v2/contracts/oracles/PendlePtLpOracle.sol\";\nimport {IPPtLpOracle} from \"@pendle/core-v2/contracts/interfaces/IPPtLpOracle.sol\";\nimport {ISwapRouter} from \"@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\";\nimport {StrategyBase} from \"../StrategyBase.sol\";\nimport {ErrorLib} from \"../../lib/ErrorLib.sol\";\nimport {IPenpie} from \"../../interfaces/pendle/IPenpie.sol\";\nimport {IMarketDepositHelper} from \"../../interfaces/pendle/IMarketDepositHelper.sol\";\n\n/// @title Base contract for pendle strategy LP\n/// @author @nimbora 2024\nabstract contract PendleLpStrategyBase is StrategyBase {\n    using SafeERC20 for IERC20;\n    using Math for uint256;\n    using PendleLpOracleLib for IPMarket;\n\n    // Constants\n    uint256 internal constant WAD = 10 ** 18;\n    IPActionAddRemoveLiqV3 internal constant PENDLE_ROUTER =\n        IPActionAddRemoveLiqV3(0x00000000005BBB0EF59571E58418F9a4357b68A0);\n    IMarketDepositHelper internal constant MARKET_DEPOSIT_HELPER =\n        IMarketDepositHelper(0x1C1Fb35334290b5ff1bF7B4c09130885b10Fc0f4);\n    IERC20 internal constant PENDLE = IERC20(0x808507121B80c02388fAd14726482e061B8da827);\n    IPPtLpOracle internal constant PTLPORACLE = IPPtLpOracle(0x66a1096C6366b2529274dF4f5D8247827fe4CEA8);\n    IPenpie internal constant PENPIE = IPenpie(0x16296859C15289731521F199F0a5f762dF6347d0);\n    address internal constant PENDLE_STAKING = 0x6E799758CEE75DAe3d84e09D40dc416eCf713652;\n    ISwapRouter internal constant UNI_V3_ROUTER = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);\n\n    // Subject to modification\n    uint32 public twapDuration;\n    bytes public uniswapPathPendleUnderlying;\n    IPMarket public market;\n    IStandardizedYield public sy;\n    address public syUnderlying;\n    uint256 public minAmountToSell;\n    // https://docs.pendle.finance/Developers/Contracts/PendleRouter#approxparams\n    ApproxParams public receiveParams;\n    uint256 public maxSingleTrade;\n    uint256 public minReceivedAmountFactor;\n\n    function _initializePendleLpStrategy(\n        address _poolingManager,\n        address _underlyingToken,\n        address _yieldToken,\n        address _bridge,\n        address _syUnderlying,\n        uint256 _maxSingleTrade\n    ) internal {\n        _strategyBase__init(_poolingManager, _underlyingToken, _yieldToken, _bridge);\n        market = IPMarket(_yieldToken);\n        if (market.isExpired()) revert ErrorLib.InvalidMarket();\n        (sy, , ) = market.readTokens();\n        if (sy.isValidTokenIn(_syUnderlying) == false) revert ErrorLib.InvalidSyUnderlyingToken();\n        syUnderlying = _syUnderlying;\n        IERC20(_underlyingToken).safeIncreaseAllowance(_addressToApproveUnderlyingToSyUnderlying(), type(uint).max);\n        IERC20(_syUnderlying).safeIncreaseAllowance(_addressToApproveSyUnderlyingToUnderlying(), type(uint).max);\n        IERC20(_syUnderlying).safeIncreaseAllowance(address(sy), type(uint).max);\n        IERC20(address(sy)).safeIncreaseAllowance(address(PENDLE_ROUTER), type(uint).max);\n        IERC20(_yieldToken).safeIncreaseAllowance(PENDLE_STAKING, type(uint).max);\n        IERC20(_yieldToken).safeIncreaseAllowance(address(PENDLE_ROUTER), type(uint).max);\n        PENDLE.safeIncreaseAllowance(address(UNI_V3_ROUTER), type(uint).max);\n        twapDuration = 1200;\n        minAmountToSell = type(uint).max;\n        receiveParams = ApproxParams({\n            guessMin: 0,\n            guessMax: type(uint256).max,\n            guessOffchain: 0,\n            maxIteration: 256,\n            eps: 1e14\n        });\n        _setMinReceivedAmountFactor((WAD * 98) / 100);\n        maxSingleTrade = _maxSingleTrade;\n\n        // check if pendle market oracle initialized for the twap duration\n        _verifyOracleReady(address(market), twapDuration);\n    }\n\n    /**\n     * @dev Replaces the current yield token market with a new one.\n     * This function performs several critical actions in the process of changing the market:\n     * 1. Validates the new market and the associated Standardized Yield (SY) token.\n     * 2. Claims rewards from the current market and possibly trades them for additional SY tokens.\n     * 3. Withdraws the liquidity from the current market and deposits it into the new market.\n     * 4. Updates the contract's state to reference the new market and its associated tokens.\n     *\n     * @param _yieldToken The address of the new market to switch to.\n     */\n    function replaceMarket(address _yieldToken) external {\n        _assertOnlyRoleOwner();\n\n        // check new market valid\n        IPMarket newMarket = IPMarket(_yieldToken);\n        if (newMarket.isExpired()) revert ErrorLib.InvalidMarket();\n        (IStandardizedYield newSy, , ) = newMarket.readTokens();\n        if (newSy != sy) revert ErrorLib.InvalidSyToken();\n\n        // claim rewards\n        _harvestAndSellRewards();\n\n        // Get potentially more SY if sold PENDLE\n        uint256 underlyingBalance = IERC20(underlyingToken).balanceOf(address(this));\n        if (underlyingBalance > 0) {\n            sy.deposit(address(this), syUnderlying, _getSyUnderlyingFromUnderlying(underlyingBalance), 1);\n        }\n\n        // withdraw all LP to sy, do not care about maxSingleTrade as market is expired and there is no price impact\n        uint256 withdrawAmount = _yieldBalance();\n        MARKET_DEPOSIT_HELPER.withdrawMarket(address(market), withdrawAmount);\n        LimitOrderData memory limit;\n        PENDLE_ROUTER.removeLiquiditySingleSy(address(this), address(market), withdrawAmount, 1, limit);\n\n        uint256 tradeSize = Math.min(IERC20(address(sy)).balanceOf(address(this)), maxSingleTrade);\n\n        // check if pendle market oracle initialized for the twap duration\n        _verifyOracleReady(address(market), twapDuration);\n\n        // Deposit all SY to the new market\n        (uint256 netLpOut, ) = PENDLE_ROUTER.addLiquiditySingleSy(\n            address(this),\n            address(newMarket),\n            tradeSize,\n            ((tradeSize * minReceivedAmountFactor) / newMarket.getLpToSyRate(twapDuration)),\n            receiveParams,\n            limit\n        );\n\n        IERC20(_yieldToken).safeIncreaseAllowance(PENDLE_STAKING, type(uint).max);\n        IERC20(_yieldToken).safeIncreaseAllowance(address(PENDLE_ROUTER), type(uint).max);\n        MARKET_DEPOSIT_HELPER.depositMarket(address(newMarket), netLpOut);\n        // replace the market\n        yieldToken = _yieldToken;\n        market = newMarket;\n    }\n\n    /**\n     * @notice Determines the address to approve for converting underlying tokens to SY tokens.\n     * @dev Must be implemented by the derived contract to specify the approval address.\n     * @return The address which will be approved to handle the underlying to SY conversion.\n     */\n    function _addressToApproveUnderlyingToSyUnderlying() internal view virtual returns (address);\n\n    /**\n     * @notice Determines the address to approve for converting SY tokens back to underlying tokens.\n     * @dev Must be implemented by the derived contract to specify the approval address.\n     * @return The address which will be approved to handle the SY to underlying conversion.\n     */\n    function _addressToApproveSyUnderlyingToUnderlying() internal view virtual returns (address);\n\n    /**\n     * @dev Converts a specified `amount` of underlying token to SY underlying token.\n     * Must be implemented by the derived contract to define the conversion logic.\n     * @param amount The amount of underlying token to convert.\n     * @return SY underlying token amount.\n     */\n    function _getSyUnderlyingFromUnderlying(uint256 amount) internal virtual returns (uint256);\n\n    /**\n     * @dev Converts a specified `amount` of sy underlying token to underlying token.\n     * Must be implemented by the derived contract to define the conversion logic.\n     * @param amount The amount of sy underlying token to convert.\n     * @return underlying token amount.\n     */\n    function _getUnderlyingFromSyUnderlying(uint256 amount) internal virtual returns (uint256);\n\n    /**\n     * @notice Sets the minimum amount of rewards that triggers selling PENDLE liquidity mining.\n     * @dev Only callable by the role owner to adjust the threshold for selling rewards.\n     * @param _minAmountToSell New minimum amount to trigger the sell operation.\n     */\n    function setMinAmountToSell(uint256 _minAmountToSell) external {\n        _assertOnlyRoleOwner();\n        minAmountToSell = _minAmountToSell;\n    }\n\n    /**\n     * @notice Sets the duration for TWAP (Time Weighted Average Price) calculation.\n     * @dev Only callable by the role owner to adjust the duration for TWAP.\n     * @param _twapDuration New duration in seconds for the TWAP calculation.\n     */\n    function setTwapDuration(uint32 _twapDuration) external {\n        _assertOnlyRoleOwner();\n        twapDuration = _twapDuration;\n        _verifyOracleReady(yieldToken, _twapDuration);\n    }\n\n    /**\n     * @notice Sets the path for swapping Pendle to the underlying token on Uniswap.\n     * @dev Only callable by the role owner to adjust the swap path used in trading operations.\n     * @param _uniswapPathPendleUnderlying The new swap path encoded as bytes.\n     */\n    function setUniswapPathPendleUnderlying(bytes memory _uniswapPathPendleUnderlying) external {\n        _assertOnlyRoleOwner();\n        uniswapPathPendleUnderlying = _uniswapPathPendleUnderlying;\n    }\n\n    /**\n     * @notice Sets the minimum receive amount factor when providing liquidity on Pendle market.\n     * @dev Only callable by the role owner, WAD unit.\n     * @param _minReceivedAmountFactor The new minimum receive amount factor.\n     */\n    function setMinReceivedAmountFactor(uint256 _minReceivedAmountFactor) external {\n        _assertOnlyRoleOwner();\n        _setMinReceivedAmountFactor(_minReceivedAmountFactor);\n    }\n\n    /**\n     * @notice Sets the maximum amount of underlying token that can be deposited and withdrawn\n     * in a single operation.\n     * @dev Only callable by the role owner to adjust the maximum trade amount.\n     * @param _maxSingleTrade New maximum single trade amount.\n     */\n    function setMaxSingleTrade(uint256 _maxSingleTrade) external {\n        _assertOnlyRoleOwner();\n        maxSingleTrade = _maxSingleTrade;\n    }\n\n    /**\n     * @notice Transfers out any token from the contract.\n     * @dev Can be used to recover tokens sent to the contract mistakenly. Only callable by the role owner.\n     * @param _token The address of the token to be swept out of the contract.\n     */\n    function sweep(address _token) external {\n        _assertOnlyRoleOwner();\n        if (_token == underlyingToken || _token == address(PENDLE) || _token == address(address(sy)))\n            revert ErrorLib.InvalidToken();\n        IERC20(_token).safeTransfer(msg.sender, IERC20(_token).balanceOf(address(this)));\n    }\n\n    /**\n     * @notice Sets the parameters for receiving yields and approximations.\n     * @dev Only callable by the role owner to adjust the parameters used in yield calculation.\n     * @param _receiveParams The structure containing the new parameters for yield receiving.\n     */\n    function setReceiveParams(ApproxParams memory _receiveParams) external {\n        _assertOnlyRoleOwner();\n        receiveParams = _receiveParams;\n    }\n\n    /// @inheritdoc\tStrategyBase\n    function addressToApprove() external view override returns (address) {\n        return (address(this));\n    }\n\n    /// @inheritdoc\tStrategyBase\n    function depositCalldata(uint256 _amount) external view override returns (address target, bytes memory cdata) {\n        target = address(this);\n        cdata = abi.encodeWithSignature(\"deposit(uint256)\", _amount);\n    }\n\n    /**\n     * @dev Deposits the specified `_amount` of the underlying token into the market.\n     * This function handles the process of converting the underlying token sy underlying tokens, depositing it into SY token and finally depositing it into LP.\n     * The process includes:w\n     * 1. Checking market expiry and caller's permissions.\n     * 2. Harvesting and selling any accrued rewards.\n     * 3. Transferring the underlying tokens from the caller to the contract.\n     * 4. Converting the underlying tokens to sy underlying.\n     * 5. Depositing the sy underlying tokens to sy.\n     * 6. Depositing sy tokens into the market to receive liquidity tokens.\n     * 7. Depositing LP tokens into penpie to boost PENDLE distribution.\n     *\n     * @param _amount The amount of the underlying token to be deposited.\n     * @notice This function should only be called by the pooling manager.\n     *         It uses the market's deposit logic and handles reward harvesting internally.\n     */\n    function deposit(uint256 _amount) external {\n        if (market.isExpired()) revert ErrorLib.Expired();\n        if (msg.sender != poolingManager) revert ErrorLib.CallerIsNotPoolingManager();\n        // sold rewards will be in underlying token\n        _harvestAndSellRewards();\n\n        IERC20(underlyingToken).safeTransferFrom(msg.sender, address(this), _amount);\n\n        // potential additional underlying after harvesting PENDLE or following a withdraw with dust underlying.\n        // wrap token to sy and deposit to market\n        sy.deposit(\n            address(this),\n            syUnderlying,\n            _getSyUnderlyingFromUnderlying(IERC20(underlyingToken).balanceOf(address(this))),\n            1\n        );\n\n        // Make sure received amount is fair\n        // deposit sy into market\n        uint256 tradeSize = Math.min(IERC20(address(sy)).balanceOf(address(this)), maxSingleTrade);\n        LimitOrderData memory limit;\n        (uint256 netLpOut, ) = PENDLE_ROUTER.addLiquiditySingleSy(\n            address(this),\n            address(market),\n            // potential additiomal sy tokens when addLiquidity due to receiveParams precision + maxSingleTrade on deposit\n            tradeSize,\n            _getSyToLpAmount(tradeSize, minReceivedAmountFactor),\n            receiveParams,\n            limit\n        );\n        MARKET_DEPOSIT_HELPER.depositMarket(address(market), netLpOut);\n    }\n\n    /// @inheritdoc\tStrategyBase\n    function _withdraw(uint256 _amount) internal override returns (uint256) {\n        // sold rewards will be in underlying token\n        _harvestAndSellRewards();\n        address self = address(this);\n        uint256 underlyingBalance = IERC20(underlyingToken).balanceOf(self);\n        uint256 withdrawAmount;\n        if (underlyingBalance >= _amount) {\n            // if there is enough underlying token, transfer it to pooling manager\n            IERC20(underlyingToken).safeTransfer(poolingManager, _amount);\n            return _amount;\n        } else {\n            // Look at required sy withdraw amount\n            withdrawAmount = _amount - underlyingBalance;\n            uint256 syBalance = IERC20(address(sy)).balanceOf(self);\n            withdrawAmount = (withdrawAmount * WAD) / sy.exchangeRate();\n            if (withdrawAmount > syBalance) {\n                // Get additional LP to withdraw to get missing sy tokens\n                withdrawAmount = Math.min((withdrawAmount - syBalance), maxSingleTrade);\n                uint256 minSyOut = ((withdrawAmount * minReceivedAmountFactor) / WAD);\n                withdrawAmount = _getSyToLpAmount(withdrawAmount, WAD);\n                uint256 yieldBalance = _yieldBalance();\n                if (withdrawAmount > yieldBalance) {\n                    minSyOut = (yieldBalance * minSyOut) / withdrawAmount;\n                    withdrawAmount = yieldBalance;\n                }\n                MARKET_DEPOSIT_HELPER.withdrawMarket(address(market), withdrawAmount);\n                LimitOrderData memory limit;\n                (withdrawAmount, ) = PENDLE_ROUTER.removeLiquiditySingleSy(\n                    address(this),\n                    address(market),\n                    withdrawAmount,\n                    minSyOut,\n                    limit\n                );\n                withdrawAmount = withdrawAmount + syBalance;\n            }\n\n            // withdraw sy balance plus obtained sy fron withdrawn LP\n            sy.redeem(address(this), withdrawAmount, syUnderlying, 0, false);\n            _getUnderlyingFromSyUnderlying(IERC20(syUnderlying).balanceOf(address(this)));\n            // sending only requested amount to pooling manager, the rest will be deposited in the next deposit\n            withdrawAmount = Math.min(_amount, IERC20(underlyingToken).balanceOf(address(this)));\n            IERC20(underlyingToken).safeTransfer(poolingManager, withdrawAmount);\n            return withdrawAmount;\n        }\n    }\n\n    function _getSyToLpAmount(uint256 _tradeSize, uint256 delta) internal view returns (uint256) {\n        return ((_tradeSize * delta) / market.getLpToSyRate(twapDuration));\n    }\n\n    function _setMinReceivedAmountFactor(uint256 _minReceivedAmountFactor) internal {\n        if (_minReceivedAmountFactor > WAD || _minReceivedAmountFactor < (WAD * 95) / 100)\n            revert ErrorLib.InvalidSlippage();\n        minReceivedAmountFactor = _minReceivedAmountFactor;\n    }\n\n    /// @inheritdoc\tStrategyBase\n    function _nav() internal view override returns (uint256) {\n        // underlying and sy tokens can be left in the contract.\n        uint256 syBalance = IERC20(address(sy)).balanceOf(address(this));\n        uint256 syValue = 0;\n        if (syBalance > 0) {\n            syValue = (sy.exchangeRate() * syBalance) / WAD;\n        }\n        return (_yieldToUnderlying(_yieldBalance()) + IERC20(underlyingToken).balanceOf(address(this)) + syValue);\n    }\n\n    /// @inheritdoc\tStrategyBase\n    function _yieldBalance() internal view override returns (uint256) {\n        return MARKET_DEPOSIT_HELPER.balance(address(market), address(this));\n    }\n\n    /// @inheritdoc\tStrategyBase\n    function _underlyingToYield(uint256 _amount) internal view override returns (uint256) {\n        // price of one LP token in WAD, oracle price is in WAD\n        // https://docs.pendle.finance/Developers/Integration/HowToIntegratePtAndLpOracle\n        uint256 price = market.getLpToAssetRate(twapDuration);\n        // amount of LP for underlying amount _amount\n        return (_amount * WAD) / price;\n    }\n\n    /// @inheritdoc\tStrategyBase\n    function _yieldToUnderlying(uint256 _amount) internal view override returns (uint256) {\n        return (_amount * market.getLpToAssetRate(twapDuration)) / WAD;\n    }\n\n    /// @notice Harvest rewards from penpie and sell it from more underlying tokens\n    function _harvestAndSellRewards() internal {\n        address[] memory stakingTokens = new address[](1);\n        stakingTokens[0] = address(market);\n        PENPIE.multiclaim(stakingTokens);\n        address self = address(this);\n        uint256 balance = PENDLE.balanceOf(self);\n        if (balance > minAmountToSell) {\n            ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({\n                path: uniswapPathPendleUnderlying,\n                recipient: self,\n                deadline: block.timestamp,\n                amountIn: balance,\n                amountOutMinimum: 0 // it's only rewards, so we can sell it for any price\n            });\n            UNI_V3_ROUTER.exactInput(params);\n        }\n    }\n\n    function _verifyOracleReady(address marketToCheck, uint32 duration) internal view {\n        (bool increaseCardinalityRequired, , bool oldestObservationSatisfied) = PTLPORACLE.getOracleState(\n            marketToCheck,\n            duration\n        );\n        if (increaseCardinalityRequired) revert ErrorLib.IncreaseCardinalityRequired();\n        if (!oldestObservationSatisfied) revert ErrorLib.OldestObservationNotSatisfied();\n    }\n}\n"
      },
      "contracts/strategies/StrategyBase.sol": {
        "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.20;\n\nimport {UUPSUpgradeable, Initializable} from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IAccessControl} from \"@openzeppelin/contracts/access/IAccessControl.sol\";\nimport {IStrategyBase} from \"../interfaces/IStrategyBase.sol\";\nimport {ErrorLib} from \"../lib/ErrorLib.sol\";\n\n/// @title The Strategy Base\n/// @author @nimbora 2024\nabstract contract StrategyBase is IStrategyBase, Initializable, UUPSUpgradeable {\n    address public poolingManager;\n    address public underlyingToken;\n    address public yieldToken;\n    address public bridge;\n\n    function _strategyBase__init(\n        address _poolingManager,\n        address _underlyingToken,\n        address _yieldToken,\n        address _bridge\n    ) internal {\n        poolingManager = _poolingManager;\n        underlyingToken = _underlyingToken;\n        yieldToken = _yieldToken;\n        bridge = _bridge;\n    }\n\n    function depositCalldata(uint256 _amount) external view virtual returns (address, bytes memory);\n\n    function addressToApprove() external view virtual returns (address);\n\n    function _yieldToUnderlying(uint256 _amount) internal view virtual returns (uint256);\n\n    function _underlyingToYield(uint256 _amount) internal view virtual returns (uint256);\n\n    function _withdraw(uint256 _amount) internal virtual returns (uint256);\n\n    /// @dev Authorizes an upgrade to a new contract implementation, ensuring that only an authorized role can perform the upgrade.\n    function _authorizeUpgrade(address) internal view override {\n        _assertOnlyRoleOwner();\n    }\n\n    function withdraw(uint256 _amount) external returns (uint256) {\n        if (msg.sender != poolingManager) revert ErrorLib.CallerIsNotPoolingManager();\n        return _withdraw(_amount);\n    }\n\n    function nav() external view returns (uint256) {\n        return _nav();\n    }\n\n    function yieldToUnderlying(uint256 _amount) external view returns (uint256) {\n        return _yieldToUnderlying(_amount);\n    }\n\n    function underlyingToYield(uint256 _amount) external view returns (uint256) {\n        return _underlyingToYield(_amount);\n    }\n\n    function yieldBalance() external view returns (uint256) {\n        return _yieldBalance();\n    }\n\n    function _assertOnlyRoleOwner() internal view {\n        if (!IAccessControl(poolingManager).hasRole(0, msg.sender)) revert ErrorLib.CallerIsNotAdmin();\n    }\n\n    function _yieldBalance() internal view virtual returns (uint256) {\n        return IERC20(yieldToken).balanceOf(address(this));\n    }\n\n    function _nav() internal view virtual returns (uint256) {\n        return _yieldToUnderlying(_yieldBalance());\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "viaIR": false,
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}