ILendingPool

// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.16;

import { IAddressProvider } from "../interfaces/IAddressProvider.sol";

import { ConfigTypes } from "../protocol/libraries/types/ConfigTypes.sol";
import { DataTypes } from "../protocol/libraries/types/DataTypes.sol";

interface ILendingPool {
    /**
     * @dev Emitted when the pause is triggered.
     */
    event Paused();

    /**
     * @dev Emitted when the pause is lifted.
     */
    event Unpaused();

    /**
     * @dev Emitted when the pause time is updated.
     */
    event PausedTimeUpdated(uint256 startTime, uint256 durationTime);

    /**
     * @notice Emitted when an asset deposit is made.
     * @param initiator The address initiating the deposit. 
     * @param collateral The Lending Pool underlying reserve collateral.
     * @param asset The ERC20, reserve asset address.
     * @param amount The amount of ERC20 tokens.
     * @param onBehalfOf The address that will receive the fTokens, same as msg.sender if the user wants to receive them on their own wallet, different if the benefitiary is a different wallet.
     * @param referalCode Code used to register the integrator originating the operation, for potential rewards. 0 if the action is executed directly by the user, without any middle-man
     **/ 
    event Deposit(
        address initiator,
        address collateral,
        address asset, 
        uint256 indexed reserveId,
        uint256 amount, 
        address indexed onBehalfOf, 
        uint16 indexed referalCode
    );

    /**
     * @notice Emitted when an asset withdraw is made.
     * @param initiator The address initiating the withdrawl / owner of fTokens.
     * @param collateral The Lending Pool underlying reserve collateral.
     * @param asset The ERC20, reserve asset address.
     * @param amount The amount of ERC20 tokens.
     * @param to The address that will receive the underlying
     **/ 
    event Withdraw(
        address indexed initiator,
        address collateral,
        address asset, 
        uint256 indexed reserveId,
        uint256 amount, 
        address indexed to
    );

 /**
     * @dev Emitted on borrow() when loan needs to be opened
     * @param initiator The address of the user initiating the borrow(), receiving the funds
     * @param reserveId The id of the underlying reserve
     * @param asset The address of the borrowed asset
     * @param amount The amount borrowed
     * @param duration The duration of the loan
     * @param collateral The address of the underlying NFT used as collateral
     * @param tokenId The token id of the underlying NFT used as collateral
     * @param onBehalfOf The address that will be getting the loan
     * @param referral The referral code used
     **/
    event Borrow(
        address initiator,
        uint256 indexed reserveId,
        address asset,
        uint256 amount,
        uint256 duration,
        address collateral,
        uint256 tokenId,
        address indexed onBehalfOf,
        uint256 borrowRate,
        uint256 borrowId,
        uint16 indexed referral
    );

    /**
     * @dev Emitted on repay()
     * @param initiator The address of the user initiating the repay(), providing the funds
     * @param reserveId The id of the underlying reserve
     * @param asset The address of the borrowed asset
     * @param amount The amount repaid
     * @param collateral The address of the underlying NFT used as collateral
     * @param tokenId The token id of the underlying NFT used as collateral
     * @param borrower The beneficiary of the repayment, getting his debt reduced
     * @param borrowId The borrow ID of the NFT borrows
     **/
    event Repay(
        address initiator,
        uint256 indexed reserveId,
        address asset,
        uint256 amount,
        address indexed collateral,
        uint256 tokenId,
        address indexed borrower,
        uint256 borrowId
    );

    /**
     * @dev Emitted on refinance()
     * @param initiator The address of the user initiating the refinance(), providing the funds
     * @param borrower The address of the borrower
     * @param borrowId The id of the borrow
     * @param collateral The address of the underlying NFT used as collateral
     * @param tokenId The token id of the underlying NFT used as collateral
     * @param asset The address of the borrowed asset
     * @param amount The final refinanced amount
     * @param amountAdded The amount added to the original borrow
     * @param amountTaken The amount taken from the original borrow
     * @param defaultFee The fee paid due to refinancing after loan due date (0 if before)
     * @param duration The duration of the refinanced borrow
     * @param timestamp The timestamp of the refinanced borrow
 
     **/
    event Refinanced(
        address initiator,
        address indexed borrower,
        uint256 indexed reserveId,
        uint256 indexed borrowId,
        address collateral,
        uint256 tokenId,
        address asset,
        uint256 amount,
        uint256 amountAdded,
        uint256 amountTaken,
        uint256 defaultFee,
        uint256 duration,
        uint256 timestamp
    );

    /**
     * @dev Emitted when a borrower's loan is liquidated.
     * @param user The address of the user initiating the auction
     * @param reserveId The id of the reserve
     * @param collateral The NFT used as collateral
     * @param tokenId The tokenId of the NFT used as collateral
     * @param borrower The borrower of the liquidated borrow
     * @param borrowId The borrow ID of the NFT borrows
     * @param paymentAsset The asset used for payment by the liquidator
     * @param paymentAmount The amount of paymentAsset paid by the liquidator
     * @param onBehalfOf The address of the user to receive the underlying NFT
     **/
    event Liquidate(
        address user,
        uint256 indexed reserveId,
        address indexed collateral,
        uint256 tokenId,
        address indexed borrower,
        uint256 borrowId,
        address paymentAsset,
        uint256 paymentAmount,
        address onBehalfOf
    );

