creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/LiquidationBot.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.13;\n\nimport {IERC20} from \"./interfaces/IERC20.sol\";\nimport {SafeTransferLib} from \"./libraries/SafeTransferLib.sol\";\nimport {ErrorsLib} from \"./libraries/ErrorsLib.sol\";\n\nimport {\n    Id,\n    IIMFMoneyMarkets,\n    MarketParams\n} from \"./interfaces/IIMFMoneyMarkets.sol\";\nimport { IIMFMoneyMarketsLiquidateCallback } from \"./interfaces/IIMFMoneyMarketsCallbacks.sol\";\n\ncontract LiquidationBot is IIMFMoneyMarketsLiquidateCallback  {\n    struct IMFLiquidateData {\n        address collateralToken;\n        address loanToken;\n        uint256 seized;\n        address swapper;\n        bytes swapData;\n    }\n    \n    string internal constant NO_PROFIT = \"no profit\";\n\n    address public owner;\n    mapping(address => bool) public authorized;\n    address public immutable imfMarkets;\n\n    constructor(address _imfMarkets) payable {\n        owner = msg.sender;\n        imfMarkets = _imfMarkets;\n    }\n\n    receive() external payable {}\n\n    modifier onlyOwner() {\n        require(msg.sender == owner, ErrorsLib.NOT_OWNER);\n        _;\n    }\n\n    modifier onlyIMF() {\n        require(msg.sender == address(imfMarkets), ErrorsLib.UNAUTHORIZED);\n        _;\n    }\n\n    modifier onlyAuthorized() {\n        require(msg.sender == owner || authorized[msg.sender], ErrorsLib.NOT_OWNER);\n        _;\n    }\n\n    function setOwner(address newOwner) external onlyOwner {\n        require(newOwner != owner, ErrorsLib.ALREADY_SET);\n        owner = newOwner;\n    }\n\n    function setAuthorized(address liquidator, bool setting) external onlyOwner {\n        require(liquidator != address(0), ErrorsLib.ZERO_ADDRESS);\n        require(authorized[liquidator] != setting, ErrorsLib.AUTHORIZATION_NOT_CHANGED);\n        authorized[liquidator] = setting;\n    }\n\n    function withdrawERC20(address token, uint256 amount) external onlyOwner {\n        SafeTransferLib.safeTransfer(IERC20(token), msg.sender, amount);\n    }\n\n    function liquidate(Id id, address borrower, uint256 seizedAssets, address pair, bytes calldata swapData) external payable onlyAuthorized {\n        MarketParams memory params = IIMFMoneyMarkets(imfMarkets).idToMarketParams(id);\n        IIMFMoneyMarkets(imfMarkets).liquidate(\n            params,\n            borrower,\n            seizedAssets,\n            0,\n            abi.encode(\n                IMFLiquidateData(\n                    params.collateralToken,\n                    params.loanToken,\n                    seizedAssets,\n                    pair,\n                    swapData\n                )\n            )\n        );\n    }\n\n    function onIMFMoneyMarketsLiquidate(uint256 repaidAssets, bytes calldata data) external onlyIMF {\n        IMFLiquidateData memory ldata = abi.decode(data, (IMFLiquidateData));\n        IERC20 collateralToken = IERC20(ldata.collateralToken);\n        IERC20 loanToken = IERC20(ldata.loanToken);\n        collateralToken.approve(ldata.swapper, ldata.seized);\n        (bool success,) = ldata.swapper.call(ldata.swapData);\n        if (!success) revert (\"swap error\");\n        loanToken.approve(imfMarkets, repaidAssets);\n    }\n}\n"
      },
      "src/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n\n    function decimals() external view returns (uint8);\n}\n"
      },
      "src/libraries/SafeTransferLib.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"../interfaces/IERC20.sol\";\n\nimport {ErrorsLib} from \"../libraries/ErrorsLib.sol\";\n\ninterface IERC20Internal {\n    function transfer(address to, uint256 value) external returns (bool);\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\n/// @title SafeTransferLib\n/// @author Morpho Labs\n/// @custom:contact security@morpho.org\n/// @notice Library to manage transfers of tokens, even if calls to the transfer or transferFrom functions are not\n/// returning a boolean.\nlibrary SafeTransferLib {\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        require(address(token).code.length > 0, ErrorsLib.NO_CODE);\n\n        (bool success, bytes memory returndata) =\n            address(token).call(abi.encodeCall(IERC20Internal.transfer, (to, value)));\n        require(success, ErrorsLib.TRANSFER_REVERTED);\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), ErrorsLib.TRANSFER_RETURNED_FALSE);\n    }\n\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        require(address(token).code.length > 0, ErrorsLib.NO_CODE);\n\n        (bool success, bytes memory returndata) =\n            address(token).call(abi.encodeCall(IERC20Internal.transferFrom, (from, to, value)));\n        require(success, ErrorsLib.TRANSFER_FROM_REVERTED);\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), ErrorsLib.TRANSFER_FROM_RETURNED_FALSE);\n    }\n}\n"
      },
      "src/libraries/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.org\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 a token to transfer doesn't have code.\n    string internal constant NO_CODE = \"no code\";\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 the market is paused\n    string internal constant MARKET_PAUSED = \"market paused\";\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 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 reverted.\n    string internal constant TRANSFER_REVERTED = \"transfer reverted\";\n\n    /// @notice Thrown when a token transfer returned false.\n    string internal constant TRANSFER_RETURNED_FALSE = \"transfer returned false\";\n\n    /// @notice Thrown when a token transferFrom reverted.\n    string internal constant TRANSFER_FROM_REVERTED = \"transferFrom reverted\";\n\n    /// @notice Thrown when a token transferFrom returned false\n    string internal constant TRANSFER_FROM_RETURNED_FALSE = \"transferFrom returned false\";\n\n    /// @notice Thrown when the maximum uint128 is exceeded.\n    string internal constant MAX_UINT128_EXCEEDED = \"max uint128 exceeded\";\n\n    /// @notice Thrown when the user authorization is not changed\n    string internal constant AUTHORIZATION_NOT_CHANGED = \"Authorization not changed\";\n}\n"
      },
      "src/interfaces/IIMFMoneyMarkets.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 collateralTokenOracle;\n    address irm;\n    uint256 lltv;\n}\n\nstruct Position {\n    uint128 borrowShares;\n    uint128 collateral;\n}\n\n/// @dev Warning: `totalBorrowAssets` does not contain the accrued interest since the last interest accrual.\nstruct Market {\n    uint128 totalBorrowAssets;\n    uint128 totalBorrowShares;\n    uint128 lastUpdate;\n    bool isPaused;\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 IIMFMoneyMarketsStaticTyping and IIMFMoneyMarkets.\n/// @dev Consider using the IIMFMoneyMarkets interface instead of this one.\ninterface IIMFMoneyMarketsBase {\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 Outstanding bad debts. Interest is split between reducing bad debt\n    /// and distributed to IMF token holders\n    // function totalBadDebtAssets() 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 The address that receives the interest.\n    function interestRecipient() external view returns (address);\n\n    /// @notice Set the address that receives the interest.\n    /// @dev It can't be the zero address.\n    function setInterestRecipient(address _newInterestRecipient) external;\n\n    /// @notice Set if a market is paused\n    function setMarketPause(MarketParams memory marketParams, bool pause) 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    /// IMFMoneyMarkets 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 IMFMoneyMarkets should only decrease on `transfer` and `transferFrom`. In particular,\n    /// tokens with\n    /// burn functions are not supported.\n    /// - The token should not re-enter IMFMoneyMarkets 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 IMFMoneyMarkets.\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 IMFMoneyMarkets's liveness\n    /// 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 Borrows `assets` or `shares` 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 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 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(MarketParams memory marketParams, uint256 assets, uint256 shares, address receiver)\n        external\n        returns (uint256 assetsBorrowed, uint256 sharesBorrowed);\n\n    /// @notice Repays `assets` or `shares`, optionally calling back the caller's\n    /// `onIMFMoneyMarketsReplay` function with the given `data`.\n    /// @dev Either `assets` or `shares` should be zero. To repay max, pass the `shares`'s balance of the caller\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 data Arbitrary data to pass to the `onIMFMoneyMarketsRepay` 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(MarketParams memory marketParams, uint256 assets, uint256 shares, bytes memory data)\n        external\n        returns (uint256 assetsRepaid, uint256 sharesRepaid);\n\n    /// @notice Supplies `assets` of collateral on behalf of `onBehalf`, optionally calling back the caller's\n    /// `onIMFMoneyMarketsSupplyCollateral` 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 data Arbitrary data to pass to the `onIMFMoneyMarketsSupplyCollateral` callback. Pass empty data if not\n    /// needed.\n    function supplyCollateral(MarketParams memory marketParams, uint256 assets, bytes memory data) 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 receiver The address that will receive the collateral assets.\n    function withdrawCollateral(MarketParams memory marketParams, uint256 assets, address receiver) 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    /// `onIMFMoneyMarketsLiquidate` 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 `onIMFMoneyMarketsLiquidate` 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 `onIMFMoneyMarketsFlashLoan` callback.\n    function flashLoan(address token, uint256 assets, bytes calldata data) external;\n\n    /// @notice Sets the authorization for `authorized` to manage `msg.sender`'s positions.\n    /// @param authorized The authorized address.\n    /// @param newIsAuthorized The new authorization status.\n    // function setAuthorization(address authorized, bool newIsAuthorized) external;\n\n    /// @notice Sets the authorization for `authorization.authorized` to manage `authorization.authorizer`'s positions.\n    /// @dev Warning: Reverts if the signature has already been submitted.\n    /// @dev The signature is malleable, but it has no impact on the security here.\n    /// @dev The nonce is passed as argument to be able to revert with a different error message.\n    /// @param authorization The `Authorization` struct.\n    /// @param signature The signature.\n    // function setAuthorizationWithSig(Authorization calldata authorization, Signature calldata signature) external;\n\n    /// @notice Accrues interest for the given market `marketParams`.\n    function accrueInterest(MarketParams memory marketParams) external;\n\n    /// @notice Returns the data stored on the different `slots`.\n    function extSloads(bytes32[] memory slots) external view returns (bytes32[] memory);\n}\n\n/// @dev This interface is inherited by IMFMoneyMarkets so that function signatures are checked by the compiler.\n/// @dev Consider using the IIMFMoneyMarkets interface instead of this one.\ninterface IIMFMoneyMarketsStaticTyping is IIMFMoneyMarketsBase {\n    /// @notice The state of the position of `user` on the market corresponding to `id`.\n    function position(Id id, address user) external view returns (uint128 borrowShares, uint128 collateral);\n\n    /// @notice The state of the market corresponding to `id`.\n    /// @dev Warning: `totalBorrowAssets` does not contain the accrued interest since the last interest accrual.\n    function market(Id id)\n        external\n        view\n        returns (uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, bool isPaused);\n\n    /// @notice The market params corresponding to `id`.\n    /// @dev This mapping is not used in IMFMoneyMarkets. It is there to enable reducing the cost associated to calldata\n    /// on layer\n    /// 2s by creating a wrapper contract with functions that take `id` as input instead of `marketParams`.\n    function idToMarketParams(Id id)\n        external\n        view\n        returns (address loanToken, address collateralToken, address collateralTokenOracle, address irm, uint256 lltv);\n}\n\n/// @title IIMFMoneyMarkets\n/// @author Morpho Labs\n/// @author An IMFer\n/// @dev Use this interface for IMFMoneyMarkets to have access to all the functions with the appropriate function\n/// signatures.\ninterface IIMFMoneyMarkets is IIMFMoneyMarketsBase {\n    /// @notice The state of the position of `user` on the market corresponding to `id`.\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.totalBorrowAssets` does not contain the accrued interest since the last 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 IMFMoneyMarkets. It is there to enable reducing the cost associated to calldata\n    /// 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"
      },
      "src/interfaces/IIMFMoneyMarketsCallbacks.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title IIMFMoneyMarketsLiquidateCallback\n/// @notice Interface that liquidators willing to use `liquidate`'s callback must implement.\ninterface IIMFMoneyMarketsLiquidateCallback {\n    /// @notice Callback called when a liquidation occurs.\n    /// @dev The callback is called only if data is not empty.\n    /// @param repaidAssets The amount of repaid assets.\n    /// @param data Arbitrary data passed to the `liquidate` function.\n    function onIMFMoneyMarketsLiquidate(uint256 repaidAssets, bytes calldata data) external;\n}\n\n/// @title IIMFMoneyMarketsRepayCallback\n/// @notice Interface that users willing to use `repay`'s callback must implement.\ninterface IIMFMoneyMarketsRepayCallback {\n    /// @notice Callback called when a repayment occurs.\n    /// @dev The callback is called only if data is not empty.\n    /// @param assets The amount of repaid assets.\n    /// @param data Arbitrary data passed to the `repay` function.\n    function onIMFMoneyMarketsRepay(uint256 assets, bytes calldata data) external;\n}\n\n/// @title IIMFMoneyMarketsSupplyCallback\n/// @notice Interface that users willing to use `supply`'s callback must implement.\ninterface IIMFMoneyMarketsSupplyCallback {\n    /// @notice Callback called when a supply occurs.\n    /// @dev The callback is called only if data is not empty.\n    /// @param assets The amount of supplied assets.\n    /// @param data Arbitrary data passed to the `supply` function.\n    function onIMFMoneyMarketsSupply(uint256 assets, bytes calldata data) external;\n}\n\n/// @title IIMFMoneyMarketsSupplyCollateralCallback\n/// @notice Interface that users willing to use `supplyCollateral`'s callback must implement.\ninterface IIMFMoneyMarketsSupplyCollateralCallback {\n    /// @notice Callback called when a supply of collateral occurs.\n    /// @dev The callback is called only if data is not empty.\n    /// @param assets The amount of supplied collateral.\n    /// @param data Arbitrary data passed to the `supplyCollateral` function.\n    function onIMFMoneyMarketsSupplyCollateral(uint256 assets, bytes calldata data) external;\n}\n\n/// @title IIMFMoneyMarketsFlashLoanCallback\n/// @notice Interface that users willing to use `flashLoan`'s callback must implement.\ninterface IIMFMoneyMarketsFlashLoanCallback {\n    /// @notice Callback called when a flash loan occurs.\n    /// @dev The callback is called only if data is not empty.\n    /// @param assets The amount of assets that was flash loaned.\n    /// @param data Arbitrary data passed to the `flashLoan` function.\n    function onIMFMoneyMarketsFlashLoan(uint256 assets, bytes calldata data) external;\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "forge-std/=lib/forge-std/src/",
        "halmos-cheatcodes/=lib/halmos-cheatcodes/src/",
        "@uniswap/v3-core/=lib/v3-core/",
        "@uniswap/v3-periphery/=lib/v3-periphery/",
        "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
        "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "openzeppelin/=lib/openzeppelin-contracts/contracts/",
        "v3-core/=lib/v3-core/",
        "v3-periphery/=lib/v3-periphery/contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 999999
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": true,
      "libraries": {}
    }
  }}