creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts/interfaces/IERC4626.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC4626.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20.sol\";\nimport \"../token/ERC20/extensions/IERC20Metadata.sol\";\n\n/**\n * @dev Interface of the ERC4626 \"Tokenized Vault Standard\", as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\n *\n * _Available since v4.7._\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 redeemption 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"
      },
      "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    constructor() {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/utils/math/SafeMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     *\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a + b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a - b;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     *\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a * b;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator.\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a / b;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a % b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {trySub}.\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        unchecked {\n            require(b <= a, errorMessage);\n            return a - b;\n        }\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        unchecked {\n            require(b > 0, errorMessage);\n            return a / b;\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting with custom message when dividing by zero.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryMod}.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        unchecked {\n            require(b > 0, errorMessage);\n            return a % b;\n        }\n    }\n}\n"
      },
      "contracts/commands/BaseDMACommand.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\n\n/// BaseDMACommand.sol\n\n// Copyright (C) 2023 Oazo Apps Limited\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\npragma solidity 0.8.22;\n\nimport { RatioUtils } from \"../libs/RatioUtils.sol\";\nimport { ICommand } from \"../interfaces/ICommand.sol\";\nimport { IServiceRegistry } from \"../interfaces/IServiceRegistry.sol\";\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport { IOperationExecutorV5, Call } from \"../interfaces/IOperationExecutorV5.sol\";\n\nstruct CommonTriggerData {\n    address positionAddress; // Address of the position - dpm proxy\n    uint16 triggerType; // Type of trigger\n    uint256 maxCoverage; // Maximum coverage amount - max amount of additional debt taken to cover execution gas fee\n    address debtToken; // Address of the debt token\n    address collateralToken; // Address of the collateral token\n    bytes32 operationName; // Operation name\n}\n\n/**\n * @title BaseDMACommand\n * @dev Abstract contract that serves as the base for DMA based commands.\n * It implements common functionality and error handling for DMA commands.\n */\nabstract contract BaseDMACommand is ReentrancyGuard, ICommand {\n    // Error declarations\n    error EmptyAddress(string name);\n    error CommandAlreadyExists(address command);\n    error InvalidTriggerType();\n    error CallerNotAutomationBot(address caller);\n    error InvalidOperationName(bytes32 operationName);\n    error InvalidSelector(bytes4 selector);\n    error ExecutionNotLegal();\n\n    using RatioUtils for uint256;\n\n    address public immutable bot;\n    address public immutable self;\n    address public immutable weth;\n    IOperationExecutorV5 public immutable operationExecutor;\n\n    string private constant AUTOMATION_BOT = \"AUTOMATION_BOT_V2\";\n    string private constant OPERATION_EXECUTOR = \"OperationExecutor_5\";\n    string private constant WETH = \"WETH\";\n\n    uint256 public constant MIN_ALLOWED_DEVIATION = 50; // corrresponds to 0.5%\n\n    /**\n     * @dev Modifier to restrict access to only the automation bot.\n     * Reverts with an error message if the caller is not the automation bot.\n     */\n    modifier onlyBot() {\n        if (bot != msg.sender) {\n            revert CallerNotAutomationBot(msg.sender);\n        }\n        _;\n    }\n\n    /**\n     * @dev Constructor function.\n     * @param _serviceRegistry The address of the service registry contract.\n     */\n    constructor(IServiceRegistry _serviceRegistry) {\n        // Validate service registry address\n        if (address(_serviceRegistry) == address(0)) {\n            revert EmptyAddress(\"service registry\");\n        }\n        // Get the address of the automation bot from the service registry\n        bot = _serviceRegistry.getRegisteredService(AUTOMATION_BOT);\n        // Validate automation bot address\n        if (bot == address(0)) {\n            revert EmptyAddress(\"bot\");\n        }\n\n        // Get the address of the operation executor from the service registry\n        operationExecutor = IOperationExecutorV5(\n            _serviceRegistry.getRegisteredService(OPERATION_EXECUTOR)\n        );\n        // Validate operation executor address\n        if (address(operationExecutor) == address(0)) {\n            revert EmptyAddress(\"operation executor\");\n        }\n\n        // Get the address of the WETH token from the service registry\n        weth = _serviceRegistry.getRegisteredService(WETH);\n        // Validate WETH address\n        if (weth == address(0)) {\n            revert EmptyAddress(\"weth\");\n        }\n        self = address(this);\n    }\n\n    /**\n     * @dev Checks if the provided deviation is valid.\n     * @param deviation The deviation value to check.\n     * @return A boolean indicating whether the deviation is valid or not.\n     */\n    function _isDeviationValid(uint256 deviation) internal pure returns (bool) {\n        return deviation >= MIN_ALLOWED_DEVIATION;\n    }\n\n    /**\n     * @dev Checks if the provided base fee is valid.\n     * @param maxAcceptableBaseFeeInGwei The maximum acceptable base fee in Gwei.\n     * @return A boolean indicating whether the base fee is valid or not.\n     */\n    function _isBaseFeeValid(uint256 maxAcceptableBaseFeeInGwei) internal view returns (bool) {\n        return block.basefee <= maxAcceptableBaseFeeInGwei * 1 gwei;\n    }\n\n    /**\n     * @dev Validates the trigger type against the expected trigger types.\n     * @param expectedTriggerTypes The array of expected trigger types.\n     * @param triggerType The trigger type to be validated.\n     */\n    function _validateTriggerType(\n        uint16[] memory expectedTriggerTypes,\n        uint16 triggerType\n    ) internal pure {\n        if (!_isTriggerTypeValid(expectedTriggerTypes, triggerType)) {\n            revert InvalidTriggerType();\n        }\n    }\n\n    /**\n     * @dev Checks if the given trigger type is valid.\n     * @param expectedTriggerTypes The trigger type to check.\n     * @param  triggerType expected trigger type.\n     * @return A boolean indicating whether the trigger type is valid or not.\n     */\n    function _isTriggerTypeValid(\n        uint16[] memory expectedTriggerTypes,\n        uint16 triggerType\n    ) internal pure returns (bool) {\n        for (uint256 i = 0; i < expectedTriggerTypes.length; i++) {\n            if (expectedTriggerTypes[i] == triggerType) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * @dev Validates the selector. Reverts in case it is not.\n     * @param expectedSelector The expected selector.\n     * @param executionData The execution data containing the selector.\n     */\n    function _validateSelector(bytes4 expectedSelector, bytes memory executionData) internal pure {\n        bytes4 selector = abi.decode(executionData, (bytes4));\n        if (!_isSelectorValid(expectedSelector, selector)) {\n            revert InvalidSelector(selector);\n        }\n    }\n\n    /**\n     * @dev Checks if the given selector is valid by comparing it with the expected selector.\n     * @param expectedSelector The expected selector.\n     * @param selector The selector to be checked.\n     * @return A boolean indicating whether the selector is valid or not.\n     */\n    function _isSelectorValid(\n        bytes4 expectedSelector,\n        bytes4 selector\n    ) internal pure returns (bool) {\n        return selector == expectedSelector;\n    }\n\n    /**\n     * @dev Validates the operation name.\n     * @param expectedOpName The expected operation name byte string stored in trigger data.\n     * @param actualOpName The actual operation name byte string computed from the calls.\n     */\n    function _validateOperationName(bytes32 expectedOpName, bytes32 actualOpName) internal pure {\n        // Compare the bytes32 form of operation name with the expected operation name (bytes32)\n        if (expectedOpName != actualOpName) {\n            revert InvalidOperationName(expectedOpName);\n        }\n    }\n}\n"
      },
      "contracts/commands/DmaMorphoBlueBasicSellCommandV2.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\n\n/// DmaMorphoBlueBasicSellCommandV2.sol\n\n// Copyright (C) 2024 Oazo Apps Limited\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\npragma solidity 0.8.22;\n\nimport {IServiceRegistry} from \"../interfaces/IServiceRegistry.sol\";\nimport {RatioUtils} from \"../libs/RatioUtils.sol\";\nimport {IAccountImplementation} from \"../interfaces/IAccountImplementation.sol\";\nimport {IOperationExecutor, Call} from \"../interfaces/IOperationExecutor.sol\";\nimport {BaseDMACommand, ICommand, CommonTriggerData} from \"./BaseDMACommand.sol\";\nimport {IMorpho, MarketParams, Id} from \"./../interfaces/MorphoBlue/IMorpho.sol\";\nimport {IOracle} from \"./../interfaces/MorphoBlue/IOracle.sol\";\nimport \"./../libs/Morpho/MorphoUtils.sol\";\n\n/**\n * @dev Struct representing the data for a basic sell trigger.\n */\n    struct BasicSellTriggerData {\n        CommonTriggerData commonTriggerData;\n        Id poolId; // ID from MarketParams\n        uint8 quoteDecimals; // Quote precision (required for LTV)\n        uint8 collateralDecimals; // As above\n        uint256 executionLtv; // Execution loan-to-value ratio\n        uint256 targetLTV; // Target loan-to-value ratio\n        uint256 minSellPrice; // Minimum sell price\n        uint64 deviation; // Deviation from target LTV after execution - eg 50 corresponds to 0.5%\n        uint32 maxBaseFeeInGwei; // Maximum base fee in Gwei\n    }\n\n/**\n * @title DmaMorphoBlueBasicSellCommandV2\n */\ncontract DmaMorphoBlueBasicSellCommandV2 is BaseDMACommand {\n    using RatioUtils for uint256;\n\n    IMorpho public immutable morphoBlue;\n\n    string private constant MORPHO_BLUE = \"MORPHO_BLUE\";\n    uint16 private constant MORPHO_BLUE_BASIC_SELL_TRIGGER_TYPE = 136;\n\n    constructor(IServiceRegistry _serviceRegistry) BaseDMACommand(_serviceRegistry) {\n        address morphoBlueAddress = _serviceRegistry.getRegisteredService(MORPHO_BLUE);\n        if (morphoBlueAddress == address(0)) {\n            revert EmptyAddress(MORPHO_BLUE);\n        }\n        morphoBlue = IMorpho(morphoBlueAddress);\n    }\n\n    /**\n     *  @inheritdoc ICommand\n     */\n    function isExecutionCorrect(bytes memory triggerData) external view override returns (bool) {\n        BasicSellTriggerData memory basicSellTriggerData = abi.decode(\n            triggerData,\n            (BasicSellTriggerData)\n        );\n\n        uint256 ltv = MorphoUtils.calculateLTV(\n            morphoBlue,\n            basicSellTriggerData.poolId,\n            basicSellTriggerData.commonTriggerData.positionAddress,\n            basicSellTriggerData.quoteDecimals,\n            basicSellTriggerData.collateralDecimals\n        );\n\n        (uint256 lowerBoundTarget, uint256 upperBoundTarget) = basicSellTriggerData.targetLTV.bounds(\n            basicSellTriggerData.deviation\n        );\n\n        return ltv <= upperBoundTarget && lowerBoundTarget <= ltv;\n    }\n\n\n    function execute(bytes calldata executionData, bytes memory triggerData) external {\n        if (bot != msg.sender) {\n            revert CallerNotAutomationBot(msg.sender);\n        }\n        BasicSellTriggerData memory basicSellTriggerData = abi.decode(\n            triggerData,\n            (BasicSellTriggerData)\n        );\n        uint16[] memory triggerTypes = new uint16[](1);\n        triggerTypes[0] = MORPHO_BLUE_BASIC_SELL_TRIGGER_TYPE;\n        _validateTriggerType(triggerTypes, basicSellTriggerData.commonTriggerData.triggerType);\n\n        _validateSelector(operationExecutor.executeOp.selector, executionData);\n        bytes32 operationName = IAccountImplementation(\n            basicSellTriggerData.commonTriggerData.positionAddress\n        ).execute(address(operationExecutor), executionData);\n\n        _validateOperationName(basicSellTriggerData.commonTriggerData.operationName, operationName);\n    }\n\n    /**\n *  @inheritdoc ICommand\n     */\n    function isTriggerDataValid(\n        bool,\n        bytes memory triggerData\n    ) external view override returns (bool) {\n        BasicSellTriggerData memory basicSellTriggerData = abi.decode(\n            triggerData,\n            (BasicSellTriggerData)\n        );\n\n        uint256 maxLtv = MorphoUtils.getMaxLTV(morphoBlue, basicSellTriggerData.poolId, 4);\n\n        // calculate +-0.5% deviation bounds from the target LTV\n        (, uint256 upperBoundTarget) = basicSellTriggerData.targetLTV.bounds(\n            basicSellTriggerData.deviation\n        );\n\n        bool executionLtvAboveUpperTarget = basicSellTriggerData.executionLtv >= upperBoundTarget;\n\n        // assure that the trigger type is the correct one\n        uint16[] memory triggerTypes = new uint16[](1);\n        triggerTypes[0] = MORPHO_BLUE_BASIC_SELL_TRIGGER_TYPE;\n        bool triggerTypeCorrect = _isTriggerTypeValid(\n            triggerTypes,\n            basicSellTriggerData.commonTriggerData.triggerType\n        );\n\n        bool executionLtvBelowMaxLtv = basicSellTriggerData.executionLtv < maxLtv;\n\n        // assure that the deviation is valid (above minimal allowed deviation)\n        bool deviationValid = _isDeviationValid(basicSellTriggerData.deviation);\n        return\n        executionLtvAboveUpperTarget &&\n        triggerTypeCorrect &&\n        executionLtvBelowMaxLtv &&\n        deviationValid;\n    }\n\n    /**\n     *  @inheritdoc ICommand\n     */\n    function isExecutionLegal(bytes memory triggerData) external view override returns (bool) {\n        BasicSellTriggerData memory basicSellTriggerData = abi.decode(\n            triggerData,\n            (BasicSellTriggerData)\n        );\n\n        uint256 ltv = MorphoUtils.calculateLTV(\n            morphoBlue,\n            basicSellTriggerData.poolId,\n            basicSellTriggerData.commonTriggerData.positionAddress,\n            basicSellTriggerData.quoteDecimals,\n            basicSellTriggerData.collateralDecimals\n        );\n\n        /*\n        if there is no debt or collateral (as indicated by 0) we skip the checks - it will happen eg if the user closed\n        the position but haven't removed the trigger\n        */\n        if (ltv == 0) {\n            return false;\n        }\n\n        uint256 maxLtv = MorphoUtils.getMaxLTV(morphoBlue, basicSellTriggerData.poolId, 4);\n\n        uint256 currentPrice = MorphoUtils.getCurrentOraclePrice(morphoBlue, basicSellTriggerData.poolId);\n\n        bool ltvAboveExecution = ltv >= basicSellTriggerData.executionLtv;\n\n        bool priceAboveMin = currentPrice >= basicSellTriggerData.minSellPrice;\n\n        // blocks base fee has to be below the limit set by the user (maxBaseFeeInGwei)\n        bool baseFeeValid = _isBaseFeeValid(basicSellTriggerData.maxBaseFeeInGwei);\n\n        bool executionLtvBelowMaxLtv = basicSellTriggerData.executionLtv < maxLtv;\n\n        return ltvAboveExecution && priceAboveMin && baseFeeValid && executionLtvBelowMaxLtv;\n    }\n\n    function getTriggerType(bytes calldata triggerData) external view override returns (uint16) {\n        BasicSellTriggerData memory basicSellTriggerData = abi.decode(\n            triggerData,\n            (BasicSellTriggerData)\n        );\n        if (!this.isTriggerDataValid(false, triggerData)) {\n            return 0;\n        }\n        return basicSellTriggerData.commonTriggerData.triggerType;\n    }\n}"
      },
      "contracts/interfaces/Chainlink/AggregatorV3Interface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n    function decimals() external view returns (uint8);\n\n    function description() external view returns (string memory);\n\n    function version() external view returns (uint256);\n\n    // getRoundData and latestRoundData should both raise \"No data present\"\n    // if they do not have data to report, instead of returning unset values\n    // which could be misinterpreted as actual reported values.\n    function getRoundData(\n        uint80 _roundId\n    )\n        external\n        view\n        returns (\n            uint80 roundId,\n            int256 answer,\n            uint256 startedAt,\n            uint256 updatedAt,\n            uint80 answeredInRound\n        );\n\n    function latestRoundData()\n        external\n        view\n        returns (\n            uint80 roundId,\n            int256 answer,\n            uint256 startedAt,\n            uint256 updatedAt,\n            uint80 answeredInRound\n        );\n\n    function phaseId() external view returns (uint16);\n}\n"
      },
      "contracts/interfaces/IAccountImplementation.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity ^0.8.0;\n\ninterface IAccountImplementation {\n    function execute(\n        address _target,\n        bytes memory _data\n    ) external payable returns (bytes32 response);\n\n    function send(address _target, bytes memory _data) external payable;\n\n    function guard() external view returns (address);\n\n    function owner() external view returns (address);\n}\n"
      },
      "contracts/interfaces/ICommand.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity ^0.8.0;\n\n/**\n * @title Command Interface\n */\ninterface ICommand {\n    /**\n     * @notice Checks the validity of the trigger data when the trigger is created\n     * @param triggerData  Encoded trigger data struct\n     * @return Correctness of the trigger data\n     */\n    function isTriggerDataValid(\n        bool continuous,\n        bytes memory triggerData\n    ) external view returns (bool);\n\n    function getTriggerType(bytes calldata triggerData) external view returns (uint16);\n\n    /**\n     * @notice Returns the correctness of the vault state post execution of the command.\n     * @param triggerData Encoded trigger data struct\n     * @return Correctness of the trigger execution\n     */\n    function isExecutionCorrect(bytes memory triggerData) external view returns (bool);\n\n    /**\n     * @notice Checks the validity of the trigger data when the trigger is executed\n     * @param triggerData  Encoded trigger data struct\n     * @return Correctness of the trigger data during execution\n     */\n    function isExecutionLegal(bytes memory triggerData) external view returns (bool);\n\n    /**\n     * @notice Executes the trigger\n     * @param executionData Execution data from the Automation Worker\n     * @param triggerData  Encoded trigger data struct\n     */\n\n    function execute(bytes calldata executionData, bytes memory triggerData) external;\n}\n"
      },
      "contracts/interfaces/IOperationExecutor.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity 0.8.22;\n\nstruct Call {\n    bytes32 targetHash;\n    bytes callData;\n    bool skipped;\n}\n\ninterface IOperationExecutor {\n    function executeOp(Call[] memory calls, string calldata operationName) external payable;\n}\n"
      },
      "contracts/interfaces/IOperationExecutorV5.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity 0.8.22;\n\nstruct Call {\n    bytes32 targetHash;\n    bytes callData;\n}\n\ninterface IOperationExecutorV5 {\n    function executeOp(Call[] memory calls) external payable returns (bytes32);\n}\n"
      },
      "contracts/interfaces/IServiceRegistry.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\npragma solidity 0.8.22;\n\ninterface IServiceRegistry {\n    function getRegisteredService(string memory) external view returns (address);\n\n    function getServiceAddress(bytes32 serviceNameHash) external view returns (address);\n}\n"
      },
      "contracts/interfaces/MorphoBlue/IChainlinkOracle.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IERC4626} from \"@openzeppelin/contracts/interfaces/IERC4626.sol\";\nimport {AggregatorV3Interface} from \"../Chainlink/AggregatorV3Interface.sol\";\nimport {IOracle} from \"./IOracle.sol\";\n\n/// @title IChainlinkOracle\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Interface of ChainlinkOracle.\ninterface IChainlinkOracle is IOracle {\n    /// @notice Returns the address of the ERC4626 vault.\n    function VAULT() external view returns (IERC4626);\n\n    /// @notice Returns the vault conversion sample.\n    function VAULT_CONVERSION_SAMPLE() external view returns (uint256);\n\n    /// @notice Returns the address of the first Chainlink base feed.\n    function BASE_FEED_1() external view returns (AggregatorV3Interface);\n\n    /// @notice Returns the address of the second Chainlink base feed.\n    function BASE_FEED_2() external view returns (AggregatorV3Interface);\n\n    /// @notice Returns the address of the first Chainlink quote feed.\n    function QUOTE_FEED_1() external view returns (AggregatorV3Interface);\n\n    /// @notice Returns the address of the second Chainlink quote feed.\n    function QUOTE_FEED_2() external view returns (AggregatorV3Interface);\n\n    /// @notice Returns the price scale factor, calculated at contract creation.\n    function SCALE_FACTOR() external view returns (uint256);\n}"
      },
      "contracts/interfaces/MorphoBlue/IIrm.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.6.2;\n\nimport {MarketParams, Market} from \"./IMorpho.sol\";\n\n/// @title IIrm\n/// @author Morpho Labs\n/// @custom:contact security@morpho.xyz\n/// @notice Interface that IRMs used by Morpho must implement.\ninterface IIrm {\n    /// @notice Returns the borrow rate of the market `marketParams`.\n    /// @param marketParams The MarketParams struct of the market.\n    /// @param market The Market struct of the market.\n    function borrowRate(MarketParams memory marketParams, Market memory market) external returns (uint256);\n\n    /// @notice Returns the borrow rate of the market `marketParams` without modifying any storage.\n    /// @param marketParams The MarketParams struct of the market.\n    /// @param market The Market struct of the market.\n    function borrowRateView(MarketParams memory marketParams, Market memory market) external view returns (uint256);\n}"
      },
      "contracts/interfaces/MorphoBlue/IMorpho.sol": {
        "content": "// 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 another chain sharing\n  /// the same chain id 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  /// @dev Here is a list of properties on the market's dependencies that could break Morpho's liveness properties\n  /// (funds could get stuck):\n  /// - The token can revert on `transfer` and `transferFrom` for a reason other than an approval or balance issue.\n  /// - A very high amount of assets (~1e35) supplied or borrowed can make the computation of `toSharesUp` and\n  /// `toSharesDown` overflow.\n  /// - The IRM can revert on `borrowRate`.\n  /// - A very high borrow rate returned by the IRM can make the computation of `interest` in `_accrueInterest`\n  /// overflow.\n  /// - The oracle can revert on `price`. Note that this can be used to prevent `borrow`, `withdrawCollateral` and\n  /// `liquidate` from being used under certain market conditions.\n  /// - A very high price returned by the oracle can make the computation of `maxBorrow` in `_isHealthy` overflow, or\n  /// the computation of `assetsRepaid` in `liquidate` 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  /// `onMorphoReplay` 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(\n    MarketParams memory marketParams,\n    uint256 assets,\n    address onBehalf,\n    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(\n    MarketParams memory marketParams,\n    uint256 assets,\n    address onBehalf,\n    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(\n    Authorization calldata authorization,\n    Signature calldata signature\n  ) 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(\n    Id id,\n    address user\n  ) external view 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(\n    Id id\n  )\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(\n    Id id\n  )\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"
      },
      "contracts/interfaces/MorphoBlue/IOracle.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title IOracle\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Interface that oracles used by Morpho must implement.\n/// @dev It is the user's responsibility to select markets with safe oracles.\ninterface IOracle {\n    /// @notice Returns the price of 1 asset of collateral token quoted in 1 asset of loan token, scaled by 1e36.\n    /// @dev It corresponds to the price of 10**(collateral token decimals) assets of collateral token quoted in\n    /// 10**(loan token decimals) assets of loan token with `36 + loan token decimals - collateral token decimals`\n    /// decimals of precision.\n    function price() external view returns (uint256);\n}"
      },
      "contracts/libs/Morpho/ErrorsLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\n/// @title ErrorsLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.xyz\n/// @notice Library exposing error messages.\nlibrary ErrorsLib {\n    /// @notice Thrown when the caller is not the owner.\n    string internal constant NOT_OWNER = \"not owner\";\n\n    /// @notice Thrown when the LLTV to enable exceeds the maximum LLTV.\n    string internal constant MAX_LLTV_EXCEEDED = \"max LLTV exceeded\";\n\n    /// @notice Thrown when the fee to set exceeds the maximum fee.\n    string internal constant MAX_FEE_EXCEEDED = \"max fee exceeded\";\n\n    /// @notice Thrown when the value is already set.\n    string internal constant ALREADY_SET = \"already set\";\n\n    /// @notice Thrown when the IRM is not enabled at market creation.\n    string internal constant IRM_NOT_ENABLED = \"IRM not enabled\";\n\n    /// @notice Thrown when the LLTV is not enabled at market creation.\n    string internal constant LLTV_NOT_ENABLED = \"LLTV not enabled\";\n\n    /// @notice Thrown when the market is already created.\n    string internal constant MARKET_ALREADY_CREATED = \"market already created\";\n\n    /// @notice Thrown when the market is not created.\n    string internal constant MARKET_NOT_CREATED = \"market not created\";\n\n    /// @notice Thrown when not exactly one of the input amount is zero.\n    string internal constant INCONSISTENT_INPUT = \"inconsistent input\";\n\n    /// @notice Thrown when zero assets is passed as input.\n    string internal constant ZERO_ASSETS = \"zero assets\";\n\n    /// @notice Thrown when a zero address is passed as input.\n    string internal constant ZERO_ADDRESS = \"zero address\";\n\n    /// @notice Thrown when the caller is not authorized to conduct an action.\n    string internal constant UNAUTHORIZED = \"unauthorized\";\n\n    /// @notice Thrown when the collateral is insufficient to `borrow` or `withdrawCollateral`.\n    string internal constant INSUFFICIENT_COLLATERAL = \"insufficient collateral\";\n\n    /// @notice Thrown when the liquidity is insufficient to `withdraw` or `borrow`.\n    string internal constant INSUFFICIENT_LIQUIDITY = \"insufficient liquidity\";\n\n    /// @notice Thrown when the position to liquidate is healthy.\n    string internal constant HEALTHY_POSITION = \"position is healthy\";\n\n    /// @notice Thrown when the authorization signature is invalid.\n    string internal constant INVALID_SIGNATURE = \"invalid signature\";\n\n    /// @notice Thrown when the authorization signature is expired.\n    string internal constant SIGNATURE_EXPIRED = \"signature expired\";\n\n    /// @notice Thrown when the nonce is invalid.\n    string internal constant INVALID_NONCE = \"invalid nonce\";\n\n    /// @notice Thrown when a token transfer has failed.\n    string internal constant TRANSFER_FAILED = \"transfer failed\";\n\n    /// @notice Thrown when a token transferFrom has failed.\n    string internal constant TRANSFER_FROM_FAILED = \"transferFrom failed\";\n\n    /// @notice Thrown when the maximum uint128 is exceeded.\n    string internal constant MAX_UINT128_EXCEEDED = \"max uint128 exceeded\";\n}"
      },
      "contracts/libs/Morpho/MarketParamsLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.13;\n\nimport {Id, MarketParams} from \"../../interfaces/MorphoBlue/IMorpho.sol\";\n\n/// @title MarketParamsLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.xyz\n/// @notice Library to convert a market to its id.\nlibrary MarketParamsLib {\n    /// @notice Returns the id of the market `marketParams`.\n    function id(MarketParams memory marketParams) internal pure returns (Id marketParamsId) {\n        assembly (\"memory-safe\") {\n            marketParamsId := keccak256(marketParams, mul(5, 32))\n        }\n    }\n}"
      },
      "contracts/libs/Morpho/MathLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nuint256 constant WAD = 1e18;\n\n/// @title MathLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.xyz\n/// @notice Library to manage fixed-point arithmetic.\nlibrary MathLib {\n    /// @dev (x * y) / WAD rounded down.\n    function wMulDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, y, WAD);\n    }\n\n    /// @dev (x * WAD) / y rounded down.\n    function wDivDown(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivDown(x, WAD, y);\n    }\n\n    /// @dev (x * WAD) / y rounded up.\n    function wDivUp(uint256 x, uint256 y) internal pure returns (uint256) {\n        return mulDivUp(x, WAD, y);\n    }\n\n    /// @dev (x * y) / denominator rounded down.\n    function mulDivDown(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256) {\n        return (x * y) / denominator;\n    }\n\n    /// @dev (x * y) / denominator rounded up.\n    function mulDivUp(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256) {\n        return (x * y + (denominator - 1)) / denominator;\n    }\n\n    /// @dev The sum of the last three terms in a four term taylor series expansion\n    ///      to approximate a continuous compound interest rate: e^(nx) - 1.\n    function wTaylorCompounded(uint256 x, uint256 n) internal pure returns (uint256) {\n        uint256 firstTerm = x * n;\n        uint256 secondTerm = mulDivDown(firstTerm, firstTerm, 2 * WAD);\n        uint256 thirdTerm = mulDivDown(secondTerm, firstTerm, 3 * WAD);\n\n        return firstTerm + secondTerm + thirdTerm;\n    }\n}"
      },
      "contracts/libs/Morpho/MorphoBalancesLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {Id, MarketParams, Market, IMorpho} from \"../../interfaces/MorphoBlue/IMorpho.sol\";\nimport {IIrm} from \"../../interfaces/MorphoBlue/IIrm.sol\";\n\nimport {MathLib} from \"./MathLib.sol\";\nimport {UtilsLib} from \"./UtilsLib.sol\";\nimport {MorphoLib} from \"./MorphoLib.sol\";\nimport {SharesMathLib} from \"./SharesMathLib.sol\";\nimport {MarketParamsLib} from \"./MarketParamsLib.sol\";\nimport {MorphoStorageLib} from \"./MorphoStorageLib.sol\";\n\ninterface IMorphoMarketStruct {\n    function market(Id id) external view returns (Market memory);\n}\n\n/// @title MorphoBalancesLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.xyz\n/// @notice Helper library exposing getters with the expected value after interest accrual.\n/// @dev This library is not used in Morpho itself and is intended to be used by integrators.\n/// @dev The getter to retrieve the expected total borrow shares is not exposed because interest accrual does not apply\n/// to it. The value can be queried directly on Morpho using `totalBorrowShares`.\nlibrary MorphoBalancesLib {\n    using MathLib for uint256;\n    using MathLib for uint128;\n    using UtilsLib for uint256;\n    using MorphoLib for IMorpho;\n    using SharesMathLib for uint256;\n    using MarketParamsLib for MarketParams;\n\n    function expectedMarketBalances(IMorpho morpho, MarketParams memory marketParams)\n    internal\n    view\n    returns (uint256, uint256, uint256, uint256)\n    {\n        Id id = marketParams.id();\n\n        Market memory market = IMorphoMarketStruct(address(morpho)).market(id);\n\n        uint256 elapsed = block.timestamp - market.lastUpdate;\n\n        if (elapsed != 0 && market.totalBorrowAssets != 0) {\n            uint256 borrowRate = IIrm(marketParams.irm).borrowRateView(marketParams, market);\n            uint256 interest = market.totalBorrowAssets.wMulDown(borrowRate.wTaylorCompounded(elapsed));\n            market.totalBorrowAssets += interest.toUint128();\n            market.totalSupplyAssets += interest.toUint128();\n\n            if (market.fee != 0) {\n                uint256 feeAmount = interest.wMulDown(market.fee);\n                // The fee amount is subtracted from the total supply in this calculation to compensate for the fact\n                // that total supply is already updated.\n                uint256 feeShares =\n                feeAmount.toSharesDown(market.totalSupplyAssets - feeAmount, market.totalSupplyShares);\n                market.totalSupplyShares += feeShares.toUint128();\n            }\n        }\n\n        return (market.totalSupplyAssets, market.totalSupplyShares, market.totalBorrowAssets, market.totalBorrowShares);\n    }\n\n    function expectedTotalSupply(IMorpho morpho, MarketParams memory marketParams)\n    internal\n    view\n    returns (uint256 totalSupplyAssets)\n    {\n        (totalSupplyAssets,,,) = expectedMarketBalances(morpho, marketParams);\n    }\n\n    function expectedTotalBorrow(IMorpho morpho, MarketParams memory marketParams)\n    internal\n    view\n    returns (uint256 totalBorrowAssets)\n    {\n        (,, totalBorrowAssets,) = expectedMarketBalances(morpho, marketParams);\n    }\n\n    function expectedTotalSupplyShares(IMorpho morpho, MarketParams memory marketParams)\n    internal\n    view\n    returns (uint256 totalSupplyShares)\n    {\n        (, totalSupplyShares,,) = expectedMarketBalances(morpho, marketParams);\n    }\n\n    /// @dev Warning: Wrong for `feeRecipient` because their supply shares increase is not taken into account.\n    function expectedSupplyBalance(IMorpho morpho, MarketParams memory marketParams, address user)\n    internal\n    view\n    returns (uint256)\n    {\n        Id id = marketParams.id();\n        uint256 supplyShares = morpho.supplyShares(id, user);\n        (uint256 totalSupplyAssets, uint256 totalSupplyShares,,) = expectedMarketBalances(morpho, marketParams);\n\n        return supplyShares.toAssetsDown(totalSupplyAssets, totalSupplyShares);\n    }\n\n    function expectedBorrowBalance(IMorpho morpho, MarketParams memory marketParams, address user)\n    internal\n    view\n    returns (uint256)\n    {\n        Id id = marketParams.id();\n        uint256 borrowShares = morpho.borrowShares(id, user);\n        (,, uint256 totalBorrowAssets, uint256 totalBorrowShares) = expectedMarketBalances(morpho, marketParams);\n\n        return borrowShares.toAssetsUp(totalBorrowAssets, totalBorrowShares);\n    }\n}"
      },
      "contracts/libs/Morpho/MorphoLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {IMorpho, Id} from \"../../interfaces/MorphoBlue/IMorpho.sol\";\nimport {MorphoStorageLib} from \"./MorphoStorageLib.sol\";\n\nlibrary MorphoLib {\n    function supplyShares(IMorpho morpho, Id id, address user) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.positionSupplySharesSlot(id, user));\n        return uint256(morpho.extSloads(slot)[0]);\n    }\n\n    function borrowShares(IMorpho morpho, Id id, address user) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.positionBorrowSharesAndCollateralSlot(id, user));\n        return uint128(uint256(morpho.extSloads(slot)[0]));\n    }\n\n    function collateral(IMorpho morpho, Id id, address user) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.positionBorrowSharesAndCollateralSlot(id, user));\n        return uint256(morpho.extSloads(slot)[0] >> 128);\n    }\n\n    function totalSupplyAssets(IMorpho morpho, Id id) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.marketTotalSupplyAssetsAndSharesSlot(id));\n        return uint128(uint256(morpho.extSloads(slot)[0]));\n    }\n\n    function totalSupplyShares(IMorpho morpho, Id id) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.marketTotalSupplyAssetsAndSharesSlot(id));\n        return uint256(morpho.extSloads(slot)[0] >> 128);\n    }\n\n    function totalBorrowAssets(IMorpho morpho, Id id) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.marketTotalBorrowAssetsAndSharesSlot(id));\n        return uint128(uint256(morpho.extSloads(slot)[0]));\n    }\n\n    function totalBorrowShares(IMorpho morpho, Id id) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.marketTotalBorrowAssetsAndSharesSlot(id));\n        return uint256(morpho.extSloads(slot)[0] >> 128);\n    }\n\n    function lastUpdate(IMorpho morpho, Id id) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.marketLastUpdateAndFeeSlot(id));\n        return uint128(uint256(morpho.extSloads(slot)[0]));\n    }\n\n    function fee(IMorpho morpho, Id id) internal view returns (uint256) {\n        bytes32[] memory slot = _array(MorphoStorageLib.marketLastUpdateAndFeeSlot(id));\n        return uint256(morpho.extSloads(slot)[0] >> 128);\n    }\n\n    function _array(bytes32 x) private pure returns (bytes32[] memory) {\n        bytes32[] memory res = new bytes32[](1);\n        res[0] = x;\n        return res;\n    }\n}"
      },
      "contracts/libs/Morpho/MorphoStorageLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {Id} from \"../../interfaces/MorphoBlue/IMorpho.sol\";\n\n/// @title MorphoStorageLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.xyz\n/// @notice Helper library exposing getters to access Morpho storage variables' slot.\n/// @dev This library is not used in Morpho itself and is intended to be used by integrators.\nlibrary MorphoStorageLib {\n    /* SLOTS */\n\n    uint256 internal constant OWNER_SLOT = 0;\n    uint256 internal constant FEE_RECIPIENT_SLOT = 1;\n    uint256 internal constant POSITION_SLOT = 2;\n    uint256 internal constant MARKET_SLOT = 3;\n    uint256 internal constant IS_IRM_ENABLED_SLOT = 4;\n    uint256 internal constant IS_LLTV_ENABLED_SLOT = 5;\n    uint256 internal constant IS_AUTHORIZED_SLOT = 6;\n    uint256 internal constant NONCE_SLOT = 7;\n    uint256 internal constant ID_TO_MARKET_PARAMS_SLOT = 8;\n\n    /* SLOT OFFSETS */\n\n    uint256 internal constant BORROWABLE_TOKEN_OFFSET = 0;\n    uint256 internal constant COLLATERAL_TOKEN_OFFSET = 1;\n    uint256 internal constant ORACLE_OFFSET = 2;\n    uint256 internal constant IRM_OFFSET = 3;\n    uint256 internal constant LLTV_OFFSET = 4;\n\n    uint256 internal constant SUPPLY_SHARES_OFFSET = 0;\n    uint256 internal constant BORROW_SHARES_AND_COLLATERAL_OFFSET = 1;\n\n    uint256 internal constant TOTAL_SUPPLY_ASSETS_AND_SHARES_OFFSET = 0;\n    uint256 internal constant TOTAL_BORROW_ASSETS_AND_SHARES_OFFSET = 1;\n    uint256 internal constant LAST_UPDATE_AND_FEE_OFFSET = 2;\n\n    /* GETTERS */\n\n    function ownerSlot() internal pure returns (bytes32) {\n        return bytes32(OWNER_SLOT);\n    }\n\n    function feeRecipientSlot() internal pure returns (bytes32) {\n        return bytes32(FEE_RECIPIENT_SLOT);\n    }\n\n    function positionSupplySharesSlot(Id id, address user) internal pure returns (bytes32) {\n        return bytes32(\n            uint256(keccak256(abi.encode(user, keccak256(abi.encode(id, POSITION_SLOT))))) + SUPPLY_SHARES_OFFSET\n        );\n    }\n\n    function positionBorrowSharesAndCollateralSlot(Id id, address user) internal pure returns (bytes32) {\n        return bytes32(\n            uint256(keccak256(abi.encode(user, keccak256(abi.encode(id, POSITION_SLOT)))))\n            + BORROW_SHARES_AND_COLLATERAL_OFFSET\n        );\n    }\n\n    function marketTotalSupplyAssetsAndSharesSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, MARKET_SLOT))) + TOTAL_SUPPLY_ASSETS_AND_SHARES_OFFSET);\n    }\n\n    function marketTotalBorrowAssetsAndSharesSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, MARKET_SLOT))) + TOTAL_BORROW_ASSETS_AND_SHARES_OFFSET);\n    }\n\n    function marketLastUpdateAndFeeSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, MARKET_SLOT))) + LAST_UPDATE_AND_FEE_OFFSET);\n    }\n\n    function isIrmEnabledSlot(address irm) internal pure returns (bytes32) {\n        return keccak256(abi.encode(irm, IS_IRM_ENABLED_SLOT));\n    }\n\n    function isLltvEnabledSlot(uint256 lltv) internal pure returns (bytes32) {\n        return keccak256(abi.encode(lltv, IS_LLTV_ENABLED_SLOT));\n    }\n\n    function isAuthorizedSlot(address authorizer, address authorizee) internal pure returns (bytes32) {\n        return keccak256(abi.encode(authorizee, keccak256(abi.encode(authorizer, IS_AUTHORIZED_SLOT))));\n    }\n\n    function nonceSlot(address authorizer) internal pure returns (bytes32) {\n        return keccak256(abi.encode(authorizer, NONCE_SLOT));\n    }\n\n    function idToBorrowableTokenSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + BORROWABLE_TOKEN_OFFSET);\n    }\n\n    function idToCollateralTokenSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + COLLATERAL_TOKEN_OFFSET);\n    }\n\n    function idToOracleSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + ORACLE_OFFSET);\n    }\n\n    function idToIrmSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + IRM_OFFSET);\n    }\n\n    function idToLltvSlot(Id id) internal pure returns (bytes32) {\n        return bytes32(uint256(keccak256(abi.encode(id, ID_TO_MARKET_PARAMS_SLOT))) + LLTV_OFFSET);\n    }\n}"
      },
      "contracts/libs/Morpho/MorphoUtils.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\n\n/// MorphoLTVHelper.sol\n\n// Copyright (C) 2021-2021 Oazo Apps Limited\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\npragma solidity 0.8.22;\n\nimport {IMorpho, MarketParams, Position, Id} from \"./../../interfaces/MorphoBlue/IMorpho.sol\";\nimport {IChainlinkOracle} from \"./../../interfaces/MorphoBlue/IChainlinkOracle.sol\";\nimport \"./MorphoBalancesLib.sol\";\n\n/// @title MorphoUtils\n/// @notice Library to help calculate Loan to Value (LTV) for loans managed by the MorphoBlue protocol.\nlibrary MorphoUtils {\n\n    /// @notice Calculates the LTV for a given loan position.\n    /// @param morphoBlue Interface to the MorphoBlue contract.\n    /// @param id The market ID related to the loan.\n    /// @param positionAddress The address of the loan position.\n    /// @param quoteDecimals The decimal precision of the quote currency.\n    /// @param collateralDecimals The decimal precision of the collateral.\n    /// @return ltv The calculated LTV as a percentage scaled to 4 decimal places.\n    /// Example: An LTV of 57% is returned as 5700.\n    function calculateLTV(\n        IMorpho morphoBlue,\n        Id id,\n        address positionAddress,\n        uint8 quoteDecimals,\n        uint8 collateralDecimals\n    ) internal view returns (uint256) {\n        MarketParams memory marketParams = morphoBlue.idToMarketParams(id);\n        Position memory position = morphoBlue.position(id, positionAddress);\n        IChainlinkOracle oracle = IChainlinkOracle(marketParams.oracle);\n\n        uint256 price = oracle.price() / oracle.SCALE_FACTOR();\n\n        // Exit early if collateral, price, or borrow shares are zero to prevent division by zero.\n        if (position.collateral == 0 || price == 0 || position.borrowShares == 0) {\n            return 0;\n        }\n\n        // Calculate the value of the collateral in terms of the quote currency.\n        uint256 collateralValueInQuote = (position.collateral * price) / (10 ** (collateralDecimals + collateralDecimals));\n\n        uint256 borrowedAssets = MorphoBalancesLib.expectedBorrowBalance(morphoBlue, marketParams, positionAddress);\n\n        // Adjusted LTV calculation, scaled to base 10,000.\n        uint8 ltvDecimalPrecision = 4;\n\n        uint256 quoteValue = (borrowedAssets * (10 ** ltvDecimalPrecision)) / (10 ** quoteDecimals);\n\n        return quoteValue / collateralValueInQuote;\n    }\n\n    /// @notice Retrieves the liquidation LTV as MaxLTV with a given decimal precision\n    /// @param morphoBlue Interface to the MorphoBlue contract.\n    /// @param id The market ID related to the loan.\n    /// @return MaxLTV\n    function getMaxLTV(\n        IMorpho morphoBlue,\n        Id id,\n        uint8 desiredDecimalPrecision\n    ) internal view returns (uint256) {\n        MarketParams memory marketParams = morphoBlue.idToMarketParams(id);\n\n        uint256 lltvDecimalPrecision = 18;\n\n        uint256 divisor = (10 ** (lltvDecimalPrecision - desiredDecimalPrecision));\n\n        uint256 maxLtv = marketParams.lltv / divisor;\n        require(maxLtv >= 1);\n\n        return maxLtv;\n    }\n\n    /// @notice Calculates the current oracle price for collateral in terms of quote\n    /// @param morphoBlue Interface to the MorphoBlue contract.\n    /// @param id The market ID related to the loan.\n    /// @return Price\n    function getCurrentOraclePrice(\n        IMorpho morphoBlue,\n        Id id\n    ) internal view returns (uint256) {\n        MarketParams memory marketParams = morphoBlue.idToMarketParams(id);\n        IChainlinkOracle oracle = IChainlinkOracle(marketParams.oracle);\n\n        return oracle.price() / oracle.SCALE_FACTOR();\n    }\n}\n"
      },
      "contracts/libs/Morpho/SharesMathLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {MathLib} from \"./MathLib.sol\";\n\n/// @title SharesMathLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.xyz\n/// @notice Shares management library.\n/// @dev This implementation mitigates share price manipulations, using OpenZeppelin's method of virtual shares:\n/// https://docs.openzeppelin.com/contracts/4.x/erc4626#inflation-attack.\nlibrary SharesMathLib {\n    using MathLib for uint256;\n\n    /// @dev The number of virtual shares has been chosen low enough to prevent overflows, and high enough to ensure\n    /// high precision computations.\n    uint256 internal constant VIRTUAL_SHARES = 1e6;\n\n    /// @dev A number of virtual assets of 1 enforces a conversion rate between shares and assets when a market is\n    /// empty.\n    uint256 internal constant VIRTUAL_ASSETS = 1;\n\n    /// @dev Calculates the value of `assets` quoted in shares, rounding down.\n    function toSharesDown(uint256 assets, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {\n        return assets.mulDivDown(totalShares + VIRTUAL_SHARES, totalAssets + VIRTUAL_ASSETS);\n    }\n\n    /// @dev Calculates the value of `shares` quoted in assets, rounding down.\n    function toAssetsDown(uint256 shares, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {\n        return shares.mulDivDown(totalAssets + VIRTUAL_ASSETS, totalShares + VIRTUAL_SHARES);\n    }\n\n    /// @dev Calculates the value of `assets` quoted in shares, rounding up.\n    function toSharesUp(uint256 assets, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {\n        return assets.mulDivUp(totalShares + VIRTUAL_SHARES, totalAssets + VIRTUAL_ASSETS);\n    }\n\n    /// @dev Calculates the value of `shares` quoted in assets, rounding up.\n    function toAssetsUp(uint256 shares, uint256 totalAssets, uint256 totalShares) internal pure returns (uint256) {\n        return shares.mulDivUp(totalAssets + VIRTUAL_ASSETS, totalShares + VIRTUAL_SHARES);\n    }\n}"
      },
      "contracts/libs/Morpho/UtilsLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {ErrorsLib} from \"./ErrorsLib.sol\";\n\n/// @title UtilsLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.xyz\n/// @notice Library exposing helpers.\n/// @dev Inspired by https://github.com/morpho-org/morpho-utils.\nlibrary UtilsLib {\n    /// @dev Returns true if there is exactly one zero.\n    function exactlyOneZero(uint256 x, uint256 y) internal pure returns (bool z) {\n        assembly {\n            z := xor(iszero(x), iszero(y))\n        }\n    }\n\n    /// @dev Returns the min of x and y.\n    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        assembly {\n            z := xor(x, mul(xor(x, y), lt(y, x)))\n        }\n    }\n\n    /// @dev Returns `x` safely cast to uint128.\n    function toUint128(uint256 x) internal pure returns (uint128) {\n        require(x <= type(uint128).max, ErrorsLib.MAX_UINT128_EXCEEDED);\n        return uint128(x);\n    }\n}"
      },
      "contracts/libs/RatioUtils.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\n\n/// BasicBuyCommand.sol\n\n// Copyright (C) 2021-2021 Oazo Apps Limited\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program.  If not, see <https://www.gnu.org/licenses/>.\npragma solidity ^0.8.0;\n\nimport { SafeMath } from \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\nlibrary RatioUtils {\n    using SafeMath for uint256;\n\n    uint256 public constant RATIO = 10 ** 4;\n    uint256 public constant WAD = 10 ** 18;\n    uint256 public constant RAY = 10 ** 27;\n    uint256 public constant RAD = 10 ** 45;\n\n    // convert base units to ratio\n    function toRatio(uint256 units) internal pure returns (uint256) {\n        return units.mul(RATIO);\n    }\n\n    function wad(uint256 ratio) internal pure returns (uint256) {\n        return ratio.mul(WAD).div(RATIO);\n    }\n\n    function ray(uint256 ratio) internal pure returns (uint256) {\n        return ratio.mul(RAY).div(RATIO);\n    }\n\n    function bounds(\n        uint256 ratio,\n        uint64 deviation\n    ) internal pure returns (uint256 lower, uint256 upper) {\n        uint256 offset = ratio.mul(deviation).div(RATIO);\n        return (ratio.sub(offset), ratio.add(offset));\n    }\n\n    function rayToWad(uint256 _ray) internal pure returns (uint256 _wad) {\n        _wad = _ray.mul(WAD).div(RAY);\n    }\n\n    function wadToRay(uint256 _wad) internal pure returns (uint256 _ray) {\n        _ray = _wad.mul(RAY).div(WAD);\n    }\n\n    function radToWad(uint256 _rad) internal pure returns (uint256 _wad) {\n        _wad = _rad.mul(WAD).div(RAD);\n    }\n\n    function wadToRad(uint256 _wad) internal pure returns (uint256 _rad) {\n        _rad = _wad.mul(RAD).div(WAD);\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 1000
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}