    function initReserve(
        ConfigTypes.InitReserveInput calldata input,
        address fTokenAddress, 
        address stableDebtTokenAddress,
        address variableDebtTokenAddress
    ) 
        external
        returns (uint256);

    function deposit(
        uint256 amount,
        uint256 reserveId,
        address onBehalfOf,
        uint16 referralCode
    ) 
        external;

    function batchDeposit(
        uint256[] calldata amounts,
        uint256[] calldata reserveIds,
        address[] calldata onBehalfOfs,
        uint16[] calldata referralCodes
    ) 
        external;

    function withdraw(
        uint256 amount,
        uint256 reserveId,
        address to
    ) 
        external;

    function batchWithdraw(
        uint256[] calldata amounts,
        uint256[] calldata reserveIds,
        address[] calldata tos
    ) 
        external;

    function borrow(
        uint256 amount, 
        uint256 tokenId,
        uint256 tokenValue,
        uint256 reserveId,
        uint256 duration,
        address onBehalfOf,
        uint16 referralCode
    )
        external;

    function batchBorrow(
        uint256[] calldata amounts, 
        uint256[] calldata tokenIds,
        uint256[] calldata tokenValues,
        uint256[] calldata reserveIds,
        uint256 duration,
        address onBehalfOf,
        uint16 referralCode
    )
        external;

    function repay(
        uint256 borrowId,
        uint256 amount
    ) 
        external;

    function batchRepay(
        uint256[] calldata borrowIds,
        uint256[] calldata amounts
    ) 
        external;

    function refinance(
        uint256 borrowId,
        uint256 amount,
        uint256 duration
    ) 
        external;

    function batchRefinance(
        uint256[] calldata borrowIds,
        uint256[] calldata amounts,
        uint256[] calldata durations
    ) 
        external;

    function auction(
        uint256 borrowId,
        address onBehalfOf
    ) 
        external;

    function batchAuction(
        uint256[] calldata borrowIds,
        address[] calldata onBehalfOfs
    ) 
        external;

    function bid(
        address asset,
        uint256 amount,
        uint256 borrowId,
        address onBehalfOf
    ) 
        external;

    function batchBid(
        address[] calldata assets,
        uint256[] calldata amounts,
        uint256[] calldata borrowIds,
        address[] calldata onBehalfOfs
    ) 
        external;

    function getReserveConfiguration(
        uint256 reserveId
    )
        external
        returns (DataTypes.ReserveConfigurationMap memory);

    function getAuctionConfiguration(uint256 reserveId) external view returns (uint256, uint256);

    function getReserveNormalizedIncome(
        uint256 reserveId
    )
        external 
        view
        returns (uint256);

    function getReserveUserStableRate(
        uint256 reserveId,
        address user
    ) 
        external 
        view
        returns (uint256);

    /**
     * @dev Set the _pause state of a reserve
     * - Only callable by the LendPool contract
     * @param val `true` to pause the reserve, `false` to un-pause it
     */
    function setPause(bool val) external;

    function setPausedTime(uint256 startTime, uint256 durationTime) external;

    /**
     * @dev Returns if the LendPool is paused
     */
    function paused() external view returns (bool);

    function getPausedTime() external view returns (uint256, uint256);

    function getAddressesProvider() external view returns (IAddressProvider);

    function finalizeTransfer(
        uint256 reserveId,
        address from,
        address to,
        uint256 amount,
        uint256 balanceFromBefore,
        uint256 balanceToBefore
    ) external view;

    function getReserveNormalizedVariableDebt(
        uint256 reserveId
    ) 
        external view returns (uint256);

    function getReserve(uint256 reserveId) external view returns (DataTypes.Reserve memory);

    function getReserveId(
        address collateral,
        address asset, 
        uint256 maxTokenId,
        uint256 minTokenId
    )
        external 
        view
        returns (uint256); 

    function getReservesList() external view returns (uint256[] memory);

    function getInitializedCollaterals() external view returns (address[] memory);

    function getInitializedAssets() external view returns (address[] memory);

    function setMaxNumberOfReserves(uint256 val) external;

    function getMaxNumberOfReserves() external view returns (uint256);

    function setReserveMaxSupply(
        uint256 reserveId,
        uint256 maxSupply
    ) 
        external;

    function setReserveInterestRateAddress(
        uint256 reserveId,
        address rateAddress
    ) 
        external;

    function setReserveConfiguration(
        uint256 reserveId,
        uint256 configuration
    ) 
        external;

    function setReserveCreatorAddress(uint256 reserveId, address creator) external;

    function setReserveCreatorPercentage(uint256 reserveId, uint256 percentage) external;

    function getBorrowHealthFactor(uint256 borrowId) external view returns (uint256, uint256, uint256);
}