{"file_path":"src/periphery/VaultV2AllocatorProxy.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\n// Copyright (c) 2025 Steakhouse Financial\npragma solidity ^0.8.28;\n\nimport {ERC1967Proxy} from \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\nimport {VaultV2Allocator} from \"./VaultV2Allocator.sol\";\n\n/**\n * @title VaultV2AllocatorProxy\n * @notice ERC1967 Proxy for VaultV2Allocator with UUPS upgradeability\n * @dev This contract deploys a proxy pointing to a VaultV2Allocator implementation.\n *      The implementation uses UUPS pattern, so upgrades are performed via the\n *      implementation's upgradeToAndCall function (controlled by DEFAULT_ADMIN_ROLE).\n *\n * Usage:\n *   1. Deploy VaultV2Allocator implementation (or reuse existing one)\n *   2. Deploy VaultV2AllocatorProxy with implementation address and admin\n *   3. Interact with the proxy address as if it were the VaultV2Allocator\n *\n * Example deployment:\n *   VaultV2Allocator impl = new VaultV2Allocator();\n *   VaultV2AllocatorProxy proxy = new VaultV2AllocatorProxy(address(impl), admin);\n *   VaultV2Allocator allocator = VaultV2Allocator(address(proxy));\n */\ncontract VaultV2AllocatorProxy is ERC1967Proxy {\n    /**\n     * @notice Deploys a new proxy pointing to a VaultV2Allocator implementation.\n     * @param implementation The address of the VaultV2Allocator implementation contract.\n     * @param initialAdmin The address to grant DEFAULT_ADMIN_ROLE and OPERATOR_ROLE.\n     */\n    constructor(\n        address implementation,\n        address initialAdmin\n    ) ERC1967Proxy(implementation, abi.encodeCall(VaultV2Allocator.initialize, (initialAdmin))) {}\n}\n","deployed_bytecode":"0x60806040527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e156048573d5ff35b3d5ffdfea26469706673582212208b78cee2a5791d471d8ae54db6028f63814939bb2e28a1412c75317098fd980f64736f6c634300081c0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"prague","libraries":{},"metadata":{"appendCBOR":true,"bytecodeHash":"ipfs","useLiteralContent":false},"optimizer":{"enabled":true,"runs":100},"outputSelection":{"*":{"":["*"],"*":["*"]}},"remappings":["@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","@vault-v2/=lib/vault-v2/","@morpho-blue/=lib/morpho-blue/src/","@aragon/osx/=lib/osx/packages/contracts/src/","ds-test/=lib/morpho-blue/lib/forge-std/lib/ds-test/src/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/morpho-blue/lib/halmos-cheatcodes/src/","metamorpho-v1.1/=lib/vault-v2/lib/metamorpho-v1.1/","metamorpho/=lib/vault-v2/lib/metamorpho/","morpho-blue-irm/=lib/vault-v2/lib/metamorpho/lib/morpho-blue-irm/src/","morpho-blue/=lib/morpho-blue/","openzeppelin-contracts/=lib/openzeppelin-contracts/","osx/=lib/osx/","solmate/=lib/vault-v2/lib/metamorpho/lib/morpho-blue-irm/lib/solmate/src/","vault-v2/=lib/vault-v2/"],"viaIR":true},"optimization_runs":100,"sourcify_repo_url":null,"decoded_constructor_args":[["0x16c23a608c25d341029579CF257c6113Fe343511",{"internalType":"address","name":"implementation","type":"address"}],["0xfeed46c11F57B7126a773EeC6ae9cA7aE1C03C9a",{"internalType":"address","name":"initialAdmin","type":"address"}]],"compiler_version":"v0.8.28+commit.7893614a","is_verified_via_verifier_alliance":false,"verified_at":"2026-01-11T09:20:13.942529Z","implementations":[{"address_hash":"0xC5A845985BdF088F44E3dDF2bd1a79b08dBe9611","name":"VaultV2Allocator"}],"proxy_type":"eip1967","external_libraries":[],"creation_bytecode":"0x60808060405234610182575f6040826102b280380380916100208285610186565b8339810103126101825761003f6020610038846101bd565b93016101bd565b60405163189acdbd60e31b602082019081526001600160a01b039092166024808301919091528152610072604482610186565b833b15610164577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0386169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a280511561015b57829182915190855af43d1561014e573d926001600160401b03841161013a5760405161012a9461011b601f8201601f191660200183610186565b8152809360203d92013e6101d1565b505b604051608290816102308239f35b634e487b7160e01b83526041600452602483fd5b61012a92606092506101d1565b5050505061012c565b634c9c8ce360e01b5f9081526001600160a01b038516600452602490fd5b5f80fd5b601f909101601f19168101906001600160401b038211908210176101a957604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361018257565b906101f557508051156101e657602081519101fd5b63d6bda27560e01b5f5260045ffd5b81511580610226575b610206575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b156101fe56fe60806040527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e156048573d5ff35b3d5ffdfea26469706673582212208b78cee2a5791d471d8ae54db6028f63814939bb2e28a1412c75317098fd980f64736f6c634300081c003300000000000000000000000016c23a608c25d341029579cf257c6113fe343511000000000000000000000000feed46c11f57b7126a773eec6ae9ca7ae1c03c9a","name":"VaultV2AllocatorProxy","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":false,"language":"solidity","evm_version":"prague","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"},{"file_path":"lib/openzeppelin-contracts/contracts/proxy/utils/UUPSUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.22;\n\nimport {IERC1822Proxiable} from \"../../interfaces/draft-IERC1822.sol\";\nimport {ERC1967Utils} from \"../ERC1967/ERC1967Utils.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 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 ERC-1967) 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 ERC-1167 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    /**\n     * @dev Implementation of the ERC-1822 {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 ERC-1967 compliant implementation pointing to self.\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 ERC-1967.\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"},{"file_path":"lib/morpho-blue/src/interfaces/IMorpho.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\ntype Id is bytes32;\n\nstruct MarketParams {\n    address loanToken;\n    address collateralToken;\n    address oracle;\n    address irm;\n    uint256 lltv;\n}\n\n/// @dev Warning: For `feeRecipient`, `supplyShares` does not contain the accrued shares since the last interest\n/// accrual.\nstruct Position {\n    uint256 supplyShares;\n    uint128 borrowShares;\n    uint128 collateral;\n}\n\n/// @dev Warning: `totalSupplyAssets` does not contain the accrued interest since the last interest accrual.\n/// @dev Warning: `totalBorrowAssets` does not contain the accrued interest since the last interest accrual.\n/// @dev Warning: `totalSupplyShares` does not contain the additional shares accrued by `feeRecipient` since the last\n/// interest accrual.\nstruct Market {\n    uint128 totalSupplyAssets;\n    uint128 totalSupplyShares;\n    uint128 totalBorrowAssets;\n    uint128 totalBorrowShares;\n    uint128 lastUpdate;\n    uint128 fee;\n}\n\nstruct Authorization {\n    address authorizer;\n    address authorized;\n    bool isAuthorized;\n    uint256 nonce;\n    uint256 deadline;\n}\n\nstruct Signature {\n    uint8 v;\n    bytes32 r;\n    bytes32 s;\n}\n\n/// @dev This interface is used for factorizing IMorphoStaticTyping and IMorpho.\n/// @dev Consider using the IMorpho interface instead of this one.\ninterface IMorphoBase {\n    /// @notice The EIP-712 domain separator.\n    /// @dev Warning: Every EIP-712 signed message based on this domain separator can be reused on chains sharing the\n    /// same chain id and on forks because the domain separator would be the same.\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n\n    /// @notice The owner of the contract.\n    /// @dev It has the power to change the owner.\n    /// @dev It has the power to set fees on markets and set the fee recipient.\n    /// @dev It has the power to enable but not disable IRMs and LLTVs.\n    function owner() external view returns (address);\n\n    /// @notice The fee recipient of all markets.\n    /// @dev The recipient receives the fees of a given market through a supply position on that market.\n    function feeRecipient() external view returns (address);\n\n    /// @notice Whether the `irm` is enabled.\n    function isIrmEnabled(address irm) external view returns (bool);\n\n    /// @notice Whether the `lltv` is enabled.\n    function isLltvEnabled(uint256 lltv) external view returns (bool);\n\n    /// @notice Whether `authorized` is authorized to modify `authorizer`'s position on all markets.\n    /// @dev Anyone is authorized to modify their own positions, regardless of this variable.\n    function isAuthorized(address authorizer, address authorized) external view returns (bool);\n\n    /// @notice The `authorizer`'s current nonce. Used to prevent replay attacks with EIP-712 signatures.\n    function nonce(address authorizer) external view returns (uint256);\n\n    /// @notice Sets `newOwner` as `owner` of the contract.\n    /// @dev Warning: No two-step transfer ownership.\n    /// @dev Warning: The owner can be set to the zero address.\n    function setOwner(address newOwner) external;\n\n    /// @notice Enables `irm` as a possible IRM for market creation.\n    /// @dev Warning: It is not possible to disable an IRM.\n    function enableIrm(address irm) external;\n\n    /// @notice Enables `lltv` as a possible LLTV for market creation.\n    /// @dev Warning: It is not possible to disable a LLTV.\n    function enableLltv(uint256 lltv) external;\n\n    /// @notice Sets the `newFee` for the given market `marketParams`.\n    /// @param newFee The new fee, scaled by WAD.\n    /// @dev Warning: The recipient can be the zero address.\n    function setFee(MarketParams memory marketParams, uint256 newFee) external;\n\n    /// @notice Sets `newFeeRecipient` as `feeRecipient` of the fee.\n    /// @dev Warning: If the fee recipient is set to the zero address, fees will accrue there and will be lost.\n    /// @dev Modifying the fee recipient will allow the new recipient to claim any pending fees not yet accrued. To\n    /// ensure that the current recipient receives all due fees, accrue interest manually prior to making any changes.\n    function setFeeRecipient(address newFeeRecipient) external;\n\n    /// @notice Creates the market `marketParams`.\n    /// @dev Here is the list of assumptions on the market's dependencies (tokens, IRM and oracle) that guarantees\n    /// Morpho behaves as expected:\n    /// - The token should be ERC-20 compliant, except that it can omit return values on `transfer` and `transferFrom`.\n    /// - The token balance of Morpho should only decrease on `transfer` and `transferFrom`. In particular, tokens with\n    /// burn functions are not supported.\n    /// - The token should not re-enter Morpho on `transfer` nor `transferFrom`.\n    /// - The token balance of the sender (resp. receiver) should decrease (resp. increase) by exactly the given amount\n    /// on `transfer` and `transferFrom`. In particular, tokens with fees on transfer are not supported.\n    /// - The IRM should not re-enter Morpho.\n    /// - The oracle should return a price with the correct scaling.\n    /// - The oracle price should not be able to change instantly such that the new price is less than the old price\n    /// multiplied by LLTV*LIF. In particular, if the loan asset is a vault that can receive donations, the oracle\n    /// should not price its shares using the AUM.\n    /// @dev Here is a list of assumptions on the market's dependencies which, if broken, could break Morpho's liveness\n    /// properties (funds could get stuck):\n    /// - The token should not revert on `transfer` and `transferFrom` if balances and approvals are right.\n    /// - The amount of assets supplied and borrowed should not be too high (max ~1e32), otherwise the number of shares\n    /// might not fit within 128 bits.\n    /// - The IRM should not revert on `borrowRate`.\n    /// - The IRM should not return a very high borrow rate (otherwise the computation of `interest` in\n    /// `_accrueInterest` can overflow).\n    /// - The oracle should not revert `price`.\n    /// - The oracle should not return a very high price (otherwise the computation of `maxBorrow` in `_isHealthy` or of\n    /// `assetsRepaid` in `liquidate` can overflow).\n    /// @dev The borrow share price of a market with less than 1e4 assets borrowed can be decreased by manipulations, to\n    /// the point where `totalBorrowShares` is very large and borrowing overflows.\n    function createMarket(MarketParams memory marketParams) external;\n\n    /// @notice Supplies `assets` or `shares` on behalf of `onBehalf`, optionally calling back the caller's\n    /// `onMorphoSupply` function with the given `data`.\n    /// @dev Either `assets` or `shares` should be zero. Most use cases should rely on `assets` as an input so the\n    /// caller is guaranteed to have `assets` tokens pulled from their balance, but the possibility to mint a specific\n    /// amount of shares is given for full compatibility and precision.\n    /// @dev Supplying a large amount can revert for overflow.\n    /// @dev Supplying an amount of shares may lead to supply more or fewer assets than expected due to slippage.\n    /// Consider using the `assets` parameter to avoid this.\n    /// @param marketParams The market to supply assets to.\n    /// @param assets The amount of assets to supply.\n    /// @param shares The amount of shares to mint.\n    /// @param onBehalf The address that will own the increased supply position.\n    /// @param data Arbitrary data to pass to the `onMorphoSupply` callback. Pass empty data if not needed.\n    /// @return assetsSupplied The amount of assets supplied.\n    /// @return sharesSupplied The amount of shares minted.\n    function supply(\n        MarketParams memory marketParams,\n        uint256 assets,\n        uint256 shares,\n        address onBehalf,\n        bytes memory data\n    ) external returns (uint256 assetsSupplied, uint256 sharesSupplied);\n\n    /// @notice Withdraws `assets` or `shares` on behalf of `onBehalf` and sends the assets to `receiver`.\n    /// @dev Either `assets` or `shares` should be zero. To withdraw max, pass the `shares`'s balance of `onBehalf`.\n    /// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.\n    /// @dev Withdrawing an amount corresponding to more shares than supplied will revert for underflow.\n    /// @dev It is advised to use the `shares` input when withdrawing the full position to avoid reverts due to\n    /// conversion roundings between shares and assets.\n    /// @param marketParams The market to withdraw assets from.\n    /// @param assets The amount of assets to withdraw.\n    /// @param shares The amount of shares to burn.\n    /// @param onBehalf The address of the owner of the supply position.\n    /// @param receiver The address that will receive the withdrawn assets.\n    /// @return assetsWithdrawn The amount of assets withdrawn.\n    /// @return sharesWithdrawn The amount of shares burned.\n    function withdraw(\n        MarketParams memory marketParams,\n        uint256 assets,\n        uint256 shares,\n        address onBehalf,\n        address receiver\n    ) external returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn);\n\n    /// @notice Borrows `assets` or `shares` on behalf of `onBehalf` and sends the assets to `receiver`.\n    /// @dev Either `assets` or `shares` should be zero. Most use cases should rely on `assets` as an input so the\n    /// caller is guaranteed to borrow `assets` of tokens, but the possibility to mint a specific amount of shares is\n    /// given for full compatibility and precision.\n    /// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.\n    /// @dev Borrowing a large amount can revert for overflow.\n    /// @dev Borrowing an amount of shares may lead to borrow fewer assets than expected due to slippage.\n    /// Consider using the `assets` parameter to avoid this.\n    /// @param marketParams The market to borrow assets from.\n    /// @param assets The amount of assets to borrow.\n    /// @param shares The amount of shares to mint.\n    /// @param onBehalf The address that will own the increased borrow position.\n    /// @param receiver The address that will receive the borrowed assets.\n    /// @return assetsBorrowed The amount of assets borrowed.\n    /// @return sharesBorrowed The amount of shares minted.\n    function borrow(\n        MarketParams memory marketParams,\n        uint256 assets,\n        uint256 shares,\n        address onBehalf,\n        address receiver\n    ) external returns (uint256 assetsBorrowed, uint256 sharesBorrowed);\n\n    /// @notice Repays `assets` or `shares` on behalf of `onBehalf`, optionally calling back the caller's\n    /// `onMorphoRepay` function with the given `data`.\n    /// @dev Either `assets` or `shares` should be zero. To repay max, pass the `shares`'s balance of `onBehalf`.\n    /// @dev Repaying an amount corresponding to more shares than borrowed will revert for underflow.\n    /// @dev It is advised to use the `shares` input when repaying the full position to avoid reverts due to conversion\n    /// roundings between shares and assets.\n    /// @dev An attacker can front-run a repay with a small repay making the transaction revert for underflow.\n    /// @param marketParams The market to repay assets to.\n    /// @param assets The amount of assets to repay.\n    /// @param shares The amount of shares to burn.\n    /// @param onBehalf The address of the owner of the debt position.\n    /// @param data Arbitrary data to pass to the `onMorphoRepay` callback. Pass empty data if not needed.\n    /// @return assetsRepaid The amount of assets repaid.\n    /// @return sharesRepaid The amount of shares burned.\n    function repay(\n        MarketParams memory marketParams,\n        uint256 assets,\n        uint256 shares,\n        address onBehalf,\n        bytes memory data\n    ) external returns (uint256 assetsRepaid, uint256 sharesRepaid);\n\n    /// @notice Supplies `assets` of collateral on behalf of `onBehalf`, optionally calling back the caller's\n    /// `onMorphoSupplyCollateral` function with the given `data`.\n    /// @dev Interest are not accrued since it's not required and it saves gas.\n    /// @dev Supplying a large amount can revert for overflow.\n    /// @param marketParams The market to supply collateral to.\n    /// @param assets The amount of collateral to supply.\n    /// @param onBehalf The address that will own the increased collateral position.\n    /// @param data Arbitrary data to pass to the `onMorphoSupplyCollateral` callback. Pass empty data if not needed.\n    function supplyCollateral(MarketParams memory marketParams, uint256 assets, address onBehalf, bytes memory data)\n        external;\n\n    /// @notice Withdraws `assets` of collateral on behalf of `onBehalf` and sends the assets to `receiver`.\n    /// @dev `msg.sender` must be authorized to manage `onBehalf`'s positions.\n    /// @dev Withdrawing an amount corresponding to more collateral than supplied will revert for underflow.\n    /// @param marketParams The market to withdraw collateral from.\n    /// @param assets The amount of collateral to withdraw.\n    /// @param onBehalf The address of the owner of the collateral position.\n    /// @param receiver The address that will receive the collateral assets.\n    function withdrawCollateral(MarketParams memory marketParams, uint256 assets, address onBehalf, address receiver)\n        external;\n\n    /// @notice Liquidates the given `repaidShares` of debt asset or seize the given `seizedAssets` of collateral on the\n    /// given market `marketParams` of the given `borrower`'s position, optionally calling back the caller's\n    /// `onMorphoLiquidate` function with the given `data`.\n    /// @dev Either `seizedAssets` or `repaidShares` should be zero.\n    /// @dev Seizing more than the collateral balance will underflow and revert without any error message.\n    /// @dev Repaying more than the borrow balance will underflow and revert without any error message.\n    /// @dev An attacker can front-run a liquidation with a small repay making the transaction revert for underflow.\n    /// @param marketParams The market of the position.\n    /// @param borrower The owner of the position.\n    /// @param seizedAssets The amount of collateral to seize.\n    /// @param repaidShares The amount of shares to repay.\n    /// @param data Arbitrary data to pass to the `onMorphoLiquidate` callback. Pass empty data if not needed.\n    /// @return The amount of assets seized.\n    /// @return The amount of assets repaid.\n    function liquidate(\n        MarketParams memory marketParams,\n        address borrower,\n        uint256 seizedAssets,\n        uint256 repaidShares,\n        bytes memory data\n    ) external returns (uint256, uint256);\n\n    /// @notice Executes a flash loan.\n    /// @dev Flash loans have access to the whole balance of the contract (the liquidity and deposited collateral of all\n    /// markets combined, plus donations).\n    /// @dev Warning: Not ERC-3156 compliant but compatibility is easily reached:\n    /// - `flashFee` is zero.\n    /// - `maxFlashLoan` is the token's balance of this contract.\n    /// - The receiver of `assets` is the caller.\n    /// @param token The token to flash loan.\n    /// @param assets The amount of assets to flash loan.\n    /// @param data Arbitrary data to pass to the `onMorphoFlashLoan` callback.\n    function flashLoan(address token, uint256 assets, bytes calldata data) external;\n\n    /// @notice Sets the authorization for `authorized` to manage `msg.sender`'s positions.\n    /// @param authorized The authorized address.\n    /// @param newIsAuthorized The new authorization status.\n    function setAuthorization(address authorized, bool newIsAuthorized) external;\n\n    /// @notice Sets the authorization for `authorization.authorized` to manage `authorization.authorizer`'s positions.\n    /// @dev Warning: Reverts if the signature has already been submitted.\n    /// @dev The signature is malleable, but it has no impact on the security here.\n    /// @dev The nonce is passed as argument to be able to revert with a different error message.\n    /// @param authorization The `Authorization` struct.\n    /// @param signature The signature.\n    function setAuthorizationWithSig(Authorization calldata authorization, Signature calldata signature) external;\n\n    /// @notice Accrues interest for the given market `marketParams`.\n    function accrueInterest(MarketParams memory marketParams) external;\n\n    /// @notice Returns the data stored on the different `slots`.\n    function extSloads(bytes32[] memory slots) external view returns (bytes32[] memory);\n}\n\n/// @dev This interface is inherited by Morpho so that function signatures are checked by the compiler.\n/// @dev Consider using the IMorpho interface instead of this one.\ninterface IMorphoStaticTyping is IMorphoBase {\n    /// @notice The state of the position of `user` on the market corresponding to `id`.\n    /// @dev Warning: For `feeRecipient`, `supplyShares` does not contain the accrued shares since the last interest\n    /// accrual.\n    function position(Id id, address user)\n        external\n        view\n        returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral);\n\n    /// @notice The state of the market corresponding to `id`.\n    /// @dev Warning: `totalSupplyAssets` does not contain the accrued interest since the last interest accrual.\n    /// @dev Warning: `totalBorrowAssets` does not contain the accrued interest since the last interest accrual.\n    /// @dev Warning: `totalSupplyShares` does not contain the accrued shares by `feeRecipient` since the last interest\n    /// accrual.\n    function market(Id id)\n        external\n        view\n        returns (\n            uint128 totalSupplyAssets,\n            uint128 totalSupplyShares,\n            uint128 totalBorrowAssets,\n            uint128 totalBorrowShares,\n            uint128 lastUpdate,\n            uint128 fee\n        );\n\n    /// @notice The market params corresponding to `id`.\n    /// @dev This mapping is not used in Morpho. It is there to enable reducing the cost associated to calldata on layer\n    /// 2s by creating a wrapper contract with functions that take `id` as input instead of `marketParams`.\n    function idToMarketParams(Id id)\n        external\n        view\n        returns (address loanToken, address collateralToken, address oracle, address irm, uint256 lltv);\n}\n\n/// @title IMorpho\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @dev Use this interface for Morpho to have access to all the functions with the appropriate function signatures.\ninterface IMorpho is IMorphoBase {\n    /// @notice The state of the position of `user` on the market corresponding to `id`.\n    /// @dev Warning: For `feeRecipient`, `p.supplyShares` does not contain the accrued shares since the last interest\n    /// accrual.\n    function position(Id id, address user) external view returns (Position memory p);\n\n    /// @notice The state of the market corresponding to `id`.\n    /// @dev Warning: `m.totalSupplyAssets` does not contain the accrued interest since the last interest accrual.\n    /// @dev Warning: `m.totalBorrowAssets` does not contain the accrued interest since the last interest accrual.\n    /// @dev Warning: `m.totalSupplyShares` does not contain the accrued shares by `feeRecipient` since the last\n    /// interest accrual.\n    function market(Id id) external view returns (Market memory m);\n\n    /// @notice The market params corresponding to `id`.\n    /// @dev This mapping is not used in Morpho. It is there to enable reducing the cost associated to calldata on layer\n    /// 2s by creating a wrapper contract with functions that take `id` as input instead of `marketParams`.\n    function idToMarketParams(Id id) external view returns (MarketParams memory);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev ERC-1822: 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"},{"file_path":"src/interfaces/IOracle.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Oracle interface to get a token price with 36 decimals of precision\ninterface IOracle {\n    function price() external view returns (uint256);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC4626.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\nimport {IERC20Metadata} from \"../token/ERC20/extensions/IERC20Metadata.sol\";\n\n/**\n * @dev Interface of the ERC-4626 \"Tokenized Vault Standard\", as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\n */\ninterface IERC4626 is IERC20, IERC20Metadata {\n    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\n\n    event Withdraw(\n        address indexed sender,\n        address indexed receiver,\n        address indexed owner,\n        uint256 assets,\n        uint256 shares\n    );\n\n    /**\n     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n     *\n     * - MUST be an ERC-20 token contract.\n     * - MUST NOT revert.\n     */\n    function asset() external view returns (address assetTokenAddress);\n\n    /**\n     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\n     *\n     * - SHOULD include any compounding that occurs from yield.\n     * - MUST be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT revert.\n     */\n    function totalAssets() external view returns (uint256 totalManagedAssets);\n\n    /**\n     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n     * through a deposit call.\n     *\n     * - MUST return a limited value if receiver is subject to some deposit limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n     * - MUST NOT revert.\n     */\n    function maxDeposit(address receiver) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n     *   in the same transaction.\n     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\n     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewDeposit(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   deposit execution, and are accounted for during deposit.\n     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function deposit(uint256 assets, address receiver) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\n     * - MUST return a limited value if receiver is subject to some mint limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\n     * - MUST NOT revert.\n     */\n    function maxMint(address receiver) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\n     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\n     *   same transaction.\n     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\n     *   would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by minting.\n     */\n    function previewMint(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\n     *   execution, and are accounted for during mint.\n     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function mint(uint256 shares, address receiver) external returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\n     * Vault, through a withdraw call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxWithdraw(address owner) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\n     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\n     *   called\n     *   in the same transaction.\n     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\n     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewWithdraw(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   withdraw execution, and are accounted for during withdraw.\n     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\n     * through a redeem call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxRedeem(address owner) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\n     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\n     *   same transaction.\n     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\n     *   redemption would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\n     */\n    function previewRedeem(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   redeem execution, and are accounted for during redeem.\n     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\n}\n"},{"file_path":"src/interfaces/IFunding.sol","source_code":"// SPDX-License-Identifier: MIT\n// Copyright (c) 2025 Steakhouse\npragma solidity >=0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IOracle} from \"./IOracle.sol\";\n\ninterface IOracleCallback {\n    /// @dev RIs considered to have a price of ORACLE_PRECISION\n    function asset() external view returns (address);\n\n    /// @dev Returns an oracle for tokens that are not the asset\n    function oracles(IERC20 token) external view returns (IOracle);\n}\n\n/**\n * @notice Interface for a funding module\n * @notice `nav` should never revert\n */\ninterface IFunding {\n    // ========== ADMIN ==========\n    function addFacility(bytes calldata facilityData) external;\n    function removeFacility(bytes calldata facilityData) external;\n    function isFacility(bytes calldata facilityData) external view returns (bool);\n    function facilities(uint256 index) external view returns (bytes memory);\n    function facilitiesLength() external view returns (uint256);\n\n    function addCollateralToken(IERC20 collateralToken) external;\n    function removeCollateralToken(IERC20 collateralToken) external;\n    function isCollateralToken(IERC20 collateralToken) external view returns (bool);\n    function collateralTokens(uint256 index) external view returns (IERC20);\n    function collateralTokensLength() external view returns (uint256);\n\n    function addDebtToken(IERC20 debtToken) external;\n    function removeDebtToken(IERC20 debtToken) external;\n    function isDebtToken(IERC20 debtToken) external view returns (bool);\n    function debtTokens(uint256 index) external view returns (IERC20);\n    function debtTokensLength() external view returns (uint256);\n\n    // ========== ACTIONS ==========\n    function skim(IERC20 token) external;\n    function pledge(bytes calldata facilityData, IERC20 collateralToken, uint256 collateralAmount) external;\n    function depledge(bytes calldata facilityData, IERC20 collateralToken, uint256 collateralAmount) external;\n    function borrow(bytes calldata facilityData, IERC20 debtToken, uint256 borrowAmount) external;\n    function repay(bytes calldata facilityData, IERC20 debtToken, uint256 repayAmount) external;\n\n    // ========== POSITION ==========\n    function ltv(bytes calldata facilityData) external view returns (uint256);\n    function debtBalance(bytes calldata facilityData, IERC20 debtToken) external view returns (uint256);\n    function collateralBalance(bytes calldata facilityData, IERC20 collateralToken) external view returns (uint256);\n    function debtBalance(IERC20 debtToken) external view returns (uint256);\n    function collateralBalance(IERC20 collateralToken) external view returns (uint256);\n    function nav(IOracleCallback oraclesProvider) external view returns (uint256);\n}\n"},{"file_path":"lib/vault-v2/src/interfaces/IERC2612.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\n// Copyright (c) 2025 Morpho Association\npragma solidity >=0.5.0;\n\ninterface IERC2612 {\n    function permit(address owner, address spender, uint256 shares, uint256 deadline, uint8 v, bytes32 r, bytes32 s)\n        external;\n    function nonces(address owner) external view returns (uint256);\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 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    /**\n     * @dev An operation with an ERC-20 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        if (!_safeTransfer(token, to, value, true)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\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        if (!_safeTransferFrom(token, from, to, value, true)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\n        return _safeTransfer(token, to, value, false);\n    }\n\n    /**\n     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\n        return _safeTransferFrom(token, from, to, value, false);\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     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\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     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\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     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\n     * only sets the \"standard\" allowance. Any temporary allowance will remain active, in addition to the value being\n     * set here.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        if (!_safeApprove(token, spender, value, false)) {\n            if (!_safeApprove(token, spender, 0, true)) revert SafeERC20FailedOperation(address(token));\n            if (!_safeApprove(token, spender, value, true)) revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            safeTransfer(token, to, value);\n        } else if (!token.transferAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferFromAndCallRelaxed(\n        IERC1363 token,\n        address from,\n        address to,\n        uint256 value,\n        bytes memory data\n    ) internal {\n        if (to.code.length == 0) {\n            safeTransferFrom(token, from, to, value);\n        } else if (!token.transferFromAndCall(from, to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n     * once without retrying, and relies on the returned value to be true.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            forceApprove(token, to, value);\n        } else if (!token.approveAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity `token.transfer(to, value)` call, relaxing the requirement on the return value: the\n     * return value is optional (but if data is returned, it must not be false).\n     *\n     * @param token The token targeted by the call.\n     * @param to The recipient of the tokens\n     * @param value The amount of token to transfer\n     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n     */\n    function _safeTransfer(IERC20 token, address to, uint256 value, bool bubble) private returns (bool success) {\n        bytes4 selector = IERC20.transfer.selector;\n\n        assembly (\"memory-safe\") {\n            let fmp := mload(0x40)\n            mstore(0x00, selector)\n            mstore(0x04, and(to, shr(96, not(0))))\n            mstore(0x24, value)\n            success := call(gas(), token, 0, 0, 0x44, 0, 0x20)\n            // if call success and return is true, all is good.\n            // otherwise (not success or return is not true), we need to perform further checks\n            if iszero(and(success, eq(mload(0x00), 1))) {\n                // if the call was a failure and bubble is enabled, bubble the error\n                if and(iszero(success), bubble) {\n                    returndatacopy(fmp, 0, returndatasize())\n                    revert(fmp, returndatasize())\n                }\n                // if the return value is not true, then the call is only successful if:\n                // - the token address has code\n                // - the returndata is empty\n                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n            }\n            mstore(0x40, fmp)\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity `token.transferFrom(from, to, value)` call, relaxing the requirement on the return\n     * value: the return value is optional (but if data is returned, it must not be false).\n     *\n     * @param token The token targeted by the call.\n     * @param from The sender of the tokens\n     * @param to The recipient of the tokens\n     * @param value The amount of token to transfer\n     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n     */\n    function _safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value,\n        bool bubble\n    ) private returns (bool success) {\n        bytes4 selector = IERC20.transferFrom.selector;\n\n        assembly (\"memory-safe\") {\n            let fmp := mload(0x40)\n            mstore(0x00, selector)\n            mstore(0x04, and(from, shr(96, not(0))))\n            mstore(0x24, and(to, shr(96, not(0))))\n            mstore(0x44, value)\n            success := call(gas(), token, 0, 0, 0x64, 0, 0x20)\n            // if call success and return is true, all is good.\n            // otherwise (not success or return is not true), we need to perform further checks\n            if iszero(and(success, eq(mload(0x00), 1))) {\n                // if the call was a failure and bubble is enabled, bubble the error\n                if and(iszero(success), bubble) {\n                    returndatacopy(fmp, 0, returndatasize())\n                    revert(fmp, returndatasize())\n                }\n                // if the return value is not true, then the call is only successful if:\n                // - the token address has code\n                // - the returndata is empty\n                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n            }\n            mstore(0x40, fmp)\n            mstore(0x60, 0)\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity `token.approve(spender, value)` call, relaxing the requirement on the return value:\n     * the return value is optional (but if data is returned, it must not be false).\n     *\n     * @param token The token targeted by the call.\n     * @param spender The spender of the tokens\n     * @param value The amount of token to transfer\n     * @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.\n     */\n    function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) {\n        bytes4 selector = IERC20.approve.selector;\n\n        assembly (\"memory-safe\") {\n            let fmp := mload(0x40)\n            mstore(0x00, selector)\n            mstore(0x04, and(spender, shr(96, not(0))))\n            mstore(0x24, value)\n            success := call(gas(), token, 0, 0, 0x44, 0, 0x20)\n            // if call success and return is true, all is good.\n            // otherwise (not success or return is not true), we need to perform further checks\n            if iszero(and(success, eq(mload(0x00), 1))) {\n                // if the call was a failure and bubble is enabled, bubble the error\n                if and(iszero(success), bubble) {\n                    returndatacopy(fmp, 0, returndatasize())\n                    revert(fmp, returndatasize())\n                }\n                // if the return value is not true, then the call is only successful if:\n                // - the token address has code\n                // - the returndata is empty\n                success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))\n            }\n            mstore(0x40, fmp)\n        }\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/access/IAccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 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 to signal 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. This account bears the admin role (for the granted role).\n     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\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"},{"file_path":"lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (proxy/ERC1967/ERC1967Utils.sol)\n\npragma solidity ^0.8.21;\n\nimport {IBeacon} from \"../beacon/IBeacon.sol\";\nimport {IERC1967} from \"../../interfaces/IERC1967.sol\";\nimport {Address} from \"../../utils/Address.sol\";\nimport {StorageSlot} from \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This library provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\n */\nlibrary ERC1967Utils {\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 ERC-1967 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 IERC1967.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 ERC-1967) 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 ERC-1967 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 IERC1967.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 ERC-1967 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 IERC1967.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"},{"file_path":"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.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 reinitialization) 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 Pointer to storage slot. Allows integrators to override it with a custom storage location.\n     *\n     * NOTE: Consider following the ERC-7201 formula to derive storage locations.\n     */\n    function _initializableStorageSlot() internal pure virtual returns (bytes32) {\n        return INITIALIZABLE_STORAGE;\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        bytes32 slot = _initializableStorageSlot();\n        assembly {\n            $.slot := slot\n        }\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"src/libraries/ErrorsLib.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\nlibrary ErrorsLib {\n    // General errors\n    error InvalidAddress();\n    error InvalidAmount();\n    error InvalidValue();\n    error CannotRemove();\n    error AlreadyWhitelisted();\n    error NotWhitelisted();\n    error NotClean();\n    error NotAllowed();\n\n    // Access control errors\n    error OnlyOwner();\n    error OnlyCurator();\n    error OnlyGuardian();\n    error OnlyCuratorOrGuardian();\n    error OnlyAllocators();\n    error OnlyFeeders();\n    error OnlySkimRecipient();\n    error OnlyAllocatorsOrWinddown();\n    error OnlyMorpho();\n    error OnlyBox();\n    error OnlyPool();\n    error OnlyThisContract();\n    error CannotDuringShutdown();\n    error CannotDuringWinddown();\n\n    // Withdraw/Redeem errors\n    error InsufficientShares();\n    error InsufficientAllowance();\n    error InsufficientLiquidity();\n    error DataAlreadyTimelocked();\n\n    // Token errors\n    error TokenNotWhitelisted();\n    error TokenAlreadyWhitelisted();\n    error OracleRequired();\n    error NoOracleForToken();\n    error TokenBalanceMustBeZero();\n    error TooManyTokens();\n\n    // Slippage errors\n    error SwapperDidSpendTooMuch();\n    error AllocationTooExpensive();\n    error TokenSaleNotGeneratingEnoughAssets();\n    error ReallocationSlippageTooHigh();\n    error TooMuchAccumulatedSlippage();\n    error SlippageTooHigh();\n\n    // Shutdown/Recover errors\n    error OnlyGuardianOrCuratorCanShutdown();\n    error OnlyGuardianCanRecover();\n    error AlreadyShutdown();\n    error NotShutdown();\n    error CannotRecoverAfterWinddown();\n\n    // Timelock errors\n    error TimelockNotExpired();\n    error DataNotTimelocked();\n    error InvalidTimelock();\n    error TimelockNotIncreasing();\n    error TimelockNotDecreasing();\n    error FunctionDisabled();\n\n    // Skim errors\n    error CannotSkimToken();\n    error CannotSkimZero();\n    error SkimChangedNav();\n    error TransferFailed();\n\n    // Funding module errors\n    error ExcessiveLTV();\n    error NoNavDuringCache();\n    error InvalidFacilityData();\n\n    // Flash callback errors\n    error ReentryNotAllowed();\n}\n"},{"file_path":"src/periphery/VaultV2Allocator.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\n// Copyright (c) 2025 Steakhouse Financial\npragma solidity ^0.8.28;\n\nimport {IMorpho} from \"@morpho-blue/interfaces/IMorpho.sol\";\nimport {AccessControl} from \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport {Initializable} from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport {UUPSUpgradeable} from \"@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {IVaultV2} from \"@vault-v2/src/interfaces/IVaultV2.sol\";\nimport {IBox} from \"./../interfaces/IBox.sol\";\nimport {IFunding} from \"./../interfaces/IFunding.sol\";\nimport {ISwapper} from \"./../interfaces/ISwapper.sol\";\nimport {ErrorsLib} from \"./../libraries/ErrorsLib.sol\";\n\n/// @notice Callback interface for Morpho flash loans\ninterface IMorphoFlashLoanCallback {\n    function onMorphoFlashLoan(uint256 assets, bytes calldata data) external;\n}\n\n/// @notice Callback interface for Box flash loans\ninterface IBoxFlashCallback {\n    function onBoxFlash(IERC20 token, uint256 amount, bytes calldata data) external;\n}\n\n/// @notice Result struct for swap operations with slippage tracking\nstruct SwapResult {\n    uint256 expected;\n    uint256 received;\n    uint256 slippageBefore;\n    uint256 slippageAfter;\n}\n\n/**\n * @title VaultV2Allocator\n * @notice Helper contract for VaultV2 and Box allocations with flash loan support\n * @dev Upgradeable via UUPS pattern. Operators can perform complex allocation operations\n *      including leverage, deleverage, and refinancing with optional collateral/loan swaps.\n */\ncontract VaultV2Allocator is Initializable, UUPSUpgradeable, AccessControl, IMorphoFlashLoanCallback, IBoxFlashCallback {\n    using SafeERC20 for IERC20;\n\n    // =========================================================================\n    //                              Constants\n    // =========================================================================\n\n    /// @notice Role for operators allowed to perform restricted actions.\n    bytes32 public constant OPERATOR_ROLE = keccak256(\"OPERATOR_ROLE\");\n\n    // =========================================================================\n    //                           Transient Storage\n    // =========================================================================\n\n    /// @dev Morpho address for flash loan callback validation\n    address internal transient _morpho;\n\n    /// @dev Box address for flash callback validation\n    address internal transient _box;\n\n    /// @dev Expected amount from last swap\n    uint256 internal transient _expected;\n\n    /// @dev Received amount from last swap\n    uint256 internal transient _received;\n\n    /// @dev Accumulated slippage before operation\n    uint256 internal transient _slippageBefore;\n\n    /// @dev Accumulated slippage after operation\n    uint256 internal transient _slippageAfter;\n\n    // =========================================================================\n    //                              Constructor\n    // =========================================================================\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor() {\n        _disableInitializers();\n    }\n\n    // =========================================================================\n    //                              Initializer\n    // =========================================================================\n\n    /**\n     * @notice Initializes the contract, setting up access control and UUPS upgradeability.\n     * @param initialAdmin The address to grant initial admin and operator roles.\n     */\n    function initialize(address initialAdmin) public initializer {\n        _grantRole(DEFAULT_ADMIN_ROLE, initialAdmin);\n        _grantRole(OPERATOR_ROLE, initialAdmin);\n    }\n\n    // =========================================================================\n    //                              Modifiers\n    // =========================================================================\n\n    /**\n     * @notice Restricts execution to OPERATOR_ROLE or DEFAULT_ADMIN_ROLE.\n     */\n    modifier onlyOperator() {\n        address sender = _msgSender();\n        require(hasRole(OPERATOR_ROLE, sender) || hasRole(DEFAULT_ADMIN_ROLE, sender), \"VaultV2Allocator: Caller is not an operator\");\n        _;\n    }\n\n    modifier onlyAdmin() {\n        require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), \"VaultV2Allocator: Caller is not an admin\");\n        _;\n    }\n\n    // =========================================================================\n    //                        Admin & Configuration\n    // =========================================================================\n\n    /**\n     * @notice Authorizes an upgrade to a new implementation.\n     * @dev Only callable by DEFAULT_ADMIN_ROLE. Part of OpenZeppelin UUPS pattern.\n     * @param newImplementation The address of the new implementation contract.\n     */\n    function _authorizeUpgrade(address newImplementation) internal override onlyAdmin {}\n\n    /**\n     * @notice Grants or revokes the OPERATOR_ROLE.\n     * @dev Only callable by DEFAULT_ADMIN_ROLE.\n     * @param operator The address to grant or revoke the role from.\n     * @param grant True to grant the role, false to revoke it.\n     */\n    function setOperatorRole(address operator, bool grant) external onlyAdmin {\n        if (grant) {\n            _grantRole(OPERATOR_ROLE, operator);\n        } else {\n            _revokeRole(OPERATOR_ROLE, operator);\n        }\n    }\n\n    // =========================================================================\n    //                        Simple Vault Operations\n    // =========================================================================\n\n    /**\n     * @notice Allocates funds from a VaultV2 to an adapter.\n     * @param vault The VaultV2 to allocate from.\n     * @param adapter The adapter to allocate to.\n     * @param amount The amount to allocate.\n     */\n    function allocateVault(IVaultV2 vault, address adapter, uint256 amount) external onlyOperator {\n        vault.allocate(adapter, \"\", amount);\n    }\n\n    /**\n     * @notice Deallocates funds from a VaultV2 adapter.\n     * @param vault The VaultV2 to deallocate from.\n     * @param adapter The adapter to deallocate from.\n     * @param amount The amount to deallocate.\n     */\n    function deallocateVault(IVaultV2 vault, address adapter, uint256 amount) external onlyOperator {\n        vault.deallocate(adapter, \"\", amount);\n    }\n\n    // =========================================================================\n    //                        Simple Box Operations\n    // =========================================================================\n\n    /**\n     * @notice Allocates base asset to a token in the Box.\n     * @param box The Box to allocate in.\n     * @param toToken The token to allocate to.\n     * @param amount The amount of base asset to allocate.\n     * @param swapper The swapper contract to use.\n     * @param swapData The swap data for the swapper.\n     * @param minExpected The minimum expected amount of tokens to receive.\n     * @return result The swap result with expected, received, and slippage tracking.\n     */\n    function allocateBox(\n        IBox box,\n        IERC20 toToken,\n        uint256 amount,\n        ISwapper swapper,\n        bytes memory swapData,\n        uint256 minExpected\n    ) external onlyOperator returns (SwapResult memory result) {\n        result.slippageBefore = box.accumulatedSlippage();\n\n        (result.expected, result.received) = box.allocate(toToken, amount, swapper, swapData);\n\n        result.slippageAfter = box.accumulatedSlippage();\n\n        require(result.received >= minExpected, \"VaultV2Allocator.allocateBox: Received less than min expected\");\n    }\n\n    /**\n     * @notice Deallocates a token back to base asset in the Box.\n     * @param box The Box to deallocate from.\n     * @param fromToken The token to deallocate.\n     * @param amount The amount of tokens to deallocate.\n     * @param swapper The swapper contract to use.\n     * @param swapData The swap data for the swapper.\n     * @param minExpected The minimum expected amount of base asset to receive.\n     * @return result The swap result with expected, received, and slippage tracking.\n     */\n    function deallocateBox(\n        IBox box,\n        IERC20 fromToken,\n        uint256 amount,\n        ISwapper swapper,\n        bytes memory swapData,\n        uint256 minExpected\n    ) external onlyOperator returns (SwapResult memory result) {\n        result.slippageBefore = box.accumulatedSlippage();\n\n        (result.expected, result.received) = box.deallocate(fromToken, amount, swapper, swapData);\n\n        result.slippageAfter = box.accumulatedSlippage();\n\n        require(result.received >= minExpected, \"VaultV2Allocator.deallocateBox: Received less than min expected\");\n    }\n\n    /**\n     * @notice Reallocates from one token to another in the Box.\n     * @param box The Box to reallocate in.\n     * @param fromToken The token to reallocate from.\n     * @param toToken The token to reallocate to.\n     * @param amount The amount of fromToken to reallocate.\n     * @param swapper The swapper contract to use.\n     * @param swapData The swap data for the swapper.\n     * @param minExpected The minimum expected amount of toToken to receive.\n     * @return result The swap result with expected, received, and slippage tracking.\n     */\n    function reallocateBox(\n        IBox box,\n        IERC20 fromToken,\n        IERC20 toToken,\n        uint256 amount,\n        ISwapper swapper,\n        bytes memory swapData,\n        uint256 minExpected\n    ) external onlyOperator returns (SwapResult memory result) {\n        result.slippageBefore = box.accumulatedSlippage();\n\n        (result.expected, result.received) = box.reallocate(fromToken, toToken, amount, swapper, swapData);\n\n        result.slippageAfter = box.accumulatedSlippage();\n\n        require(result.received >= minExpected, \"VaultV2Allocator.reallocateBox: Received less than min expected\");\n    }\n\n    // =========================================================================\n    //                        Box Funding Operations\n    // =========================================================================\n\n    /**\n     * @notice Pledges collateral to a funding module via the Box.\n     */\n    function pledgeBox(\n        IBox box,\n        IFunding fundingModule,\n        bytes memory facilityData,\n        IERC20 collateralToken,\n        uint256 collateralAmount\n    ) external onlyOperator {\n        box.pledge(fundingModule, facilityData, collateralToken, collateralAmount);\n    }\n\n    /**\n     * @notice Depledges collateral from a funding module via the Box.\n     */\n    function depledgeBox(\n        IBox box,\n        IFunding fundingModule,\n        bytes memory facilityData,\n        IERC20 collateralToken,\n        uint256 collateralAmount\n    ) external onlyOperator {\n        box.depledge(fundingModule, facilityData, collateralToken, collateralAmount);\n    }\n\n    /**\n     * @notice Borrows from a funding module via the Box.\n     */\n    function borrowBox(\n        IBox box,\n        IFunding fundingModule,\n        bytes memory facilityData,\n        IERC20 borrowToken,\n        uint256 borrowAmount\n    ) external onlyOperator {\n        box.borrow(fundingModule, facilityData, borrowToken, borrowAmount);\n    }\n\n    /**\n     * @notice Repays debt to a funding module via the Box.\n     */\n    function repayBox(\n        IBox box,\n        IFunding fundingModule,\n        bytes memory facilityData,\n        IERC20 debtToken,\n        uint256 repayAmount\n    ) external onlyOperator {\n        box.repay(fundingModule, facilityData, debtToken, repayAmount);\n    }\n\n    // =========================================================================\n    //                    Combined Vault + Box Operations\n    // =========================================================================\n\n    /**\n     * @notice Allocates from VaultV2 through Box to a token.\n     * @dev Handles liquidity sourcing from both Box and Vault.\n     */\n    function allocateToken(\n        IVaultV2 vault,\n        address adapter,\n        IBox box,\n        IERC20 toToken,\n        uint256 amount,\n        ISwapper swapper,\n        bytes memory swapData,\n        uint256 minExpected\n    ) external onlyOperator returns (SwapResult memory result) {\n        IERC20 currency = IERC20(vault.asset());\n\n        uint256 boxLiquidity = currency.balanceOf(address(box));\n        uint256 vaultLiquidity = currency.balanceOf(address(vault));\n        uint256 neededFromVault = amount > boxLiquidity ? amount - boxLiquidity : 0;\n\n        if (neededFromVault > 0) {\n            uint256 availableLiquidity = boxLiquidity + vaultLiquidity;\n            uint256 missingLiquidity = amount > availableLiquidity ? amount - availableLiquidity : 0;\n\n            // If there's not enough liquidity in the box + vault, deallocate from the liquidity adapter\n            address liquidityAdapter = vault.liquidityAdapter();\n            if (missingLiquidity > 0 && liquidityAdapter != address(0)) {\n                vault.deallocate(liquidityAdapter, vault.liquidityData(), missingLiquidity);\n            }\n\n            vault.allocate(adapter, \"\", neededFromVault);\n        }\n\n        result.slippageBefore = box.accumulatedSlippage();\n\n        (result.expected, result.received) = box.allocate(toToken, amount, swapper, swapData);\n\n        result.slippageAfter = box.accumulatedSlippage();\n\n        require(result.received >= minExpected, \"VaultV2Allocator.allocateToken: Received less than min expected\");\n    }\n\n    /**\n     * @notice Deallocates a token from Box back to VaultV2.\n     */\n    function deallocateToken(\n        IVaultV2 vault,\n        address adapter,\n        IBox box,\n        IERC20 fromToken,\n        uint256 amount,\n        ISwapper swapper,\n        bytes memory swapData,\n        uint256 minExpected\n    ) external onlyOperator returns (SwapResult memory result) {\n        result.slippageBefore = box.accumulatedSlippage();\n\n        (result.expected, result.received) = box.deallocate(fromToken, amount, swapper, swapData);\n\n        result.slippageAfter = box.accumulatedSlippage();\n\n        require(result.received >= minExpected, \"VaultV2Allocator.deallocateToken: Received less than min expected\");\n\n        vault.deallocate(adapter, \"\", result.received);\n\n        address liquidityAdapter = vault.liquidityAdapter();\n        if (liquidityAdapter != address(0)) {\n            vault.allocate(liquidityAdapter, vault.liquidityData(), result.received);\n        }\n    }\n\n    // =========================================================================\n    //                     Flash Loan Operations (Leverage)\n    // =========================================================================\n\n    /**\n     * @notice Leverages a position using a Morpho flash loan.\n     * @dev Flow: Flash loan -> Swap loan to collateral -> Pledge collateral -> Borrow to repay flash loan\n     * @param morpho The Morpho protocol address for flash loans.\n     * @param box The Box to perform operations on.\n     * @param fundingModule The funding module to use.\n     * @param facilityData The facility data for the funding module.\n     * @param swapper The swapper for loan-to-collateral conversion.\n     * @param swapData The swap data for the swapper.\n     * @param collateralToken The collateral token to acquire.\n     * @param loanToken The loan token to flash loan and borrow.\n     * @param loanAmount The amount to flash loan/borrow.\n     * @return result The swap result with expected, received, and slippage tracking.\n     */\n    function leverage(\n        IMorpho morpho,\n        IBox box,\n        IFunding fundingModule,\n        bytes calldata facilityData,\n        ISwapper swapper,\n        bytes calldata swapData,\n        IERC20 collateralToken,\n        IERC20 loanToken,\n        uint256 loanAmount\n    ) external onlyOperator returns (SwapResult memory result) {\n        _morpho = address(morpho);\n        _box = address(box);\n        _slippageBefore = box.accumulatedSlippage();\n\n        bytes4 operation = VaultV2Allocator.leverage.selector;\n        bytes memory data = abi.encode(\n            operation,\n            address(box),\n            fundingModule,\n            facilityData,\n            collateralToken,\n            loanToken,\n            loanAmount,\n            swapper,\n            swapData\n        );\n\n        morpho.flashLoan(address(loanToken), loanAmount, data);\n\n        result.expected = _expected;\n        result.received = _received;\n        result.slippageBefore = _slippageBefore;\n        result.slippageAfter = box.accumulatedSlippage();\n    }\n\n    /**\n     * @notice Deleverages a position using a Morpho flash loan.\n     * @dev Flow: Flash loan -> Repay debt -> Depledge collateral -> Swap collateral to loan to repay flash\n     * @param morpho The Morpho protocol address for flash loans.\n     * @param box The Box to perform operations on.\n     * @param fundingModule The funding module to use.\n     * @param facilityData The facility data for the funding module.\n     * @param swapper The swapper for collateral-to-loan conversion.\n     * @param swapData The swap data for the swapper.\n     * @param collateralToken The collateral token to withdraw.\n     * @param collateralAmount The amount of collateral to withdraw (type(uint256).max for all).\n     * @param loanToken The loan token to repay.\n     * @param loanAmount The amount of debt to repay (type(uint256).max for all).\n     * @return result The swap result with expected, received, and slippage tracking.\n     */\n    function deleverage(\n        IMorpho morpho,\n        IBox box,\n        IFunding fundingModule,\n        bytes calldata facilityData,\n        ISwapper swapper,\n        bytes calldata swapData,\n        IERC20 collateralToken,\n        uint256 collateralAmount,\n        IERC20 loanToken,\n        uint256 loanAmount\n    ) external onlyOperator returns (SwapResult memory result) {\n        _morpho = address(morpho);\n        _box = address(box);\n        _slippageBefore = box.accumulatedSlippage();\n\n        if (loanAmount == type(uint256).max) {\n            loanAmount = fundingModule.debtBalance(facilityData, loanToken);\n        }\n\n        bytes4 operation = VaultV2Allocator.deleverage.selector;\n        bytes memory data = abi.encode(\n            operation,\n            address(box),\n            fundingModule,\n            facilityData,\n            collateralToken,\n            collateralAmount,\n            loanToken,\n            loanAmount,\n            swapper,\n            swapData\n        );\n\n        morpho.flashLoan(address(loanToken), loanAmount, data);\n\n        result.expected = _expected;\n        result.received = _received;\n        result.slippageBefore = _slippageBefore;\n        result.slippageAfter = box.accumulatedSlippage();\n    }\n\n    /**\n     * @notice Refinances a position to a new facility (same collateral and loan).\n     * @dev Flow: Flash loan -> Repay old debt -> Depledge -> Pledge to new -> Borrow from new to repay flash\n     * @param morpho The Morpho protocol address for flash loans.\n     * @param box The Box to perform operations on.\n     * @param fromFundingModule The funding module to refinance from.\n     * @param fromFacilityData The facility data for the source.\n     * @param toFundingModule The funding module to refinance to.\n     * @param toFacilityData The facility data for the destination.\n     * @param collateralToken The collateral token.\n     * @param collateralAmount The amount of collateral (type(uint256).max for all).\n     * @param loanToken The loan token.\n     * @param loanAmount The amount of debt (type(uint256).max for all).\n     */\n    function refinance(\n        IMorpho morpho,\n        IBox box,\n        IFunding fromFundingModule,\n        bytes calldata fromFacilityData,\n        IFunding toFundingModule,\n        bytes calldata toFacilityData,\n        IERC20 collateralToken,\n        uint256 collateralAmount,\n        IERC20 loanToken,\n        uint256 loanAmount\n    ) external onlyOperator {\n        _morpho = address(morpho);\n        _box = address(box);\n\n        if (loanAmount == type(uint256).max) {\n            loanAmount = fromFundingModule.debtBalance(fromFacilityData, loanToken);\n        }\n        if (collateralAmount == type(uint256).max) {\n            collateralAmount = fromFundingModule.collateralBalance(fromFacilityData, collateralToken);\n        }\n\n        bytes4 operation = VaultV2Allocator.refinance.selector;\n        bytes memory data = abi.encode(\n            operation,\n            address(box),\n            fromFundingModule,\n            fromFacilityData,\n            toFundingModule,\n            toFacilityData,\n            collateralToken,\n            collateralAmount,\n            loanToken,\n            loanAmount\n        );\n\n        morpho.flashLoan(address(loanToken), loanAmount, data);\n    }\n\n    /**\n     * @notice Refinances to a new facility while swapping collateral to a new type.\n     * @dev Flow: Flash loan -> Repay old debt -> Depledge old collateral -> Swap to new collateral\n     *            -> Pledge new collateral to new facility -> Borrow to repay flash loan\n     * @param morpho The Morpho protocol address for flash loans.\n     * @param box The Box to perform operations on.\n     * @param fromFundingModule The funding module to refinance from.\n     * @param fromFacilityData The facility data for the source.\n     * @param toFundingModule The funding module to refinance to.\n     * @param toFacilityData The facility data for the destination.\n     * @param fromCollateralToken The original collateral token.\n     * @param fromCollateralAmount The amount of original collateral (type(uint256).max for all).\n     * @param toCollateralToken The new collateral token.\n     * @param loanToken The loan token (same for both facilities).\n     * @param loanAmount The amount of debt (type(uint256).max for all).\n     * @param swapper The swapper for collateral conversion.\n     * @param swapData The swap data for the swapper.\n     * @return result The swap result with expected, received, and slippage tracking.\n     */\n    function refinanceSwapCollateral(\n        IMorpho morpho,\n        IBox box,\n        IFunding fromFundingModule,\n        bytes calldata fromFacilityData,\n        IFunding toFundingModule,\n        bytes calldata toFacilityData,\n        IERC20 fromCollateralToken,\n        uint256 fromCollateralAmount,\n        IERC20 toCollateralToken,\n        IERC20 loanToken,\n        uint256 loanAmount,\n        ISwapper swapper,\n        bytes calldata swapData\n    ) external onlyOperator returns (SwapResult memory result) {\n        _morpho = address(morpho);\n        _box = address(box);\n        _slippageBefore = box.accumulatedSlippage();\n\n        if (loanAmount == type(uint256).max) {\n            loanAmount = fromFundingModule.debtBalance(fromFacilityData, loanToken);\n        }\n        if (fromCollateralAmount == type(uint256).max) {\n            fromCollateralAmount = fromFundingModule.collateralBalance(fromFacilityData, fromCollateralToken);\n        }\n\n        bytes4 operation = VaultV2Allocator.refinanceSwapCollateral.selector;\n        bytes memory data = abi.encode(\n            operation,\n            address(box),\n            fromFundingModule,\n            fromFacilityData,\n            toFundingModule,\n            toFacilityData,\n            fromCollateralToken,\n            fromCollateralAmount,\n            toCollateralToken,\n            loanToken,\n            loanAmount,\n            swapper,\n            swapData\n        );\n\n        morpho.flashLoan(address(loanToken), loanAmount, data);\n\n        result.expected = _expected;\n        result.received = _received;\n        result.slippageBefore = _slippageBefore;\n        result.slippageAfter = box.accumulatedSlippage();\n    }\n\n    /**\n     * @notice Refinances to a new facility while swapping the loan asset.\n     * @dev Flow: Flash loan new loan token -> Swap to old loan token -> Repay old debt\n     *            -> Depledge collateral -> Pledge collateral to new facility\n     *            -> Borrow new loan token to repay flash loan\n     * @param morpho The Morpho protocol address for flash loans.\n     * @param box The Box to perform operations on.\n     * @param fromFundingModule The funding module to refinance from.\n     * @param fromFacilityData The facility data for the source.\n     * @param toFundingModule The funding module to refinance to.\n     * @param toFacilityData The facility data for the destination.\n     * @param collateralToken The collateral token (same for both facilities).\n     * @param collateralAmount The amount of collateral (type(uint256).max for all).\n     * @param fromLoanToken The original loan token.\n     * @param fromLoanAmount The amount of original debt (type(uint256).max for all).\n     * @param toLoanToken The new loan token.\n     * @param toLoanAmount The amount of new loan token to flash loan.\n     * @param swapper The swapper for loan token conversion.\n     * @param swapData The swap data for the swapper.\n     * @return result The swap result with expected, received, and slippage tracking.\n     */\n    function refinanceSwapLoan(\n        IMorpho morpho,\n        IBox box,\n        IFunding fromFundingModule,\n        bytes calldata fromFacilityData,\n        IFunding toFundingModule,\n        bytes calldata toFacilityData,\n        IERC20 collateralToken,\n        uint256 collateralAmount,\n        IERC20 fromLoanToken,\n        uint256 fromLoanAmount,\n        IERC20 toLoanToken,\n        uint256 toLoanAmount,\n        ISwapper swapper,\n        bytes calldata swapData\n    ) external onlyOperator returns (SwapResult memory result) {\n        _morpho = address(morpho);\n        _box = address(box);\n        _slippageBefore = box.accumulatedSlippage();\n\n        if (fromLoanAmount == type(uint256).max) {\n            fromLoanAmount = fromFundingModule.debtBalance(fromFacilityData, fromLoanToken);\n        }\n        if (collateralAmount == type(uint256).max) {\n            collateralAmount = fromFundingModule.collateralBalance(fromFacilityData, collateralToken);\n        }\n\n        bytes4 operation = VaultV2Allocator.refinanceSwapLoan.selector;\n        bytes memory data = abi.encode(\n            operation,\n            address(box),\n            fromFundingModule,\n            fromFacilityData,\n            toFundingModule,\n            toFacilityData,\n            collateralToken,\n            collateralAmount,\n            fromLoanToken,\n            fromLoanAmount,\n            toLoanToken,\n            toLoanAmount,\n            swapper,\n            swapData\n        );\n\n        morpho.flashLoan(address(toLoanToken), toLoanAmount, data);\n\n        result.expected = _expected;\n        result.received = _received;\n        result.slippageBefore = _slippageBefore;\n        result.slippageAfter = box.accumulatedSlippage();\n    }\n\n    // =========================================================================\n    //                        Flash Loan Callbacks\n    // =========================================================================\n\n    /**\n     * @notice Morpho flash loan callback.\n     * @dev Called by Morpho after flash loan funds are transferred.\n     */\n    function onMorphoFlashLoan(uint256 assets, bytes calldata data) external override {\n        require(msg.sender == _morpho, ErrorsLib.OnlyMorpho());\n\n        bytes4 operation = abi.decode(data, (bytes4));\n\n        IBox box;\n        IERC20 loanToken;\n\n        if (operation == VaultV2Allocator.leverage.selector) {\n            (, box, , , , loanToken, , , ) = abi.decode(data, (bytes4, IBox, IFunding, bytes, IERC20, IERC20, uint256, ISwapper, bytes));\n        } else if (operation == VaultV2Allocator.deleverage.selector) {\n            (, box, , , , , loanToken, , , ) = abi.decode(\n                data,\n                (bytes4, IBox, IFunding, bytes, IERC20, uint256, IERC20, uint256, ISwapper, bytes)\n            );\n        } else if (operation == VaultV2Allocator.refinance.selector) {\n            (, box, , , , , , , loanToken, ) = abi.decode(\n                data,\n                (bytes4, IBox, IFunding, bytes, IFunding, bytes, IERC20, uint256, IERC20, uint256)\n            );\n        } else if (operation == VaultV2Allocator.refinanceSwapCollateral.selector) {\n            (, box, , , , , , , , loanToken, , , ) = abi.decode(\n                data,\n                (bytes4, IBox, IFunding, bytes, IFunding, bytes, IERC20, uint256, IERC20, IERC20, uint256, ISwapper, bytes)\n            );\n        } else if (operation == VaultV2Allocator.refinanceSwapLoan.selector) {\n            // For refinanceSwapLoan, we flash the NEW loan token (toLoanToken)\n            (, box, , , , , , , , , loanToken, , , ) = abi.decode(\n                data,\n                (bytes4, IBox, IFunding, bytes, IFunding, bytes, IERC20, uint256, IERC20, uint256, IERC20, uint256, ISwapper, bytes)\n            );\n        } else {\n            revert(\"VaultV2Allocator: Invalid operation\");\n        }\n\n        // Approve the box to pull the flash loan amount\n        loanToken.forceApprove(address(box), assets);\n\n        // Call box.flash which will call back to us via onBoxFlash\n        box.flash(loanToken, assets, data);\n\n        // Repay the flash loan to Morpho\n        loanToken.forceApprove(msg.sender, assets);\n    }\n\n    /**\n     * @notice Box flash callback.\n     * @dev Called by Box after flash funds are transferred. Executes the actual operation logic.\n     */\n    function onBoxFlash(IERC20, uint256, bytes calldata data) external override {\n        require(msg.sender == _box, ErrorsLib.OnlyBox());\n\n        bytes4 operation = abi.decode(data, (bytes4));\n        IBox box = IBox(msg.sender);\n\n        if (operation == VaultV2Allocator.leverage.selector) {\n            _handleLeverage(box, data);\n        } else if (operation == VaultV2Allocator.deleverage.selector) {\n            _handleDeleverage(box, data);\n        } else if (operation == VaultV2Allocator.refinance.selector) {\n            _handleRefinance(box, data);\n        } else if (operation == VaultV2Allocator.refinanceSwapCollateral.selector) {\n            _handleRefinanceSwapCollateral(box, data);\n        } else if (operation == VaultV2Allocator.refinanceSwapLoan.selector) {\n            _handleRefinanceSwapLoan(box, data);\n        } else {\n            revert(\"VaultV2Allocator: Invalid operation\");\n        }\n    }\n\n    // =========================================================================\n    //                     Internal Flash Loan Handlers\n    // =========================================================================\n\n    function _handleLeverage(IBox box, bytes calldata data) internal {\n        (\n            ,\n            ,\n            IFunding fundingModule,\n            bytes memory facilityData,\n            IERC20 collateralToken,\n            IERC20 loanToken,\n            uint256 loanAmount,\n            ISwapper swapper,\n            bytes memory swapData\n        ) = abi.decode(data, (bytes4, IBox, IFunding, bytes, IERC20, IERC20, uint256, ISwapper, bytes));\n\n        // Record collateral balance before swap\n        uint256 beforeCollateral = collateralToken.balanceOf(address(box));\n\n        // Swap loan tokens to collateral tokens\n        _swap(box, swapper, swapData, loanToken, collateralToken, loanAmount);\n\n        // Check how much collateral was received\n        uint256 afterCollateral = collateralToken.balanceOf(address(box));\n        uint256 collateralReceived = afterCollateral - beforeCollateral;\n\n        // Pledge collateral to funding module\n        box.pledge(fundingModule, facilityData, collateralToken, collateralReceived);\n\n        // Borrow loan tokens to repay flash loan\n        box.borrow(fundingModule, facilityData, loanToken, loanAmount);\n    }\n\n    function _handleDeleverage(IBox box, bytes calldata data) internal {\n        (\n            ,\n            ,\n            IFunding fundingModule,\n            bytes memory facilityData,\n            IERC20 collateralToken,\n            uint256 collateralAmount,\n            IERC20 loanToken,\n            uint256 loanAmount,\n            ISwapper swapper,\n            bytes memory swapData\n        ) = abi.decode(data, (bytes4, IBox, IFunding, bytes, IERC20, uint256, IERC20, uint256, ISwapper, bytes));\n\n        // Repay debt with flash loaned tokens\n        box.repay(fundingModule, facilityData, loanToken, loanAmount);\n\n        // Withdraw collateral\n        box.depledge(fundingModule, facilityData, collateralToken, collateralAmount);\n\n        // Swap collateral to loan tokens to repay flash loan\n        _swap(box, swapper, swapData, collateralToken, loanToken, collateralAmount);\n    }\n\n    function _handleRefinance(IBox box, bytes calldata data) internal {\n        (\n            ,\n            ,\n            IFunding fromFundingModule,\n            bytes memory fromFacilityData,\n            IFunding toFundingModule,\n            bytes memory toFacilityData,\n            IERC20 collateralToken,\n            uint256 collateralAmount,\n            IERC20 loanToken,\n            uint256 loanAmount\n        ) = abi.decode(data, (bytes4, IBox, IFunding, bytes, IFunding, bytes, IERC20, uint256, IERC20, uint256));\n\n        // Repay old debt\n        box.repay(fromFundingModule, fromFacilityData, loanToken, loanAmount);\n\n        // Withdraw collateral from old facility\n        box.depledge(fromFundingModule, fromFacilityData, collateralToken, collateralAmount);\n\n        // Pledge collateral to new facility\n        box.pledge(toFundingModule, toFacilityData, collateralToken, collateralAmount);\n\n        // Borrow from new facility to repay flash loan\n        box.borrow(toFundingModule, toFacilityData, loanToken, loanAmount);\n    }\n\n    function _handleRefinanceSwapCollateral(IBox box, bytes calldata data) internal {\n        (\n            ,\n            ,\n            IFunding fromFundingModule,\n            bytes memory fromFacilityData,\n            IFunding toFundingModule,\n            bytes memory toFacilityData,\n            IERC20 fromCollateralToken,\n            uint256 fromCollateralAmount,\n            IERC20 toCollateralToken,\n            IERC20 loanToken,\n            uint256 loanAmount,\n            ISwapper swapper,\n            bytes memory swapData\n        ) = abi.decode(data, (bytes4, IBox, IFunding, bytes, IFunding, bytes, IERC20, uint256, IERC20, IERC20, uint256, ISwapper, bytes));\n\n        // Repay old debt with flash loaned tokens\n        box.repay(fromFundingModule, fromFacilityData, loanToken, loanAmount);\n\n        // Withdraw old collateral\n        box.depledge(fromFundingModule, fromFacilityData, fromCollateralToken, fromCollateralAmount);\n\n        // Record new collateral balance before swap\n        uint256 beforeNewCollateral = toCollateralToken.balanceOf(address(box));\n\n        // Swap old collateral to new collateral\n        _swap(box, swapper, swapData, fromCollateralToken, toCollateralToken, fromCollateralAmount);\n\n        // Calculate how much new collateral was received\n        uint256 afterNewCollateral = toCollateralToken.balanceOf(address(box));\n        uint256 newCollateralReceived = afterNewCollateral - beforeNewCollateral;\n\n        // Pledge new collateral to new facility\n        box.pledge(toFundingModule, toFacilityData, toCollateralToken, newCollateralReceived);\n\n        // Borrow from new facility to repay flash loan\n        box.borrow(toFundingModule, toFacilityData, loanToken, loanAmount);\n    }\n\n    function _handleRefinanceSwapLoan(IBox box, bytes calldata data) internal {\n        (\n            ,\n            ,\n            IFunding fromFundingModule,\n            bytes memory fromFacilityData,\n            IFunding toFundingModule,\n            bytes memory toFacilityData,\n            IERC20 collateralToken,\n            uint256 collateralAmount,\n            IERC20 fromLoanToken,\n            uint256 fromLoanAmount,\n            IERC20 toLoanToken,\n            uint256 toLoanAmount,\n            ISwapper swapper,\n            bytes memory swapData\n        ) = abi.decode(\n                data,\n                (bytes4, IBox, IFunding, bytes, IFunding, bytes, IERC20, uint256, IERC20, uint256, IERC20, uint256, ISwapper, bytes)\n            );\n\n        // Record old loan token balance before swap\n        uint256 beforeOldLoan = fromLoanToken.balanceOf(address(box));\n\n        // Swap new loan token (from flash loan) to old loan token\n        _swap(box, swapper, swapData, toLoanToken, fromLoanToken, toLoanAmount);\n\n        // Calculate how much old loan token we received\n        uint256 afterOldLoan = fromLoanToken.balanceOf(address(box));\n        uint256 oldLoanReceived = afterOldLoan - beforeOldLoan;\n\n        // Use whatever we received to repay (should be >= fromLoanAmount)\n        uint256 repayAmount = oldLoanReceived > fromLoanAmount ? fromLoanAmount : oldLoanReceived;\n\n        // Repay old debt\n        box.repay(fromFundingModule, fromFacilityData, fromLoanToken, repayAmount);\n\n        // Withdraw collateral from old facility\n        box.depledge(fromFundingModule, fromFacilityData, collateralToken, collateralAmount);\n\n        // Pledge collateral to new facility\n        box.pledge(toFundingModule, toFacilityData, collateralToken, collateralAmount);\n\n        // Borrow new loan token from new facility to repay flash loan\n        box.borrow(toFundingModule, toFacilityData, toLoanToken, toLoanAmount);\n    }\n\n    // =========================================================================\n    //                         Internal Helpers\n    // =========================================================================\n\n    /**\n     * @dev Executes a swap via Box allocation functions based on token types.\n     */\n    function _swap(IBox box, ISwapper swapper, bytes memory swapData, IERC20 fromToken, IERC20 toToken, uint256 amount) internal {\n        if (address(fromToken) == box.asset()) {\n            (_expected, _received) = box.allocate(toToken, amount, swapper, swapData);\n        } else if (address(toToken) == box.asset()) {\n            (_expected, _received) = box.deallocate(fromToken, amount, swapper, swapData);\n        } else {\n            (_expected, _received) = box.reallocate(fromToken, toToken, amount, swapper, swapData);\n        }\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\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"},{"file_path":"lib/openzeppelin-contracts/contracts/proxy/Proxy.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n    /**\n     * @dev Delegates the current call to `implementation`.\n     *\n     * This function does not return to its internal call site, it will return directly to the external caller.\n     */\n    function _delegate(address implementation) internal virtual {\n        assembly {\n            // Copy msg.data. We take full control of memory in this inline assembly\n            // block because it will not return to Solidity code. We overwrite the\n            // Solidity scratch pad at memory position 0.\n            calldatacopy(0, 0, calldatasize())\n\n            // Call the implementation.\n            // out and outsize are 0 because we don't know the size yet.\n            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n            // Copy the returned data.\n            returndatacopy(0, 0, returndatasize())\n\n            switch result\n            // delegatecall returns 0 on error.\n            case 0 {\n                revert(0, returndatasize())\n            }\n            default {\n                return(0, returndatasize())\n            }\n        }\n    }\n\n    /**\n     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback\n     * function and {_fallback} should delegate.\n     */\n    function _implementation() internal view virtual returns (address);\n\n    /**\n     * @dev Delegates the current call to the address returned by `_implementation()`.\n     *\n     * This function does not return to its internal call site, it will return directly to the external caller.\n     */\n    function _fallback() internal virtual {\n        _delegate(_implementation());\n    }\n\n    /**\n     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n     * function in the contract matches the call data.\n     */\n    fallback() external payable virtual {\n        _fallback();\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 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"},{"file_path":"lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n    /*\n     * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n     * 0xb0202a11 ===\n     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n     */\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @param data Additional data with no specified format, sent in call to `spender`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n"},{"file_path":"src/interfaces/IBox.sol","source_code":"// SPDX-License-Identifier: MIT\n// Copyright (c) 2025 Steakhouse\npragma solidity >=0.8.0;\n\nimport {IERC4626} from \"@openzeppelin/contracts/interfaces/IERC4626.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IFunding, IOracleCallback} from \"./IFunding.sol\";\nimport {IOracle} from \"./IOracle.sol\";\nimport {ISwapper} from \"./ISwapper.sol\";\n\n/// @notice Callback interface for Box flash loans\ninterface IBoxFlashCallback {\n    function onBoxFlash(IERC20 token, uint256 amount, bytes calldata data) external;\n}\n\ninterface IBox is IERC4626, IOracleCallback {\n    /* FUNCTIONS */\n\n    // ========== STATE FUNCTIONS ==========\n    function asset() external view override(IERC4626, IOracleCallback) returns (address);\n    function slippageEpochDuration() external view returns (uint256);\n    function shutdownSlippageDuration() external view returns (uint256);\n    function shutdownWarmup() external view returns (uint256);\n    function owner() external view returns (address);\n    function curator() external view returns (address);\n    function guardian() external view returns (address);\n    function shutdownTime() external view returns (uint256);\n    function skimRecipient() external view returns (address);\n    function isAllocator(address account) external view returns (bool);\n    function isFeeder(address account) external view returns (bool);\n    function tokens(uint256 index) external view returns (IERC20);\n    function oracles(IERC20 token) external view returns (IOracle);\n    function maxSlippage() external view returns (uint256);\n    function accumulatedSlippage() external view returns (uint256);\n    function slippageEpochStart() external view returns (uint256);\n    function executableAt(bytes calldata data) external view returns (uint256);\n\n    // ========== INVESTMENT MANAGEMENT ==========\n    function skim(IERC20 token) external;\n    function skimFunding(IFunding fundingModule, IERC20 token) external;\n    function allocate(\n        IERC20 token,\n        uint256 assetsAmount,\n        ISwapper swapper,\n        bytes calldata data\n    ) external returns (uint256 expected, uint256 received);\n    function deallocate(\n        IERC20 token,\n        uint256 tokensAmount,\n        ISwapper swapper,\n        bytes calldata data\n    ) external returns (uint256 expected, uint256 received);\n    function reallocate(\n        IERC20 from,\n        IERC20 to,\n        uint256 tokensAmount,\n        ISwapper swapper,\n        bytes calldata data\n    ) external returns (uint256 expected, uint256 received);\n\n    // ========== SIMPLE FUNDING OPERATIONS ==========\n    function pledge(IFunding fundingModule, bytes calldata facilityData, IERC20 collateralToken, uint256 collateralAmount) external;\n    function depledge(IFunding fundingModule, bytes calldata facilityData, IERC20 collateralToken, uint256 collateralAmount) external;\n    function borrow(IFunding fundingModule, bytes calldata facilityData, IERC20 debtToken, uint256 borrowAmount) external;\n    function repay(IFunding fundingModule, bytes calldata facilityData, IERC20 debtToken, uint256 repayAmount) external;\n\n    // ========== COMPLEX FUNDING OPERATIONS WITH FLASHLOAN AND SWAPPER ==========\n    function flash(IERC20 flashToken, uint256 flashAmount, bytes calldata data) external;\n\n    // ========== BATCHING ==========\n    function multicall(bytes[] calldata data) external;\n\n    // ========== EMERGENCY ==========\n    function shutdown() external;\n    function recover() external;\n\n    // ========== ADMIN FUNCTIONS ==========\n    function setSkimRecipient(address newSkimRecipient) external;\n    function transferOwnership(address newOwner) external;\n    function setCurator(address newCurator) external;\n    function setGuardian(address newGuardian) external;\n    function setIsAllocator(address account, bool newIsAllocator) external;\n\n    // ========== TIMELOCK GOVERNANCE ==========\n    function submit(bytes calldata data) external;\n    function timelock(bytes4 selector) external view returns (uint256);\n    function revoke(bytes calldata data) external;\n    function increaseTimelock(bytes4 selector, uint256 newDuration) external;\n    function decreaseTimelock(bytes4 selector, uint256 newDuration) external;\n    function abdicateTimelock(bytes4 selector) external;\n\n    // ========== TIMELOCKED FUNCTIONS ==========\n    function setIsFeeder(address account, bool newIsFeeder) external;\n    function setMaxSlippage(uint256 newMaxSlippage) external;\n    function addToken(IERC20 token, IOracle oracle) external;\n    function removeToken(IERC20 token) external;\n    function changeTokenOracle(IERC20 token, IOracle oracle) external;\n\n    // ========== VIEW FUNCTIONS ==========\n    function isToken(IERC20 token) external view returns (bool);\n    function isTokenOrAsset(IERC20 token) external view returns (bool);\n    function tokensLength() external view returns (uint256);\n    function isShutdown() external view returns (bool);\n    function isWinddown() external view returns (bool);\n\n    // ========== FUNDING ADMIN FUNCTIONS ==========\n    function addFunding(IFunding fundingModule) external;\n    function addFundingFacility(IFunding fundingModule, bytes calldata facilityData) external;\n    function addFundingCollateral(IFunding fundingModule, IERC20 collateralToken) external;\n    function addFundingDebt(IFunding fundingModule, IERC20 debtToken) external;\n    function removeFunding(IFunding fundingModule) external;\n    function removeFundingFacility(IFunding fundingModule, bytes calldata facilityData) external;\n    function removeFundingCollateral(IFunding fundingModule, IERC20 collateralToken) external;\n    function removeFundingDebt(IFunding fundingModule, IERC20 debtToken) external;\n\n    // ========== FUNDING VIEW FUNCTIONS ==========\n    function fundings(uint256 index) external view returns (IFunding);\n    function fundingsLength() external view returns (uint256);\n    function isFunding(IFunding fundingModule) external view returns (bool);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.22;\n\nimport {Proxy} from \"../Proxy.sol\";\nimport {ERC1967Utils} from \"./ERC1967Utils.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy {\n    /**\n     * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`.\n     *\n     * If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an\n     * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.\n     *\n     * Requirements:\n     *\n     * - If `data` is empty, `msg.value` must be zero.\n     */\n    constructor(address implementation, bytes memory _data) payable {\n        ERC1967Utils.upgradeToAndCall(implementation, _data);\n    }\n\n    /**\n     * @dev Returns the current implementation address.\n     *\n     * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\n     * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n     * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n     */\n    function _implementation() internal view virtual override returns (address) {\n        return ERC1967Utils.getImplementation();\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1967.sol)\n\npragma solidity >=0.4.11;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n */\ninterface IERC1967 {\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"},{"file_path":"lib/openzeppelin-contracts/contracts/access/AccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.20;\n\nimport {IAccessControl} from \"./IAccessControl.sol\";\nimport {Context} from \"../utils/Context.sol\";\nimport {IERC165, ERC165} from \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n    struct RoleData {\n        mapping(address account => bool) hasRole;\n        bytes32 adminRole;\n    }\n\n    mapping(bytes32 role => RoleData) private _roles;\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with an {AccessControlUnauthorizedAccount} error including the required role.\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role);\n        _;\n    }\n\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n        return _roles[role].hasRole[account];\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, _msgSender());\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n     * is missing `role`.\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!hasRole(role, account)) {\n            revert AccessControlUnauthorizedAccount(account, role);\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n        return _roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n        if (callerConfirmation != _msgSender()) {\n            revert AccessControlBadConfirmation();\n        }\n\n        _revokeRole(role, callerConfirmation);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        _roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /**\n     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n        if (!hasRole(role, account)) {\n            _roles[role].hasRole[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n        if (hasRole(role, account)) {\n            _roles[role].hasRole[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/Errors.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of common custom errors used in multiple contracts\n *\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\n * It is recommended to avoid relying on the error API for critical functionality.\n *\n * _Available since v5.1._\n */\nlibrary Errors {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error InsufficientBalance(uint256 balance, uint256 needed);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedCall();\n\n    /**\n     * @dev The deployment failed.\n     */\n    error FailedDeployment();\n\n    /**\n     * @dev A necessary precompile is missing.\n     */\n    error MissingPrecompile(address);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (proxy/beacon/IBeacon.sol)\n\npragma solidity >=0.4.16;\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"},{"file_path":"lib/vault-v2/src/interfaces/IERC20.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\n// Copyright (c) 2025 Morpho Association\npragma solidity >=0.5.0;\n\ninterface IERC20 {\n    function decimals() external view returns (uint8);\n    function name() external view returns (string memory);\n    function symbol() external view returns (string memory);\n    function totalSupply() external view returns (uint256);\n    function balanceOf(address account) external view returns (uint256);\n    function transfer(address to, uint256 shares) external returns (bool success);\n    function transferFrom(address from, address to, uint256 shares) external returns (bool success);\n    function approve(address spender, uint256 shares) external returns (bool success);\n    function allowance(address owner, address spender) external view returns (uint256);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.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 ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\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 *\n * TIP: Consider using this library along with {SlotDerivation}.\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 Int256Slot {\n        int256 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        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n     */\n    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\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        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\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        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n}\n"},{"file_path":"src/interfaces/ISwapper.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface ISwapper {\n    /// @dev Sells `amountIn` of `input` tokens for `output` tokens.\n    /// @param input The address of the input token.\n    /// @param output The address of the output token.\n    /// @param amountIn The amount of input tokens to sell.\n    /// @param data Additional data to pass to the swapper.\n    function sell(IERC20 input, IERC20 output, uint256 amountIn, bytes calldata data) external;\n}\n"},{"file_path":"lib/vault-v2/src/interfaces/IVaultV2.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\n// Copyright (c) 2025 Morpho Association\npragma solidity >=0.5.0;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC4626} from \"./IERC4626.sol\";\nimport {IERC2612} from \"./IERC2612.sol\";\n\nstruct Caps {\n    uint256 allocation;\n    uint128 absoluteCap;\n    uint128 relativeCap;\n}\n\ninterface IVaultV2 is IERC4626, IERC2612 {\n    // State variables\n    function virtualShares() external view returns (uint256);\n    function owner() external view returns (address);\n    function curator() external view returns (address);\n    function receiveSharesGate() external view returns (address);\n    function sendSharesGate() external view returns (address);\n    function receiveAssetsGate() external view returns (address);\n    function sendAssetsGate() external view returns (address);\n    function adapterRegistry() external view returns (address);\n    function isSentinel(address account) external view returns (bool);\n    function isAllocator(address account) external view returns (bool);\n    function firstTotalAssets() external view returns (uint256);\n    function _totalAssets() external view returns (uint128);\n    function lastUpdate() external view returns (uint64);\n    function maxRate() external view returns (uint64);\n    function adapters(uint256 index) external view returns (address);\n    function adaptersLength() external view returns (uint256);\n    function isAdapter(address account) external view returns (bool);\n    function allocation(bytes32 id) external view returns (uint256);\n    function absoluteCap(bytes32 id) external view returns (uint256);\n    function relativeCap(bytes32 id) external view returns (uint256);\n    function forceDeallocatePenalty(address adapter) external view returns (uint256);\n    function liquidityAdapter() external view returns (address);\n    function liquidityData() external view returns (bytes memory);\n    function timelock(bytes4 selector) external view returns (uint256);\n    function abdicated(bytes4 selector) external view returns (bool);\n    function executableAt(bytes memory data) external view returns (uint256);\n    function performanceFee() external view returns (uint96);\n    function performanceFeeRecipient() external view returns (address);\n    function managementFee() external view returns (uint96);\n    function managementFeeRecipient() external view returns (address);\n\n    // Gating\n    function canSendShares(address account) external view returns (bool);\n    function canReceiveShares(address account) external view returns (bool);\n    function canSendAssets(address account) external view returns (bool);\n    function canReceiveAssets(address account) external view returns (bool);\n\n    // Multicall\n    function multicall(bytes[] memory data) external;\n\n    // Owner functions\n    function setOwner(address newOwner) external;\n    function setCurator(address newCurator) external;\n    function setIsSentinel(address account, bool isSentinel) external;\n    function setName(string memory newName) external;\n    function setSymbol(string memory newSymbol) external;\n\n    // Timelocks for curator functions\n    function submit(bytes memory data) external;\n    function revoke(bytes memory data) external;\n\n    // Curator functions\n    function setIsAllocator(address account, bool newIsAllocator) external;\n    function setReceiveSharesGate(address newReceiveSharesGate) external;\n    function setSendSharesGate(address newSendSharesGate) external;\n    function setReceiveAssetsGate(address newReceiveAssetsGate) external;\n    function setSendAssetsGate(address newSendAssetsGate) external;\n    function setAdapterRegistry(address newAdapterRegistry) external;\n    function addAdapter(address account) external;\n    function removeAdapter(address account) external;\n    function increaseTimelock(bytes4 selector, uint256 newDuration) external;\n    function decreaseTimelock(bytes4 selector, uint256 newDuration) external;\n    function abdicate(bytes4 selector) external;\n    function setPerformanceFee(uint256 newPerformanceFee) external;\n    function setManagementFee(uint256 newManagementFee) external;\n    function setPerformanceFeeRecipient(address newPerformanceFeeRecipient) external;\n    function setManagementFeeRecipient(address newManagementFeeRecipient) external;\n    function increaseAbsoluteCap(bytes memory idData, uint256 newAbsoluteCap) external;\n    function decreaseAbsoluteCap(bytes memory idData, uint256 newAbsoluteCap) external;\n    function increaseRelativeCap(bytes memory idData, uint256 newRelativeCap) external;\n    function decreaseRelativeCap(bytes memory idData, uint256 newRelativeCap) external;\n    function setMaxRate(uint256 newMaxRate) external;\n    function setForceDeallocatePenalty(address adapter, uint256 newForceDeallocatePenalty) external;\n\n    // Allocator functions\n    function allocate(address adapter, bytes memory data, uint256 assets) external;\n    function deallocate(address adapter, bytes memory data, uint256 assets) external;\n    function setLiquidityAdapterAndData(address newLiquidityAdapter, bytes memory newLiquidityData) external;\n\n    // Exchange rate\n    function accrueInterest() external;\n    function accrueInterestView()\n        external\n        view\n        returns (uint256 newTotalAssets, uint256 performanceFeeShares, uint256 managementFeeShares);\n\n    // Force deallocate\n    function forceDeallocate(address adapter, bytes memory data, uint256 assets, address onBehalf)\n        external\n        returns (uint256 penaltyShares);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"},{"file_path":"lib/vault-v2/src/interfaces/IERC4626.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\n// Copyright (c) 2025 Morpho Association\npragma solidity >=0.5.0;\n\nimport {IERC20} from \"./IERC20.sol\";\n\ninterface IERC4626 is IERC20 {\n    function asset() external view returns (address);\n    function totalAssets() external view returns (uint256);\n    function convertToAssets(uint256 shares) external view returns (uint256 assets);\n    function convertToShares(uint256 assets) external view returns (uint256 shares);\n    function deposit(uint256 assets, address onBehalf) external returns (uint256 shares);\n    function mint(uint256 shares, address onBehalf) external returns (uint256 assets);\n    function withdraw(uint256 assets, address onBehalf, address receiver) external returns (uint256 shares);\n    function redeem(uint256 shares, address onBehalf, address receiver) external returns (uint256 assets);\n    function previewDeposit(uint256 assets) external view returns (uint256 shares);\n    function previewMint(uint256 shares) external view returns (uint256 assets);\n    function previewWithdraw(uint256 assets) external view returns (uint256 shares);\n    function previewRedeem(uint256 shares) external view returns (uint256 assets);\n    function maxDeposit(address onBehalf) external view returns (uint256 assets);\n    function maxMint(address onBehalf) external view returns (uint256 shares);\n    function maxWithdraw(address onBehalf) external view returns (uint256 assets);\n    function maxRedeem(address onBehalf) external view returns (uint256 shares);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/Address.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\nimport {Errors} from \"./Errors.sol\";\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\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 Errors.InsufficientBalance(address(this).balance, amount);\n        }\n\n        (bool success, bytes memory returndata) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            _revert(returndata);\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     * {Errors.FailedCall} 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 Errors.InsufficientBalance(address(this).balance, value);\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 {Errors.FailedCall}) in case\n     * of an 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 {Errors.FailedCall} 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 {Errors.FailedCall}.\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            assembly (\"memory-safe\") {\n                revert(add(returndata, 0x20), mload(returndata))\n            }\n        } else {\n            revert Errors.FailedCall();\n        }\n    }\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"implementation","type":"address"},{"internalType":"address","name":"initialAdmin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x00000000000000000000000016c23a608c25d341029579cf257c6113fe343511000000000000000000000000feed46c11f57b7126a773eec6ae9ca7ae1c03c9a"}